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/02 02:09:49 UTC
[13/18] incubator-calcite git commit: [CALCITE-819] Add RelRoot,
a contract for the result of a relational expression
[CALCITE-819] Add RelRoot, a contract for the result of a relational expression
Remove PRESERVE collation
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/5a397063
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/5a397063
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/5a397063
Branch: refs/heads/master
Commit: 5a3970635030ddde27e4237da5d8c5c3419c34b5
Parents: 0c1a135
Author: Julian Hyde <jh...@apache.org>
Authored: Thu Aug 13 01:00:09 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Tue Sep 1 16:17:16 2015 -0700
----------------------------------------------------------------------
.../adapter/enumerable/EnumerableProject.java | 3 +-
.../enumerable/EnumerableProjectRule.java | 15 +-
.../apache/calcite/interpreter/ProjectNode.java | 2 +-
.../org/apache/calcite/jdbc/CalcitePrepare.java | 11 +-
.../org/apache/calcite/materialize/Lattice.java | 2 +-
.../org/apache/calcite/plan/RelOptTable.java | 5 +-
.../org/apache/calcite/plan/RelOptUtil.java | 7 +-
.../calcite/prepare/CalciteMaterializer.java | 2 +-
.../calcite/prepare/CalcitePrepareImpl.java | 102 ++++---
.../calcite/prepare/LixToRelTranslator.java | 3 +-
.../org/apache/calcite/prepare/PlannerImpl.java | 29 +-
.../org/apache/calcite/prepare/Prepare.java | 103 +++----
.../calcite/rel/RelCollationTraitDef.java | 6 +-
.../org/apache/calcite/rel/RelCollations.java | 1 +
.../java/org/apache/calcite/rel/RelInput.java | 6 +
.../java/org/apache/calcite/rel/RelRoot.java | 171 ++++++++++++
.../java/org/apache/calcite/rel/SingleRel.java | 2 +-
.../calcite/rel/externalize/RelJsonReader.java | 40 ++-
.../rel/rules/AggregateStarTableRule.java | 4 +-
.../java/org/apache/calcite/rex/RexUtil.java | 4 -
.../apache/calcite/schema/impl/ViewTable.java | 16 +-
.../sql2rel/RelStructuredTypeFlattener.java | 13 +-
.../calcite/sql2rel/SqlToRelConverter.java | 274 ++++++++++---------
.../java/org/apache/calcite/tools/Planner.java | 5 +
.../java/org/apache/calcite/tools/Programs.java | 13 +-
.../java/org/apache/calcite/tools/RuleSets.java | 3 +-
.../apache/calcite/util/ImmutableIntList.java | 6 +-
.../apache/calcite/test/InterpreterTest.java | 13 +
.../calcite/test/JdbcFrontLinqBackTest.java | 13 +-
.../java/org/apache/calcite/test/JdbcTest.java | 8 +-
.../apache/calcite/test/RelMetadataTest.java | 9 +-
.../apache/calcite/test/RelOptRulesTest.java | 28 +-
.../org/apache/calcite/test/RelOptTestBase.java | 4 +-
.../apache/calcite/test/RexTransformerTest.java | 6 +-
.../calcite/test/SqlToRelConverterTest.java | 2 +-
.../apache/calcite/test/SqlToRelTestBase.java | 19 +-
.../org/apache/calcite/tools/PlannerTest.java | 29 +-
.../calcite/test/SqlToRelConverterTest.xml | 15 +-
core/src/test/resources/sql/sort.oq | 13 +
39 files changed, 617 insertions(+), 390 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProject.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProject.java
index 9ab0fb2..e6852f7 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProject.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProject.java
@@ -63,7 +63,8 @@ public class EnumerableProject extends Project implements EnumerableRel {
Util.discard(flags);
}
- /** Creates a LogicalProject, specifying row type rather than field names. */
+ /** Creates an EnumerableProject, specifying row type rather than field
+ * names. */
public static EnumerableProject create(final RelNode input,
final List<? extends RexNode> projects, RelDataType rowType) {
final RelOptCluster cluster = input.getCluster();
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProjectRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProjectRule.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProjectRule.java
index 459e025..3f998da 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProjectRule.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableProjectRule.java
@@ -18,8 +18,6 @@ package org.apache.calcite.adapter.enumerable;
import org.apache.calcite.plan.Convention;
import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.rel.RelCollationTraitDef;
-import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.convert.ConverterRule;
import org.apache.calcite.rel.logical.LogicalProject;
@@ -36,18 +34,7 @@ class EnumerableProjectRule extends ConverterRule {
public RelNode convert(RelNode rel) {
final LogicalProject project = (LogicalProject) rel;
- if (rel.getTraitSet().getTrait(RelCollationTraitDef.INSTANCE)
- != RelCollations.PRESERVE) {
- return EnumerableProject.create(
- convert(project.getInput(),
- project.getInput().getTraitSet()
- .replace(EnumerableConvention.INSTANCE)),
- project.getProjects(),
- project.getRowType());
- }
- // Special case for PRESERVE, to hand-create collation.
- return new EnumerableProject(rel.getCluster(),
- rel.getTraitSet().replace(EnumerableConvention.INSTANCE),
+ return EnumerableProject.create(
convert(project.getInput(),
project.getInput().getTraitSet()
.replace(EnumerableConvention.INSTANCE)),
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/interpreter/ProjectNode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/interpreter/ProjectNode.java b/core/src/main/java/org/apache/calcite/interpreter/ProjectNode.java
index 576bf6f..4c280b7 100644
--- a/core/src/main/java/org/apache/calcite/interpreter/ProjectNode.java
+++ b/core/src/main/java/org/apache/calcite/interpreter/ProjectNode.java
@@ -20,7 +20,7 @@ import org.apache.calcite.rel.core.Project;
/**
* Interpreter node that implements a
- * {@link org.apache.calcite.rel.logical.LogicalFilter}.
+ * {@link org.apache.calcite.rel.core.Project}.
*/
public class ProjectNode extends AbstractSingleNode<Project> {
private final Scalar scalar;
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
index fe2f898..ae5fba4 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
@@ -32,6 +32,7 @@ import org.apache.calcite.plan.RelOptRule;
import org.apache.calcite.prepare.CalcitePrepareImpl;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rex.RexNode;
@@ -226,12 +227,12 @@ public interface CalcitePrepare {
/** The result of parsing and validating a SQL query and converting it to
* relational algebra. */
class ConvertResult extends ParseResult {
- public final RelNode relNode;
+ public final RelRoot root;
public ConvertResult(CalcitePrepareImpl prepare, SqlValidator validator,
- String sql, SqlNode sqlNode, RelDataType rowType, RelNode relNode) {
+ String sql, SqlNode sqlNode, RelDataType rowType, RelRoot root) {
super(prepare, validator, sql, sqlNode, rowType);
- this.relNode = relNode;
+ this.root = root;
}
}
@@ -245,10 +246,10 @@ public interface CalcitePrepare {
public AnalyzeViewResult(CalcitePrepareImpl prepare,
SqlValidator validator, String sql, SqlNode sqlNode,
- RelDataType rowType, RelNode relNode, Table table,
+ RelDataType rowType, RelRoot root, Table table,
ImmutableList<String> tablePath, RexNode constraint,
ImmutableIntList columnMapping) {
- super(prepare, validator, sql, sqlNode, rowType, relNode);
+ super(prepare, validator, sql, sqlNode, rowType, root);
this.table = table;
this.tablePath = tablePath;
this.constraint = constraint;
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/materialize/Lattice.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/materialize/Lattice.java b/core/src/main/java/org/apache/calcite/materialize/Lattice.java
index c2b07c3..ee7fef6 100644
--- a/core/src/main/java/org/apache/calcite/materialize/Lattice.java
+++ b/core/src/main/java/org/apache/calcite/materialize/Lattice.java
@@ -584,7 +584,7 @@ public class Lattice {
// Walk the join tree.
List<RelNode> relNodes = Lists.newArrayList();
List<int[][]> tempLinks = Lists.newArrayList();
- populate(relNodes, tempLinks, parsed.relNode);
+ populate(relNodes, tempLinks, parsed.root.rel);
// Get aliases.
List<String> aliases = Lists.newArrayList();
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/plan/RelOptTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptTable.java b/core/src/main/java/org/apache/calcite/plan/RelOptTable.java
index 8f34ed4..56d01d7 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptTable.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptTable.java
@@ -20,6 +20,7 @@ import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelDistribution;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
@@ -112,9 +113,7 @@ public interface RelOptTable {
/** Can expand a view into relational expressions. */
interface ViewExpander {
- RelNode expandView(
- RelDataType rowType,
- String queryString,
+ RelRoot expandView(RelDataType rowType, String queryString,
List<String> schemaPath);
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 76af520..7762bf7 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -19,6 +19,7 @@ package org.apache.calcite.plan;
import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.rel.RelHomogeneousShuttle;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.RelShuttle;
import org.apache.calcite.rel.RelVisitor;
import org.apache.calcite.rel.RelWriter;
@@ -385,6 +386,7 @@ public abstract class RelOptUtil {
AggregateCall.create(minFunction,
false,
ImmutableList.of(0),
+ -1,
0,
ret,
null,
@@ -462,6 +464,7 @@ public abstract class RelOptUtil {
AggregateCall.create(minFunction,
false,
ImmutableList.of(projectedKeyCount),
+ -1,
projectedKeyCount,
ret,
null,
@@ -2566,9 +2569,7 @@ public abstract class RelOptUtil {
return cluster;
}
- public RelNode expandView(
- RelDataType rowType,
- String queryString,
+ public RelRoot expandView(RelDataType rowType, String queryString,
List<String> schemaPath) {
throw new UnsupportedOperationException();
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java b/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java
index 901dcb8..36f621e 100644
--- a/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java
+++ b/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java
@@ -81,7 +81,7 @@ class CalciteMaterializer extends CalcitePrepareImpl.CalcitePreparingStmt {
getSqlToRelConverter(getSqlValidator(), catalogReader);
materialization.queryRel =
- sqlToRelConverter2.convertQuery(node, true, true);
+ sqlToRelConverter2.convertQuery(node, true, true).rel;
// Identify and substitute a StarTable in queryRel.
//
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
index 524e34f..3f9293c 100644
--- a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
+++ b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
@@ -18,6 +18,7 @@ package org.apache.calcite.prepare;
import org.apache.calcite.DataContext;
import org.apache.calcite.adapter.enumerable.EnumerableBindable;
+import org.apache.calcite.adapter.enumerable.EnumerableCalc;
import org.apache.calcite.adapter.enumerable.EnumerableConvention;
import org.apache.calcite.adapter.enumerable.EnumerableInterpretable;
import org.apache.calcite.adapter.enumerable.EnumerableInterpreterRule;
@@ -64,7 +65,9 @@ import org.apache.calcite.plan.hep.HepProgramBuilder;
import org.apache.calcite.plan.volcano.VolcanoPlanner;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollationTraitDef;
+import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.core.Filter;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.TableScan;
@@ -94,6 +97,7 @@ import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexInputRef;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexProgram;
import org.apache.calcite.runtime.Bindable;
import org.apache.calcite.runtime.Hook;
import org.apache.calcite.runtime.Typed;
@@ -117,6 +121,7 @@ import org.apache.calcite.sql2rel.SqlToRelConverter;
import org.apache.calcite.sql2rel.StandardConvertletTable;
import org.apache.calcite.tools.Frameworks;
import org.apache.calcite.util.ImmutableIntList;
+import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;
import com.google.common.collect.ImmutableList;
@@ -293,17 +298,18 @@ public class CalcitePrepareImpl implements CalcitePrepare {
if (analyze) {
converter.enableTableAccessConversion(false);
}
- final RelNode relNode = converter.convertQuery(sqlNode1, false, true);
+ final RelRoot root = converter.convertQuery(sqlNode1, false, true);
if (analyze) {
- return analyze_(validator, sql, sqlNode1, relNode, fail);
+ return analyze_(validator, sql, sqlNode1, root, fail);
}
return new ConvertResult(this, validator, sql, sqlNode1,
- validator.getValidatedNodeType(sqlNode1), relNode);
+ validator.getValidatedNodeType(sqlNode1), root);
}
private AnalyzeViewResult analyze_(SqlValidator validator, String sql,
- SqlNode sqlNode, RelNode rel, boolean fail) {
- final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
+ SqlNode sqlNode, RelRoot root, boolean fail) {
+ final RexBuilder rexBuilder = root.rel.getCluster().getRexBuilder();
+ RelNode rel = root.rel;
final RelNode viewRel = rel;
Project project;
if (rel instanceof Project) {
@@ -331,7 +337,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
RESOURCE.modifiableViewMustBeBasedOnSingleTable());
}
return new AnalyzeViewResult(this, validator, sql, sqlNode,
- validator.getValidatedNodeType(sqlNode), rel, null, null, null,
+ validator.getValidatedNodeType(sqlNode), root, null, null, null,
null);
}
final RelOptTable targetRelTable = scan.getTable();
@@ -357,7 +363,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
Util.last(tablePath)));
}
return new AnalyzeViewResult(this, validator, sql, sqlNode,
- validator.getValidatedNodeType(sqlNode), rel, null, null, null,
+ validator.getValidatedNodeType(sqlNode), root, null, null, null,
null);
}
projectMap.put(index, rexBuilder.makeInputRef(viewRel, node.i));
@@ -396,12 +402,12 @@ public class CalcitePrepareImpl implements CalcitePrepare {
Util.last(tablePath)));
}
return new AnalyzeViewResult(this, validator, sql, sqlNode,
- validator.getValidatedNodeType(sqlNode), rel, null, null, null,
+ validator.getValidatedNodeType(sqlNode), root, null, null, null,
null);
}
return new AnalyzeViewResult(this, validator, sql, sqlNode,
- validator.getValidatedNodeType(sqlNode), rel, table,
+ validator.getValidatedNodeType(sqlNode), root, table,
ImmutableList.copyOf(tablePath),
constraint, ImmutableIntList.copyOf(columnMapping));
}
@@ -594,7 +600,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
getColumnMetaDataList(typeFactory, x, x, origins);
final Meta.CursorFactory cursorFactory =
Meta.CursorFactory.deduce(columns, null);
- return new CalciteSignature<T>(
+ return new CalciteSignature<>(
sql,
ImmutableList.<AvaticaParameter>of(),
ImmutableMap.<String, Object>of(),
@@ -688,7 +694,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
preparingStmt.prepareQueryable(queryable, x);
}
- final List<AvaticaParameter> parameters = new ArrayList<AvaticaParameter>();
+ final List<AvaticaParameter> parameters = new ArrayList<>();
final RelDataType parameterRowType = preparedResult.getParameterRowType();
for (RelDataTypeField field : parameterRowType.getFieldList()) {
RelDataType type = field.getType();
@@ -732,7 +738,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
private List<ColumnMetaData> getColumnMetaDataList(
JavaTypeFactory typeFactory, RelDataType x, RelDataType jdbcType,
List<List<String>> originList) {
- final List<ColumnMetaData> columns = new ArrayList<ColumnMetaData>();
+ final List<ColumnMetaData> columns = new ArrayList<>();
for (Ord<RelDataTypeField> pair : Ord.zip(jdbcType.getFieldList())) {
final RelDataTypeField field = pair.e;
final RelDataType type = field.getType();
@@ -931,9 +937,15 @@ public class CalcitePrepareImpl implements CalcitePrepare {
final RelOptCluster cluster = prepare.createCluster(planner, rexBuilder);
- RelNode rootRel =
+ final RelNode rel =
new LixToRelTranslator(cluster, CalcitePreparingStmt.this)
.translate(queryable);
+ final RelDataType rowType = rel.getRowType();
+ final List<Pair<Integer, String>> fields =
+ Pair.zip(ImmutableIntList.identity(rowType.getFieldCount()),
+ rowType.getFieldNames());
+ RelRoot root = new RelRoot(rel, resultType, SqlKind.SELECT, fields,
+ RelCollations.EMPTY);
if (timingTracer != null) {
timingTracer.traceTime("end sql2rel");
@@ -946,23 +958,20 @@ public class CalcitePrepareImpl implements CalcitePrepare {
// Structured type flattening, view expansion, and plugging in
// physical storage.
- rootRel = flattenTypes(rootRel, true);
+ root = root.withRel(flattenTypes(root.rel, true));
// Trim unused fields.
- rootRel = trimUnusedFields(rootRel);
+ root = trimUnusedFields(root);
final List<Materialization> materializations = ImmutableList.of();
final List<CalciteSchema.LatticeEntry> lattices = ImmutableList.of();
- rootRel = optimize(rootRel, materializations, lattices);
+ root = optimize(root, materializations, lattices);
if (timingTracer != null) {
timingTracer.traceTime("end optimization");
}
- return implement(
- resultType,
- rootRel,
- SqlKind.SELECT);
+ return implement(root);
}
@Override protected SqlToRelConverter getSqlToRelConverter(
@@ -991,9 +1000,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
return sqlToRelConverter.decorrelate(query, rootRel);
}
- @Override public RelNode expandView(
- RelDataType rowType,
- String queryString,
+ @Override public RelRoot expandView(RelDataType rowType, String queryString,
List<String> schemaPath) {
expansionDepth++;
@@ -1012,11 +1019,11 @@ public class CalcitePrepareImpl implements CalcitePrepare {
SqlToRelConverter sqlToRelConverter =
getSqlToRelConverter(validator, catalogReader);
- RelNode relNode =
+ RelRoot root =
sqlToRelConverter.convertQuery(sqlNode1, true, false);
--expansionDepth;
- return relNode;
+ return root;
}
private SqlValidatorImpl createSqlValidator(CatalogReader catalogReader) {
@@ -1035,25 +1042,34 @@ public class CalcitePrepareImpl implements CalcitePrepare {
@Override protected PreparedResult createPreparedExplanation(
RelDataType resultType,
RelDataType parameterRowType,
- RelNode rootRel,
+ RelRoot root,
boolean explainAsXml,
SqlExplainLevel detailLevel) {
return new CalcitePreparedExplain(
- resultType, parameterRowType, rootRel, explainAsXml, detailLevel);
+ resultType, parameterRowType, root, explainAsXml, detailLevel);
}
- @Override protected PreparedResult implement(
- RelDataType rowType,
- RelNode rootRel,
- SqlKind sqlKind) {
- RelDataType resultType = rootRel.getRowType();
- boolean isDml = sqlKind.belongsTo(SqlKind.DML);
+ @Override protected PreparedResult implement(RelRoot root) {
+ RelDataType resultType = root.rel.getRowType();
+ boolean isDml = root.kind.belongsTo(SqlKind.DML);
final Bindable bindable;
if (resultConvention == BindableConvention.INSTANCE) {
- bindable = Interpreters.bindable(rootRel);
+ bindable = Interpreters.bindable(root.rel);
} else {
+ EnumerableRel enumerable = (EnumerableRel) root.rel;
+ if (!root.isRefTrivial()) {
+ final List<RexNode> projects = new ArrayList<>();
+ final RexBuilder rexBuilder = enumerable.getCluster().getRexBuilder();
+ for (int field : Pair.left(root.fields)) {
+ projects.add(rexBuilder.makeInputRef(enumerable, field));
+ }
+ RexProgram program = RexProgram.create(enumerable.getRowType(),
+ projects, null, root.validatedRowType, rexBuilder);
+ enumerable = EnumerableCalc.create(enumerable, program);
+ }
+
bindable = EnumerableInterpretable.toBindable(internalParameters,
- context.spark(), (EnumerableRel) rootRel, prefer);
+ context.spark(), enumerable, prefer);
}
if (timingTracer != null) {
@@ -1068,9 +1084,11 @@ public class CalcitePrepareImpl implements CalcitePrepare {
resultType,
parameterRowType,
fieldOrigins,
- ImmutableList.copyOf(collations),
- rootRel,
- mapTableModOp(isDml, sqlKind),
+ root.collation.getFieldCollations().isEmpty()
+ ? ImmutableList.<RelCollation>of()
+ : ImmutableList.of(root.collation),
+ root.rel,
+ mapTableModOp(isDml, root.kind),
isDml) {
public String getCode() {
throw new UnsupportedOperationException();
@@ -1092,10 +1110,10 @@ public class CalcitePrepareImpl implements CalcitePrepare {
public CalcitePreparedExplain(
RelDataType resultType,
RelDataType parameterRowType,
- RelNode rootRel,
+ RelRoot root,
boolean explainAsXml,
SqlExplainLevel detailLevel) {
- super(resultType, parameterRowType, rootRel, explainAsXml, detailLevel);
+ super(resultType, parameterRowType, root, explainAsXml, detailLevel);
}
public Bindable getBindable() {
@@ -1131,7 +1149,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
public List<RexNode> toRexList(BlockStatement statement) {
final List<Expression> simpleList = simpleList(statement);
- final List<RexNode> list = new ArrayList<RexNode>();
+ final List<RexNode> list = new ArrayList<>();
for (Expression expression1 : simpleList) {
list.add(toRex(expression1));
}
@@ -1216,7 +1234,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
}
private List<RexNode> toRex(List<Expression> expressions) {
- ArrayList<RexNode> list = new ArrayList<RexNode>();
+ final List<RexNode> list = new ArrayList<>();
for (Expression expression : expressions) {
list.add(toRex(expression));
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/prepare/LixToRelTranslator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/prepare/LixToRelTranslator.java b/core/src/main/java/org/apache/calcite/prepare/LixToRelTranslator.java
index ed1671c..4f6a94f 100644
--- a/core/src/main/java/org/apache/calcite/prepare/LixToRelTranslator.java
+++ b/core/src/main/java/org/apache/calcite/prepare/LixToRelTranslator.java
@@ -28,6 +28,7 @@ import org.apache.calcite.linq4j.tree.Types;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.logical.LogicalFilter;
import org.apache.calcite.rel.logical.LogicalProject;
import org.apache.calcite.rel.logical.LogicalTableScan;
@@ -63,7 +64,7 @@ class LixToRelTranslator implements RelOptTable.ToRelContext {
return cluster;
}
- public RelNode expandView(RelDataType rowType, String queryString,
+ public RelRoot expandView(RelDataType rowType, String queryString,
List<String> schemaPath) {
return preparingStmt.expandView(rowType, queryString, schemaPath);
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java b/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java
index 1c67178..d58cfd8 100644
--- a/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java
+++ b/core/src/main/java/org/apache/calcite/prepare/PlannerImpl.java
@@ -25,6 +25,7 @@ import org.apache.calcite.plan.RelOptTable.ViewExpander;
import org.apache.calcite.plan.RelTraitDef;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.schema.SchemaPlus;
@@ -75,7 +76,7 @@ public class PlannerImpl implements Planner {
private SqlNode validatedSqlNode;
// set in STATE_5_CONVERT
- private RelNode rel;
+ private RelRoot root;
/** Creates a planner. Not a public API; call
* {@link org.apache.calcite.tools.Frameworks#getPlanner} instead. */
@@ -178,7 +179,11 @@ public class PlannerImpl implements Planner {
return validatedSqlNode;
}
- public RelNode convert(SqlNode sql) throws RelConversionException {
+ public final RelNode convert(SqlNode sql) throws RelConversionException {
+ return rel(sql).rel;
+ }
+
+ public RelRoot rel(SqlNode sql) throws RelConversionException {
ensure(State.STATE_4_VALIDATED);
assert validatedSqlNode != null;
final RexBuilder rexBuilder = createRexBuilder();
@@ -188,17 +193,18 @@ public class PlannerImpl implements Planner {
createCatalogReader(), cluster, convertletTable);
sqlToRelConverter.setTrimUnusedFields(false);
sqlToRelConverter.enableTableAccessConversion(false);
- rel = sqlToRelConverter.convertQuery(validatedSqlNode, false, true);
- rel = sqlToRelConverter.flattenTypes(rel, true);
- rel = RelDecorrelator.decorrelateQuery(rel);
+ root =
+ sqlToRelConverter.convertQuery(validatedSqlNode, false, true);
+ root = root.withRel(sqlToRelConverter.flattenTypes(root.rel, true));
+ root = root.withRel(RelDecorrelator.decorrelateQuery(root.rel));
state = State.STATE_5_CONVERTED;
- return rel;
+ return root;
}
/** Implements {@link org.apache.calcite.plan.RelOptTable.ViewExpander}
* interface for {@link org.apache.calcite.tools.Planner}. */
public class ViewExpanderImpl implements ViewExpander {
- public RelNode expandView(RelDataType rowType, String queryString,
+ public RelRoot expandView(RelDataType rowType, String queryString,
List<String> schemaPath) {
SqlParser parser = SqlParser.create(queryString, parserConfig);
SqlNode sqlNode;
@@ -224,12 +230,11 @@ public class PlannerImpl implements Planner {
sqlToRelConverter.setTrimUnusedFields(false);
sqlToRelConverter.enableTableAccessConversion(false);
- RelNode rel =
- sqlToRelConverter.convertQuery(validatedSqlNode, true, false);
- rel = sqlToRelConverter.flattenTypes(rel, true);
- rel = RelDecorrelator.decorrelateQuery(rel);
+ root = sqlToRelConverter.convertQuery(validatedSqlNode, true, false);
+ root = root.withRel(sqlToRelConverter.flattenTypes(root.rel, true));
+ root = root.withRel(RelDecorrelator.decorrelateQuery(root.rel));
- return rel;
+ return PlannerImpl.this.root;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/prepare/Prepare.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/prepare/Prepare.java b/core/src/main/java/org/apache/calcite/prepare/Prepare.java
index 403ad76..43ae738 100644
--- a/core/src/main/java/org/apache/calcite/prepare/Prepare.java
+++ b/core/src/main/java/org/apache/calcite/prepare/Prepare.java
@@ -30,7 +30,7 @@ import org.apache.calcite.plan.RelOptUtil;
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.rel.RelRoot;
import org.apache.calcite.rel.logical.LogicalTableModify;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexExecutorImpl;
@@ -57,7 +57,6 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.lang.reflect.Type;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
@@ -79,8 +78,6 @@ public abstract class Prepare {
protected final Convention resultConvention;
protected CalciteTimingTracer timingTracer;
protected List<List<String>> fieldOrigins;
- protected final List<RelCollation> collations = new ArrayList<>();
- protected boolean ordered;
protected RelDataType parameterRowType;
// temporary. for testing.
@@ -102,26 +99,26 @@ public abstract class Prepare {
protected abstract PreparedResult createPreparedExplanation(
RelDataType resultType,
RelDataType parameterRowType,
- RelNode rootRel,
+ RelRoot root,
boolean explainAsXml,
SqlExplainLevel detailLevel);
/**
* Optimizes a query plan.
*
- * @param rootRel root of a relational expression
+ * @param root Root of relational expression tree
* @param materializations Tables known to be populated with a given query
* @param lattices Lattices
* @return an equivalent optimized relational expression
*/
- protected RelNode optimize(final RelNode rootRel,
+ protected RelRoot optimize(final RelRoot root,
final List<Materialization> materializations,
final List<CalciteSchema.LatticeEntry> lattices) {
- final RelOptPlanner planner = rootRel.getCluster().getPlanner();
+ final RelOptPlanner planner = root.rel.getCluster().getPlanner();
- planner.setRoot(rootRel);
+ planner.setRoot(root.rel);
- final RelTraitSet desiredTraits = getDesiredRootTraitSet(rootRel);
+ final RelTraitSet desiredTraits = getDesiredRootTraitSet(root);
final Program program = getProgram();
final DataContext dataContext = context.getDataContext();
@@ -144,14 +141,14 @@ public abstract class Prepare {
new RelOptLattice(lattice.getLattice(), starRelOptTable));
}
- final RelNode rootRel4 = program.run(planner, rootRel, desiredTraits);
+ final RelNode rootRel4 = program.run(planner, root.rel, desiredTraits);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(
"Plan after physical tweaks: "
+ RelOptUtil.toString(rootRel4, SqlExplainLevel.ALL_ATTRIBUTES));
}
- return rootRel4;
+ return root.withRel(rootRel4);
}
private Program getProgram() {
@@ -166,22 +163,21 @@ public abstract class Prepare {
return Programs.standard();
}
- protected RelTraitSet getDesiredRootTraitSet(RelNode rootRel) {
+ protected RelTraitSet getDesiredRootTraitSet(RelRoot root) {
// Make sure non-CallingConvention traits, if any, are preserved
- return rootRel.getTraitSet()
- .replace(resultConvention).simplify();
+ return root.rel.getTraitSet()
+ .replace(resultConvention)
+ .replace(root.collation)
+ .simplify();
}
/**
* Implements a physical query plan.
*
- * @param rowType original row type returned by query validator
- * @param rootRel root of the relational expression.
- * @param sqlKind SqlKind of the original statement.
+ * @param root Root of the relational expression tree
* @return an executable plan
*/
- protected abstract PreparedResult implement(
- RelDataType rowType, RelNode rootRel, SqlKind sqlKind);
+ protected abstract PreparedResult implement(RelRoot root);
public PreparedResult prepareSql(
SqlNode sqlQuery,
@@ -223,23 +219,14 @@ public abstract class Prepare {
sqlToRelConverter.setIsExplain(sqlExplain.getDynamicParamCount());
}
- RelNode rootRel =
+ RelRoot root =
sqlToRelConverter.convertQuery(sqlQuery, needsValidation, true);
- Hook.CONVERTED.run(rootRel);
+ Hook.CONVERTED.run(root.rel);
if (timingTracer != null) {
timingTracer.traceTime("end sql2rel");
}
- // A query can have 0 collations and still be ordered (if it is ordered
- // on a non-projected expression). But otherwise,
- // ordered == !collations.isEmpty().
- ordered = !SqlToRelConverter.isUnordered(sqlQuery);
- assert collations.isEmpty();
- if (rootRel instanceof Sort) {
- collations.add(((Sort) rootRel).getCollation());
- }
-
final RelDataType resultType = validator.getValidatedNodeType(sqlQuery);
fieldOrigins = validator.getFieldOrigins(sqlQuery);
assert fieldOrigins.size() == resultType.getFieldCount();
@@ -258,24 +245,24 @@ public abstract class Prepare {
resultType, parameterRowType, null, explainAsXml, detailLevel);
case LOGICAL:
return createPreparedExplanation(
- null, parameterRowType, rootRel, explainAsXml, detailLevel);
+ null, parameterRowType, root, explainAsXml, detailLevel);
default:
}
}
// Structured type flattening, view expansion, and plugging in physical
// storage.
- rootRel = flattenTypes(rootRel, true);
+ root = root.withRel(flattenTypes(root.rel, true));
if (this.context.config().forceDecorrelate()) {
// Subquery decorrelation.
- rootRel = decorrelate(sqlToRelConverter, sqlQuery, rootRel);
+ root = root.withRel(decorrelate(sqlToRelConverter, sqlQuery, root.rel));
}
// Trim unused fields.
- rootRel = trimUnusedFields(rootRel);
+ root = trimUnusedFields(root);
- Hook.TRIMMED.run(rootRel);
+ Hook.TRIMMED.run(root.rel);
// Display physical plan after decorrelation.
if (sqlExplain != null) {
@@ -285,13 +272,13 @@ public abstract class Prepare {
switch (explainDepth) {
case PHYSICAL:
default:
- rootRel = optimize(rootRel, materializations, lattices);
+ root = optimize(root, materializations, lattices);
return createPreparedExplanation(
- null, parameterRowType, rootRel, explainAsXml, detailLevel);
+ null, parameterRowType, root, explainAsXml, detailLevel);
}
}
- rootRel = optimize(rootRel, materializations, lattices);
+ root = optimize(root, materializations, lattices);
if (timingTracer != null) {
timingTracer.traceTime("end optimization");
@@ -300,14 +287,10 @@ public abstract class Prepare {
// For transformation from DML -> DML, use result of rewrite
// (e.g. UPDATE -> MERGE). For anything else (e.g. CALL -> SELECT),
// use original kind.
- SqlKind kind = sqlQuery.getKind();
- if (!kind.belongsTo(SqlKind.DML)) {
- kind = sqlNodeOriginal.getKind();
+ if (!root.kind.belongsTo(SqlKind.DML)) {
+ root = root.withKind(sqlNodeOriginal.getKind());
}
- return implement(
- resultType,
- rootRel,
- kind);
+ return implement(root);
}
protected LogicalTableModify.Operation mapTableModOp(
@@ -350,15 +333,17 @@ public abstract class Prepare {
* expression that projects
* only the columns required by its consumer.
*
- * @param rootRel Relational expression that is at the root of the tree
+ * @param root Root of relational expression tree
* @return Trimmed relational expression
*/
- protected RelNode trimUnusedFields(RelNode rootRel) {
+ protected RelRoot trimUnusedFields(RelRoot root) {
final SqlToRelConverter converter =
getSqlToRelConverter(
getSqlValidator(), catalogReader);
- converter.setTrimUnusedFields(shouldTrim(rootRel));
- return converter.trimUnusedFields(ordered, rootRel);
+ converter.setTrimUnusedFields(shouldTrim(root.rel));
+ final boolean ordered = !root.collation.getFieldCollations().isEmpty();
+ final boolean dml = SqlKind.DML.contains(root.kind);
+ return root.withRel(converter.trimUnusedFields(dml || ordered, root.rel));
}
private boolean shouldTrim(RelNode rootRel) {
@@ -377,9 +362,7 @@ public abstract class Prepare {
* @param schemaPath List of schema names wherein to find referenced tables
* @return Relational expression
*/
- public RelNode expandView(
- RelDataType rowType,
- String queryString,
+ public RelRoot expandView(RelDataType rowType, String queryString,
List<String> schemaPath) {
throw new UnsupportedOperationException();
}
@@ -413,28 +396,28 @@ public abstract class Prepare {
implements PreparedResult {
private final RelDataType rowType;
private final RelDataType parameterRowType;
- private final RelNode rel;
+ private final RelRoot root;
private final boolean asXml;
private final SqlExplainLevel detailLevel;
public PreparedExplain(
RelDataType rowType,
RelDataType parameterRowType,
- RelNode rel,
+ RelRoot root,
boolean asXml,
SqlExplainLevel detailLevel) {
this.rowType = rowType;
this.parameterRowType = parameterRowType;
- this.rel = rel;
+ this.root = root;
this.asXml = asXml;
this.detailLevel = detailLevel;
}
public String getCode() {
- if (rel == null) {
+ if (root == null) {
return RelOptUtil.dumpType(rowType);
} else {
- return RelOptUtil.dumpPlan("", rel, asXml, detailLevel);
+ return RelOptUtil.dumpPlan("", root.rel, asXml, detailLevel);
}
}
@@ -455,10 +438,6 @@ public abstract class Prepare {
Collections.<String>nCopies(4, null));
}
- public RelNode getRel() {
- return rel;
- }
-
public abstract Bindable getBindable();
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/rel/RelCollationTraitDef.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/RelCollationTraitDef.java b/core/src/main/java/org/apache/calcite/rel/RelCollationTraitDef.java
index dee2596..aa3e8bf 100644
--- a/core/src/main/java/org/apache/calcite/rel/RelCollationTraitDef.java
+++ b/core/src/main/java/org/apache/calcite/rel/RelCollationTraitDef.java
@@ -64,10 +64,6 @@ public class RelCollationTraitDef extends RelTraitDef<RelCollation> {
RelNode rel,
RelCollation toCollation,
boolean allowInfiniteCostConverters) {
- if (toCollation == RelCollations.PRESERVE) {
- return null;
- }
-
if (toCollation.getFieldCollations().isEmpty()) {
// An empty sort doesn't make sense.
return null;
@@ -87,7 +83,7 @@ public class RelCollationTraitDef extends RelTraitDef<RelCollation> {
public boolean canConvert(
RelOptPlanner planner, RelCollation fromTrait, RelCollation toTrait) {
- return toTrait != RelCollations.PRESERVE;
+ return true;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/rel/RelCollations.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/RelCollations.java b/core/src/main/java/org/apache/calcite/rel/RelCollations.java
index 36f1327..07a7410 100644
--- a/core/src/main/java/org/apache/calcite/rel/RelCollations.java
+++ b/core/src/main/java/org/apache/calcite/rel/RelCollations.java
@@ -43,6 +43,7 @@ public class RelCollations {
* A collation that cannot be replicated by applying a sort. The only
* implementation choice is to apply operations that preserve order.
*/
+ @Deprecated // to be removed before 2.0
public static final RelCollation PRESERVE =
RelCollationTraitDef.INSTANCE.canonize(
new RelCollationImpl(
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/rel/RelInput.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/RelInput.java b/core/src/main/java/org/apache/calcite/rel/RelInput.java
index a8678cb..6179c04 100644
--- a/core/src/main/java/org/apache/calcite/rel/RelInput.java
+++ b/core/src/main/java/org/apache/calcite/rel/RelInput.java
@@ -78,6 +78,12 @@ public interface RelInput {
List<RexNode> getExpressionList(String tag);
+ List<String> getStringList(String tag);
+
+ List<Integer> getIntegerList(String tag);
+
+ List<List<Integer>> getIntegerListList(String tag);
+
RelDataType getRowType(String tag);
RelDataType getRowType(String expressionsTag, String fieldsTag);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/rel/RelRoot.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/RelRoot.java b/core/src/main/java/org/apache/calcite/rel/RelRoot.java
new file mode 100644
index 0000000..77f3782
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rel/RelRoot.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.rel;
+
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.util.ImmutableIntList;
+import org.apache.calcite.util.Pair;
+import org.apache.calcite.util.mapping.Mappings;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Root of a tree of {@link RelNode}.
+ *
+ * <p>One important reason that RelRoot exists is to deal with queries like
+ *
+ * <blockquote><code>SELECT name
+ * FROM emp
+ * ORDER BY empno DESC</code></blockquote>
+ *
+ * <p>Calcite knows that the result must be sorted, but cannot represent its
+ * sort order as a collation, because {@code empno} is not a field in the
+ * result.
+ *
+ * <p>Instead we represent this as
+ *
+ * <blockquote><code>RelRoot: {
+ * rel: Sort($1 DESC)
+ * Project(name, empno)
+ * TableScan(EMP)
+ * fields: [0]
+ * collation: [1 DESC]
+ * }</code></blockquote>
+ *
+ * <p>Note that the {@code empno} field is present in the result, but the
+ * {@code fields} mask tells the consumer to throw it away.
+ *
+ * <p>Another use case is queries like this:
+ *
+ * <blockquote><code>SELECT name AS n, name AS n2, empno AS n
+ * FROM emp</code></blockquote>
+ *
+ * <p>The there are multiple uses of the {@code name} field. and there are
+ * multiple columns aliased as {@code n}. You can represent this as
+ *
+ * <blockquote><code>RelRoot: {
+ * rel: Project(name, empno)
+ * TableScan(EMP)
+ * fields: [(0, "n"), (0, "n2"), (1, "n")]
+ * collation: []
+ * }</code></blockquote>
+ */
+public class RelRoot {
+ public final RelNode rel;
+ public final RelDataType validatedRowType;
+ public final SqlKind kind;
+ public final ImmutableList<Pair<Integer, String>> fields;
+ public final RelCollation collation;
+
+ /**
+ * Creates a RelRoot.
+ *
+ * @param validatedRowType Original row type returned by query validator
+ * @param kind Type of query (SELECT, UPDATE, ...)
+ */
+
+ public RelRoot(RelNode rel, RelDataType validatedRowType, SqlKind kind,
+ List<Pair<Integer, String>> fields, RelCollation collation) {
+ this.rel = rel;
+ this.validatedRowType = validatedRowType;
+ this.kind = kind;
+ this.fields = ImmutableList.copyOf(fields);
+ this.collation = Preconditions.checkNotNull(collation);
+ }
+
+ /** Creates a simple RelRoot. */
+ public static RelRoot of(RelNode rel, SqlKind kind) {
+ return of(rel, rel.getRowType(), kind);
+ }
+
+ /** Creates a simple RelRoot. */
+ public static RelRoot of(RelNode rel, RelDataType rowType, SqlKind kind) {
+ final ImmutableIntList refs =
+ ImmutableIntList.identity(rowType.getFieldCount());
+ final List<String> names = rowType.getFieldNames();
+ return new RelRoot(rel, rowType, kind, Pair.zip(refs, names),
+ RelCollations.EMPTY);
+ }
+
+ /** Creates a copy of this RelRoot, assigning a {@link RelNode}. */
+ public RelRoot withRel(RelNode rel) {
+ if (rel == this.rel) {
+ return this;
+ }
+ return new RelRoot(rel, validatedRowType, kind, fields, collation);
+ }
+
+ /** Creates a copy, assigning a new kind. */
+ public RelRoot withKind(SqlKind kind) {
+ if (kind == this.kind) {
+ return this;
+ }
+ return new RelRoot(rel, validatedRowType, kind, fields, collation);
+ }
+
+ public RelRoot withCollation(RelCollation collation) {
+ return new RelRoot(rel, validatedRowType, kind, fields, collation);
+ }
+
+ /** Returns the root relational expression, creating a {@link LogicalProject}
+ * if necessary to remove fields that are not needed. */
+ public RelNode project() {
+ if (isRefTrivial()) {
+ return rel;
+ }
+ final List<RexNode> projects = new ArrayList<>();
+ final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
+ for (Pair<Integer, String> field : fields) {
+ projects.add(rexBuilder.makeInputRef(rel, field.left));
+ }
+ return LogicalProject.create(rel, projects, Pair.right(fields));
+ }
+
+ public boolean isNameTrivial() {
+ final RelDataType inputRowType = rel.getRowType();
+ return Pair.right(fields).equals(inputRowType.getFieldNames());
+ }
+
+ public boolean isRefTrivial() {
+ if (SqlKind.DML.contains(kind)) {
+ // DML statements return a single count column.
+ // The validated type is of the SELECT.
+ // Still, we regard the mapping as trivial.
+ return true;
+ }
+ final RelDataType inputRowType = rel.getRowType();
+ return Mappings.isIdentity(Pair.left(fields), inputRowType.getFieldCount());
+ }
+
+ public boolean isCollationTrivial() {
+ final List<RelCollation> collations = rel.getTraitSet()
+ .getTraits(RelCollationTraitDef.INSTANCE);
+ return collations != null
+ && collations.size() == 1
+ && collations.get(0).equals(collation);
+ }
+}
+
+// End RelRoot.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/rel/SingleRel.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/SingleRel.java b/core/src/main/java/org/apache/calcite/rel/SingleRel.java
index 27e0bf6..5fbb2c6 100644
--- a/core/src/main/java/org/apache/calcite/rel/SingleRel.java
+++ b/core/src/main/java/org/apache/calcite/rel/SingleRel.java
@@ -35,7 +35,7 @@ import java.util.List;
public abstract class SingleRel extends AbstractRelNode {
//~ Instance fields --------------------------------------------------------
- private RelNode input;
+ protected RelNode input;
//~ Constructors -----------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java b/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java
index b3f9a56..57a7f76 100644
--- a/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java
+++ b/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonReader.java
@@ -60,24 +60,24 @@ public class RelJsonReader {
private final RelOptCluster cluster;
private final RelOptSchema relOptSchema;
- private final Schema schema;
private final RelJson relJson = new RelJson(null);
- private final Map<String, RelNode> relMap =
- new LinkedHashMap<String, RelNode>();
+ private final Map<String, RelNode> relMap = new LinkedHashMap<>();
private RelNode lastRel;
public RelJsonReader(RelOptCluster cluster, RelOptSchema relOptSchema,
Schema schema) {
this.cluster = cluster;
this.relOptSchema = relOptSchema;
- this.schema = schema;
+ Util.discard(schema);
}
public RelNode read(String s) throws IOException {
lastRel = null;
final ObjectMapper mapper = new ObjectMapper();
Map<String, Object> o = mapper.readValue(s, TYPE_REF);
- readRels((List<Map<String, Object>>) o.get("rels"));
+ @SuppressWarnings("unchecked")
+ final List<Map<String, Object>> rels = (List) o.get("rels");
+ readRels(rels);
System.out.println(lastRel);
return lastRel;
}
@@ -102,7 +102,7 @@ public class RelJsonReader {
}
public RelOptTable getTable(String table) {
- final List<String> list = (List<String>) jsonRel.get(table);
+ final List<String> list = getStringList(table);
return relOptSchema.getTableForMember(list);
}
@@ -113,11 +113,11 @@ public class RelJsonReader {
}
public List<RelNode> getInputs() {
- List<String> jsonInputs = (List<String>) jsonRel.get("inputs");
+ final List<String> jsonInputs = getStringList("inputs");
if (jsonInputs == null) {
return ImmutableList.of(lastRel);
}
- final List<RelNode> inputs = new ArrayList<RelNode>();
+ final List<RelNode> inputs = new ArrayList<>();
for (String jsonInput : jsonInputs) {
inputs.add(lookupInput(jsonInput));
}
@@ -145,17 +145,25 @@ public class RelJsonReader {
return builder.build();
}
+ public List<String> getStringList(String tag) {
+ //noinspection unchecked
+ return (List<String>) jsonRel.get(tag);
+ }
+
public List<Integer> getIntegerList(String tag) {
+ //noinspection unchecked
return (List<Integer>) jsonRel.get(tag);
}
public List<List<Integer>> getIntegerListList(String tag) {
+ //noinspection unchecked
return (List<List<Integer>>) jsonRel.get(tag);
}
public List<AggregateCall> getAggregateCalls(String tag) {
- List<Map<String, Object>> jsonAggs = (List) jsonRel.get(tag);
- final List<AggregateCall> inputs = new ArrayList<AggregateCall>();
+ @SuppressWarnings("unchecked")
+ final List<Map<String, Object>> jsonAggs = (List) jsonRel.get(tag);
+ final List<AggregateCall> inputs = new ArrayList<>();
for (Map<String, Object> jsonAggCall : jsonAggs) {
inputs.add(toAggCall(jsonAggCall));
}
@@ -184,8 +192,9 @@ public class RelJsonReader {
}
public List<RexNode> getExpressionList(String tag) {
+ @SuppressWarnings("unchecked")
final List<Object> jsonNodes = (List) jsonRel.get(tag);
- final List<RexNode> nodes = new ArrayList<RexNode>();
+ final List<RexNode> nodes = new ArrayList<>();
for (Object jsonNode : jsonNodes) {
nodes.add(relJson.toRex(this, jsonNode));
}
@@ -215,6 +224,7 @@ public class RelJsonReader {
}
public RelCollation getCollation() {
+ //noinspection unchecked
return relJson.toCollation((List) get("collation"));
}
@@ -223,7 +233,8 @@ public class RelJsonReader {
}
public ImmutableList<ImmutableList<RexLiteral>> getTuples(String tag) {
- List<List> jsonTuples = (List) get(tag);
+ //noinspection unchecked
+ final List<List> jsonTuples = (List) get(tag);
final ImmutableList.Builder<ImmutableList<RexLiteral>> builder =
ImmutableList.builder();
for (List jsonTuple : jsonTuples) {
@@ -245,9 +256,7 @@ public class RelJsonReader {
final RelNode rel = (RelNode) constructor.newInstance(input);
relMap.put(id, rel);
lastRel = rel;
- } catch (InstantiationException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
+ } catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
final Throwable e2 = e.getCause();
@@ -263,6 +272,7 @@ public class RelJsonReader {
final SqlAggFunction aggregation =
relJson.toAggregation(aggName, jsonAggCall);
final Boolean distinct = (Boolean) jsonAggCall.get("distinct");
+ @SuppressWarnings("unchecked")
final List<Integer> operands = (List<Integer>) jsonAggCall.get("operands");
final Integer filterOperand = (Integer) jsonAggCall.get("filter");
final RelDataType type =
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
index de7f67f..e9c7c9c 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
@@ -200,7 +200,7 @@ public class AggregateStarTableRule extends RelOptRule {
if (roll == null) {
break tryRoll;
}
- return AggregateCall.create(roll, false, ImmutableList.of(offset + i),
+ return AggregateCall.create(roll, false, ImmutableList.of(offset + i), -1,
groupCount, input, null, aggregateCall.name);
}
@@ -215,7 +215,7 @@ public class AggregateStarTableRule extends RelOptRule {
}
newArgs.add(z);
}
- return AggregateCall.create(aggregation, false, newArgs,
+ return AggregateCall.create(aggregation, false, newArgs, -1,
groupCount, input, null, aggregateCall.name);
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/rex/RexUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
index 1cac0f8..f7e6a9e 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -754,10 +754,6 @@ public class RexUtil {
List<RelCollation> collationList) {
final List<RelCollation> newCollationList = new ArrayList<>();
for (RelCollation collation : collationList) {
- if (collation == RelCollations.PRESERVE) {
- newCollationList.add(collation);
- continue;
- }
final List<RelFieldCollation> newFieldCollationList = new ArrayList<>();
for (RelFieldCollation fieldCollation
: collation.getFieldCollations()) {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/schema/impl/ViewTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/schema/impl/ViewTable.java b/core/src/main/java/org/apache/calcite/schema/impl/ViewTable.java
index b3a8ff7..1da29ef 100644
--- a/core/src/main/java/org/apache/calcite/schema/impl/ViewTable.java
+++ b/core/src/main/java/org/apache/calcite/schema/impl/ViewTable.java
@@ -25,6 +25,7 @@ import org.apache.calcite.linq4j.Queryable;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeImpl;
@@ -116,19 +117,16 @@ public class ViewTable
public RelNode toRel(
RelOptTable.ToRelContext context,
RelOptTable relOptTable) {
- return expandView(context, relOptTable.getRowType(), viewSql);
+ return expandView(context, relOptTable.getRowType(), viewSql).rel;
}
- private RelNode expandView(
- RelOptTable.ToRelContext preparingStmt,
- RelDataType rowType,
- String queryString) {
+ private RelRoot expandView(RelOptTable.ToRelContext preparingStmt,
+ RelDataType rowType, String queryString) {
try {
- RelNode rel = preparingStmt.expandView(rowType, queryString, schemaPath);
+ RelRoot root = preparingStmt.expandView(rowType, queryString, schemaPath);
- rel = RelOptUtil.createCastRel(rel, rowType, true);
- //rel = viewExpander.flattenTypes(rel, false);
- return rel;
+ root = root.withRel(RelOptUtil.createCastRel(root.rel, rowType, true));
+ return root;
} catch (Throwable e) {
throw Util.newInternal(
e, "Error while parsing view definition: " + queryString);
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java b/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java
index f4765b4..4d8f0a5 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java
@@ -343,9 +343,13 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor {
public void rewriteRel(LogicalTableModify rel) {
LogicalTableModify newRel =
- LogicalTableModify.create(rel.getTable(), rel.getCatalogReader(),
- getNewForOldRel(rel.getInput()), rel.getOperation(),
- rel.getUpdateColumnList(), true);
+ LogicalTableModify.create(
+ rel.getTable(),
+ rel.getCatalogReader(),
+ getNewForOldRel(rel.getInput()),
+ rel.getOperation(),
+ rel.getUpdateColumnList(),
+ true);
setNewForOldRel(rel, newRel);
}
@@ -394,8 +398,7 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor {
public void rewriteRel(LogicalJoin rel) {
LogicalJoin newRel =
- LogicalJoin.create(
- getNewForOldRel(rel.getLeft()),
+ LogicalJoin.create(getNewForOldRel(rel.getLeft()),
getNewForOldRel(rel.getRight()),
rel.getCondition().accept(new RewriteRexShuttle()),
rel.getJoinType(),
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index ae73586..50f22c1 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -31,6 +31,7 @@ import org.apache.calcite.rel.RelCollationTraitDef;
import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.RelShuttle;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
@@ -42,6 +43,7 @@ import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.RelFactories;
import org.apache.calcite.rel.core.Sample;
+import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.core.Uncollect;
import org.apache.calcite.rel.logical.LogicalAggregate;
import org.apache.calcite.rel.logical.LogicalCorrelate;
@@ -56,6 +58,7 @@ import org.apache.calcite.rel.logical.LogicalTableScan;
import org.apache.calcite.rel.logical.LogicalUnion;
import org.apache.calcite.rel.logical.LogicalValues;
import org.apache.calcite.rel.metadata.RelColumnMapping;
+import org.apache.calcite.rel.stream.Delta;
import org.apache.calcite.rel.stream.LogicalDelta;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
@@ -102,6 +105,7 @@ import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlNumericLiteral;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlOperatorTable;
+import org.apache.calcite.sql.SqlOrderBy;
import org.apache.calcite.sql.SqlSampleSpec;
import org.apache.calcite.sql.SqlSelect;
import org.apache.calcite.sql.SqlSelectKeyword;
@@ -425,26 +429,36 @@ public class SqlToRelConverter {
}
private void checkConvertedType(SqlNode query, RelNode result) {
- if (!query.isA(SqlKind.DML)) {
- // Verify that conversion from SQL to relational algebra did
- // not perturb any type information. (We can't do this if the
- // SQL statement is something like an INSERT which has no
- // validator type information associated with its result,
- // hence the namespace check above.)
- RelDataType convertedRowType = result.getRowType();
- if (!checkConvertedRowType(query, convertedRowType)) {
- RelDataType validatedRowType =
- validator.getValidatedNodeType(query);
- validatedRowType = uniquifyFields(validatedRowType);
- throw Util.newInternal("Conversion to relational algebra failed to "
- + "preserve datatypes:\n"
- + "validated type:\n"
- + validatedRowType.getFullTypeString()
- + "\nconverted type:\n"
- + convertedRowType.getFullTypeString()
- + "\nrel:\n"
- + RelOptUtil.toString(result));
- }
+ if (query.isA(SqlKind.DML)) {
+ return;
+ }
+ // Verify that conversion from SQL to relational algebra did
+ // not perturb any type information. (We can't do this if the
+ // SQL statement is something like an INSERT which has no
+ // validator type information associated with its result,
+ // hence the namespace check above.)
+ final List<RelDataTypeField> validatedFields =
+ validator.getValidatedNodeType(query).getFieldList();
+ final RelDataType validatedRowType =
+ validator.getTypeFactory().createStructType(
+ Pair.right(validatedFields),
+ SqlValidatorUtil.uniquify(Pair.left(validatedFields)));
+
+ final List<RelDataTypeField> convertedFields =
+ result.getRowType().getFieldList().subList(0, validatedFields.size());
+ final RelDataType convertedRowType =
+ validator.getTypeFactory().createStructType(convertedFields);
+
+ if (!RelOptUtil.equal("validated row type", validatedRowType,
+ "converted row type", convertedRowType, false)) {
+ throw Util.newInternal("Conversion to relational algebra failed to "
+ + "preserve datatypes:\n"
+ + "validated type:\n"
+ + validatedRowType.getFullTypeString()
+ + "\nconverted type:\n"
+ + convertedRowType.getFullTypeString()
+ + "\nrel:\n"
+ + RelOptUtil.toString(result));
}
}
@@ -501,7 +515,10 @@ public class SqlToRelConverter {
final List<RelCollation> collations =
rootRel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE);
rootRel = trimmer.trim(rootRel);
- if (!ordered && collations != null) {
+ if (!ordered
+ && collations != null
+ && !collations.isEmpty()
+ && !collations.equals(ImmutableList.of(RelCollations.EMPTY))) {
final RelTraitSet traitSet = rootRel.getTraitSet()
.replace(RelCollationTraitDef.INSTANCE, collations);
rootRel = rootRel.copy(traitSet, rootRel.getInputs());
@@ -539,7 +556,7 @@ public class SqlToRelConverter {
* will become a JDBC result set; <code>false</code> if
* the query will be part of a view.
*/
- public RelNode convertQuery(
+ public RelRoot convertQuery(
SqlNode query,
final boolean needsValidation,
final boolean top) {
@@ -547,13 +564,17 @@ public class SqlToRelConverter {
query = validator.validate(query);
}
- RelNode result = convertQueryRecursive(query, top, null);
- if (top && isStream(query)) {
- result = new LogicalDelta(cluster, result.getTraitSet(), result);
+ RelNode result = convertQueryRecursive(query, top, null).rel;
+ if (top) {
+ if (isStream(query)) {
+ result = new LogicalDelta(cluster, result.getTraitSet(), result);
+ }
}
- if (isUnordered(query)) {
- result = result.copy(result.getTraitSet().replace(RelCollations.EMPTY),
- result.getInputs());
+ RelCollation collation = RelCollations.EMPTY;
+ if (!query.isA(SqlKind.DML)) {
+ if (isOrdered(query)) {
+ collation = requiredCollation(result);
+ }
}
checkConvertedType(query, result);
@@ -567,7 +588,9 @@ public class SqlToRelConverter {
SqlExplainLevel.EXPPLAN_ATTRIBUTES));
}
- return result;
+ final RelDataType validatedRowType = validator.getValidatedNodeType(query);
+ return RelRoot.of(result, validatedRowType, query.getKind())
+ .withCollation(collation);
}
private static boolean isStream(SqlNode query) {
@@ -575,33 +598,39 @@ public class SqlToRelConverter {
&& ((SqlSelect) query).isKeywordPresent(SqlSelectKeyword.STREAM);
}
- public static boolean isUnordered(SqlNode query) {
- return query instanceof SqlSelect
- && ((SqlSelect) query).getOrderList() == null;
- }
-
- protected boolean checkConvertedRowType(
- SqlNode query,
- RelDataType convertedRowType) {
- RelDataType validatedRowType = validator.getValidatedNodeType(query);
- validatedRowType = uniquifyFields(validatedRowType);
-
- return RelOptUtil.equal("validated row type", validatedRowType,
- "converted row type", convertedRowType, false);
+ public static boolean isOrdered(SqlNode query) {
+ switch (query.getKind()) {
+ case SELECT:
+ return ((SqlSelect) query).getOrderList() != null
+ && ((SqlSelect) query).getOrderList().size() > 0;
+ case WITH:
+ return isOrdered(((SqlWith) query).body);
+ case ORDER_BY:
+ return ((SqlOrderBy) query).orderList.size() > 0;
+ default:
+ return false;
+ }
}
- protected RelDataType uniquifyFields(RelDataType rowType) {
- return validator.getTypeFactory().createStructType(
- RelOptUtil.getFieldTypeList(rowType),
- SqlValidatorUtil.uniquify(rowType.getFieldNames()));
+ private RelCollation requiredCollation(RelNode r) {
+ if (r instanceof Sort) {
+ return ((Sort) r).collation;
+ }
+ if (r instanceof Project) {
+ return requiredCollation(((Project) r).getInput());
+ }
+ if (r instanceof Delta) {
+ return requiredCollation(((Delta) r).getInput());
+ }
+ throw new AssertionError();
}
/**
* Converts a SELECT statement's parse tree into a relational expression.
*/
- public RelNode convertSelect(SqlSelect select) {
+ public RelNode convertSelect(SqlSelect select, boolean top) {
final SqlValidatorScope selectScope = validator.getWhereScope(select);
- final Blackboard bb = createBlackboard(selectScope, null);
+ final Blackboard bb = createBlackboard(selectScope, null, top);
convertSelectImpl(bb, select);
return bb.root;
}
@@ -609,15 +638,14 @@ public class SqlToRelConverter {
/**
* Factory method for creating translation workspace.
*/
- protected Blackboard createBlackboard(
- SqlValidatorScope scope,
- Map<String, RexNode> nameToNodeMap) {
- return new Blackboard(scope, nameToNodeMap);
+ protected Blackboard createBlackboard(SqlValidatorScope scope,
+ Map<String, RexNode> nameToNodeMap, boolean top) {
+ return new Blackboard(scope, nameToNodeMap, top);
}
/**
- * Implementation of {@link #convertSelect(SqlSelect)}; derived class may
- * override.
+ * Implementation of {@link #convertSelect(SqlSelect, boolean)};
+ * derived class may override.
*/
protected void convertSelectImpl(
final Blackboard bb,
@@ -796,8 +824,11 @@ public class SqlToRelConverter {
false);
// If extra expressions were added to the project list for sorting,
- // add another project to remove them.
- if (orderExprList.size() > 0) {
+ // add another project to remove them. But make the collation empty, because
+ // we can't represent the real collation.
+ //
+ // If it is the top node, use the real collation, but don't trim fields.
+ if (orderExprList.size() > 0 && !bb.top) {
final List<RexNode> exprs = new ArrayList<>();
final RelDataType rowType = bb.root.getRowType();
final int fieldCount =
@@ -806,13 +837,8 @@ public class SqlToRelConverter {
exprs.add(rexBuilder.makeInputRef(bb.root, i));
}
bb.setRoot(
- new LogicalProject(
- cluster,
- cluster.traitSetOf(RelCollations.PRESERVE),
- bb.root,
- exprs,
- cluster.getTypeFactory().createStructType(
- rowType.getFieldList().subList(0, fieldCount))),
+ LogicalProject.create(bb.root, exprs,
+ rowType.getFieldNames().subList(0, fieldCount)),
false);
}
}
@@ -1437,7 +1463,7 @@ public class SqlToRelConverter {
(seek instanceof SqlSelect)
? validator.getSelectScope((SqlSelect) seek)
: null;
- final Blackboard seekBb = createBlackboard(seekScope, null);
+ final Blackboard seekBb = createBlackboard(seekScope, null, false);
RelNode seekRel = convertQueryOrInList(seekBb, seek, targetDataType);
return RelOptUtil.createExistsPlan(seekRel, subqueryType, logic,
@@ -1462,7 +1488,7 @@ public class SqlToRelConverter {
false,
targetRowType);
} else {
- return convertQueryRecursive(seek, false, null);
+ return convertQueryRecursive(seek, false, null).project();
}
}
@@ -1721,10 +1747,9 @@ public class SqlToRelConverter {
public RexNode convertExpression(
SqlNode node) {
Map<String, RelDataType> nameToTypeMap = Collections.emptyMap();
- Blackboard bb =
- createBlackboard(
- new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap),
- null);
+ final ParameterScope scope =
+ new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap);
+ final Blackboard bb = createBlackboard(scope, null, false);
return bb.convertExpression(node);
}
@@ -1746,10 +1771,9 @@ public class SqlToRelConverter {
for (Map.Entry<String, RexNode> entry : nameToNodeMap.entrySet()) {
nameToTypeMap.put(entry.getKey(), entry.getValue().getType());
}
- Blackboard bb =
- createBlackboard(
- new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap),
- nameToNodeMap);
+ final ParameterScope scope =
+ new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap);
+ final Blackboard bb = createBlackboard(scope, nameToNodeMap, false);
return bb.convertExpression(node);
}
@@ -1925,20 +1949,22 @@ public class SqlToRelConverter {
case JOIN:
final SqlJoin join = (SqlJoin) from;
- final Blackboard fromBlackboard =
- createBlackboard(validator.getJoinScope(from), null);
+ final SqlValidatorScope scope = validator.getJoinScope(from);
+ final Blackboard fromBlackboard = createBlackboard(scope, null, false);
SqlNode left = join.getLeft();
SqlNode right = join.getRight();
final boolean isNatural = join.isNatural();
final JoinType joinType = join.getJoinType();
+ final SqlValidatorScope leftScope =
+ Util.first(validator.getJoinScope(left),
+ ((DelegatingScope) bb.scope).getParent());
final Blackboard leftBlackboard =
- createBlackboard(
- Util.first(validator.getJoinScope(left),
- ((DelegatingScope) bb.scope).getParent()), null);
+ createBlackboard(leftScope, null, false);
+ final SqlValidatorScope rightScope =
+ Util.first(validator.getJoinScope(right),
+ ((DelegatingScope) bb.scope).getParent());
final Blackboard rightBlackboard =
- createBlackboard(
- Util.first(validator.getJoinScope(right),
- ((DelegatingScope) bb.scope).getParent()), null);
+ createBlackboard(rightScope, null, false);
convertFrom(leftBlackboard, left);
RelNode leftRel = leftBlackboard.root;
convertFrom(rightBlackboard, right);
@@ -1981,7 +2007,7 @@ public class SqlToRelConverter {
case INTERSECT:
case EXCEPT:
case UNION:
- final RelNode rel = convertQueryRecursive(from, false, null);
+ final RelNode rel = convertQueryRecursive(from, false, null).project();
bb.setRoot(rel, true);
return;
@@ -2029,7 +2055,7 @@ public class SqlToRelConverter {
datasetStack.push(sampleName);
SqlCall cursorCall = call.operand(1);
SqlNode query = cursorCall.operand(0);
- RelNode converted = convertQuery(query, false, false);
+ RelNode converted = convertQuery(query, false, false).rel;
bb.setRoot(converted, false);
datasetStack.pop();
return;
@@ -2788,29 +2814,28 @@ public class SqlToRelConverter {
* @param targetRowType Target row type, or null
* @return Relational expression
*/
- protected RelNode convertQueryRecursive(
- SqlNode query,
- boolean top,
+ protected RelRoot convertQueryRecursive(SqlNode query, boolean top,
RelDataType targetRowType) {
- switch (query.getKind()) {
+ final SqlKind kind = query.getKind();
+ switch (kind) {
case SELECT:
- return convertSelect((SqlSelect) query);
+ return RelRoot.of(convertSelect((SqlSelect) query, top), kind);
case INSERT:
- return convertInsert((SqlInsert) query);
+ return RelRoot.of(convertInsert((SqlInsert) query), kind);
case DELETE:
- return convertDelete((SqlDelete) query);
+ return RelRoot.of(convertDelete((SqlDelete) query), kind);
case UPDATE:
- return convertUpdate((SqlUpdate) query);
+ return RelRoot.of(convertUpdate((SqlUpdate) query), kind);
case MERGE:
- return convertMerge((SqlMerge) query);
+ return RelRoot.of(convertMerge((SqlMerge) query), kind);
case UNION:
case INTERSECT:
case EXCEPT:
- return convertSetOp((SqlCall) query);
+ return RelRoot.of(convertSetOp((SqlCall) query), kind);
case WITH:
- return convertWith((SqlWith) query);
+ return convertWith((SqlWith) query, top);
case VALUES:
- return convertValues((SqlCall) query, targetRowType);
+ return RelRoot.of(convertValues((SqlCall) query, targetRowType), kind);
default:
throw Util.newInternal("not a query: " + query);
}
@@ -2824,8 +2849,10 @@ public class SqlToRelConverter {
* @return Relational expression
*/
protected RelNode convertSetOp(SqlCall call) {
- final RelNode left = convertQueryRecursive(call.operand(0), false, null);
- final RelNode right = convertQueryRecursive(call.operand(1), false, null);
+ final RelNode left =
+ convertQueryRecursive(call.operand(0), false, null).project();
+ final RelNode right =
+ convertQueryRecursive(call.operand(1), false, null).project();
boolean all = false;
if (call.getOperator() instanceof SqlSetOperator) {
all = ((SqlSetOperator) (call.getOperator())).isAll();
@@ -2864,8 +2891,7 @@ public class SqlToRelConverter {
validator.getValidatedNodeType(call);
assert targetRowType != null;
RelNode sourceRel =
- convertQueryRecursive(
- call.getSource(), false, targetRowType);
+ convertQueryRecursive(call.getSource(), false, targetRowType).project();
RelNode massagedRel = convertColumnList(call, sourceRel);
return createModify(targetTable, massagedRel);
@@ -2953,9 +2979,7 @@ public class SqlToRelConverter {
return cluster;
}
- public RelNode expandView(
- RelDataType rowType,
- String queryString,
+ public RelRoot expandView(RelDataType rowType, String queryString,
List<String> schemaPath) {
return viewExpander.expandView(rowType, queryString, schemaPath);
}
@@ -3084,7 +3108,7 @@ public class SqlToRelConverter {
private RelNode convertDelete(SqlDelete call) {
RelOptTable targetTable = getTargetTable(call);
- RelNode sourceRel = convertSelect(call.getSourceSelect());
+ RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
return LogicalTableModify.create(targetTable, catalogReader, sourceRel,
LogicalTableModify.Operation.DELETE, null, false);
}
@@ -3100,7 +3124,7 @@ public class SqlToRelConverter {
targetColumnNameList.add(name);
}
- RelNode sourceRel = convertSelect(call.getSourceSelect());
+ RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
return LogicalTableModify.create(targetTable, catalogReader, sourceRel,
LogicalTableModify.Operation.UPDATE, targetColumnNameList, false);
@@ -3129,7 +3153,7 @@ public class SqlToRelConverter {
// first, convert the merge's source select to construct the columns
// from the target table and the set expressions in the update call
- RelNode mergeSourceRel = convertSelect(call.getSourceSelect());
+ RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
// then, convert the insert statement so we can get the insert
// values expressions
@@ -3199,7 +3223,6 @@ public class SqlToRelConverter {
final SqlQualified qualified;
if (bb.scope != null) {
qualified = bb.scope.fullyQualify(identifier);
- identifier = qualified.identifier;
} else {
qualified = SqlQualified.create(null, 1, null, identifier);
}
@@ -3271,7 +3294,7 @@ public class SqlToRelConverter {
final SqlCall cursorCall = (SqlCall) subQuery.node;
assert cursorCall.operandCount() == 1;
SqlNode query = cursorCall.operand(0);
- RelNode converted = convertQuery(query, false, false);
+ RelNode converted = convertQuery(query, false, false).rel;
int iCursor = bb.cursors.size();
bb.cursors.add(converted);
subQuery.expr =
@@ -3305,21 +3328,18 @@ public class SqlToRelConverter {
if (op == SqlStdOperatorTable.MULTISET_VALUE) {
final SqlNodeList list =
new SqlNodeList(call.getOperandList(), call.getParserPosition());
-// assert bb.scope instanceof SelectScope : bb.scope;
CollectNamespace nss =
(CollectNamespace) validator.getNamespace(call);
Blackboard usedBb;
if (null != nss) {
- usedBb = createBlackboard(nss.getScope(), null);
+ usedBb = createBlackboard(nss.getScope(), null, false);
} else {
usedBb =
- createBlackboard(
- new ListScope(bb.scope) {
- public SqlNode getNode() {
- return call;
- }
- },
- null);
+ createBlackboard(new ListScope(bb.scope) {
+ public SqlNode getNode() {
+ return call;
+ }
+ }, null, false);
}
RelDataType multisetType = validator.getValidatedNodeType(call);
validator.setValidatedNodeType(
@@ -3327,7 +3347,8 @@ public class SqlToRelConverter {
multisetType.getComponentType());
input = convertQueryOrInList(usedBb, list, null);
} else {
- input = convertQuery(call.operand(0), false, true);
+ final RelRoot root = convertQuery(call.operand(0), false, true);
+ input = root.rel;
}
if (lastList.size() > 0) {
@@ -3492,8 +3513,8 @@ public class SqlToRelConverter {
/**
* Converts a WITH sub-query into a relational expression.
*/
- public RelNode convertWith(SqlWith with) {
- return convertQuery(with.body, false, false);
+ public RelRoot convertWith(SqlWith with, boolean top) {
+ return convertQuery(with.body, false, top);
}
/**
@@ -3504,7 +3525,7 @@ public class SqlToRelConverter {
RelDataType targetRowType) {
final SqlValidatorScope scope = validator.getOverScope(values);
assert scope != null;
- final Blackboard bb = createBlackboard(scope, null);
+ final Blackboard bb = createBlackboard(scope, null, false);
convertValuesImpl(bb, values, targetRowType);
return bb.root;
}
@@ -3538,7 +3559,7 @@ public class SqlToRelConverter {
final List<RelNode> unionRels = new ArrayList<>();
for (SqlNode rowConstructor1 : values.getOperandList()) {
SqlCall rowConstructor = (SqlCall) rowConstructor1;
- Blackboard tmpBb = createBlackboard(bb.scope, null);
+ Blackboard tmpBb = createBlackboard(bb.scope, null, false);
replaceSubqueries(tmpBb, rowConstructor,
RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
final List<Pair<RexNode, String>> exps = new ArrayList<>();
@@ -3604,7 +3625,7 @@ public class SqlToRelConverter {
private final Map<String, RexNode> mapCorrelateVariableToRexNode =
new HashMap<>();
- List<RelNode> cursors;
+ final List<RelNode> cursors = new ArrayList<>();
/**
* List of <code>IN</code> and <code>EXISTS</code> nodes inside this
@@ -3637,6 +3658,7 @@ public class SqlToRelConverter {
new ArrayList<>();
private final List<RelDataTypeField> systemFieldList = new ArrayList<>();
+ final boolean top;
/**
* Creates a Blackboard.
@@ -3647,13 +3669,13 @@ public class SqlToRelConverter {
* @param nameToNodeMap Map which translates the expression to map a
* given parameter into, if translating expressions;
* null otherwise
+ * @param top Whether this is the root of the query
*/
- protected Blackboard(
- SqlValidatorScope scope,
- Map<String, RexNode> nameToNodeMap) {
+ protected Blackboard(SqlValidatorScope scope,
+ Map<String, RexNode> nameToNodeMap, boolean top) {
this.scope = scope;
this.nameToNodeMap = nameToNodeMap;
- this.cursors = new ArrayList<>();
+ this.top = top;
subqueryNeedsOuterJoin = false;
}
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/5a397063/core/src/main/java/org/apache/calcite/tools/Planner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/Planner.java b/core/src/main/java/org/apache/calcite/tools/Planner.java
index 98c1649..73c8047 100644
--- a/core/src/main/java/org/apache/calcite/tools/Planner.java
+++ b/core/src/main/java/org/apache/calcite/tools/Planner.java
@@ -18,6 +18,7 @@ package org.apache.calcite.tools;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.parser.SqlParseException;
@@ -61,6 +62,10 @@ public interface Planner {
* @throws org.apache.calcite.tools.RelConversionException if the node
* cannot be converted or has not been validated
*/
+ RelRoot rel(SqlNode sql) throws RelConversionException;
+
+ /** @deprecated Use {@link #rel}. */
+ @Deprecated // to removed before 2.0
RelNode convert(SqlNode sql) throws RelConversionException;
/** Returns the type factory. */