You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ma...@apache.org on 2015/04/29 01:18:58 UTC

phoenix git commit: add testScalarSubquery

Repository: phoenix
Updated Branches:
  refs/heads/calcite 0b1b7e0f0 -> 2d0834592


add testScalarSubquery


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/2d083459
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/2d083459
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/2d083459

Branch: refs/heads/calcite
Commit: 2d083459267f4442cda674c94ea2a376a14f7f7e
Parents: 0b1b7e0
Author: maryannxue <we...@intel.com>
Authored: Tue Apr 28 19:18:44 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Tue Apr 28 19:18:44 2015 -0400

----------------------------------------------------------------------
 .../org/apache/phoenix/calcite/CalciteTest.java | 95 +++++++++++++++-----
 .../apache/phoenix/calcite/CalciteUtils.java    |  2 +-
 .../calcite/jdbc/PhoenixPrepareImpl.java        |  2 +
 .../PhoenixSingleValueAggregateRemoveRule.java  | 55 ++++++++++++
 4 files changed, 129 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/2d083459/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
index 91eb6b9..7b9c30d 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
@@ -3,7 +3,6 @@ package org.apache.phoenix.calcite;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
-import org.apache.calcite.adapter.jdbc.JdbcSchema;
 import org.apache.calcite.jdbc.CalciteConnection;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.phoenix.end2end.BaseClientManagedTimeIT;
@@ -17,8 +16,6 @@ import java.sql.*;
 import java.util.List;
 import java.util.Map;
 
-import javax.sql.DataSource;
-
 import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE_FULL_NAME;
 import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE_FULL_NAME;
 import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE_FULL_NAME;
@@ -156,17 +153,42 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         calciteConnection.setSchema("phoenix");
         return connection;
     }
+
+    private static final String FOODMART_SCHEMA = "     {\n"
+            + "       type: 'jdbc',\n"
+            + "       name: 'foodmart',\n"
+            + "       jdbcDriver: 'org.hsqldb.jdbcDriver',\n"
+            + "       jdbcUser: 'FOODMART',\n"
+            + "       jdbcPassword: 'FOODMART',\n"
+            + "       jdbcUrl: 'jdbc:hsqldb:res:foodmart',\n"
+            + "       jdbcCatalog: null,\n"
+            + "       jdbcSchema: 'foodmart'\n"
+            + "     }";
     
-    private static Connection createConnectionWithHsqldb() throws SQLException {
-        final Connection connection = createConnection();
-        final CalciteConnection calciteConnection =
-                connection.unwrap(CalciteConnection.class);
-        DataSource dataSource =
-                JdbcSchema.dataSource("jdbc:hsqldb:res:foodmart", "org.hsqldb.jdbcDriver", "FOODMART", "FOODMART");
-        SchemaPlus rootSchema = calciteConnection.getRootSchema();
-        rootSchema.add("foodmart",
-                JdbcSchema.create(rootSchema, "foodmart", dataSource, null,
-                    "foodmart"));
+    private static final String PHOENIX_SCHEMA = "    {\n"
+            + "      name: 'phoenix',\n"
+            + "      type: 'custom',\n"
+            + "      factory: 'org.apache.phoenix.calcite.PhoenixSchema$Factory',\n"
+            + "      operand: {\n"
+            + "        url: \"" + getUrl() + "\"\n"
+            + "      }\n"
+            + "    }";
+
+    private static Connection connectWithHsqldbUsingModel() throws Exception {
+        final File file = File.createTempFile("model", ".json");
+        final PrintWriter pw = new PrintWriter(new FileWriter(file));
+        pw.print(
+            "{\n"
+                + "  version: '1.0',\n"
+                + "  defaultSchema: 'phoenix',\n"
+                + "  schemas: [\n"
+                + PHOENIX_SCHEMA + ",\n"
+                + FOODMART_SCHEMA + "\n"
+                + "  ]\n"
+                + "}\n");
+        pw.close();
+        final Connection connection =
+            DriverManager.getConnection("jdbc:phoenixcalcite:model=" + file.getAbsolutePath());
         return connection;
     }
 
@@ -621,7 +643,7 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         final Start start = new Start() {
             @Override
             Connection createConnection() throws Exception {
-                return createConnectionWithHsqldb();
+                return connectWithHsqldbUsingModel();
             }
         };
         start.sql("select the_year, quantity as q, (select count(*) cnt \n"
@@ -631,16 +653,15 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                        "  EnumerableJoin(condition=[=($6, $7)], joinType=[left])\n" +
                        "    PhoenixToEnumerableConverter\n" +
                        "      PhoenixTableScan(table=[[phoenix, Join, OrderTable]])\n" +
-                       "    EnumerableAggregate(group=[{0}], agg#0=[SINGLE_VALUE($1)])\n" +
-                       "      EnumerableAggregate(group=[{0}], CNT=[COUNT()])\n" +
-                       "        EnumerableCalc(expr#0..10=[{inputs}], expr#11=[0], expr#12=[CAST($t5):INTEGER], expr#13=[=($t12, $t0)], THE_YEAR=[$t0], $f0=[$t11], $condition=[$t13])\n" +
-                       "          EnumerableJoin(condition=[true], joinType=[inner])\n" +
-                       "            PhoenixToEnumerableConverter\n" +
-                       "              PhoenixServerAggregate(group=[{0}])\n" +
-                       "                PhoenixServerProject(THE_YEAR=[$6])\n" +
-                       "                  PhoenixTableScan(table=[[phoenix, Join, OrderTable]])\n" +
-                       "            JdbcToEnumerableConverter\n" +
-                       "              JdbcTableScan(table=[[foodmart, time_by_day]])\n")
+                       "    EnumerableAggregate(group=[{0}], CNT=[COUNT()])\n" +
+                       "      EnumerableCalc(expr#0..10=[{inputs}], expr#11=[0], expr#12=[CAST($t5):INTEGER], expr#13=[=($t12, $t0)], THE_YEAR=[$t0], $f0=[$t11], $condition=[$t13])\n" +
+                       "        EnumerableJoin(condition=[true], joinType=[inner])\n" +
+                       "          PhoenixToEnumerableConverter\n" +
+                       "            PhoenixServerAggregate(group=[{0}])\n" +
+                       "              PhoenixServerProject(THE_YEAR=[$6])\n" +
+                       "                PhoenixTableScan(table=[[phoenix, Join, OrderTable]])\n" +
+                       "          JdbcToEnumerableConverter\n" +
+                       "            JdbcTableScan(table=[[foodmart, time_by_day]])\n")
             .resultIs(new Object[][] {
                     new Object[] {1997, 1000, 365L}, 
                     new Object[] {1997, 2000, 365L},
@@ -649,6 +670,32 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                     new Object[] {1998, 5000, 365L}})
             .close();;
     }
+    
+    @Test public void testScalarSubquery() {
+        start().sql("select \"item_id\", name, (select max(quantity) sq \n"
+            + "from " + JOIN_ORDER_TABLE_FULL_NAME + " o where o.\"item_id\" = i.\"item_id\")\n"
+            + "from " + JOIN_ITEM_TABLE_FULL_NAME + " i")
+            .explainIs("PhoenixToEnumerableConverter\n" +
+                       "  PhoenixServerProject(item_id=[$0], NAME=[$1], EXPR$2=[$8])\n" +
+                       "    PhoenixServerJoin(condition=[=($0, $7)], joinType=[left])\n" +
+                       "      PhoenixTableScan(table=[[phoenix, Join, ItemTable]])\n" +
+                       "      PhoenixServerAggregate(group=[{0}], SQ=[MAX($1)])\n" +
+                       "        PhoenixServerProject(item_id0=[$7], QUANTITY=[$4])\n" +
+                       "          PhoenixServerJoin(condition=[=($2, $7)], joinType=[inner])\n" +
+                       "            PhoenixTableScan(table=[[phoenix, Join, OrderTable]])\n" +
+                       "            PhoenixServerAggregate(group=[{0}])\n" +
+                       "              PhoenixServerProject(item_id=[$0])\n" +
+                       "                PhoenixTableScan(table=[[phoenix, Join, ItemTable]])\n")
+            .resultIs(new Object[][] {
+                    new Object[] {"0000000001", "T1", 1000}, 
+                    new Object[] {"0000000002", "T2", 3000}, 
+                    new Object[] {"0000000003", "T3", 5000}, 
+                    new Object[] {"0000000004", "T4", null}, 
+                    new Object[] {"0000000005", "T5", null}, 
+                    new Object[] {"0000000006", "T6", 4000}, 
+                    new Object[] {"invalid001", "INVALID-1", null}})
+            .close();;
+    }
 
     @Test public void testConnectUsingModel() throws Exception {
         final Start start = new Start() {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/2d083459/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
index a3fbce8..ab2bf21 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
@@ -123,7 +123,7 @@ public class CalciteUtils {
                 return new CountAggregateFunction(args);
             }
         });
-        FUNCTION_MAP.put("SUM", new FunctionFactory() {
+        FUNCTION_MAP.put("$SUM0", new FunctionFactory() {
             @Override
             public FunctionExpression newFunction(SqlFunction sqlFunc,
                     List<Expression> args) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/2d083459/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
index aa628e7..beaea4b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
@@ -14,6 +14,7 @@ import org.apache.phoenix.calcite.rules.PhoenixServerAggregateRule;
 import org.apache.phoenix.calcite.rules.PhoenixServerJoinRule;
 import org.apache.phoenix.calcite.rules.PhoenixServerProjectRule;
 import org.apache.phoenix.calcite.rules.PhoenixServerSortRule;
+import org.apache.phoenix.calcite.rules.PhoenixSingleValueAggregateRemoveRule;
 
 public class PhoenixPrepareImpl extends CalcitePrepareImpl {
 
@@ -46,6 +47,7 @@ public class PhoenixPrepareImpl extends CalcitePrepareImpl {
         planner.addRule(PhoenixServerSortRule.SORT_SERVERPROJECT);
         planner.addRule(PhoenixCompactClientSortRule.SORT_SERVERAGGREGATE);
         planner.addRule(PhoenixClientJoinRule.INSTANCE);
+        planner.addRule(PhoenixSingleValueAggregateRemoveRule.INSTANCE);
 
         return planner;
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/2d083459/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixSingleValueAggregateRemoveRule.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixSingleValueAggregateRemoveRule.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixSingleValueAggregateRemoveRule.java
new file mode 100644
index 0000000..5ef2f2a
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixSingleValueAggregateRemoveRule.java
@@ -0,0 +1,55 @@
+package org.apache.phoenix.calcite.rules;
+
+import java.util.List;
+
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.phoenix.calcite.rel.PhoenixAbstractAggregate;
+import com.google.common.base.Predicate;
+
+public class PhoenixSingleValueAggregateRemoveRule extends RelOptRule {
+
+    /** Predicate that returns true if SINGLE_VALUE is the only aggregate call in the Aggregate. */
+    private static final Predicate<PhoenixAbstractAggregate> SINGLE_VALUE_FUNC_ONLY =
+            new Predicate<PhoenixAbstractAggregate>() {
+        @Override
+        public boolean apply(PhoenixAbstractAggregate phoenixAggregate) {
+            List<AggregateCall> aggCalls = phoenixAggregate.getAggCallList();
+            return aggCalls.size() == 1 
+                    && aggCalls.get(0).getAggregation().getName().equals("SINGLE_VALUE");
+        }
+    };
+    
+    public static PhoenixSingleValueAggregateRemoveRule INSTANCE = new PhoenixSingleValueAggregateRemoveRule();
+
+    private PhoenixSingleValueAggregateRemoveRule() {
+        super(
+            operand(
+                    PhoenixAbstractAggregate.class, null, SINGLE_VALUE_FUNC_ONLY,
+                    operand(
+                            // TODO check returns single value?
+                            PhoenixAbstractAggregate.class, any())), 
+            "PhoenixSingleValueAggregateRemoveRule");
+    }
+
+    @Override
+    public void onMatch(RelOptRuleCall call) {
+        PhoenixAbstractAggregate aggregate = call.rel(0);
+        PhoenixAbstractAggregate innerAggregate = call.rel(1);
+        int groupCount = aggregate.getGroupCount();
+        int innerGroupCount = innerAggregate.getGroupCount();
+        if (groupCount != innerGroupCount)
+            return;
+        
+        List<Integer> ordinals = aggregate.getGroupSet().asList();
+        for (int i = 0; i < ordinals.size(); i++) {
+            if (ordinals.get(i) != i) {
+                return;
+            }
+        }
+        
+        call.transformTo(innerAggregate);
+    }
+
+}