You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2015/09/29 22:21:56 UTC
[3/3] incubator-calcite git commit: [CALCITE-893] Theta join in
JdbcAdapter
[CALCITE-893] Theta join in JdbcAdapter
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/c2950eba
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/c2950eba
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/c2950eba
Branch: refs/heads/master
Commit: c2950ebaf83176e56d3cb4bf44ca74078dc45a83
Parents: 0f8b866
Author: Julian Hyde <jh...@apache.org>
Authored: Tue Sep 29 12:53:07 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Tue Sep 29 12:53:07 2015 -0700
----------------------------------------------------------------------
.../calcite/adapter/jdbc/JdbcImplementor.java | 54 ++++++++++++++++----
.../apache/calcite/adapter/jdbc/JdbcRules.java | 10 ++--
.../apache/calcite/test/JdbcAdapterTest.java | 16 ++++++
3 files changed, 67 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c2950eba/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcImplementor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcImplementor.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcImplementor.java
index aa6c041..02f9e07 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcImplementor.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcImplementor.java
@@ -29,7 +29,6 @@ import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexProgram;
-import org.apache.calcite.sql.SqlAggFunction;
import org.apache.calcite.sql.SqlBinaryOperator;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlDataTypeSpec;
@@ -82,7 +81,7 @@ public class JdbcImplementor {
SqlFunctionCategory.STRING);
final SqlDialect dialect;
- private final Set<String> aliasSet = new LinkedHashSet<String>();
+ private final Set<String> aliasSet = new LinkedHashSet<>();
public JdbcImplementor(SqlDialect dialect, JavaTypeFactory typeFactory) {
this.dialect = dialect;
@@ -105,8 +104,7 @@ public class JdbcImplementor {
/** Creates a result based on a join. (Each join could contain one or more
* relational expressions.) */
public Result result(SqlNode join, Result leftResult, Result rightResult) {
- final List<Pair<String, RelDataType>> list =
- new ArrayList<Pair<String, RelDataType>>();
+ final List<Pair<String, RelDataType>> list = new ArrayList<>();
list.addAll(leftResult.aliases);
list.addAll(rightResult.aliases);
return new Result(join, Expressions.list(Clause.FROM), null, list);
@@ -133,7 +131,7 @@ public class JdbcImplementor {
* {@link RelNode}) into a {@link SqlNode} expression (within a SQL parse
* tree). */
public abstract class Context {
- private final int fieldCount;
+ final int fieldCount;
protected Context(int fieldCount) {
this.fieldCount = fieldCount;
@@ -280,7 +278,7 @@ public class JdbcImplementor {
}
private List<SqlNode> toSql(RexProgram program, List<RexNode> operandList) {
- final List<SqlNode> list = new ArrayList<SqlNode>();
+ final List<SqlNode> list = new ArrayList<>();
for (RexNode rex : operandList) {
list.add(toSql(program, rex));
}
@@ -301,7 +299,7 @@ public class JdbcImplementor {
/** Converts a call to an aggregate function to an expression. */
public SqlNode toSql(AggregateCall aggCall) {
- SqlOperator op = (SqlAggFunction) aggCall.getAggregation();
+ SqlOperator op = aggCall.getAggregation();
if (op instanceof SqlSumEmptyIsZeroAggFunction) {
op = SqlStdOperatorTable.SUM;
}
@@ -332,6 +330,10 @@ public class JdbcImplementor {
}
return node;
}
+
+ public JdbcImplementor implementor() {
+ return JdbcImplementor.this;
+ }
}
private static int computeFieldCount(
@@ -343,13 +345,23 @@ public class JdbcImplementor {
return x;
}
+ Context aliasContext(List<Pair<String, RelDataType>> aliases,
+ boolean qualified) {
+ return new AliasContext(aliases, qualified);
+ }
+
+ Context joinContext(Context leftContext, Context rightContext) {
+ return new JoinContext(leftContext, rightContext);
+ }
+
/** Implementation of Context that precedes field references with their
* "table alias" based on the current sub-query's FROM clause. */
public class AliasContext extends Context {
private final boolean qualified;
private final List<Pair<String, RelDataType>> aliases;
- public AliasContext(List<Pair<String, RelDataType>> aliases,
+ /** Creates an AliasContext; use {@link #aliasContext(List, boolean)}. */
+ private AliasContext(List<Pair<String, RelDataType>> aliases,
boolean qualified) {
super(computeFieldCount(aliases));
this.aliases = aliases;
@@ -373,6 +385,28 @@ public class JdbcImplementor {
}
}
+ /** Context for translating ON clause of a JOIN from {@link RexNode} to
+ * {@link SqlNode}. */
+ class JoinContext extends Context {
+ private final JdbcImplementor.Context leftContext;
+ private final JdbcImplementor.Context rightContext;
+
+ /** Creates a JoinContext; use {@link #joinContext(Context, Context)}. */
+ private JoinContext(Context leftContext, Context rightContext) {
+ super(leftContext.fieldCount + rightContext.fieldCount);
+ this.leftContext = leftContext;
+ this.rightContext = rightContext;
+ }
+
+ public SqlNode field(int ordinal) {
+ if (ordinal < leftContext.fieldCount) {
+ return leftContext.field(ordinal);
+ } else {
+ return rightContext.field(ordinal - leftContext.fieldCount);
+ }
+ }
+ }
+
/** Result of implementing a node. */
public class Result {
final SqlNode node;
@@ -439,7 +473,7 @@ public class JdbcImplementor {
}
};
} else {
- newContext = new AliasContext(aliases, aliases.size() > 1);
+ newContext = aliasContext(aliases, aliases.size() > 1);
}
return new Builder(rel, clauseList, select, newContext);
}
@@ -495,7 +529,7 @@ public class JdbcImplementor {
* Context deals with just one arm of a join, yet we wish to generate
* a join condition that qualifies column names to disambiguate them. */
public Context qualifiedContext() {
- return new AliasContext(aliases, true);
+ return aliasContext(aliases, true);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c2950eba/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
index c52d7f3..cd91515 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
@@ -392,7 +392,8 @@ public class JdbcRules {
case LESS_THAN_OR_EQUAL:
operands = ((RexCall) node).getOperands();
op = ((RexCall) node).getOperator();
- if (operands.get(0) instanceof RexInputRef
+ if (operands.size() == 2
+ && operands.get(0) instanceof RexInputRef
&& operands.get(1) instanceof RexInputRef) {
final RexInputRef op0 = (RexInputRef) operands.get(0);
final RexInputRef op1 = (RexInputRef) operands.get(1);
@@ -412,6 +413,9 @@ public class JdbcRules {
rightContext.field(op0.getIndex() - leftFieldCount));
}
}
+ final JdbcImplementor.Context joinContext =
+ leftContext.implementor().joinContext(leftContext, rightContext);
+ return joinContext.toSql(null, node);
}
throw new AssertionError(node);
}
@@ -1155,9 +1159,9 @@ public class JdbcRules {
final List<String> fields = getRowType().getFieldNames();
final List<JdbcImplementor.Clause> clauses = Collections.singletonList(
JdbcImplementor.Clause.SELECT);
+ final List<Pair<String, RelDataType>> pairs = ImmutableList.of();
final JdbcImplementor.Context context =
- implementor.new AliasContext(
- Collections.<Pair<String, RelDataType>>emptyList(), false);
+ implementor.aliasContext(pairs, false);
final List<SqlSelect> selects = new ArrayList<>();
for (List<RexLiteral> tuple : tuples) {
final List<SqlNode> selectList = new ArrayList<>();
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c2950eba/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
index 265990e..1bc8b0a 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
@@ -294,6 +294,22 @@ public class JdbcAdapterTest {
}
/** Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-893">[CALCITE-893]
+ * Theta join in JdbcAdapter</a>. */
+ @Test public void testJoinPlan() {
+ final String sql = "SELECT T1.\"brand_name\"\n"
+ + "FROM \"foodmart\".\"product\" AS T1\n"
+ + " INNER JOIN \"foodmart\".\"product_class\" AS T2\n"
+ + " ON T1.\"product_class_id\" = T2.\"product_class_id\"\n"
+ + "WHERE T2.\"product_department\" = 'Frozen Foods'\n"
+ + " OR T2.\"product_department\" = 'Baking Goods'\n"
+ + " AND T1.\"brand_name\" <> 'King'";
+ CalciteAssert.model(JdbcTest.FOODMART_MODEL)
+ .query(sql).runs()
+ .returnsCount(275);
+ }
+
+ /** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-657">[CALCITE-657]
* NullPointerException when executing JdbcAggregate implement method</a>. */
@Test public void testJdbcAggregate() throws Exception {