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 2014/12/02 22:51:23 UTC
[1/2] phoenix git commit: Sync changes from
https://github.com/julianhyde/phoenix/tree/calcite
Repository: phoenix
Updated Branches:
refs/heads/calcite 766eec2b5 -> b005b1246
Sync changes from https://github.com/julianhyde/phoenix/tree/calcite
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/76a858a4
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/76a858a4
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/76a858a4
Branch: refs/heads/calcite
Commit: 76a858a411b0a497037f1c5384a4cd9ca838a991
Parents: 766eec2
Author: maryannxue <ma...@apache.org>
Authored: Tue Dec 2 16:49:09 2014 -0500
Committer: maryannxue <ma...@apache.org>
Committed: Tue Dec 2 16:49:09 2014 -0500
----------------------------------------------------------------------
.../org/apache/phoenix/calcite/CalciteTest.java | 226 +++++++++++++
.../apache/phoenix/calcite/BuiltInMethod.java | 44 +++
.../apache/phoenix/calcite/CalciteRuntime.java | 79 +++++
.../apache/phoenix/calcite/CalciteUtils.java | 90 +++++
.../phoenix/calcite/PhoenixAggregate.java | 53 +++
.../apache/phoenix/calcite/PhoenixFilter.java | 40 +++
.../calcite/PhoenixFilterScanMergeRule.java | 36 ++
.../org/apache/phoenix/calcite/PhoenixJoin.java | 40 +++
.../apache/phoenix/calcite/PhoenixProject.java | 40 +++
.../org/apache/phoenix/calcite/PhoenixRel.java | 39 +++
.../calcite/PhoenixRelImplementorImpl.java | 91 +++++
.../apache/phoenix/calcite/PhoenixRules.java | 334 +++++++++++++++++++
.../apache/phoenix/calcite/PhoenixSchema.java | 135 ++++++++
.../org/apache/phoenix/calcite/PhoenixSort.java | 32 ++
.../apache/phoenix/calcite/PhoenixTable.java | 77 +++++
.../phoenix/calcite/PhoenixTableScan.java | 60 ++++
.../calcite/PhoenixToEnumerableConverter.java | 72 ++++
.../apache/phoenix/calcite/PhoenixUnion.java | 39 +++
.../apache/phoenix/calcite/PhoenixValues.java | 36 ++
.../phoenix/calcite/ToExpressionTest.java | 77 +++++
20 files changed, 1640 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/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
new file mode 100644
index 0000000..9bce0a3
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
@@ -0,0 +1,226 @@
+package org.apache.phoenix.calcite;
+
+import com.google.common.collect.Lists;
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.phoenix.end2end.BaseClientManagedTimeIT;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.query.BaseTest;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.sql.*;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.*;
+
+/**
+ * Integration test for queries powered by Calcite.
+ */
+public class CalciteTest extends BaseClientManagedTimeIT {
+ public static final String ATABLE_NAME = "ATABLE";
+
+ public static Start start() {
+ return new Start();
+ }
+
+ public static class Start {
+ private Connection connection;
+
+ Connection createConnection() throws Exception {
+ return CalciteTest.createConnection();
+ }
+
+ public Sql sql(String sql) {
+ return new Sql(this, sql);
+ }
+
+ public Connection getConnection() {
+ if (connection == null) {
+ try {
+ connection = createConnection();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return connection;
+ }
+
+ public void close() {
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+
+ /** Fluid class for a test that has specified a SQL query. */
+ static class Sql {
+ private final Start start;
+ private final String sql;
+
+ public Sql(Start start, String sql) {
+ this.start = start;
+ this.sql = sql;
+ }
+
+ public List<String> getResult(ResultSet resultSet) throws SQLException {
+ final List<String> list = Lists.newArrayList();
+ populateResult(resultSet, list);
+ return list;
+ }
+
+ private void populateResult(ResultSet resultSet, List<String> list) throws SQLException {
+ final StringBuilder buf = new StringBuilder();
+ final int columnCount = resultSet.getMetaData().getColumnCount();
+ while (resultSet.next()) {
+ for (int i = 0; i < columnCount; i++) {
+ if (i > 0) {
+ buf.append(", ");
+ }
+ buf.append(resultSet.getString(i + 1));
+ }
+ list.add(buf.toString());
+ buf.setLength(0);
+ }
+ }
+
+ public Sql explainIs(String expected) {
+ final List<String> list = getResult("explain plan for " + sql);
+ if (list.size() != 1) {
+ fail("explain should return 1 row, got " + list.size());
+ }
+ String explain = list.get(0);
+ assertThat(explain, equalTo(expected));
+ return this;
+ }
+
+ public List<String> getResult(String sql) {
+ try {
+ final Statement statement = start.getConnection().createStatement();
+ final ResultSet resultSet = statement.executeQuery(sql);
+ List<String> list = getResult(resultSet);
+ resultSet.close();
+ statement.close();
+ return list;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void close() {
+ start.close();
+ }
+
+ public Sql resultIs(String... lines) {
+ assertThat(Arrays.asList(lines), equalTo(getResult(sql)));
+ return this;
+ }
+ }
+
+ private static Connection createConnection() throws SQLException {
+ final Connection connection = DriverManager.getConnection(
+ "jdbc:calcite:");
+ final CalciteConnection calciteConnection =
+ connection.unwrap(CalciteConnection.class);
+ final String url = getUrl();
+ final PhoenixConnection phoenixConnection =
+ DriverManager.getConnection(url).unwrap(PhoenixConnection.class);
+ BaseTest.ensureTableCreated(url, ATABLE_NAME);
+ calciteConnection.getRootSchema().add("phoenix",
+ new PhoenixSchema(phoenixConnection));
+ calciteConnection.setSchema("phoenix");
+ return connection;
+ }
+
+ private static Connection connectUsingModel() throws Exception {
+ final File file = File.createTempFile("model", ".json");
+ final String url = getUrl();
+ final PrintWriter pw = new PrintWriter(new FileWriter(file));
+ pw.print(
+ "{\n"
+ + " version: '1.0',\n"
+ + " defaultSchema: 'HR',\n"
+ + " schemas: [\n"
+ + " {\n"
+ + " name: 'HR',\n"
+ + " type: 'custom',\n"
+ + " factory: 'org.apache.phoenix.calcite.PhoenixSchema$Factory',\n"
+ + " operand: {\n"
+ + " url: \"" + url + "\",\n"
+ + " user: \"scott\",\n"
+ + " password: \"tiger\"\n"
+ + " }\n"
+ + " }\n"
+ + " ]\n"
+ + "}\n");
+ pw.close();
+ final Connection connection =
+ DriverManager.getConnection("jdbc:calcite:model=" + file.getAbsolutePath());
+ BaseTest.ensureTableCreated(url, ATABLE_NAME);
+ return connection;
+ }
+
+ @Test public void testConnect() throws Exception {
+ final Connection connection = DriverManager.getConnection("jdbc:calcite:");
+ final CalciteConnection calciteConnection =
+ connection.unwrap(CalciteConnection.class);
+ Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
+ final String url = getUrl();
+ final PhoenixConnection phoenixConnection =
+ DriverManager.getConnection(url).unwrap(PhoenixConnection.class);
+ ensureTableCreated(url, ATABLE_NAME);
+ initATableValues(getOrganizationId(), null, url);
+ calciteConnection.getRootSchema().add("phoenix",
+ new PhoenixSchema(phoenixConnection));
+ calciteConnection.setSchema("phoenix");
+ final Statement statement = calciteConnection.createStatement();
+ final ResultSet resultSet = statement.executeQuery("select * from aTable where a_string = 'a'");
+ while (resultSet.next()) {
+ System.out.println("org_id=" + resultSet.getObject(1) + ",entity_id=" + resultSet.getObject(2) + ",a_string=" + resultSet.getObject("A_STRING"));
+ }
+ resultSet.close();
+ statement.close();
+ connection.close();
+ }
+
+ @Test public void testExplainPlanForSelectWhereQuery() {
+ start()
+ .sql("select * from aTable where a_string = 'a'")
+ .explainIs(
+ "PhoenixToEnumerableConverter\n"
+ + " PhoenixTableScan(table=[[phoenix, ATABLE]], filter=[=($2, 'a')])\n")
+ .close();
+ }
+
+ @Test public void testExplainProject() {
+ start()
+ .sql("select a_string, b_string from aTable where a_string = 'a'")
+ .explainIs(
+ "PhoenixToEnumerableConverter\n"
+ + " PhoenixProject(A_STRING=[$2], B_STRING=[$3])\n"
+ + " PhoenixTableScan(table=[[phoenix, ATABLE]], filter=[=($2, 'a')])\n")
+ .close();
+ }
+
+ @Test public void testConnectUsingModel() throws Exception {
+ final Start start = new Start() {
+ @Override
+ Connection createConnection() throws Exception {
+ return connectUsingModel();
+ }
+ };
+ start.sql("select * from aTable")
+ .explainIs("PhoenixToEnumerableConverter\n"
+ + " PhoenixTableScan(table=[[HR, ATABLE]])\n")
+ // .resultIs("Xx")
+ .close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java
new file mode 100644
index 0000000..192b421
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java
@@ -0,0 +1,44 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.linq4j.tree.Types;
+import org.apache.phoenix.compile.QueryPlan;
+import org.apache.phoenix.iterate.ResultIterator;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * Built-in methods.
+ */
+public enum BuiltInMethod {
+ RESULT_ITERATOR_NEXT(ResultIterator.class, "next"),
+ TO_ENUMERABLE(CalciteRuntime.class, "toEnumerable", QueryPlan.class);
+
+ public final Method method;
+ public final Constructor constructor;
+
+ public static final ImmutableMap<Method, BuiltInMethod> MAP;
+
+ static {
+ final ImmutableMap.Builder<Method, BuiltInMethod> builder =
+ ImmutableMap.builder();
+ for (BuiltInMethod value : BuiltInMethod.values()) {
+ if (value.method != null) {
+ builder.put(value.method, value);
+ }
+ }
+ MAP = builder.build();
+ }
+
+ BuiltInMethod(Class clazz, String methodName, Class... argumentTypes) {
+ this.method = Types.lookupMethod(clazz, methodName, argumentTypes);
+ this.constructor = null;
+ }
+
+ BuiltInMethod(Class clazz, Class... argumentTypes) {
+ this.method = null;
+ this.constructor = Types.lookupConstructor(clazz, argumentTypes);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteRuntime.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteRuntime.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteRuntime.java
new file mode 100644
index 0000000..a167ea6
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteRuntime.java
@@ -0,0 +1,79 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.linq4j.AbstractEnumerable;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.ColumnProjector;
+import org.apache.phoenix.compile.QueryPlan;
+import org.apache.phoenix.compile.RowProjector;
+import org.apache.phoenix.iterate.ResultIterator;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+import java.sql.SQLException;
+
+/**
+ * Methods used by code generated by Calcite.
+ */
+public class CalciteRuntime {
+ public static Enumerable<Object[]> toEnumerable2(final ResultIterator iterator, final RowProjector rowProjector) {
+ return new AbstractEnumerable<Object[]>() {
+ @Override
+ public Enumerator<Object[]> enumerator() {
+ return toEnumerator(iterator, rowProjector);
+ }
+ };
+ }
+
+ public static Enumerable<Object[]> toEnumerable(final QueryPlan plan) {
+ try {
+ return toEnumerable2(plan.iterator(), plan.getProjector());
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Enumerator<Object[]> toEnumerator(final ResultIterator iterator, final RowProjector rowProjector) {
+ return new Enumerator<Object[]>() {
+ Object[] current = new Object[rowProjector.getColumnCount()];
+ private final ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+
+ @Override
+ public Object[] current() {
+ return current;
+ }
+
+ @Override
+ public boolean moveNext() {
+ try {
+ final Tuple tuple = iterator.next();
+ if (tuple == null) {
+ current = null;
+ return false;
+ }
+ for (int i = 0; i < current.length; i++) {
+ ColumnProjector projector = rowProjector.getColumnProjector(i);
+ current[i] = projector.getValue(tuple, projector.getExpression().getDataType(), ptr);
+ }
+ return true;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void reset() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void close() {
+ try {
+ iterator.close();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/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
new file mode 100644
index 0000000..956f317
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
@@ -0,0 +1,90 @@
+package org.apache.phoenix.calcite;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexInputRef;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.calcite.PhoenixRel.Implementor;
+import org.apache.phoenix.expression.ComparisonExpression;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.ExpressionType;
+import org.apache.phoenix.expression.LiteralExpression;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Utilities for interacting with Calcite.
+ */
+public class CalciteUtils {
+ private CalciteUtils() {}
+
+ private static final Map<SqlKind, ExpressionFactory> EXPRESSION_MAP = Maps
+ .newHashMapWithExpectedSize(ExpressionType.values().length);
+ private static final ExpressionFactory getFactory(RexNode node) {
+ ExpressionFactory eFactory = EXPRESSION_MAP.get(node.getKind());
+ if (eFactory == null) {
+ throw new UnsupportedOperationException("Unsupported RexNode: "
+ + node);
+ }
+ return eFactory;
+ }
+ static {
+ EXPRESSION_MAP.put(SqlKind.EQUALS, new ExpressionFactory() {
+
+ @Override
+ public Expression newExpression(RexNode node, Implementor implementor) {
+ RexCall call = (RexCall) node;
+ List<Expression> children = Lists.newArrayListWithExpectedSize(call.getOperands().size());
+ for (RexNode op : call.getOperands()) {
+ Expression child = getFactory(op).newExpression(op, implementor);
+ children.add(child);
+ }
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ try {
+ return ComparisonExpression.create(CompareOp.EQUAL, children, ptr);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ });
+ EXPRESSION_MAP.put(SqlKind.LITERAL, new ExpressionFactory() {
+
+ @Override
+ public Expression newExpression(RexNode node, Implementor implementor) {
+ RexLiteral lit = (RexLiteral) node;
+ Object o = lit.getValue2();
+ return LiteralExpression.newConstant(o);
+ }
+
+ });
+ EXPRESSION_MAP.put(SqlKind.INPUT_REF, new ExpressionFactory() {
+
+ @Override
+ public Expression newExpression(RexNode node, Implementor implementor) {
+ RexInputRef ref = (RexInputRef) node;
+ int index = ref.getIndex();
+ return implementor.newColumnExpression(index);
+ }
+
+ });
+ }
+
+ static Expression toExpression(RexNode node, Implementor implementor) {
+ ExpressionFactory eFactory = getFactory(node);
+ Expression expression = eFactory.newExpression(node, implementor);
+ return expression;
+ }
+
+ public static interface ExpressionFactory {
+ public Expression newExpression(RexNode node, Implementor implementor);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixAggregate.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixAggregate.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixAggregate.java
new file mode 100644
index 0000000..b5e55e7
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixAggregate.java
@@ -0,0 +1,53 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.InvalidRelException;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Aggregate;
+import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link org.apache.calcite.rel.core.Aggregate}
+ * relational expression in Phoenix.
+ */
+public class PhoenixAggregate extends Aggregate implements PhoenixRel {
+ public PhoenixAggregate(RelOptCluster cluster, RelTraitSet traits, RelNode child, boolean indicator, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) throws InvalidRelException {
+ super(cluster, traits, child, indicator, groupSet, groupSets, aggCalls);
+ assert getConvention() == PhoenixRel.CONVENTION;
+ assert getConvention() == child.getConvention();
+
+ for (AggregateCall aggCall : aggCalls) {
+ if (aggCall.isDistinct()) {
+ throw new InvalidRelException( "distinct aggregation not supported");
+ }
+ }
+ switch (getGroupType()) {
+ case SIMPLE:
+ break;
+ default:
+ throw new InvalidRelException("unsupported group type: " + getGroupType());
+ }
+ }
+
+ @Override
+ public PhoenixAggregate copy(RelTraitSet traits, RelNode input, boolean indicator, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggregateCalls) {
+ try {
+ return new PhoenixAggregate(getCluster(), traits, input, indicator, groupSet, groupSets, aggregateCalls);
+ } catch (InvalidRelException e) {
+ // Semantic error not possible. Must be a bug. Convert to
+ // internal error.
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public void implement(Implementor implementor, PhoenixConnection conn) {
+ implementor.visitInput(0, (PhoenixRel) getInput());
+ throw new UnsupportedOperationException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixFilter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixFilter.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixFilter.java
new file mode 100644
index 0000000..dc4bfc1
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixFilter.java
@@ -0,0 +1,40 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptCost;
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Filter;
+import org.apache.calcite.rex.RexNode;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+
+/**
+ * Implementation of {@link org.apache.calcite.rel.core.Filter}
+ * relational expression in Phoenix.
+ */
+public class PhoenixFilter extends Filter implements PhoenixRel {
+ protected PhoenixFilter(RelOptCluster cluster, RelTraitSet traits, RelNode input, RexNode condition) {
+ super(cluster, traits, input, condition);
+ assert getConvention() == PhoenixRel.CONVENTION;
+ assert getConvention() == input.getConvention();
+ }
+
+ public PhoenixFilter copy(RelTraitSet traitSet, RelNode input, RexNode condition) {
+ return new PhoenixFilter(getCluster(), traitSet, input, condition);
+ }
+
+ @Override
+ public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ return super.computeSelfCost(planner).multiplyBy(PHOENIX_FACTOR);
+ }
+
+ public void implement(Implementor implementor, PhoenixConnection conn) {
+ implementor.visitInput(0, (PhoenixRel) getInput());
+ // TODO: what to do with the Expression?
+ // Already determined this filter cannot be pushed down, so
+ // this will be run
+ Expression expr = CalciteUtils.toExpression(condition, implementor);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixFilterScanMergeRule.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixFilterScanMergeRule.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixFilterScanMergeRule.java
new file mode 100644
index 0000000..808fa99
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixFilterScanMergeRule.java
@@ -0,0 +1,36 @@
+package org.apache.phoenix.calcite;
+
+import com.google.common.base.Predicate;
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.rel.core.Filter;
+
+public class PhoenixFilterScanMergeRule extends RelOptRule {
+
+ /** Predicate that returns true if a table scan has no filter. */
+ private static final Predicate<PhoenixTableScan> NO_FILTER =
+ new Predicate<PhoenixTableScan>() {
+ @Override
+ public boolean apply(PhoenixTableScan phoenixTableScan) {
+ return phoenixTableScan.filter == null;
+ }
+ };
+
+ public static final PhoenixFilterScanMergeRule INSTANCE = new PhoenixFilterScanMergeRule();
+
+ private PhoenixFilterScanMergeRule() {
+ super(
+ operand(Filter.class,
+ operand(PhoenixTableScan.class, null, NO_FILTER, any())));
+ }
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+ Filter filter = call.rel(0);
+ PhoenixTableScan scan = call.rel(1);
+ assert scan.filter == null : "predicate should have ensured no filter";
+ call.transformTo(new PhoenixTableScan(scan.getCluster(),
+ scan.getTraitSet(), scan.getTable(),
+ filter.getCondition()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixJoin.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixJoin.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixJoin.java
new file mode 100644
index 0000000..afbe604
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixJoin.java
@@ -0,0 +1,40 @@
+package org.apache.phoenix.calcite;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.apache.calcite.linq4j.Ord;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Join;
+import org.apache.calcite.rel.core.JoinRelType;
+import org.apache.calcite.rel.core.SetOp;
+import org.apache.calcite.rel.core.Union;
+import org.apache.calcite.rex.RexNode;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Implementation of {@link org.apache.calcite.rel.core.Join}
+ * relational expression in Phoenix.
+ */
+public class PhoenixJoin extends Join implements PhoenixRel {
+ public PhoenixJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, JoinRelType joinType, Set<String> variablesStopped) {
+ super( cluster, traits, left, right, condition, joinType, variablesStopped);
+ assert getConvention() == PhoenixRel.CONVENTION;
+ assert left.getConvention() == PhoenixRel.CONVENTION;
+ assert right.getConvention() == PhoenixRel.CONVENTION;
+ }
+
+ @Override
+ public PhoenixJoin copy(RelTraitSet traits, RexNode condition, RelNode left, RelNode right, JoinRelType joinRelType, boolean semiJoinDone) {
+ return new PhoenixJoin(getCluster(), traits, left, right, condition, joinRelType, ImmutableSet.<String>of());
+ }
+
+ @Override
+ public void implement(Implementor implementor, PhoenixConnection conn) {
+ throw new UnsupportedOperationException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixProject.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixProject.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixProject.java
new file mode 100644
index 0000000..2e90397
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixProject.java
@@ -0,0 +1,40 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptCost;
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexNode;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link org.apache.calcite.rel.core.Project}
+ * relational expression in Phoenix.
+ */
+public class PhoenixProject extends Project implements PhoenixRel {
+ public PhoenixProject(RelOptCluster cluster, RelTraitSet traits, RelNode input, List<? extends RexNode> projects, RelDataType rowType) {
+ super(cluster, traits, input, projects, rowType, Flags.BOXED);
+ assert getConvention() == PhoenixRel.CONVENTION;
+ assert getConvention() == input.getConvention();
+ }
+
+ @Override
+ public PhoenixProject copy(RelTraitSet traits, RelNode input, List<RexNode> projects, RelDataType rowType) {
+ return new PhoenixProject(getCluster(), traits, input, projects, rowType);
+ }
+
+ public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ return super.computeSelfCost(planner).multiplyBy(PHOENIX_FACTOR);
+ }
+
+ @Override
+ public void implement(Implementor implementor, PhoenixConnection conn) {
+ implementor.visitInput(0, (PhoenixRel) getInput());
+ throw new UnsupportedOperationException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRel.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRel.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRel.java
new file mode 100644
index 0000000..c255e90
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRel.java
@@ -0,0 +1,39 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.plan.Convention;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rex.RexNode;
+import org.apache.phoenix.compile.QueryPlan;
+import org.apache.phoenix.compile.RowProjector;
+import org.apache.phoenix.expression.ColumnExpression;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.schema.PTable;
+
+/**
+ * Relational expression in Phoenix.
+ *
+ * <p>Phoenix evaluates relational expressions using {@link java.util.Iterator}s
+ * over streams of {@link org.apache.phoenix.schema.tuple.Tuple}s.</p>
+ */
+public interface PhoenixRel extends RelNode {
+ /** Calling convention for relational operations that occur in Phoenix. */
+ Convention CONVENTION = new Convention.Impl("PHOENIX", PhoenixRel.class);
+
+ /** Relative cost of Phoenix versus Enumerable convention.
+ *
+ * <p>Multiply by the value (which is less than unity), and you will get a cheaper cost.
+ * Phoenix is cheaper.
+ */
+ double PHOENIX_FACTOR = 0.5;
+
+ void implement(Implementor implementor, PhoenixConnection conn);
+
+ /** Holds context for an traversal over a tree of relational expressions
+ * to convert it to an executable plan. */
+ interface Implementor {
+ void visitInput(int i, PhoenixRel input);
+ ColumnExpression newColumnExpression(int index);
+ void setContext(PhoenixConnection conn, PTable pTable, RexNode filter);
+ QueryPlan makePlan();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java
new file mode 100644
index 0000000..a7d62e2
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java
@@ -0,0 +1,91 @@
+package org.apache.phoenix.calcite;
+
+import java.sql.SQLException;
+import java.util.Collections;
+
+import org.apache.calcite.rex.RexNode;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.phoenix.compile.ColumnResolver;
+import org.apache.phoenix.compile.FromCompiler;
+import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
+import org.apache.phoenix.compile.ProjectionCompiler;
+import org.apache.phoenix.compile.QueryPlan;
+import org.apache.phoenix.compile.RowProjector;
+import org.apache.phoenix.compile.SequenceManager;
+import org.apache.phoenix.compile.StatementContext;
+import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.compile.WhereCompiler;
+import org.apache.phoenix.compile.WhereOptimizer;
+import org.apache.phoenix.execute.AggregatePlan;
+import org.apache.phoenix.execute.ScanPlan;
+import org.apache.phoenix.expression.ColumnExpression;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.iterate.ParallelIteratorFactory;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.ColumnDef;
+import org.apache.phoenix.parse.FilterableStatement;
+import org.apache.phoenix.parse.NamedTableNode;
+import org.apache.phoenix.parse.SelectStatement;
+import org.apache.phoenix.parse.TableName;
+import org.apache.phoenix.schema.ColumnRef;
+import org.apache.phoenix.schema.PDatum;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.TableRef;
+
+import com.google.common.collect.ImmutableList;
+
+class PhoenixRelImplementorImpl implements PhoenixRel.Implementor {
+ private TableRef tableRef;
+ private PhoenixConnection conn;
+ private StatementContext context;
+ private RowProjector projector;
+ private SelectStatement select;
+
+ @Override
+ public void visitInput(int i, PhoenixRel input) {
+ input.implement(this, conn);
+ }
+
+ @Override
+ public ColumnExpression newColumnExpression(int index) {
+ ColumnRef colRef = new ColumnRef(tableRef, index);
+ return colRef.newColumnExpression();
+ }
+
+
+ @Override
+ public void setContext(PhoenixConnection conn, PTable table, RexNode filter) {
+ this.conn = conn;
+ this.tableRef = new TableRef(table);
+ PhoenixStatement stmt = new PhoenixStatement(conn);
+ ColumnResolver resolver;
+ try {
+ resolver = FromCompiler.getResolver(
+ NamedTableNode.create(
+ null,
+ TableName.create(tableRef.getTable().getSchemaName().getString(), tableRef.getTable().getTableName().getString()),
+ ImmutableList.<ColumnDef>of()), conn);
+ this.context = new StatementContext(stmt, resolver, new Scan(), new SequenceManager(stmt));
+ // TODO: real projection
+ this.select = SelectStatement.SELECT_STAR;
+ this.projector = ProjectionCompiler.compile(context, select, GroupBy.EMPTY_GROUP_BY, Collections.<PDatum>emptyList());
+ if (filter != null) {
+ Expression filterExpr = CalciteUtils.toExpression(filter, this);
+ filterExpr = WhereOptimizer.pushKeyExpressionsToScan(context, select, filterExpr);
+ WhereCompiler.setScanFilter(context, select, filterExpr, true, false);
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public QueryPlan makePlan() {
+ Integer limit = null;
+ OrderBy orderBy = OrderBy.EMPTY_ORDER_BY;
+ ParallelIteratorFactory iteratorFactory = null;
+ return new ScanPlan(context, select, tableRef, projector, limit, orderBy, iteratorFactory, true);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRules.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRules.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRules.java
new file mode 100644
index 0000000..77a8b7b
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRules.java
@@ -0,0 +1,334 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.adapter.enumerable.EnumerableConvention;
+import org.apache.calcite.plan.*;
+import org.apache.calcite.rel.InvalidRelException;
+import org.apache.calcite.rel.RelCollationImpl;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.convert.ConverterRule;
+import org.apache.calcite.rel.core.Sort;
+import org.apache.calcite.rel.core.Union;
+import org.apache.calcite.rel.logical.LogicalAggregate;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.util.trace.CalciteTrace;
+
+import java.util.logging.Logger;
+
+/**
+ * Rules and relational operators for
+ * {@link PhoenixRel#CONVENTION PHOENIX}
+ * calling convention.
+ */
+public class PhoenixRules {
+ private PhoenixRules() {}
+
+ protected static final Logger LOGGER = CalciteTrace.getPlannerTracer();
+
+ public static final RelOptRule[] RULES = {
+ PhoenixToEnumerableConverterRule.INSTANCE,
+ PhoenixSortRule.INSTANCE,
+ PhoenixFilterRule.INSTANCE,
+ PhoenixProjectRule.INSTANCE,
+ PhoenixAggregateRule.INSTANCE,
+ PhoenixUnionRule.INSTANCE,
+ };
+
+ /** Base class for planner rules that convert a relational expression to
+ * Phoenix calling convention. */
+ abstract static class PhoenixConverterRule extends ConverterRule {
+ protected final Convention out;
+ public PhoenixConverterRule(
+ Class<? extends RelNode> clazz,
+ RelTrait in,
+ Convention out,
+ String description) {
+ super(clazz, in, out, description);
+ this.out = out;
+ }
+ }
+
+ /**
+ * Rule to convert a {@link org.apache.calcite.rel.core.Sort} to a
+ * {@link PhoenixSort}.
+ */
+ private static class PhoenixSortRule extends PhoenixConverterRule {
+ public static final PhoenixSortRule INSTANCE = new PhoenixSortRule();
+
+ private PhoenixSortRule() {
+ super(Sort.class, Convention.NONE, PhoenixRel.CONVENTION,
+ "PhoenixSortRule");
+ }
+
+ public RelNode convert(RelNode rel) {
+ final Sort sort = (Sort) rel;
+ final RelTraitSet traitSet =
+ sort.getTraitSet().replace(out)
+ .replace(sort.getCollation());
+ return new PhoenixSort(rel.getCluster(), traitSet,
+ convert(sort.getInput(), traitSet.replace(RelCollationImpl.EMPTY)),
+ sort.getCollation(), sort.offset, sort.fetch);
+ }
+ }
+
+ /**
+ * Rule to convert a {@link org.apache.calcite.rel.logical.LogicalFilter} to a
+ * {@link PhoenixFilter}.
+ */
+ private static class PhoenixFilterRule extends PhoenixConverterRule {
+ private static final PhoenixFilterRule INSTANCE = new PhoenixFilterRule();
+
+ private PhoenixFilterRule() {
+ super(LogicalFilter.class, Convention.NONE, PhoenixRel.CONVENTION,
+ "PhoenixFilterRule");
+ }
+
+ public RelNode convert(RelNode rel) {
+ final LogicalFilter filter = (LogicalFilter) rel;
+ final RelTraitSet traitSet = filter.getTraitSet().replace(out);
+ return new PhoenixFilter(
+ rel.getCluster(),
+ traitSet,
+ convert(filter.getInput(), traitSet),
+ filter.getCondition());
+ }
+ }
+
+ /**
+ * Rule to convert a {@link org.apache.calcite.rel.logical.LogicalProject}
+ * to a {@link PhoenixProject}.
+ */
+ private static class PhoenixProjectRule extends PhoenixConverterRule {
+ private static final PhoenixProjectRule INSTANCE = new PhoenixProjectRule();
+
+ private PhoenixProjectRule() {
+ super(LogicalProject.class, Convention.NONE, PhoenixRel.CONVENTION,
+ "PhoenixProjectRule");
+ }
+
+ public RelNode convert(RelNode rel) {
+ final LogicalProject project = (LogicalProject) rel;
+ final RelTraitSet traitSet = project.getTraitSet().replace(out);
+ return new PhoenixProject(project.getCluster(), traitSet,
+ convert(project.getInput(), traitSet), project.getProjects(),
+ project.getRowType());
+ }
+ }
+
+ /**
+ * Rule to convert a {@link org.apache.calcite.rel.logical.LogicalAggregate}
+ * to an {@link PhoenixAggregate}.
+ */
+ private static class PhoenixAggregateRule extends PhoenixConverterRule {
+ public static final RelOptRule INSTANCE = new PhoenixAggregateRule();
+
+ private PhoenixAggregateRule() {
+ super(LogicalAggregate.class, Convention.NONE, PhoenixRel.CONVENTION,
+ "PhoenixAggregateRule");
+ }
+
+ public RelNode convert(RelNode rel) {
+ final LogicalAggregate agg = (LogicalAggregate) rel;
+ final RelTraitSet traitSet =
+ agg.getTraitSet().replace(out);
+ try {
+ return new PhoenixAggregate(
+ rel.getCluster(),
+ traitSet,
+ convert(agg.getInput(), traitSet),
+ agg.indicator,
+ agg.getGroupSet(),
+ agg.getGroupSets(),
+ agg.getAggCallList());
+ } catch (InvalidRelException e) {
+ LOGGER.warning(e.toString());
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Rule to convert a {@link org.apache.calcite.rel.core.Union} to a
+ * {@link PhoenixUnion}.
+ */
+ private static class PhoenixUnionRule extends PhoenixConverterRule {
+ public static final PhoenixUnionRule INSTANCE = new PhoenixUnionRule();
+
+ private PhoenixUnionRule() {
+ super(Union.class, Convention.NONE, PhoenixRel.CONVENTION,
+ "PhoenixUnionRule");
+ }
+
+ public RelNode convert(RelNode rel) {
+ final Union union = (Union) rel;
+ final RelTraitSet traitSet = union.getTraitSet().replace(out);
+ return new PhoenixUnion(rel.getCluster(), traitSet, convertList(union.getInputs(), out),
+ union.all);
+ }
+ }
+
+ /**
+ * Rule to convert an {@link org.apache.calcite.rel.logical.LogicalIntersect}
+ * to an {@link PhoenixIntersectRel}.
+ o/
+ private static class PhoenixIntersectRule
+ extends PhoenixConverterRule {
+ private PhoenixIntersectRule(PhoenixConvention out) {
+ super(
+ LogicalIntersect.class,
+ Convention.NONE,
+ out,
+ "PhoenixIntersectRule");
+ }
+
+ public RelNode convert(RelNode rel) {
+ final LogicalIntersect intersect = (LogicalIntersect) rel;
+ if (intersect.all) {
+ return null; // INTERSECT ALL not implemented
+ }
+ final RelTraitSet traitSet =
+ intersect.getTraitSet().replace(out);
+ return new PhoenixIntersectRel(
+ rel.getCluster(),
+ traitSet,
+ convertList(intersect.getInputs(), traitSet),
+ intersect.all);
+ }
+ }
+
+ public static class PhoenixIntersectRel
+ extends Intersect
+ implements PhoenixRel {
+ public PhoenixIntersectRel(
+ RelOptCluster cluster,
+ RelTraitSet traitSet,
+ List<RelNode> inputs,
+ boolean all) {
+ super(cluster, traitSet, inputs, all);
+ assert !all;
+ }
+
+ public PhoenixIntersectRel copy(
+ RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
+ return new PhoenixIntersectRel(getCluster(), traitSet, inputs, all);
+ }
+
+ public SqlString implement(PhoenixImplementor implementor) {
+ return setOpSql(this, implementor, " intersect ");
+ }
+ }
+
+ /**
+ * Rule to convert an {@link org.apache.calcite.rel.logical.LogicalMinus}
+ * to an {@link PhoenixMinusRel}.
+ o/
+ private static class PhoenixMinusRule
+ extends PhoenixConverterRule {
+ private PhoenixMinusRule(PhoenixConvention out) {
+ super(
+ LogicalMinus.class,
+ Convention.NONE,
+ out,
+ "PhoenixMinusRule");
+ }
+
+ public RelNode convert(RelNode rel) {
+ final LogicalMinus minus = (LogicalMinus) rel;
+ if (minus.all) {
+ return null; // EXCEPT ALL not implemented
+ }
+ final RelTraitSet traitSet =
+ rel.getTraitSet().replace(out);
+ return new PhoenixMinusRel(
+ rel.getCluster(),
+ traitSet,
+ convertList(minus.getInputs(), traitSet),
+ minus.all);
+ }
+ }
+
+ public static class PhoenixMinusRel
+ extends Minus
+ implements PhoenixRel {
+ public PhoenixMinusRel(
+ RelOptCluster cluster,
+ RelTraitSet traitSet,
+ List<RelNode> inputs,
+ boolean all) {
+ super(cluster, traitSet, inputs, all);
+ assert !all;
+ }
+
+ public PhoenixMinusRel copy(
+ RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
+ return new PhoenixMinusRel(getCluster(), traitSet, inputs, all);
+ }
+
+ public SqlString implement(PhoenixImplementor implementor) {
+ return setOpSql(this, implementor, " minus ");
+ }
+ }
+ */
+
+ /*
+ public static class PhoenixValuesRule extends PhoenixConverterRule {
+ private PhoenixValuesRule() {
+ super(Values.class, Convention.NONE, PhoenixRel.CONVENTION, "PhoenixValuesRule");
+ }
+
+ @Override public RelNode convert(RelNode rel) {
+ Values valuesRel = (Values) rel;
+ return new PhoenixValuesRel(
+ valuesRel.getCluster(),
+ valuesRel.getRowType(),
+ valuesRel.getTuples(),
+ valuesRel.getTraitSet().plus(out));
+ }
+ }
+
+ public static class PhoenixValuesRel
+ extends Values
+ implements PhoenixRel {
+ PhoenixValuesRel(
+ RelOptCluster cluster,
+ RelDataType rowType,
+ List<List<RexLiteral>> tuples,
+ RelTraitSet traitSet) {
+ super(cluster, rowType, tuples, traitSet);
+ }
+
+ @Override public RelNode copy(
+ RelTraitSet traitSet, List<RelNode> inputs) {
+ assert inputs.isEmpty();
+ return new PhoenixValuesRel(
+ getCluster(), rowType, tuples, traitSet);
+ }
+
+ public SqlString implement(PhoenixImplementor implementor) {
+ throw new AssertionError(); // TODO:
+ }
+ }
+*/
+
+ /**
+ * Rule to convert a relational expression from
+ * {@link org.apache.phoenix.calcite.PhoenixRel#CONVENTION} to
+ * {@link org.apache.calcite.adapter.enumerable.EnumerableConvention}.
+ */
+ public static class PhoenixToEnumerableConverterRule extends ConverterRule {
+ public static final ConverterRule INSTANCE =
+ new PhoenixToEnumerableConverterRule();
+
+ private PhoenixToEnumerableConverterRule() {
+ super(RelNode.class, PhoenixRel.CONVENTION, EnumerableConvention.INSTANCE,
+ "PhoenixToEnumerableConverterRule");
+ }
+
+ @Override public RelNode convert(RelNode rel) {
+ RelTraitSet newTraitSet = rel.getTraitSet().replace(getOutConvention());
+ return new PhoenixToEnumerableConverter(rel.getCluster(), newTraitSet, rel);
+ }
+ }
+}
+
+// End PhoenixRules.java
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java
new file mode 100644
index 0000000..d48ffca
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java
@@ -0,0 +1,135 @@
+package org.apache.phoenix.calcite;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.apache.calcite.linq4j.tree.Expression;
+import org.apache.calcite.schema.*;
+import org.apache.phoenix.compile.ColumnResolver;
+import org.apache.phoenix.compile.FromCompiler;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.parse.ColumnDef;
+import org.apache.phoenix.parse.NamedTableNode;
+import org.apache.phoenix.parse.TableName;
+import org.apache.phoenix.schema.MetaDataClient;
+import org.apache.phoenix.schema.TableRef;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.*;
+
+/**
+ * Implementation of Calcite's {@link Schema} SPI for Phoenix.
+ */
+public class PhoenixSchema implements Schema {
+ private final String schemaName = null;
+ private final PhoenixConnection pc;
+ protected final MetaDataClient client;
+
+ PhoenixSchema(PhoenixConnection pc) {
+ this.pc = pc;
+ this.client = new MetaDataClient(pc);
+ }
+
+ private static Schema create(SchemaPlus parentSchema, String name, Map<String, Object> operand) {
+ String url = (String) operand.get("url");
+ final Properties properties = new Properties();
+ for (Map.Entry<String, Object> entry : operand.entrySet()) {
+ properties.setProperty(entry.getKey(), String.valueOf(entry.getValue()));
+ }
+ try {
+ final Connection connection =
+ DriverManager.getConnection(url, properties);
+ final PhoenixConnection phoenixConnection =
+ connection.unwrap(PhoenixConnection.class);
+ return new PhoenixSchema(phoenixConnection);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Table getTable(String name) {
+ try {
+ ColumnResolver x = FromCompiler.getResolver(
+ NamedTableNode.create(
+ null,
+ TableName.create(schemaName, name),
+ ImmutableList.<ColumnDef>of()), pc);
+ final List<TableRef> tables = x.getTables();
+ assert tables.size() == 1;
+ return new PhoenixTable(pc, tables.get(0).getTable());
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Set<String> getTableNames() {
+ return ImmutableSet.of("ATABLE");
+ }
+
+ @Override
+ public Collection<Function> getFunctions(String name) {
+ return ImmutableSet.of();
+ }
+
+ @Override
+ public Set<String> getFunctionNames() {
+ return ImmutableSet.of();
+ }
+
+ @Override
+ public Schema getSubSchema(String name) {
+ return null;
+ }
+
+ @Override
+ public Set<String> getSubSchemaNames() {
+ return ImmutableSet.of();
+ }
+
+ @Override
+ public Expression getExpression(SchemaPlus parentSchema, String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isMutable() {
+ return false;
+ }
+
+ @Override
+ public boolean contentsHaveChangedSince(long lastCheck, long now) {
+ return false;
+ }
+
+ /** Schema factory that creates a
+ * {@link org.apache.phoenix.calcite.PhoenixSchema}.
+ * This allows you to create a Phoenix schema inside a model.json file.
+ *
+ * <pre>{@code
+ * {
+ * version: '1.0',
+ * defaultSchema: 'HR',
+ * schemas: [
+ * {
+ * name: 'HR',
+ * type: 'custom',
+ * factory: 'org.apache.phoenix.calcite.PhoenixSchema.Factory',
+ * operand: {
+ * url: "jdbc:phoenix:localhost",
+ * user: "scott",
+ * password: "tiger"
+ * }
+ * }
+ * ]
+ * }
+ * }</pre>
+ */
+ public static class Factory implements SchemaFactory {
+ public Schema create(SchemaPlus parentSchema, String name, Map<String, Object> operand) {
+ return PhoenixSchema.create(parentSchema, name, operand);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSort.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSort.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSort.java
new file mode 100644
index 0000000..8062c1b
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSort.java
@@ -0,0 +1,32 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Sort;
+import org.apache.calcite.rex.RexNode;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+
+/**
+ * Implementation of {@link org.apache.calcite.rel.core.Sort}
+ * relational expression in Phoenix.
+ *
+ * <p>Like {@code Sort}, it also supports LIMIT and OFFSET.
+ */
+public class PhoenixSort extends Sort implements PhoenixRel {
+ public PhoenixSort(RelOptCluster cluster, RelTraitSet traits, RelNode child, RelCollation collation, RexNode offset, RexNode fetch) {
+ super(cluster, traits, child, collation, offset, fetch);
+ }
+
+ @Override
+ public PhoenixSort copy(RelTraitSet traitSet, RelNode newInput, RelCollation newCollation, RexNode offset, RexNode fetch) {
+ return new PhoenixSort(getCluster(), traitSet, newInput, newCollation, offset, fetch);
+ }
+
+ @Override
+ public void implement(Implementor implementor, PhoenixConnection conn) {
+ implementor.visitInput(0, (PhoenixRel) getInput());
+ throw new UnsupportedOperationException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java
new file mode 100644
index 0000000..9b58d68
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java
@@ -0,0 +1,77 @@
+package org.apache.phoenix.calcite;
+
+import com.google.common.base.Preconditions;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.schema.Statistic;
+import org.apache.calcite.schema.TranslatableTable;
+import org.apache.calcite.schema.impl.AbstractTable;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.PTable;
+
+/**
+ * Implementation of Calcite {@link org.apache.calcite.schema.Table} SPI for
+ * Phoenix.
+ */
+public class PhoenixTable extends AbstractTable implements TranslatableTable {
+ public final PTable pTable;
+ public final PhoenixConnection pc;
+
+ public PhoenixTable(PhoenixConnection pc, PTable pTable) {
+ this.pc = Preconditions.checkNotNull(pc);
+ this.pTable = Preconditions.checkNotNull(pTable);
+ }
+
+ public PTable getTable() {
+ return pTable;
+ }
+
+ @Override
+ public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+ final RelDataTypeFactory.FieldInfoBuilder builder = typeFactory.builder();
+ for (PColumn pColumn : pTable.getColumns()) {
+ final int sqlTypeId = pColumn.getDataType().getResultSetSqlType();
+ final PDataType pDataType = PDataType.fromTypeId(sqlTypeId);
+ final SqlTypeName sqlTypeName1 = SqlTypeName.valueOf(pDataType.getSqlTypeName());
+ final Integer maxLength = pColumn.getMaxLength();
+ final Integer scale = pColumn.getScale();
+ if (maxLength != null && scale != null) {
+ builder.add(pColumn.getName().getString(), sqlTypeName1, maxLength, scale);
+ } else if (maxLength != null) {
+ builder.add(pColumn.getName().getString(), sqlTypeName1, maxLength);
+ } else {
+ builder.add(pColumn.getName().getString(), sqlTypeName1);
+ }
+ }
+ return builder.build();
+ }
+
+ @Override
+ public RelNode toRel(RelOptTable.ToRelContext context, RelOptTable relOptTable) {
+ final RelOptCluster cluster = context.getCluster();
+ return new PhoenixTableScan(cluster, cluster.traitSetOf(PhoenixRel.CONVENTION), relOptTable, null);
+ }
+
+ @Override
+ public Statistic getStatistic() {
+ return new Statistic() {
+ @Override
+ public Double getRowCount() {
+ return 100d;
+ }
+
+ @Override
+ public boolean isKey(ImmutableBitSet immutableBitSet) {
+ return false;
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTableScan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTableScan.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTableScan.java
new file mode 100644
index 0000000..a08ab73
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTableScan.java
@@ -0,0 +1,60 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.plan.*;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rex.RexNode;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
+
+import java.util.List;
+
+/**
+ * Scan of a Phoenix table.
+ */
+public class PhoenixTableScan extends TableScan implements PhoenixRel {
+ public final RexNode filter;
+
+ protected PhoenixTableScan(RelOptCluster cluster, RelTraitSet traits, RelOptTable table, RexNode filter) {
+ super(cluster, traits, table);
+ this.filter = filter;
+ }
+
+ @Override
+ public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ assert inputs.isEmpty();
+ return this;
+ }
+
+ @Override
+ public void register(RelOptPlanner planner) {
+ RelOptRule[] rules = PhoenixRules.RULES;
+ for (RelOptRule rule : rules) {
+ planner.addRule(rule);
+ }
+ planner.addRule(PhoenixFilterScanMergeRule.INSTANCE);
+ }
+
+ @Override
+ public RelWriter explainTerms(RelWriter pw) {
+ return super.explainTerms(pw)
+ .itemIf("filter", filter, filter != null);
+ }
+
+ @Override
+ public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ RelOptCost cost = super.computeSelfCost(planner).multiplyBy(PHOENIX_FACTOR);
+ if (filter != null && !filter.isAlwaysTrue()) {
+ final Double selectivity = RelMetadataQuery.getSelectivity(this, filter);
+ cost = cost.multiplyBy(selectivity);
+ }
+ return cost;
+ }
+
+ @Override
+ public void implement(Implementor implementor, PhoenixConnection conn) {
+ final PhoenixTable phoenixTable = table.unwrap(PhoenixTable.class);
+ implementor.setContext(phoenixTable.pc, phoenixTable.getTable(), filter);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixToEnumerableConverter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixToEnumerableConverter.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixToEnumerableConverter.java
new file mode 100644
index 0000000..fc2af9c
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixToEnumerableConverter.java
@@ -0,0 +1,72 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.DataContext;
+import org.apache.calcite.adapter.enumerable.*;
+import org.apache.calcite.linq4j.tree.*;
+import org.apache.calcite.plan.*;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.convert.ConverterImpl;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.phoenix.compile.QueryPlan;
+
+import java.util.List;
+
+/**
+ * Scan of a Phoenix table.
+ */
+public class PhoenixToEnumerableConverter extends ConverterImpl implements EnumerableRel {
+ protected PhoenixToEnumerableConverter(
+ RelOptCluster cluster,
+ RelTraitSet traits,
+ RelNode input) {
+ super(cluster, ConventionTraitDef.INSTANCE, traits, input);
+ }
+
+ @Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ return new PhoenixToEnumerableConverter(getCluster(), traitSet, sole(inputs));
+ }
+
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ return super.computeSelfCost(planner).multiplyBy(.1);
+ }
+
+ @Override
+ public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
+ // Generates code that instantiates a result iterator, then converts it
+ // to an enumerable.
+ //
+ // ResultIterator iterator = root.get("x");
+ // return CalciteRuntime.toEnumerable(iterator);
+ final BlockBuilder list = new BlockBuilder();
+ QueryPlan plan = makePlan((PhoenixRel)getInput());
+ Expression var = stash(implementor, plan, QueryPlan.class);
+ final RelDataType rowType = getRowType();
+ final PhysType physType =
+ PhysTypeImpl.of(
+ implementor.getTypeFactory(), rowType,
+ pref.prefer(JavaRowFormat.ARRAY));
+ final Expression iterator_ =
+ list.append("iterator", var);
+ final Expression enumerable_ =
+ list.append("enumerable",
+ Expressions.call(BuiltInMethod.TO_ENUMERABLE.method,
+ iterator_));
+ list.add(Expressions.return_(null, enumerable_));
+ return implementor.result(physType, list.toBlock());
+ }
+
+ static QueryPlan makePlan(PhoenixRel rel) {
+ final PhoenixRel.Implementor phoenixImplementor = new PhoenixRelImplementorImpl();
+ phoenixImplementor.visitInput(0, rel);
+ return phoenixImplementor.makePlan();
+ }
+
+ static Expression stash(EnumerableRelImplementor implementor, Object o, Class clazz) {
+ ParameterExpression x = implementor.register(o, clazz);
+ MethodCallExpression e =
+ Expressions.call(implementor.getRootExpression(),
+ org.apache.calcite.util.BuiltInMethod.DATA_CONTEXT_GET.method,
+ Expressions.constant(x.name));
+ return Expressions.convert_(e, clazz);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixUnion.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixUnion.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixUnion.java
new file mode 100644
index 0000000..85493fb
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixUnion.java
@@ -0,0 +1,39 @@
+package org.apache.phoenix.calcite;
+
+import org.apache.calcite.linq4j.Ord;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.SetOp;
+import org.apache.calcite.rel.core.Union;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link org.apache.calcite.rel.core.Union}
+ * relational expression in Phoenix.
+ */
+public class PhoenixUnion extends Union implements PhoenixRel {
+ protected PhoenixUnion(RelOptCluster cluster, RelTraitSet traits, List<RelNode> inputs, boolean all) {
+ super(cluster, traits, inputs, all);
+ assert getConvention() == PhoenixRel.CONVENTION;
+
+ for (RelNode input : inputs) {
+ assert getConvention() == input.getConvention();
+ }
+ }
+
+ @Override
+ public PhoenixUnion copy(RelTraitSet traits, List<RelNode> inputs, boolean all) {
+ return new PhoenixUnion(getCluster(), traits, inputs, all);
+ }
+
+ @Override
+ public void implement(Implementor implementor, PhoenixConnection conn) {
+ for (Ord<RelNode> input : Ord.zip(inputs)) {
+ implementor.visitInput(input.i, (PhoenixRel) input.e);
+ }
+ throw new UnsupportedOperationException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixValues.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixValues.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixValues.java
new file mode 100644
index 0000000..420152b
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixValues.java
@@ -0,0 +1,36 @@
+package org.apache.phoenix.calcite;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.plan.Convention;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Values;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link org.apache.calcite.rel.core.Values}
+ * relational expression in Phoenix.
+ */
+public class PhoenixValues extends Values implements PhoenixRel {
+ public PhoenixValues(RelOptCluster cluster, RelDataType rowType, ImmutableList<ImmutableList<RexLiteral>> tuples, RelTraitSet traits) {
+ super(cluster, rowType, tuples, traits);
+ assert getConvention() == PhoenixRel.CONVENTION;
+ }
+
+ @Override
+ public PhoenixValues copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ assert traitSet.containsIfApplicable(Convention.NONE);
+ assert inputs.isEmpty();
+ return new PhoenixValues(getCluster(), rowType, tuples, traitSet);
+ }
+
+ @Override
+ public void implement(Implementor implementor, PhoenixConnection conn) {
+ throw new UnsupportedOperationException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76a858a4/phoenix-core/src/test/java/org/apache/phoenix/calcite/ToExpressionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/calcite/ToExpressionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/calcite/ToExpressionTest.java
new file mode 100644
index 0000000..91628ff
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/calcite/ToExpressionTest.java
@@ -0,0 +1,77 @@
+package org.apache.phoenix.calcite;
+
+import static org.junit.Assert.*;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexInputRef;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.phoenix.calcite.PhoenixRel.Implementor;
+import org.apache.phoenix.compile.ColumnResolver;
+import org.apache.phoenix.compile.FromCompiler;
+import org.apache.phoenix.compile.GroupByCompiler;
+import org.apache.phoenix.compile.HavingCompiler;
+import org.apache.phoenix.compile.LimitCompiler;
+import org.apache.phoenix.compile.QueryPlan;
+import org.apache.phoenix.compile.StatementContext;
+import org.apache.phoenix.compile.WhereCompiler;
+import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.expression.ColumnExpression;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.ParseNode;
+import org.apache.phoenix.parse.SQLParser;
+import org.apache.phoenix.parse.SelectStatement;
+import org.apache.phoenix.parse.SubqueryParseNode;
+import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.schema.ColumnRef;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTableKey;
+import org.junit.Test;
+
+
+public class ToExpressionTest extends BaseConnectionlessQueryTest {
+
+ private static Expression compileExpression(PhoenixStatement statement, StatementContext context, String selectStmt) throws SQLException {
+ // Re-parse the WHERE clause as we don't store it any where
+ SelectStatement select = new SQLParser(selectStmt).parseQuery();
+ Expression where = WhereCompiler.compile(context, select, null, Collections.<SubqueryParseNode>emptySet());
+ return where;
+ }
+
+ @Test
+ public void toExpressionTest() throws Exception {
+ final String expectedColName = "K2";
+ final Object expectedValue = "foo";
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE t(k1 VARCHAR PRIMARY KEY, k2 VARCHAR, v1 VARCHAR)");
+ final PTable table = conn.unwrap(PhoenixConnection.class).getMetaDataCache().getTable(new PTableKey(null,"T"));
+ PhoenixStatement stmt = conn.createStatement().unwrap(PhoenixStatement.class);
+ String query = "SELECT * FROM T WHERE K2 = 'foo'";
+ QueryPlan plan = stmt.compileQuery(query);
+ Expression where = compileExpression(stmt, plan.getContext(), query);
+
+ JavaTypeFactoryImpl typeFactory = new JavaTypeFactoryImpl();
+ RexBuilder builder = new RexBuilder(typeFactory);
+ RelDataType dataType = typeFactory.createSqlType(SqlTypeName.VARCHAR, 10);
+ RexInputRef ref = builder.makeInputRef(dataType,table.getColumn(expectedColName).getPosition());
+ RexNode lit = builder.makeLiteral(expectedValue, dataType, true);
+ RexNode call = builder.makeCall(SqlStdOperatorTable.EQUALS, ref, lit);
+
+ Implementor implementor = new PhoenixRelImplementorImpl();
+ implementor.setContext(conn.unwrap(PhoenixConnection.class), table, null);
+ Expression e = CalciteUtils.toExpression(call, implementor);
+ assertEquals(where,e);
+ }
+}
[2/2] phoenix git commit: Sync changes from
https://github.com/julianhyde/phoenix/tree/calcite
Posted by ma...@apache.org.
Sync changes from https://github.com/julianhyde/phoenix/tree/calcite
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/b005b124
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/b005b124
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/b005b124
Branch: refs/heads/calcite
Commit: b005b1246841e677be6890583597531f0c8036c9
Parents: 76a858a
Author: maryannxue <ma...@apache.org>
Authored: Tue Dec 2 16:50:32 2014 -0500
Committer: maryannxue <ma...@apache.org>
Committed: Tue Dec 2 16:50:32 2014 -0500
----------------------------------------------------------------------
phoenix-core/pom.xml | 8 ++++++++
.../phoenix/calcite/PhoenixRelImplementorImpl.java | 6 +++++-
.../java/org/apache/phoenix/compile/FromCompiler.java | 3 ++-
.../java/org/apache/phoenix/compile/WhereCompiler.java | 2 +-
.../java/org/apache/phoenix/parse/SelectStatement.java | 7 +++++++
pom.xml | 11 +++++++++++
6 files changed, 34 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b005b124/phoenix-core/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-core/pom.xml b/phoenix-core/pom.xml
index b98e9b2..70d54e7 100644
--- a/phoenix-core/pom.xml
+++ b/phoenix-core/pom.xml
@@ -319,6 +319,14 @@
<artifactId>commons-csv</artifactId>
</dependency>
<dependency>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite-avatica</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite-core</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b005b124/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java
index a7d62e2..a833b6b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixRelImplementorImpl.java
@@ -82,10 +82,14 @@ class PhoenixRelImplementorImpl implements PhoenixRel.Implementor {
@Override
public QueryPlan makePlan() {
+ try {
Integer limit = null;
OrderBy orderBy = OrderBy.EMPTY_ORDER_BY;
ParallelIteratorFactory iteratorFactory = null;
- return new ScanPlan(context, select, tableRef, projector, limit, orderBy, iteratorFactory, true);
+ return new ScanPlan(context, select, tableRef, projector, limit, orderBy, iteratorFactory, true);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b005b124/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
index fb3183a..2c4a578 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import com.google.common.base.Preconditions;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.client.HTableInterface;
import org.apache.phoenix.coprocessor.MetaDataProtocol;
@@ -317,7 +318,7 @@ public class FromCompiler {
private final int tsAddition;
private BaseColumnResolver(PhoenixConnection connection, int tsAddition) {
- this.connection = connection;
+ this.connection = Preconditions.checkNotNull(connection);
this.client = connection == null ? null : new MetaDataClient(connection);
this.tsAddition = tsAddition;
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b005b124/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
index b3a9c2d..694eb6a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java
@@ -232,7 +232,7 @@ public class WhereCompiler {
* @param context the shared context during query compilation
* @param whereClause the final where clause expression.
*/
- private static void setScanFilter(StatementContext context, FilterableStatement statement, Expression whereClause, boolean disambiguateWithFamily, boolean hashJoinOptimization) {
+ public static void setScanFilter(StatementContext context, FilterableStatement statement, Expression whereClause, boolean disambiguateWithFamily, boolean hashJoinOptimization) {
Scan scan = context.getScan();
if (LiteralExpression.isFalse(whereClause)) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b005b124/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
index 961846b..1f032a9 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
@@ -34,6 +34,13 @@ import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo;
* @since 0.1
*/
public class SelectStatement implements FilterableStatement {
+ public static final SelectStatement SELECT_STAR =
+ new SelectStatement(
+ null, null, false,
+ Collections.<AliasedNode>singletonList(new AliasedNode(null, WildcardParseNode.INSTANCE)),
+ null, Collections.<ParseNode>emptyList(),
+ null, Collections.<OrderByNode>emptyList(),
+ null, 0, false, false);
public static final SelectStatement SELECT_ONE =
new SelectStatement(
null, null, false,
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b005b124/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index a8d1f10..f5fbc5f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,6 +103,7 @@
<htrace.version>2.04</htrace.version>
<collections.version>3.2.1</collections.version>
<jodatime.version>2.3</jodatime.version>
+ <calcite.version>1.0.0-incubating-SNAPSHOT</calcite.version>
<!-- Test Dependencies -->
<mockito-all.version>1.8.5</mockito-all.version>
@@ -652,6 +653,16 @@
<artifactId>joda-time</artifactId>
<version>${jodatime.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite-avatica</artifactId>
+ <version>${calcite.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite-core</artifactId>
+ <version>${calcite.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>