This is an automated email from the ASF dual-hosted git repository. danny0405 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push: new 6257609 [CALCITE-3730] Add hints to RelBuilder 6257609 is described below commit 6257609c6be438ba9103666ea41e3191d851abd0 Author: yuzhao.cyz <yuzhao....@gmail.com> AuthorDate: Tue Jan 14 11:52:33 2020 +0800 [CALCITE-3730] Add hints to RelBuilder * Add #hints to RelBuilder * Add hints to RelNode factories * In logical RelNode classes that implement Hintable, add hints to #create method --- .../org/apache/calcite/adapter/jdbc/JdbcRules.java | 8 +- .../apache/calcite/plan/RelOptAbstractTable.java | 3 +- .../apache/calcite/plan/RelOptMaterialization.java | 4 +- .../java/org/apache/calcite/plan/RelOptUtil.java | 17 +-- .../org/apache/calcite/plan/ViewExpanders.java | 2 +- .../apache/calcite/prepare/LixToRelTranslator.java | 7 +- .../calcite/prepare/QueryableRelBuilder.java | 6 +- .../apache/calcite/prepare/RelOptTableImpl.java | 6 +- .../main/java/org/apache/calcite/rel/RelRoot.java | 6 +- .../org/apache/calcite/rel/core/RelFactories.java | 79 ++++++++++---- .../calcite/rel/logical/LogicalAggregate.java | 19 +++- .../apache/calcite/rel/logical/LogicalJoin.java | 33 ++++-- .../apache/calcite/rel/logical/LogicalProject.java | 20 +++- .../calcite/rel/logical/LogicalTableScan.java | 9 +- .../calcite/rel/logical/ToLogicalConverter.java | 2 +- .../rel/rules/JoinAddRedundantSemiJoinRule.java | 2 + .../calcite/rel/rules/LoptSemiJoinOptimizer.java | 4 +- .../rel/rules/SemiJoinFilterTransposeRule.java | 3 + .../rel/rules/SemiJoinJoinTransposeRule.java | 3 + .../rel/rules/SemiJoinProjectTransposeRule.java | 7 +- .../org/apache/calcite/rel/stream/StreamRules.java | 8 +- .../main/java/org/apache/calcite/sql/SqlUtil.java | 6 +- .../apache/calcite/sql2rel/RelDecorrelator.java | 11 +- .../sql2rel/RelStructuredTypeFlattener.java | 8 +- .../apache/calcite/sql2rel/SqlToRelConverter.java | 40 ++++--- .../java/org/apache/calcite/tools/RelBuilder.java | 117 ++++++++++++++++++--- .../org/apache/calcite/plan/RelOptUtilTest.java | 2 + .../org/apache/calcite/plan/RelWriterTest.java | 12 ++- .../calcite/plan/volcano/TraitPropagationTest.java | 3 +- .../java/org/apache/calcite/test/Matchers.java | 12 +++ .../org/apache/calcite/test/RelBuilderTest.java | 89 ++++++++++++++++ .../org/apache/calcite/test/RelMetadataTest.java | 35 +++--- .../apache/calcite/test/SqlHintsConverterTest.java | 11 +- .../org/apache/calcite/test/SqlToRelTestBase.java | 6 +- .../calcite/test/catalog/MockCatalogReader.java | 11 +- .../apache/calcite/test/SqlHintsConverterTest.xml | 4 +- .../apache/calcite/adapter/druid/DruidTable.java | 2 +- .../calcite/adapter/pig/PigRelFactories.java | 16 ++- .../org/apache/calcite/piglet/PigRelBuilder.java | 4 +- site/_docs/history.md | 1 + .../calcite/adapter/splunk/SplunkPushDownRule.java | 5 +- 41 files changed, 480 insertions(+), 163 deletions(-) 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 52525c0..c8a3e64 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 @@ -96,7 +96,7 @@ public class JdbcRules { protected static final Logger LOGGER = CalciteTrace.getPlannerTracer(); static final RelFactories.ProjectFactory PROJECT_FACTORY = - (input, projects, fieldNames) -> { + (input, hints, projects, fieldNames) -> { final RelOptCluster cluster = input.getCluster(); final RelDataType rowType = RexUtil.createStructType(cluster.getTypeFactory(), projects, @@ -114,7 +114,7 @@ public class JdbcRules { }; static final RelFactories.JoinFactory JOIN_FACTORY = - (left, right, condition, variablesSet, joinType, semiJoinDone) -> { + (left, right, hints, condition, variablesSet, joinType, semiJoinDone) -> { final RelOptCluster cluster = left.getCluster(); final RelTraitSet traitSet = cluster.traitSetOf(left.getConvention()); try { @@ -146,7 +146,7 @@ public class JdbcRules { }; public static final RelFactories.AggregateFactory AGGREGATE_FACTORY = - (input, groupSet, groupSets, aggCalls) -> { + (input, hints, groupSet, groupSets, aggCalls) -> { final RelOptCluster cluster = input.getCluster(); final RelTraitSet traitSet = cluster.traitSetOf(input.getConvention()); try { @@ -187,7 +187,7 @@ public class JdbcRules { }; public static final RelFactories.TableScanFactory TABLE_SCAN_FACTORY = - (cluster, table) -> { + (cluster, table, hints) -> { throw new UnsupportedOperationException(); }; diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptAbstractTable.java b/core/src/main/java/org/apache/calcite/plan/RelOptAbstractTable.java index 05333a3..216f7fb 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptAbstractTable.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptAbstractTable.java @@ -108,7 +108,8 @@ public abstract class RelOptAbstractTable implements RelOptTable { } public RelNode toRel(ToRelContext context) { - return LogicalTableScan.create(context.getCluster(), this); + return LogicalTableScan.create(context.getCluster(), this, + context.getTableHints()); } public Expression getExpression(Class clazz) { diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java b/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java index 1baf55f..0b9a48a 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java @@ -156,7 +156,7 @@ public class RelOptMaterialization { Mappings.offsetSource(rightMapping, offset), leftMapping.getTargetCount())); final RelNode project = RelOptUtil.createProject( - LogicalTableScan.create(cluster, leftRelOptTable), + LogicalTableScan.create(cluster, leftRelOptTable, ImmutableList.of()), Mappings.asList(mapping.inverse())); final List<RexNode> conditions = new ArrayList<>(); if (left.condition != null) { @@ -180,7 +180,7 @@ public class RelOptMaterialization { Mappings.offsetSource(leftMapping, offset), Mappings.offsetTarget(rightMapping, leftCount)); final RelNode project = RelOptUtil.createProject( - LogicalTableScan.create(cluster, rightRelOptTable), + LogicalTableScan.create(cluster, rightRelOptTable, ImmutableList.of()), Mappings.asList(mapping.inverse())); final List<RexNode> conditions = new ArrayList<>(); if (left.condition != null) { 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 a965a23..a69afcd 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java @@ -667,8 +667,8 @@ public abstract class RelOptUtil { || logic == RelOptUtil.Logic.TRUE_FALSE_UNKNOWN; if (!outerJoin) { final LogicalAggregate aggregate = - LogicalAggregate.create(ret, ImmutableBitSet.range(keyCount), null, - ImmutableList.of()); + LogicalAggregate.create(ret, ImmutableList.of(), ImmutableBitSet.range(keyCount), + null, ImmutableList.of()); return new Exists(aggregate, false, false); } @@ -867,14 +867,17 @@ public abstract class RelOptUtil { final RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); List<RexNode> castExps; RelNode input; + List<RelHint> hints = ImmutableList.of(); if (rel instanceof Project) { // No need to create another project node if the rel // is already a project. + final Project project = (Project) rel; castExps = RexUtil.generateCastExpressions( rexBuilder, castRowType, ((Project) rel).getProjects()); input = rel.getInput(0); + hints = project.getHints(); } else { castExps = RexUtil.generateCastExpressions( rexBuilder, @@ -884,11 +887,11 @@ public abstract class RelOptUtil { } if (rename) { // Use names and types from castRowType. - return projectFactory.createProject(input, castExps, + return projectFactory.createProject(input, hints, castExps, castRowType.getFieldNames()); } else { // Use names from rowType, types from castRowType. - return projectFactory.createProject(input, castExps, + return projectFactory.createProject(input, hints, castExps, rowType.getFieldNames()); } } @@ -927,13 +930,15 @@ public abstract class RelOptUtil { null)); } - return LogicalAggregate.create(rel, ImmutableBitSet.of(), null, aggCalls); + return LogicalAggregate.create(rel, ImmutableList.of(), ImmutableBitSet.of(), + null, aggCalls); } /** @deprecated Use {@link RelBuilder#distinct()}. */ @Deprecated // to be removed before 2.0 public static RelNode createDistinctRel(RelNode rel) { return LogicalAggregate.create(rel, + ImmutableList.of(), ImmutableBitSet.range(rel.getRowType().getFieldCount()), null, ImmutableList.of()); } @@ -3381,7 +3386,7 @@ public abstract class RelOptUtil { : fieldNames.get(i)); exprList.add(rexBuilder.makeInputRef(rel, source)); } - return projectFactory.createProject(rel, exprList, outputNameList); + return projectFactory.createProject(rel, ImmutableList.of(), exprList, outputNameList); } /** Predicate for whether a {@link Calc} contains multisets or windowed diff --git a/core/src/main/java/org/apache/calcite/plan/ViewExpanders.java b/core/src/main/java/org/apache/calcite/plan/ViewExpanders.java index 13c188e..0767307 100644 --- a/core/src/main/java/org/apache/calcite/plan/ViewExpanders.java +++ b/core/src/main/java/org/apache/calcite/plan/ViewExpanders.java @@ -80,7 +80,7 @@ public abstract class ViewExpanders { } public List<RelHint> getTableHints() { - throw new UnsupportedOperationException(); + return ImmutableList.of(); } }; } 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 e6ab3bc..6bdb9be 100644 --- a/core/src/main/java/org/apache/calcite/prepare/LixToRelTranslator.java +++ b/core/src/main/java/org/apache/calcite/prepare/LixToRelTranslator.java @@ -88,6 +88,7 @@ class LixToRelTranslator { case SELECT: input = translate(call.targetExpression); return LogicalProject.create(input, + ImmutableList.of(), toRex(input, (FunctionExpression) call.expressions.get(0)), (List<String>) null); @@ -103,7 +104,8 @@ class LixToRelTranslator { Types.toClass( Types.getElementType(call.targetExpression.getType()))), ImmutableList.of(), - call.targetExpression)); + call.targetExpression), + ImmutableList.of()); case SCHEMA_GET_TABLE: return LogicalTableScan.create(cluster, @@ -111,7 +113,8 @@ class LixToRelTranslator { typeFactory.createJavaType((Class) ((ConstantExpression) call.expressions.get(1)).value), ImmutableList.of(), - call.targetExpression)); + call.targetExpression), + ImmutableList.of()); default: throw new UnsupportedOperationException( diff --git a/core/src/main/java/org/apache/calcite/prepare/QueryableRelBuilder.java b/core/src/main/java/org/apache/calcite/prepare/QueryableRelBuilder.java index b43c0b6..9624470 100644 --- a/core/src/main/java/org/apache/calcite/prepare/QueryableRelBuilder.java +++ b/core/src/main/java/org/apache/calcite/prepare/QueryableRelBuilder.java @@ -48,6 +48,8 @@ import org.apache.calcite.schema.QueryableTable; import org.apache.calcite.schema.TranslatableTable; import org.apache.calcite.schema.impl.AbstractTableQueryable; +import com.google.common.collect.ImmutableList; + import java.math.BigDecimal; import java.util.Comparator; import java.util.List; @@ -102,7 +104,7 @@ class QueryableRelBuilder<T> implements QueryableFactory<T> { return ((TranslatableTable) table).toRel(translator.toRelContext(), relOptTable); } else { - return LogicalTableScan.create(translator.cluster, relOptTable); + return LogicalTableScan.create(translator.cluster, relOptTable, ImmutableList.of()); } } return translator.translate(queryable.getExpression()); @@ -536,7 +538,7 @@ class QueryableRelBuilder<T> implements QueryableFactory<T> { RelNode child = toRel(source); List<RexNode> nodes = translator.toRexList(selector, child); setRel( - LogicalProject.create(child, nodes, (List<String>) null)); + LogicalProject.create(child, ImmutableList.of(), nodes, (List<String>) null)); return null; } diff --git a/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java b/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java index 769dd27..021a300 100644 --- a/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java +++ b/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java @@ -290,7 +290,7 @@ public class RelOptTableImpl extends Prepare.AbstractPreparingTable { } final RelOptCluster cluster = context.getCluster(); if (Hook.ENABLE_BINDABLE.get(false)) { - return LogicalTableScan.create(cluster, this); + return LogicalTableScan.create(cluster, this, context.getTableHints()); } if (CalciteSystemProperty.ENABLE_ENUMERABLE.value() && table instanceof QueryableTable @@ -301,7 +301,7 @@ public class RelOptTableImpl extends Prepare.AbstractPreparingTable { if (table instanceof ScannableTable || table instanceof FilterableTable || table instanceof ProjectableFilterableTable) { - return LogicalTableScan.create(cluster, this); + return LogicalTableScan.create(cluster, this, context.getTableHints()); } // Some tests rely on the old behavior when tables were immediately converted to // EnumerableTableScan @@ -311,7 +311,7 @@ public class RelOptTableImpl extends Prepare.AbstractPreparingTable { || EnumerableTableScan.canHandle(this))) { return EnumerableTableScan.create(cluster, this); } - return LogicalTableScan.create(cluster, this); + return LogicalTableScan.create(cluster, this, context.getTableHints()); } public List<RelCollation> getCollationList() { diff --git a/core/src/main/java/org/apache/calcite/rel/RelRoot.java b/core/src/main/java/org/apache/calcite/rel/RelRoot.java index 80cd6ce..27e8e45 100644 --- a/core/src/main/java/org/apache/calcite/rel/RelRoot.java +++ b/core/src/main/java/org/apache/calcite/rel/RelRoot.java @@ -16,7 +16,6 @@ */ package org.apache.calcite.rel; -import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.rel.hint.RelHint; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.type.RelDataType; @@ -167,10 +166,7 @@ public class RelRoot { for (Pair<Integer, String> field : fields) { projects.add(rexBuilder.makeInputRef(rel, field.left)); } - return RelOptUtil.copyRelHints( - rel, - LogicalProject.create(rel, projects, Pair.right(fields)), - false); + return LogicalProject.create(rel, hints, projects, Pair.right(fields)); } public boolean isNameTrivial() { diff --git a/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java b/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java index 92473bc..4518524 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java +++ b/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java @@ -25,6 +25,7 @@ import org.apache.calcite.plan.ViewExpanders; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelDistribution; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.hint.RelHint; import org.apache.calcite.rel.logical.LogicalAggregate; import org.apache.calcite.rel.logical.LogicalCorrelate; import org.apache.calcite.rel.logical.LogicalExchange; @@ -143,9 +144,23 @@ public class RelFactories { * appropriate type for this rule's calling convention. */ public interface ProjectFactory { - /** Creates a project. */ - RelNode createProject(RelNode input, List<? extends RexNode> childExprs, - List<String> fieldNames); + /** + * Creates a project. + * + * @param input The input + * @param hints The hints + * @param childExprs The projection expressions + * @param fieldNames The projection field names + * @return a project + */ + RelNode createProject(RelNode input, List<RelHint> hints, + List<? extends RexNode> childExprs, List<String> fieldNames); + + @Deprecated // to be removed before 1.23 + default RelNode createProject(RelNode input, + List<? extends RexNode> childExprs, List<String> fieldNames) { + return createProject(input, ImmutableList.of(), childExprs, fieldNames); + } } /** @@ -153,9 +168,9 @@ public class RelFactories { * {@link org.apache.calcite.rel.logical.LogicalProject}. */ private static class ProjectFactoryImpl implements ProjectFactory { - public RelNode createProject(RelNode input, + public RelNode createProject(RelNode input, List<RelHint> hints, List<? extends RexNode> childExprs, List<String> fieldNames) { - return LogicalProject.create(input, childExprs, fieldNames); + return LogicalProject.create(input, hints, childExprs, fieldNames); } } @@ -272,15 +287,21 @@ public class RelFactories { */ public interface AggregateFactory { /** Creates an aggregate. */ - RelNode createAggregate(RelNode input, ImmutableBitSet groupSet, + RelNode createAggregate(RelNode input, List<RelHint> hints, ImmutableBitSet groupSet, ImmutableList<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls); - @Deprecated // to be removed before 2.0 + @Deprecated // to be removed before 1.23 + default RelNode createAggregate(RelNode input, ImmutableBitSet groupSet, + ImmutableList<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { + return createAggregate(input, ImmutableList.of(), groupSet, groupSets, aggCalls); + } + + @Deprecated // to be removed before 1.23 default RelNode createAggregate(RelNode input, boolean indicator, ImmutableBitSet groupSet, ImmutableList<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { Aggregate.checkIndicator(indicator); - return createAggregate(input, groupSet, groupSets, aggCalls); + return createAggregate(input, ImmutableList.of(), groupSet, groupSets, aggCalls); } } @@ -289,10 +310,10 @@ public class RelFactories { * that returns a vanilla {@link LogicalAggregate}. */ private static class AggregateFactoryImpl implements AggregateFactory { - public RelNode createAggregate(RelNode input, + public RelNode createAggregate(RelNode input, List<RelHint> hints, ImmutableBitSet groupSet, ImmutableList<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { - return LogicalAggregate.create(input, groupSet, groupSets, aggCalls); + return LogicalAggregate.create(input, hints, groupSet, groupSets, aggCalls); } } @@ -346,6 +367,7 @@ public class RelFactories { * * @param left Left input * @param right Right input + * @param hints Hints * @param condition Join condition * @param variablesSet Set of variables that are set by the * LHS and used by the RHS and are not available to @@ -354,15 +376,23 @@ public class RelFactories { * @param semiJoinDone Whether this join has been translated to a * semi-join */ - RelNode createJoin(RelNode left, RelNode right, RexNode condition, - Set<CorrelationId> variablesSet, JoinRelType joinType, + RelNode createJoin(RelNode left, RelNode right, List<RelHint> hints, + RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType, boolean semiJoinDone); - @Deprecated // to be removed before 2.0 + @Deprecated // to be removed before 1.23 + default RelNode createJoin(RelNode left, RelNode right, RexNode condition, + Set<CorrelationId> variablesSet, JoinRelType joinType, + boolean semiJoinDone) { + return createJoin(left, right, ImmutableList.of(), condition, variablesSet, + joinType, semiJoinDone); + } + + @Deprecated // to be removed before 1.23 default RelNode createJoin(RelNode left, RelNode right, RexNode condition, JoinRelType joinType, Set<String> variablesStopped, boolean semiJoinDone) { - return createJoin(left, right, condition, + return createJoin(left, right, ImmutableList.of(), condition, CorrelationId.setOf(variablesStopped), joinType, semiJoinDone); } } @@ -372,10 +402,10 @@ public class RelFactories { * {@link org.apache.calcite.rel.logical.LogicalJoin}. */ private static class JoinFactoryImpl implements JoinFactory { - public RelNode createJoin(RelNode left, RelNode right, + public RelNode createJoin(RelNode left, RelNode right, List<RelHint> hints, RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType, boolean semiJoinDone) { - return LogicalJoin.create(left, right, condition, variablesSet, joinType, + return LogicalJoin.create(left, right, hints, condition, variablesSet, joinType, semiJoinDone, ImmutableList.of()); } } @@ -479,7 +509,12 @@ public class RelFactories { /** * Creates a {@link TableScan}. */ - RelNode createScan(RelOptCluster cluster, RelOptTable table); + RelNode createScan(RelOptCluster cluster, RelOptTable table, List<RelHint> hints); + + @Deprecated // to be removed before 1.23 + default RelNode createScan(RelOptCluster cluster, RelOptTable table) { + return createScan(cluster, table, ImmutableList.of()); + } } /** @@ -487,8 +522,8 @@ public class RelFactories { * {@link LogicalTableScan}. */ private static class TableScanFactoryImpl implements TableScanFactory { - public RelNode createScan(RelOptCluster cluster, RelOptTable table) { - return LogicalTableScan.create(cluster, table); + public RelNode createScan(RelOptCluster cluster, RelOptTable table, List<RelHint> hints) { + return LogicalTableScan.create(cluster, table, hints); } } @@ -521,15 +556,15 @@ public class RelFactories { @Nonnull public static TableScanFactory expandingScanFactory( @Nonnull RelOptTable.ViewExpander viewExpander, @Nonnull TableScanFactory tableScanFactory) { - return (cluster, table) -> { + return (cluster, table, hints) -> { final TranslatableTable translatableTable = table.unwrap(TranslatableTable.class); if (translatableTable != null) { final RelOptTable.ToRelContext toRelContext = - ViewExpanders.toRelContext(viewExpander, cluster); + ViewExpanders.toRelContext(viewExpander, cluster, hints); return translatableTable.toRel(toRelContext, table); } - return tableScanFactory.createScan(cluster, table); + return tableScanFactory.createScan(cluster, table, hints); }; } diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java index 3da516b..115e423 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java @@ -107,9 +107,19 @@ public final class LogicalAggregate extends Aggregate { /** Creates a LogicalAggregate. */ public static LogicalAggregate create(final RelNode input, - ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, + List<RelHint> hints, + ImmutableBitSet groupSet, + List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { - return create_(input, groupSet, groupSets, aggCalls); + return create_(input, hints, groupSet, groupSets, aggCalls); + } + + @Deprecated // to be removed before 2.0 + public static LogicalAggregate create(final RelNode input, + ImmutableBitSet groupSet, + List<ImmutableBitSet> groupSets, + List<AggregateCall> aggCalls) { + return create_(input, ImmutableList.of(), groupSet, groupSets, aggCalls); } @Deprecated // to be removed before 2.0 @@ -119,16 +129,17 @@ public final class LogicalAggregate extends Aggregate { List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { checkIndicator(indicator); - return create_(input, groupSet, groupSets, aggCalls); + return create_(input, ImmutableList.of(), groupSet, groupSets, aggCalls); } private static LogicalAggregate create_(final RelNode input, + List<RelHint> hints, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { final RelOptCluster cluster = input.getCluster(); final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE); - return new LogicalAggregate(cluster, traitSet, ImmutableList.of(), input, groupSet, + return new LogicalAggregate(cluster, traitSet, hints, input, groupSet, groupSets, aggCalls); } diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalJoin.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalJoin.java index a3fb061..f37c3d7 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalJoin.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalJoin.java @@ -152,30 +152,45 @@ public final class LogicalJoin extends Join { ImmutableList.of()); } + /** Creates a LogicalJoin. */ + public static LogicalJoin create(RelNode left, RelNode right, List<RelHint> hints, + RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType) { + return create(left, right, hints, condition, variablesSet, joinType, false, + ImmutableList.of()); + } + /** Creates a LogicalJoin, flagged with whether it has been translated to a * semi-join. */ - public static LogicalJoin create(RelNode left, RelNode right, + public static LogicalJoin create(RelNode left, RelNode right, List<RelHint> hints, RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType, boolean semiJoinDone, ImmutableList<RelDataTypeField> systemFieldList) { final RelOptCluster cluster = left.getCluster(); final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE); - return new LogicalJoin(cluster, traitSet, ImmutableList.of(), left, right, condition, + return new LogicalJoin(cluster, traitSet, hints, left, right, condition, variablesSet, joinType, semiJoinDone, systemFieldList); } - @Deprecated // to be removed before 2.0 + @Deprecated // to be removed before 1.23 public static LogicalJoin create(RelNode left, RelNode right, - RexNode condition, JoinRelType joinType, Set<String> variablesStopped, + RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType) { + return create(left, right, ImmutableList.of(), condition, variablesSet, + joinType, false, ImmutableList.of()); + } + + @Deprecated // to be removed before 1.23 + public static LogicalJoin create(RelNode left, RelNode right, + RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType, boolean semiJoinDone, ImmutableList<RelDataTypeField> systemFieldList) { - return create(left, right, condition, CorrelationId.setOf(variablesStopped), + return create(left, right, ImmutableList.of(), condition, variablesSet, joinType, semiJoinDone, systemFieldList); } - /** Creates a LogicalJoin. */ + @Deprecated // to be removed before 2.0 public static LogicalJoin create(RelNode left, RelNode right, - RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType) { - return create(left, right, condition, variablesSet, joinType, false, - ImmutableList.of()); + RexNode condition, JoinRelType joinType, Set<String> variablesStopped, + boolean semiJoinDone, ImmutableList<RelDataTypeField> systemFieldList) { + return create(left, right, condition, CorrelationId.setOf(variablesStopped), + joinType, semiJoinDone, systemFieldList); } @Deprecated // to be removed before 2.0 diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java index c5baecb..605b875 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java @@ -102,17 +102,17 @@ public final class LogicalProject extends Project { //~ Methods ---------------------------------------------------------------- /** Creates a LogicalProject. */ - public static LogicalProject create(final RelNode input, + public static LogicalProject create(final RelNode input, List<RelHint> hints, final List<? extends RexNode> projects, List<String> fieldNames) { final RelOptCluster cluster = input.getCluster(); final RelDataType rowType = RexUtil.createStructType(cluster.getTypeFactory(), projects, fieldNames, SqlValidatorUtil.F_SUGGESTER); - return create(input, projects, rowType); + return create(input, hints, projects, rowType); } /** Creates a LogicalProject, specifying row type rather than field names. */ - public static LogicalProject create(final RelNode input, + public static LogicalProject create(final RelNode input, List<RelHint> hints, final List<? extends RexNode> projects, RelDataType rowType) { final RelOptCluster cluster = input.getCluster(); final RelMetadataQuery mq = cluster.getMetadataQuery(); @@ -120,7 +120,19 @@ public final class LogicalProject extends Project { cluster.traitSet().replace(Convention.NONE) .replaceIfs(RelCollationTraitDef.INSTANCE, () -> RelMdCollation.project(mq, input, projects)); - return new LogicalProject(cluster, traitSet, ImmutableList.of(), input, projects, rowType); + return new LogicalProject(cluster, traitSet, hints, input, projects, rowType); + } + + @Deprecated // to be removed before 1.23 + public static LogicalProject create(final RelNode input, + final List<? extends RexNode> projects, List<String> fieldNames) { + return create(input, ImmutableList.of(), projects, fieldNames); + } + + @Deprecated // to be removed before 1.23 + public static LogicalProject create(final RelNode input, + final List<? extends RexNode> projects, RelDataType rowType) { + return create(input, ImmutableList.of(), projects, rowType); } @Override public LogicalProject copy(RelTraitSet traitSet, RelNode input, diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableScan.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableScan.java index 8876e01..9d62e37 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableScan.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableScan.java @@ -29,7 +29,6 @@ import org.apache.calcite.schema.Table; import com.google.common.collect.ImmutableList; -import java.util.ArrayList; import java.util.List; /** @@ -115,14 +114,10 @@ public final class LogicalTableScan extends TableScan { return new LogicalTableScan(cluster, traitSet, hints, relOptTable); } - /** Creates a LogicalTableScan. - * - * @param cluster Cluster - * @param relOptTable Table - */ + @Deprecated // to be removed before 1.23 public static LogicalTableScan create(RelOptCluster cluster, final RelOptTable relOptTable) { - return create(cluster, relOptTable, new ArrayList<>()); + return create(cluster, relOptTable, ImmutableList.of()); } @Override public RelNode withHints(List<RelHint> hintList) { diff --git a/core/src/main/java/org/apache/calcite/rel/logical/ToLogicalConverter.java b/core/src/main/java/org/apache/calcite/rel/logical/ToLogicalConverter.java index 60ff322..5b262c2 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/ToLogicalConverter.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/ToLogicalConverter.java @@ -52,7 +52,7 @@ public class ToLogicalConverter extends RelShuttleImpl { } @Override public RelNode visit(TableScan scan) { - return LogicalTableScan.create(scan.getCluster(), scan.getTable()); + return LogicalTableScan.create(scan.getCluster(), scan.getTable(), scan.getHints()); } @Override public RelNode visit(RelNode relNode) { diff --git a/core/src/main/java/org/apache/calcite/rel/rules/JoinAddRedundantSemiJoinRule.java b/core/src/main/java/org/apache/calcite/rel/rules/JoinAddRedundantSemiJoinRule.java index de03c14..5cbd49d 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/JoinAddRedundantSemiJoinRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/JoinAddRedundantSemiJoinRule.java @@ -26,6 +26,7 @@ import org.apache.calcite.rel.core.RelFactories; import org.apache.calcite.rel.logical.LogicalJoin; import org.apache.calcite.tools.RelBuilderFactory; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; /** @@ -74,6 +75,7 @@ public class JoinAddRedundantSemiJoinRule extends RelOptRule { RelNode semiJoin = LogicalJoin.create(origJoinRel.getLeft(), origJoinRel.getRight(), + ImmutableList.of(), origJoinRel.getCondition(), ImmutableSet.of(), JoinRelType.SEMI); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java b/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java index aed93a0..1ae11a5 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/LoptSemiJoinOptimizer.java @@ -37,6 +37,7 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.Util; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; @@ -320,7 +321,7 @@ public class LoptSemiJoinOptimizer { multiJoin.getNumFieldsInJoinFactor(factIdx), semiJoinCondition); } - return LogicalJoin.create(factRel, dimRel, semiJoinCondition, + return LogicalJoin.create(factRel, dimRel, ImmutableList.of(), semiJoinCondition, ImmutableSet.of(), JoinRelType.SEMI); } @@ -581,6 +582,7 @@ public class LoptSemiJoinOptimizer { LogicalJoin chosenSemiJoin = LogicalJoin.create(factRel, chosenSemiJoins[bestDimIdx], + ImmutableList.of(), semiJoin.getCondition(), ImmutableSet.of(), JoinRelType.SEMI); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinFilterTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinFilterTransposeRule.java index b3068ba..1e15233 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinFilterTransposeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinFilterTransposeRule.java @@ -26,6 +26,7 @@ import org.apache.calcite.rel.logical.LogicalFilter; import org.apache.calcite.rel.logical.LogicalJoin; import org.apache.calcite.tools.RelBuilderFactory; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; /** @@ -65,6 +66,8 @@ public class SemiJoinFilterTransposeRule extends RelOptRule { RelNode newSemiJoin = LogicalJoin.create(filter.getInput(), semiJoin.getRight(), + // No need to copy the hints, the framework would try to do that. + ImmutableList.of(), semiJoin.getCondition(), ImmutableSet.of(), JoinRelType.SEMI); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinJoinTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinJoinTransposeRule.java index cf83391..824d5e6 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinJoinTransposeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinJoinTransposeRule.java @@ -29,6 +29,7 @@ import org.apache.calcite.rex.RexNode; import org.apache.calcite.tools.RelBuilderFactory; import org.apache.calcite.util.ImmutableIntList; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.ArrayList; @@ -159,6 +160,8 @@ public class SemiJoinJoinTransposeRule extends RelOptRule { LogicalJoin newSemiJoin = LogicalJoin.create(leftSemiJoinOp, semiJoin.getRight(), + // No need to copy the hints, the framework would try to do that. + ImmutableList.of(), newSemiJoinFilter, ImmutableSet.of(), JoinRelType.SEMI); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinProjectTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinProjectTransposeRule.java index f601893..e786d8a 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinProjectTransposeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinProjectTransposeRule.java @@ -36,6 +36,7 @@ import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilderFactory; import org.apache.calcite.util.Pair; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.List; @@ -83,7 +84,11 @@ public class SemiJoinProjectTransposeRule extends RelOptRule { RexNode newCondition = adjustCondition(project, semiJoin); LogicalJoin newSemiJoin = - LogicalJoin.create(project.getInput(), semiJoin.getRight(), newCondition, + LogicalJoin.create(project.getInput(), + semiJoin.getRight(), + // No need to copy the hints, the framework would try to do that. + ImmutableList.of(), + newCondition, ImmutableSet.of(), JoinRelType.SEMI); // Create the new projection. Note that the projection expressions diff --git a/core/src/main/java/org/apache/calcite/rel/stream/StreamRules.java b/core/src/main/java/org/apache/calcite/rel/stream/StreamRules.java index 14c0c67..03ebb7b 100644 --- a/core/src/main/java/org/apache/calcite/rel/stream/StreamRules.java +++ b/core/src/main/java/org/apache/calcite/rel/stream/StreamRules.java @@ -87,7 +87,9 @@ public class StreamRules { final Project project = call.rel(1); final LogicalDelta newDelta = LogicalDelta.create(project.getInput()); final LogicalProject newProject = - LogicalProject.create(newDelta, project.getProjects(), + LogicalProject.create(newDelta, + project.getHints(), + project.getProjects(), project.getRowType().getFieldNames()); call.transformTo(newProject); } @@ -142,7 +144,7 @@ public class StreamRules { final LogicalDelta newDelta = LogicalDelta.create(aggregate.getInput()); final LogicalAggregate newAggregate = - LogicalAggregate.create(newDelta, aggregate.getGroupSet(), + LogicalAggregate.create(newDelta, aggregate.getHints(), aggregate.getGroupSet(), aggregate.groupSets, aggregate.getAggCallList()); call.transformTo(newAggregate); } @@ -241,7 +243,7 @@ public class StreamRules { .addAll(relOptTable.getQualifiedName()) .add("(STREAM)").build()); final LogicalTableScan newScan = - LogicalTableScan.create(cluster, relOptTable2); + LogicalTableScan.create(cluster, relOptTable2, scan.getHints()); call.transformTo(newScan); } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlUtil.java b/core/src/main/java/org/apache/calcite/sql/SqlUtil.java index 640b080..4f09cc9 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlUtil.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlUtil.java @@ -988,10 +988,10 @@ public abstract class SqlUtil { * @return the {@code RelHint} list */ public static List<RelHint> getRelHint(HintStrategyTable hintStrategies, SqlNodeList sqlHints) { - final List<RelHint> relHints = new ArrayList<>(); if (sqlHints == null || sqlHints.size() == 0) { - return relHints; + return ImmutableList.of(); } + final ImmutableList.Builder<RelHint> relHints = ImmutableList.builder(); for (SqlNode node : sqlHints) { assert node instanceof SqlHint; final SqlHint sqlHint = (SqlHint) node; @@ -1017,7 +1017,7 @@ public abstract class SqlUtil { relHints.add(relHint); } } - return ImmutableList.copyOf(relHints); + return relHints.build(); } /** diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java b/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java index 0eae4d6..61b6422 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java @@ -1183,7 +1183,7 @@ public class RelDecorrelator implements ReflectiveVisitor { final RexNode condition = RexUtil.composeConjunction(relBuilder.getRexBuilder(), conditions); RelNode newJoin = relBuilder.push(leftFrame.r).push(rightFrame.r) - .join(rel.getJoinType(), condition, ImmutableSet.of()).build(); + .join(rel.getJoinType(), condition).build(); return register(rel, newJoin, mapOldToNewOutputs, corDefOutputs); } @@ -1220,12 +1220,12 @@ public class RelDecorrelator implements ReflectiveVisitor { RelNode newJoin = relBuilder .push(leftFrame.r) .push(rightFrame.r) - .join(rel.getJoinType(), decorrelateExpr(currentRel, map, cm, rel.getCondition()), + .join(rel.getJoinType(), + decorrelateExpr(currentRel, map, cm, rel.getCondition()), ImmutableSet.of()) + .hints(rel.getHints()) .build(); - newJoin = RelOptUtil.copyRelHints(rel, newJoin); - // Create the mapping between the output of the old correlation rel // and the new join rel Map<Integer, Integer> mapOldToNewOutputs = new HashMap<>(); @@ -2299,8 +2299,7 @@ public class RelDecorrelator implements ReflectiveVisitor { "nullIndicator"))); Join join = - (Join) relBuilder.push(left).push(right) - .join(joinType, joinCond, ImmutableSet.of()).build(); + (Join) relBuilder.push(left).push(right).join(joinType, joinCond).build(); // To the consumer of joinOutputProjRel, nullIndicator is located // at the end 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 5436a26..4bf07b1 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java @@ -434,12 +434,12 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor { } public void rewriteRel(LogicalJoin rel) { - LogicalJoin newRel = + final LogicalJoin newRel = LogicalJoin.create(getNewForOldRel(rel.getLeft()), getNewForOldRel(rel.getRight()), + rel.getHints(), rel.getCondition().accept(new RewriteRexShuttle()), rel.getVariablesSet(), rel.getJoinType()); - newRel = (LogicalJoin) RelOptUtil.copyRelHints(rel, newRel); setNewForOldRel(rel, newRel); } @@ -508,10 +508,10 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor { RelNode newInput = getNewForOldRel(rel.getInput()); List<RexNode> newProjects = Pair.left(flattenedExpList); List<String> newNames = Pair.right(flattenedExpList); - RelNode newRel = relBuilder.push(newInput) + final RelNode newRel = relBuilder.push(newInput) .projectNamed(newProjects, newNames, true) + .hints(rel.getHints()) .build(); - newRel = RelOptUtil.copyRelHints(rel, newRel); setNewForOldRel(rel, newRel); } 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 e22cb50..8ed2017 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java @@ -767,8 +767,8 @@ public class SqlToRelConverter { } } rel = - LogicalProject.create(rel, Pair.left(newProjects), - Pair.right(newProjects)); + LogicalProject.create(rel, ImmutableList.of(), + Pair.left(newProjects), Pair.right(newProjects)); bb.root = rel; distinctify(bb, false); rel = bb.root; @@ -787,8 +787,8 @@ public class SqlToRelConverter { } rel = - LogicalProject.create(rel, Pair.left(undoProjects), - Pair.right(undoProjects)); + LogicalProject.create(rel, ImmutableList.of(), + Pair.left(undoProjects), Pair.right(undoProjects)); bb.setRoot( rel, false); @@ -863,7 +863,9 @@ public class SqlToRelConverter { exprs.add(rexBuilder.makeInputRef(bb.root, i)); } bb.setRoot( - LogicalProject.create(bb.root, exprs, + LogicalProject.create(bb.root, + ImmutableList.of(), + exprs, rowType.getFieldNames().subList(0, fieldCount)), false); } @@ -1166,7 +1168,10 @@ public class SqlToRelConverter { final int keyCount = leftKeys.size(); final List<Integer> args = ImmutableIntList.range(0, keyCount); LogicalAggregate aggregate = - LogicalAggregate.create(seek, ImmutableBitSet.of(), null, + LogicalAggregate.create(seek, + ImmutableList.of(), + ImmutableBitSet.of(), + null, ImmutableList.of( AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, false, ImmutableList.of(), -1, RelCollations.EMPTY, @@ -1174,8 +1179,8 @@ public class SqlToRelConverter { AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, false, args, -1, RelCollations.EMPTY, longType, null))); LogicalJoin join = - LogicalJoin.create(bb.root, aggregate, rexBuilder.makeLiteral(true), - ImmutableSet.of(), JoinRelType.INNER); + LogicalJoin.create(bb.root, aggregate, ImmutableList.of(), + rexBuilder.makeLiteral(true), ImmutableSet.of(), JoinRelType.INNER); bb.setRoot(join, false); } final RexNode rex = @@ -2397,12 +2402,15 @@ public class SqlToRelConverter { table = table.extend(extendedFields); } final RelNode tableRel; - final List<RelHint> hints = SqlUtil.getRelHint(hintStrategies, tableHints); + // Review Danny 2020-01-13: hacky to construct a new table scan + // in order to apply the hint strategies. + final List<RelHint> hints = hintStrategies.apply( + SqlUtil.getRelHint(hintStrategies, tableHints), + LogicalTableScan.create(cluster, table, ImmutableList.of())); if (config.isConvertTableAccess()) { tableRel = toRel(table, hints); } else { - tableRel = SqlUtil.attachRelHint(hintStrategies, - hints, LogicalTableScan.create(cluster, table)); + tableRel = LogicalTableScan.create(cluster, table, hints); } bb.setRoot(tableRel, true); if (usedDataset[0]) { @@ -2564,7 +2572,7 @@ public class SqlToRelConverter { final Join originalJoin = (Join) RelFactories.DEFAULT_JOIN_FACTORY.createJoin(leftRel, rightRel, - joinCond, ImmutableSet.of(), joinType, false); + ImmutableList.of(), joinCond, ImmutableSet.of(), joinType, false); RelNode node = RelOptUtil.pushDownJoinConditions(originalJoin, relBuilder); // If join conditions are pushed down, update the leaves. @@ -3059,7 +3067,7 @@ public class SqlToRelConverter { */ protected RelNode createAggregate(Blackboard bb, ImmutableBitSet groupSet, ImmutableList<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { - return LogicalAggregate.create(bb.root, groupSet, groupSets, aggCalls); + return LogicalAggregate.create(bb.root, ImmutableList.of(), groupSet, groupSets, aggCalls); } public RexDynamicParam convertDynamicParam( @@ -3382,10 +3390,7 @@ public class SqlToRelConverter { } public RelNode toRel(final RelOptTable table, @Nonnull final List<RelHint> hints) { - final RelNode rel = table.toRel(createToRelContext(hints)); - final RelNode scan = rel instanceof Hintable && hints.size() > 0 - ? SqlUtil.attachRelHint(hintStrategies, hints, (Hintable) rel) - : rel; + final RelNode scan = table.toRel(createToRelContext(hints)); final InitializerExpressionFactory ief = Util.first(table.unwrap(InitializerExpressionFactory.class), @@ -3965,6 +3970,7 @@ public class SqlToRelConverter { RelFactories.DEFAULT_JOIN_FACTORY.createJoin( ret, relNode, + ImmutableList.of(), rexBuilder.makeLiteral(true), ImmutableSet.of(), JoinRelType.INNER, diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java index f31d892..7b240e6 100644 --- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java +++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java @@ -53,6 +53,8 @@ import org.apache.calcite.rel.core.TableScan; import org.apache.calcite.rel.core.TableSpool; import org.apache.calcite.rel.core.Union; import org.apache.calcite.rel.core.Values; +import org.apache.calcite.rel.hint.Hintable; +import org.apache.calcite.rel.hint.RelHint; import org.apache.calcite.rel.logical.LogicalFilter; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.metadata.RelColumnMapping; @@ -1071,7 +1073,7 @@ public class RelBuilder { if (relOptTable == null) { throw RESOURCE.tableNotFound(String.join(".", names)).ex(); } - final RelNode scan = scanFactory.createScan(cluster, relOptTable); + final RelNode scan = scanFactory.createScan(cluster, relOptTable, ImmutableList.of()); push(scan); rename(relOptTable.getRowType().getFieldNames()); @@ -1254,6 +1256,34 @@ public class RelBuilder { return project(nodes, fieldNames, false); } + /** Creates a {@link Project} of the given list + * of expressions, using the given names. + * + * <p>Names are deduced as follows: + * <ul> + * <li>If the length of {@code fieldNames} is greater than the index of + * the current entry in {@code nodes}, and the entry in + * {@code fieldNames} is not null, uses it; otherwise + * <li>If an expression projects an input field, + * or is a cast an input field, + * uses the input field name; otherwise + * <li>If an expression is a call to + * {@link SqlStdOperatorTable#AS} + * (see {@link #alias}), removes the call but uses the intended alias. + * </ul> + * + * <p>After the field names have been inferred, makes the + * field names unique by appending numeric suffixes. + * + * @param nodes Expressions + * @param fieldNames Suggested field names + * @param force create project even if it is identity + */ + public RelBuilder project(Iterable<? extends RexNode> nodes, + Iterable<String> fieldNames, boolean force) { + return project_(nodes, fieldNames, ImmutableList.of(), force); + } + /** Creates a {@link Project} of all original fields, plus the given * expressions. */ public RelBuilder projectPlus(RexNode... nodes) { @@ -1319,11 +1349,13 @@ public class RelBuilder { * * @param nodes Expressions * @param fieldNames Suggested field names + * @param hints Hints * @param force create project even if it is identity */ - public RelBuilder project( + private RelBuilder project_( Iterable<? extends RexNode> nodes, Iterable<String> fieldNames, + Iterable<RelHint> hints, boolean force) { final Frame frame = stack.peek(); final RelDataType inputRowType = frame.rel.getRowType(); @@ -1379,7 +1411,10 @@ public class RelBuilder { } } stack.push(new Frame(project.getInput(), ImmutableList.copyOf(fields))); - return project(newNodes, fieldNameList, force); + final ImmutableSet.Builder<RelHint> mergedHints = ImmutableSet.builder(); + mergedHints.addAll(project.getHints()); + mergedHints.addAll(hints); + return project_(newNodes, fieldNameList, mergedHints.build(), force); } // Simplify expressions. @@ -1439,12 +1474,15 @@ public class RelBuilder { } else { // create "virtual" row type for project only rename fields stack.pop(); + // Ignore the hints. stack.push(new Frame(frame.rel, fields.build())); - return this; } + return this; } final RelNode project = - projectFactory.createProject(frame.rel, ImmutableList.copyOf(nodeList), + projectFactory.createProject(frame.rel, + ImmutableList.copyOf(hints), + ImmutableList.copyOf(nodeList), fieldNameList); stack.pop(); stack.push(new Frame(project, fields.build())); @@ -1497,7 +1535,7 @@ public class RelBuilder { final Project childProject = (Project) frame.rel; final Project newInput = childProject.copy(childProject.getTraitSet(), childProject.getInput(), childProject.getProjects(), rowType); - stack.push(new Frame(newInput, frame.fields)); + stack.push(new Frame(newInput.attachHints(childProject.getHints()), frame.fields)); } } else { project(nodeList, rowType.getFieldNames(), force); @@ -1590,7 +1628,7 @@ public class RelBuilder { .collect(Collectors.toList())); } - /** Creates an {@link Aggregate} with a list of + /** Creates an {@link Aggregate} with multiple * calls. */ public RelBuilder aggregate(GroupKey groupKey, Iterable<AggCall> aggCalls) { final Registrar registrar = @@ -1736,7 +1774,7 @@ public class RelBuilder { List<AggregateCall> aggregateCalls, List<RexNode> extraNodes, ImmutableList<Field> inFields) { final RelNode aggregate = aggregateFactory.createAggregate(input, - groupSet, groupSets, aggregateCalls); + ImmutableList.of(), groupSet, groupSets, aggregateCalls); // build field list final ImmutableList.Builder<Field> fields = ImmutableList.builder(); @@ -1878,7 +1916,7 @@ public class RelBuilder { rowType, transientTable, ImmutableList.of(tableName)); - RelNode scan = scanFactory.createScan(cluster, relOptTable); + RelNode scan = scanFactory.createScan(cluster, relOptTable, ImmutableList.of()); push(scan); rename(rowType.getFieldNames()); return this; @@ -1973,7 +2011,7 @@ public class RelBuilder { } } - /** Creates a {@link Join}. */ + /** Creates a {@link Join} with an array of conditions. */ public RelBuilder join(JoinRelType joinType, RexNode condition0, RexNode... conditions) { return join(joinType, Lists.asList(condition0, conditions)); @@ -1987,12 +2025,12 @@ public class RelBuilder { ImmutableSet.of()); } + /** Creates a {@link Join} with one condition. */ public RelBuilder join(JoinRelType joinType, RexNode condition) { return join(joinType, condition, ImmutableSet.of()); } - /** Creates a {@link Join} with correlating - * variables. */ + /** Creates a {@link Join} with correlating variables. */ public RelBuilder join(JoinRelType joinType, RexNode condition, Set<CorrelationId> variablesSet) { Frame right = stack.pop(); @@ -2032,7 +2070,7 @@ public class RelBuilder { join = correlateFactory.createCorrelate(left.rel, right.rel, id, requiredColumns, joinType); } else { - join = joinFactory.createJoin(left.rel, right.rel, condition, + join = joinFactory.createJoin(left.rel, right.rel, ImmutableList.of(), condition, variablesSet, joinType, false); } final ImmutableList.Builder<Field> fields = ImmutableList.builder(); @@ -2118,8 +2156,13 @@ public class RelBuilder { public RelBuilder semiJoin(Iterable<? extends RexNode> conditions) { final Frame right = stack.pop(); final RelNode semiJoin = - joinFactory.createJoin(peek(), right.rel, - and(conditions), ImmutableSet.of(), JoinRelType.SEMI, false); + joinFactory.createJoin(peek(), + right.rel, + ImmutableList.of(), + and(conditions), + ImmutableSet.of(), + JoinRelType.SEMI, + false); replaceTop(semiJoin); return this; } @@ -2150,8 +2193,13 @@ public class RelBuilder { public RelBuilder antiJoin(Iterable<? extends RexNode> conditions) { final Frame right = stack.pop(); final RelNode antiJoin = - joinFactory.createJoin(peek(), right.rel, - and(conditions), ImmutableSet.of(), JoinRelType.ANTI, false); + joinFactory.createJoin(peek(), + right.rel, + ImmutableList.of(), + and(conditions), + ImmutableSet.of(), + JoinRelType.ANTI, + false); replaceTop(antiJoin); return this; } @@ -2431,6 +2479,7 @@ public class RelBuilder { offsetNode, fetchNode); replaceTop( projectFactory.createProject(sort, + project.getHints(), project.getProjects(), Pair.right(project.getNamedProjects()))); return this; @@ -2556,6 +2605,40 @@ public class RelBuilder { return this; } + /** + * Attaches an array of hints to the stack top relational expression. + * + * <p>The redundant hints would be eliminated. + * + * @param hints Hints + * + * @throws AssertionError if the top relational expression does not implement + * {@link org.apache.calcite.rel.hint.Hintable} + */ + public RelBuilder hints(RelHint... hints) { + return hints(ImmutableList.copyOf(hints)); + } + + /** + * Attaches multiple hints to the stack top relational expression. + * + * <p>The redundant hints would be eliminated. + * + * @param hints Hints + * + * @throws AssertionError if the top relational expression does not implement + * {@link org.apache.calcite.rel.hint.Hintable} + */ + public RelBuilder hints(Iterable<RelHint> hints) { + Objects.requireNonNull(hints); + final Frame frame = peek_(); + assert frame != null : "There is no relational expression to attach the hints"; + assert frame.rel instanceof Hintable : "The top relational expression is not a Hintable"; + Hintable hintable = (Hintable) frame.rel; + replaceTop(hintable.attachHints(ImmutableList.copyOf(hints))); + return this; + } + /** Clears the stack. * * <p>The builder's state is now the same as when it was created. */ diff --git a/core/src/test/java/org/apache/calcite/plan/RelOptUtilTest.java b/core/src/test/java/org/apache/calcite/plan/RelOptUtilTest.java index bd49d78..e4dd6d0 100644 --- a/core/src/test/java/org/apache/calcite/plan/RelOptUtilTest.java +++ b/core/src/test/java/org/apache/calcite/plan/RelOptUtilTest.java @@ -610,6 +610,7 @@ public class RelOptUtilTest { .DEFAULT_PROJECT_FACTORY .createProject( agg, + ImmutableList.of(), ImmutableList.of( RexInputRef.of(0, agg.getRowType()), RexInputRef.of(1, agg.getRowType()), @@ -632,6 +633,7 @@ public class RelOptUtilTest { .DEFAULT_PROJECT_FACTORY .createProject( agg, + ImmutableList.of(), ImmutableList.of( RexInputRef.of(0, agg.getRowType()), RexInputRef.of(1, agg.getRowType()), diff --git a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java index f0362f4..1714f2e 100644 --- a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java +++ b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java @@ -362,7 +362,8 @@ public class RelWriterTest { LogicalTableScan scan = LogicalTableScan.create(cluster, relOptSchema.getTableForMember( - Arrays.asList("hr", "emps"))); + Arrays.asList("hr", "emps")), + ImmutableList.of()); final RexBuilder rexBuilder = cluster.getRexBuilder(); LogicalFilter filter = LogicalFilter.create(scan, @@ -376,7 +377,10 @@ public class RelWriterTest { final RelDataType bigIntType = cluster.getTypeFactory().createSqlType(SqlTypeName.BIGINT); LogicalAggregate aggregate = - LogicalAggregate.create(filter, ImmutableBitSet.of(0), null, + LogicalAggregate.create(filter, + ImmutableList.of(), + ImmutableBitSet.of(0), + null, ImmutableList.of( AggregateCall.create(SqlStdOperatorTable.COUNT, true, false, false, ImmutableList.of(1), -1, @@ -403,12 +407,14 @@ public class RelWriterTest { LogicalTableScan scan = LogicalTableScan.create(cluster, relOptSchema.getTableForMember( - Arrays.asList("hr", "emps"))); + Arrays.asList("hr", "emps")), + ImmutableList.of()); final RexBuilder rexBuilder = cluster.getRexBuilder(); final RelDataType bigIntType = cluster.getTypeFactory().createSqlType(SqlTypeName.BIGINT); LogicalProject project = LogicalProject.create(scan, + ImmutableList.of(), ImmutableList.of( rexBuilder.makeInputRef(scan, 0), rexBuilder.makeOver(bigIntType, diff --git a/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java b/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java index 5394cd0..bb3918c 100644 --- a/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java +++ b/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java @@ -153,10 +153,11 @@ public class TraitPropagationTest { } }; - final RelNode rt1 = LogicalTableScan.create(cluster, t1); + final RelNode rt1 = LogicalTableScan.create(cluster, t1, ImmutableList.of()); // project s column RelNode project = LogicalProject.create(rt1, + ImmutableList.of(), ImmutableList.of( (RexNode) rexBuilder.makeInputRef(stringType, 0), rexBuilder.makeInputRef(integerType, 1)), diff --git a/core/src/test/java/org/apache/calcite/test/Matchers.java b/core/src/test/java/org/apache/calcite/test/Matchers.java index d22024c..2acd22a 100644 --- a/core/src/test/java/org/apache/calcite/test/Matchers.java +++ b/core/src/test/java/org/apache/calcite/test/Matchers.java @@ -18,6 +18,7 @@ package org.apache.calcite.test; import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.hint.Hintable; import org.apache.calcite.util.TestUtil; import org.apache.calcite.util.Util; @@ -205,6 +206,17 @@ public class Matchers { } /** + * Creates a Matcher that matches a {@link RelNode} if its hints string + * representation is equal to the given {@code value}. + */ + public static Matcher<RelNode> hasHints(final String value) { + return compose(Is.is(value), + input -> input instanceof Hintable + ? ((Hintable) input).getHints().toString() + : "[]"); + } + + /** * Creates a {@link Matcher} that matches execution plan and trims {@code , id=123} node ids. * {@link RelNode#getId()} is not stable across runs, so this matcher enables to trim those. * @param value execpted execution plan diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java index e5468dc..471152e 100644 --- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java @@ -33,6 +33,7 @@ import org.apache.calcite.rel.core.RelFactories; import org.apache.calcite.rel.core.TableFunctionScan; import org.apache.calcite.rel.core.TableModify; import org.apache.calcite.rel.core.Window; +import org.apache.calcite.rel.hint.RelHint; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeField; @@ -83,6 +84,7 @@ import java.util.TreeSet; import java.util.function.Function; import javax.annotation.Nonnull; +import static org.apache.calcite.test.Matchers.hasHints; import static org.apache.calcite.test.Matchers.hasTree; import static org.hamcrest.CoreMatchers.allOf; @@ -3051,4 +3053,91 @@ public class RelBuilderTest { + " LogicalTableScan(table=[[scott, DEPT]])\n"; assertThat(root, hasTree(expected)); } + + @Test public void testHints() { + final RelHint indexHint = RelHint.of(Collections.emptyList(), + "INDEX", + Arrays.asList("_idx1", "_idx2")); + final RelHint propsHint = RelHint.of(Collections.singletonList(0), + "PROPERTIES", + ImmutableMap.of("parallelism", "3", "mem", "20Mb")); + final RelHint noHashJoinHint = RelHint.of(Collections.singletonList(0), + "NO_HASH_JOIN"); + final RelBuilder builder = RelBuilder.create(config().build()); + // Equivalent SQL: + // SELECT * + // FROM emp /*+ INDEX(_idx1, _idx2) */ + final RelNode root = builder + .scan("EMP") + .hints(indexHint) + .build(); + assertThat(root, + hasHints("[[INDEX inheritPath:[] options:[_idx1, _idx2]]]")); + // Equivalent SQL: + // SELECT /*+ PROPERTIES(parallelism='3', mem='20Mb') */ + // * + // FROM emp /*+ INDEX(_idx1, _idx2) */ + final RelNode root1 = builder + .scan("EMP") + .hints(indexHint, propsHint) + .build(); + assertThat(root1, + hasHints("[[INDEX inheritPath:[] options:[_idx1, _idx2]], " + + "[PROPERTIES inheritPath:[0] options:{parallelism=3, mem=20Mb}]]")); + // Equivalent SQL: + // SELECT /*+ NO_HASH_JOIN */ + // * + // FROM emp + // join dept + // on emp.deptno = dept.deptno + final RelNode root2 = builder + .scan("EMP") + .scan("DEPT") + .join(JoinRelType.INNER, + builder.equals( + builder.field(2, 0, "DEPTNO"), + builder.field(2, 1, "DEPTNO"))) + .hints(noHashJoinHint) + .build(); + assertThat(root2, hasHints("[[NO_HASH_JOIN inheritPath:[0]]]")); + } + + @Test public void testHintsOnEmptyStack() { + final RelHint indexHint = RelHint.of(Collections.emptyList(), + "INDEX", + Arrays.asList("_idx1", "_idx2")); + // Attach hints on empty stack. + final AssertionError error = assertThrows( + AssertionError.class, + () -> RelBuilder.create(config().build()).hints(indexHint), + "hints() should fail on empty stack"); + assertThat(error.getMessage(), + containsString("There is no relational expression to attach the hints")); + } + + @Test public void testHintsOnNonHintable() { + final RelHint indexHint = RelHint.of(Collections.emptyList(), + "INDEX", + Arrays.asList("_idx1", "_idx2")); + // Attach hints on non hintable. + final AssertionError error1 = assertThrows( + AssertionError.class, + () -> { + final RelBuilder builder = RelBuilder.create(config().build()); + // Equivalent SQL: + // SELECT * + // FROM emp + // WHERE EMPNO = 124 + builder + .scan("EMP") + .filter( + builder.equals( + builder.field("EMPNO"), + builder.literal(124))) + .hints(indexHint); + }, + "hints() should fail on non Hintable relational expression"); + assertThat(error1.getMessage(), + containsString("The top relational expression is not a Hintable")); + } } diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java index 29ecb5d..2b84ae2 100644 --- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java @@ -1468,7 +1468,7 @@ public class RelMetadataTest extends SqlToRelTestBase { private void checkCollation(RelOptCluster cluster, RelOptTable empTable, RelOptTable deptTable) { final RexBuilder rexBuilder = cluster.getRexBuilder(); - final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable); + final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable, ImmutableList.of()); List<RelCollation> collations = RelMdCollation.table(empScan.getTable()); @@ -1500,11 +1500,13 @@ public class RelMetadataTest extends SqlToRelTestBase { assertThat(collations.get(0).getFieldCollations().get(1).getFieldIndex(), equalTo(0)); - final LogicalProject project = LogicalProject.create(empSort, projects, + final LogicalProject project = LogicalProject.create(empSort, + ImmutableList.of(), + projects, ImmutableList.of("a", "b", "c", "d")); final LogicalTableScan deptScan = - LogicalTableScan.create(cluster, deptTable); + LogicalTableScan.create(cluster, deptTable, ImmutableList.of()); final RelCollation deptCollation = RelCollations.of(new RelFieldCollation(0), new RelFieldCollation(1)); @@ -1653,7 +1655,7 @@ public class RelMetadataTest extends SqlToRelTestBase { RelOptTable deptTable) { final RexBuilder rexBuilder = cluster.getRexBuilder(); final RelMetadataQuery mq = cluster.getMetadataQuery(); - final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable); + final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable, ImmutableList.of()); Double rowSize = mq.getAverageRowSize(empScan); List<Double> columnSizes = mq.getAverageColumnSizes(empScan); @@ -1708,7 +1710,7 @@ public class RelMetadataTest extends SqlToRelTestBase { // Filter final LogicalTableScan deptScan = - LogicalTableScan.create(cluster, deptTable); + LogicalTableScan.create(cluster, deptTable, ImmutableList.of()); final LogicalFilter filter = LogicalFilter.create(deptScan, rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, @@ -1723,6 +1725,7 @@ public class RelMetadataTest extends SqlToRelTestBase { // Project final LogicalProject deptProject = LogicalProject.create(filter, + ImmutableList.of(), ImmutableList.of( rexBuilder.makeInputRef(filter, 0), rexBuilder.makeInputRef(filter, 1), @@ -1740,8 +1743,8 @@ public class RelMetadataTest extends SqlToRelTestBase { // Join final LogicalJoin join = - LogicalJoin.create(empScan, deptProject, rexBuilder.makeLiteral(true), - ImmutableSet.of(), JoinRelType.INNER); + LogicalJoin.create(empScan, deptProject, ImmutableList.of(), + rexBuilder.makeLiteral(true), ImmutableSet.of(), JoinRelType.INNER); rowSize = mq.getAverageRowSize(join); columnSizes = mq.getAverageColumnSizes(join); assertThat(columnSizes.size(), equalTo(13)); @@ -1753,7 +1756,9 @@ public class RelMetadataTest extends SqlToRelTestBase { // Aggregate final LogicalAggregate aggregate = - LogicalAggregate.create(join, ImmutableBitSet.of(2, 0), + LogicalAggregate.create(join, + ImmutableList.of(), + ImmutableBitSet.of(2, 0), ImmutableList.of(), ImmutableList.of( AggregateCall.create(SqlStdOperatorTable.COUNT, @@ -1793,7 +1798,8 @@ public class RelMetadataTest extends SqlToRelTestBase { final RelBuilder relBuilder = RelBuilder.proto().create(cluster, null); final RelMetadataQuery mq = cluster.getMetadataQuery(); - final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable); + final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable, + ImmutableList.of()); relBuilder.push(empScan); RelOptPredicateList predicates = @@ -1809,7 +1815,7 @@ public class RelMetadataTest extends SqlToRelTestBase { assertThat(predicates.pulledUpPredicates, sortsAs("[=($0, 1)]")); final LogicalTableScan deptScan = - LogicalTableScan.create(cluster, deptTable); + LogicalTableScan.create(cluster, deptTable, ImmutableList.of()); relBuilder.push(deptScan); relBuilder.semiJoin( @@ -2396,7 +2402,8 @@ public class RelMetadataTest extends SqlToRelTestBase { final RelBuilder relBuilder = RelBuilder.proto().create(cluster, null); final RelMetadataQuery mq = cluster.getMetadataQuery(); - final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable); + final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable, + ImmutableList.of()); relBuilder.push(empScan); RelOptPredicateList predicates = @@ -2417,7 +2424,7 @@ public class RelMetadataTest extends SqlToRelTestBase { assertThat(inputRef1.getIndex(), is(0)); final LogicalTableScan deptScan = - LogicalTableScan.create(cluster, deptTable); + LogicalTableScan.create(cluster, deptTable, ImmutableList.of()); relBuilder.push(deptScan); relBuilder.join(JoinRelType.INNER, @@ -2602,8 +2609,8 @@ public class RelMetadataTest extends SqlToRelTestBase { final RexBuilder rexBuilder = node.getCluster().getRexBuilder(); // Join final LogicalJoin join = - LogicalJoin.create(nodeWithUnknown, node, rexBuilder.makeLiteral(true), - ImmutableSet.of(), JoinRelType.INNER); + LogicalJoin.create(nodeWithUnknown, node, ImmutableList.of(), + rexBuilder.makeLiteral(true), ImmutableSet.of(), JoinRelType.INNER); final RelMetadataQuery mq = node.getCluster().getMetadataQuery(); final Set<RelTableRef> tableReferences = mq.getTableReferences(join); assertNull(tableReferences); diff --git a/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java index 48801d3..e94a271 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java @@ -90,6 +90,7 @@ import static org.hamcrest.collection.IsIn.in; import static org.hamcrest.core.Is.is; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; /** * Unit test for {@link org.apache.calcite.rel.hint.RelHint}. @@ -477,10 +478,11 @@ public class SqlHintsConverterTest extends SqlToRelTestBase { assertThat(1, is(join.getHints().size())); call.transformTo( LogicalJoin.create(join.getLeft(), - join.getRight(), - join.getCondition(), - join.getVariablesSet(), - join.getJoinType())); + join.getRight(), + ImmutableList.of(), + join.getCondition(), + join.getVariablesSet(), + join.getJoinType())); } } @@ -599,6 +601,7 @@ public class SqlHintsConverterTest extends SqlToRelTestBase { void fails(String failedMsg) { try { tester.convertSqlToRel(sql); + fail("Unexpected exception"); } catch (AssertionError e) { assertThat(e.getMessage(), is(failedMsg)); } diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java b/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java index edf6735..c79019c 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java +++ b/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java @@ -411,7 +411,8 @@ public abstract class SqlToRelTestBase { } public RelNode toRel(ToRelContext context) { - return LogicalTableScan.create(context.getCluster(), this); + return LogicalTableScan.create(context.getCluster(), this, + context.getTableHints()); } public List<RelCollation> getCollationList() { @@ -493,7 +494,8 @@ public abstract class SqlToRelTestBase { } public RelNode toRel(ToRelContext context) { - return LogicalTableScan.create(context.getCluster(), this); + return LogicalTableScan.create(context.getCluster(), this, + context.getTableHints()); } public List<RelCollation> getCollationList() { diff --git a/core/src/test/java/org/apache/calcite/test/catalog/MockCatalogReader.java b/core/src/test/java/org/apache/calcite/test/catalog/MockCatalogReader.java index 05b9b19..fcad4d1 100644 --- a/core/src/test/java/org/apache/calcite/test/catalog/MockCatalogReader.java +++ b/core/src/test/java/org/apache/calcite/test/catalog/MockCatalogReader.java @@ -493,7 +493,7 @@ public abstract class MockCatalogReader extends CalciteCatalogReader { } public RelNode toRel(ToRelContext context) { - return LogicalTableScan.create(context.getCluster(), this); + return LogicalTableScan.create(context.getCluster(), this, context.getTableHints()); } public List<RelCollation> getCollationList() { @@ -864,7 +864,8 @@ public abstract class MockCatalogReader extends CalciteCatalogReader { } @Override public RelNode toRel(ToRelContext context) { - RelNode rel = LogicalTableScan.create(context.getCluster(), fromTable); + RelNode rel = LogicalTableScan.create(context.getCluster(), fromTable, + context.getTableHints()); final RexBuilder rexBuilder = context.getCluster().getRexBuilder(); rel = LogicalFilter.create( rel, getConstraint(rexBuilder, rel.getRowType())); @@ -880,7 +881,9 @@ public abstract class MockCatalogReader extends CalciteCatalogReader { return mapping.size(); } }; - return LogicalProject.create(rel, Pair.left(projects), + return LogicalProject.create(rel, + ImmutableList.of(), + Pair.left(projects), Pair.right(projects)); } @@ -919,7 +922,7 @@ public abstract class MockCatalogReader extends CalciteCatalogReader { } @Override public RelNode toRel(RelOptTable.ToRelContext context, RelOptTable relOptTable) { - return LogicalTableScan.create(context.getCluster(), relOptTable); + return LogicalTableScan.create(context.getCluster(), relOptTable, context.getTableHints()); } } diff --git a/core/src/test/resources/org/apache/calcite/test/SqlHintsConverterTest.xml b/core/src/test/resources/org/apache/calcite/test/SqlHintsConverterTest.xml index 04f247d..d9eb8ef 100644 --- a/core/src/test/resources/org/apache/calcite/test/SqlHintsConverterTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/SqlHintsConverterTest.xml @@ -23,7 +23,7 @@ from (select /*+ resource(mem='20Mb')*/ empno, ename from emp)]]> </Resource> <Resource name="hints"> <![CDATA[ -Project:[[RESOURCE inheritPath:[] options:{PARALLELISM=3}], [REPARTITION inheritPath:[] options:[10]]] +Project:[[RESOURCE inheritPath:[] options:{MEM=20Mb}], [RESOURCE inheritPath:[] options:{PARALLELISM=3}], [REPARTITION inheritPath:[] options:[10]]] ]]> </Resource> </TestCase> @@ -165,7 +165,7 @@ from emp left join dept on emp.deptno = dept.deptno)]]> </Resource> <Resource name="hints"> <![CDATA[ -Project:[[RESOURCE inheritPath:[] options:{PARALLELISM=3}], [NO_HASH_JOIN inheritPath:[]]] +Project:[[RESOURCE inheritPath:[] options:{MEM=20Mb}], [RESOURCE inheritPath:[] options:{PARALLELISM=3}], [NO_HASH_JOIN inheritPath:[]]] LogicalJoin:[[NO_HASH_JOIN inheritPath:[0]]] ]]> </Resource> diff --git a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidTable.java b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidTable.java index e7ef4b0..9c9f43c 100644 --- a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidTable.java +++ b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidTable.java @@ -242,7 +242,7 @@ public class DruidTable extends AbstractTable implements TranslatableTable { public RelNode toRel(RelOptTable.ToRelContext context, RelOptTable relOptTable) { final RelOptCluster cluster = context.getCluster(); - final TableScan scan = LogicalTableScan.create(cluster, relOptTable); + final TableScan scan = LogicalTableScan.create(cluster, relOptTable, ImmutableList.of()); return DruidQuery.create(cluster, cluster.traitSetOf(BindableConvention.INSTANCE), relOptTable, this, ImmutableList.of(scan)); diff --git a/pig/src/main/java/org/apache/calcite/adapter/pig/PigRelFactories.java b/pig/src/main/java/org/apache/calcite/adapter/pig/PigRelFactories.java index e1c3050..6cccb6a 100644 --- a/pig/src/main/java/org/apache/calcite/adapter/pig/PigRelFactories.java +++ b/pig/src/main/java/org/apache/calcite/adapter/pig/PigRelFactories.java @@ -26,8 +26,10 @@ import org.apache.calcite.rel.core.AggregateCall; import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.core.RelFactories; +import org.apache.calcite.rel.hint.RelHint; import org.apache.calcite.rex.RexNode; import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.Util; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -58,7 +60,9 @@ public class PigRelFactories { public static final PigTableScanFactory INSTANCE = new PigTableScanFactory(); - @Override public RelNode createScan(RelOptCluster cluster, RelOptTable table) { + @Override public RelNode createScan(RelOptCluster cluster, + RelOptTable table, List<RelHint> hints) { + Util.discard(hints); return new PigTableScan(cluster, cluster.traitSetOf(PigRel.CONVENTION), table); } } @@ -92,8 +96,10 @@ public class PigRelFactories { public static final PigAggregateFactory INSTANCE = new PigAggregateFactory(); @Override public RelNode createAggregate(RelNode input, + List<RelHint> hints, ImmutableBitSet groupSet, ImmutableList<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { + Util.discard(hints); return new PigAggregate(input.getCluster(), input.getTraitSet(), input, groupSet, groupSets, aggCalls); } @@ -108,8 +114,12 @@ public class PigRelFactories { public static final PigJoinFactory INSTANCE = new PigJoinFactory(); - @Override public RelNode createJoin(RelNode left, RelNode right, RexNode condition, - Set<CorrelationId> variablesSet, JoinRelType joinType, boolean semiJoinDone) { + @Override public RelNode createJoin(RelNode left, RelNode right, List<RelHint> hints, + RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType, + boolean semiJoinDone) { + Util.discard(hints); + Util.discard(variablesSet); + Util.discard(semiJoinDone); return new PigJoin(left.getCluster(), left.getTraitSet(), left, right, condition, joinType); } diff --git a/piglet/src/main/java/org/apache/calcite/piglet/PigRelBuilder.java b/piglet/src/main/java/org/apache/calcite/piglet/PigRelBuilder.java index e85d5b3..96150af 100644 --- a/piglet/src/main/java/org/apache/calcite/piglet/PigRelBuilder.java +++ b/piglet/src/main/java/org/apache/calcite/piglet/PigRelBuilder.java @@ -78,7 +78,7 @@ public class PigRelBuilder extends RelBuilder { /** Creates a PigRelBuilder. */ public static PigRelBuilder create(FrameworkConfig config) { final RelBuilder relBuilder = RelBuilder.create(config); - Hook.REL_BUILDER_SIMPLIFY.add(Hook.propertyJ(false)); + Hook.REL_BUILDER_SIMPLIFY.addThread(Hook.propertyJ(false)); return new PigRelBuilder(config.getContext(), relBuilder.getCluster(), relBuilder.getRelOptSchema()); } @@ -253,7 +253,7 @@ public class PigRelBuilder extends RelBuilder { * @return This builder */ private RelBuilder scan(RelOptTable tableSchema) { - final RelNode scan = getScanFactory().createScan(cluster, tableSchema); + final RelNode scan = getScanFactory().createScan(cluster, tableSchema, ImmutableList.of()); push(scan); return this; } diff --git a/site/_docs/history.md b/site/_docs/history.md index b24c767..cc842df 100644 --- a/site/_docs/history.md +++ b/site/_docs/history.md @@ -33,6 +33,7 @@ Downloads are available on the #### Breaking Changes * Constructors for `Project`, `TableScan`, `Calc`, `Aggregate` and `Join` introduce new parameter named "hints"; +* Logical `RelNode`'s `create` method need to pass in hints explicitly; * `Project` names will not represent in `RelNode` digest anymore; * `RexCall`s are default to be normalized in the `RelNode` digest. diff --git a/splunk/src/main/java/org/apache/calcite/adapter/splunk/SplunkPushDownRule.java b/splunk/src/main/java/org/apache/calcite/adapter/splunk/SplunkPushDownRule.java index 2163d8e..10ca4f8 100644 --- a/splunk/src/main/java/org/apache/calcite/adapter/splunk/SplunkPushDownRule.java +++ b/splunk/src/main/java/org/apache/calcite/adapter/splunk/SplunkPushDownRule.java @@ -228,7 +228,7 @@ public class SplunkPushDownRule // handle top projection (ie reordering and renaming) List<RelDataTypeField> newFields = bottomFields; if (topProj != null) { - LOGGER.debug("topProj: {}", String.valueOf(topProj.getPermutation())); + LOGGER.debug("topProj: {}", topProj.getPermutation()); newFields = new ArrayList<>(); int i = 0; for (RexNode rn : topProj.getProjects()) { @@ -279,7 +279,8 @@ public class SplunkPushDownRule if (proj == null) { return rel; } - return LogicalProject.create(rel, proj.getProjects(), proj.getRowType()); + return LogicalProject.create(rel, proj.getHints(), + proj.getProjects(), proj.getRowType()); } // TODO: use StringBuilder instead of String