From 617c084bcfe6d7665012ba751bd4d8fe6cd8f017 Mon Sep 17 00:00:00 2001 From: Mihai Budiu Date: Wed, 10 Apr 2024 10:55:33 -0700 Subject: [PATCH] [CALCITE-6071] RexCall should carry source position information for runtime error reporting Signed-off-by: Mihai Budiu --- .../adapter/enumerable/RexImpTable.java | 2 +- .../org/apache/calcite/plan/RelOptUtil.java | 4 +- .../calcite/plan/SubstitutionVisitor.java | 15 +- .../calcite/rel/core/AggregateCall.java | 78 ++++--- .../org/apache/calcite/rel/core/Window.java | 2 +- .../rel/externalize/RelJsonReader.java | 3 +- .../calcite/rel/rel2sql/SqlImplementor.java | 2 +- .../rel/rules/AggregateCaseToFilterRule.java | 11 +- ...AggregateExpandDistinctAggregatesRule.java | 20 +- .../AggregateExpandWithinDistinctRule.java | 9 +- .../rules/AggregateFilterTransposeRule.java | 3 +- .../rules/AggregateReduceFunctionsRule.java | 120 +++++----- .../rel/rules/AggregateRemoveRule.java | 5 +- .../rel/rules/AggregateStarTableRule.java | 4 +- .../rules/AggregateUnionTransposeRule.java | 2 +- .../rel/rules/ProjectAggregateMergeRule.java | 2 +- .../calcite/rel/rules/ReduceDecimalsRule.java | 187 ++++++++------- .../MaterializedViewAggregateRule.java | 6 +- .../materialize/MaterializedViewJoinRule.java | 2 + .../org/apache/calcite/rex/RexBuilder.java | 157 +++++++++++-- .../java/org/apache/calcite/rex/RexCall.java | 26 ++- .../org/apache/calcite/rex/RexCopier.java | 2 +- .../org/apache/calcite/rex/RexSimplify.java | 60 ++--- .../java/org/apache/calcite/rex/RexUtil.java | 42 ++-- .../org/apache/calcite/runtime/Resources.java | 2 - .../schema/impl/ModifiableViewTable.java | 5 +- .../calcite/sql/SqlSplittableAggFunction.java | 23 +- .../apache/calcite/sql2rel/AggConverter.java | 1 + .../calcite/sql2rel/RelDecorrelator.java | 1 + .../sql2rel/RelStructuredTypeFlattener.java | 8 +- .../calcite/sql2rel/SqlToRelConverter.java | 54 +++-- .../sql2rel/StandardConvertletTable.java | 220 ++++++++++-------- .../org/apache/calcite/tools/RelBuilder.java | 143 ++++++------ .../calcite/examples/RelBuilderExample.java | 3 +- .../NormalizationTrimFieldTest.java | 2 +- .../apache/calcite/plan/RelWriterTest.java | 4 +- .../plan/volcano/TraitPropagationTest.java | 3 +- .../rel/rel2sql/RelToSqlConverterTest.java | 13 +- .../apache/calcite/rex/RexBuilderTest.java | 7 +- .../calcite/rex/RexProgramBuilderBase.java | 19 +- .../apache/calcite/test/RelBuilderTest.java | 40 ++-- .../apache/calcite/test/RelMetadataTest.java | 3 +- .../calcite/test/fuzzer/RexShrinker.java | 2 +- .../calcite/piglet/PigToSqlAggregateRule.java | 7 +- .../calcite/adapter/tpcds/TpcdsTest.java | 9 +- 45 files changed, 800 insertions(+), 533 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java index 7a323ee9ee90..3977ecba6f14 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java @@ -4486,7 +4486,7 @@ private static class QuantifyCollectionImplementor extends AbstractRexCallImplem final ParameterExpression lambdaArg = Expressions.parameter(translator.typeFactory.getJavaClass(rightComponentType), "el"); final RexCall binaryImplementorRexCall = - (RexCall) translator.builder.makeCall(binaryOperator, leftRex, + (RexCall) translator.builder.makeCall(call.getParserPosition(), binaryOperator, leftRex, translator.builder.makeDynamicParam(rightComponentType, 0)); final List binaryImplementorArgs = ImmutableList.of( 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 5387acd8cf83..c07923a274e9 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java @@ -89,6 +89,7 @@ import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.MultisetSqlType; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.tools.RelBuilder; @@ -980,7 +981,8 @@ public static RelNode createSingleValueAggRel( for (int i = 0; i < aggCallCnt; i++) { aggCalls.add( - AggregateCall.create(SqlStdOperatorTable.SINGLE_VALUE, false, false, + AggregateCall.create( + SqlParserPos.ZERO, SqlStdOperatorTable.SINGLE_VALUE, false, false, false, ImmutableList.of(), ImmutableList.of(i), -1, null, RelCollations.EMPTY, 0, rel, null, null)); } diff --git a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java index 206830532102..8b0aacab87b5 100644 --- a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java +++ b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java @@ -341,7 +341,7 @@ private static RexNode canonizeNode(RexBuilder rexBuilder, RexNode condition) { if (newOperands.size() < 2) { return newOperands.values().iterator().next(); } - return rexBuilder.makeCall(call.getOperator(), + return rexBuilder.makeCall(call.getParserPosition(), call.getOperator(), ImmutableList.copyOf(newOperands.values())); } case EQUALS: @@ -353,7 +353,8 @@ private static RexNode canonizeNode(RexBuilder rexBuilder, RexNode condition) { RexCall call = (RexCall) condition; RexNode left = canonizeNode(rexBuilder, call.getOperands().get(0)); RexNode right = canonizeNode(rexBuilder, call.getOperands().get(1)); - call = (RexCall) rexBuilder.makeCall(call.getOperator(), left, right); + call = + (RexCall) rexBuilder.makeCall(call.getParserPosition(), call.getOperator(), left, right); if (left.toString().compareTo(right.toString()) <= 0) { return call; @@ -375,10 +376,11 @@ private static RexNode canonizeNode(RexBuilder rexBuilder, RexNode condition) { RexNode right = canonizeNode(rexBuilder, call.getOperands().get(1)); if (left.toString().compareTo(right.toString()) <= 0) { - return rexBuilder.makeCall(call.getOperator(), left, right); + return rexBuilder.makeCall(call.getParserPosition(), call.getOperator(), left, right); } - RexNode newCall = rexBuilder.makeCall(call.getOperator(), right, left); + RexNode newCall = + rexBuilder.makeCall(call.getParserPosition(), call.getOperator(), right, left); // new call should not be used if its inferred type is not same as old if (!newCall.getType().equals(call.getType())) { return call; @@ -1979,7 +1981,8 @@ public static MutableAggregate permute(MutableAggregate aggregate, final SqlAggFunction aggFunction = aggregateCall.getAggregation().getRollup(); if (aggFunction != null) { newAggCall = - AggregateCall.create(aggFunction, aggregateCall.isDistinct(), + AggregateCall.create(aggregateCall.getParserPosition(), + aggFunction, aggregateCall.isDistinct(), aggregateCall.isApproximate(), aggregateCall.ignoreNulls(), aggregateCall.rexList, ImmutableList.of(target.groupSet.cardinality() + i), -1, @@ -2049,7 +2052,7 @@ public static MutableAggregate permute(MutableAggregate aggregate, if (!isAllowBuild) { return null; } - return AggregateCall.create(aggregation, + return AggregateCall.create(queryAggCall.getParserPosition(), aggregation, queryAggCall.isDistinct(), queryAggCall.isApproximate(), queryAggCall.ignoreNulls(), queryAggCall.rexList, newArgList, -1, queryAggCall.distinctKeys, diff --git a/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java b/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java index aa6ea524ac5f..a8230cba5456 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java +++ b/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java @@ -26,6 +26,7 @@ import org.apache.calcite.rex.RexUtil; import org.apache.calcite.sql.SqlAggFunction; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeUtil; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.Optionality; @@ -50,6 +51,14 @@ public class AggregateCall { //~ Instance fields -------------------------------------------------------- + /** + * Some aggregate calls may produce runtime errors. For these + * we need to keep around the original source position information + * so that the runtime can produce error messages pointing to + * the offending source operation. For "safe" aggregations + * this field may be ZERO. + */ + private final SqlParserPos pos; private final SqlAggFunction aggFunction; private final boolean distinct; @@ -84,7 +93,7 @@ public AggregateCall( List argList, RelDataType type, String name) { - this(aggFunction, distinct, false, false, + this(SqlParserPos.ZERO, aggFunction, distinct, false, false, ImmutableList.of(), argList, -1, null, RelCollations.EMPTY, type, name); } @@ -92,6 +101,9 @@ public AggregateCall( /** * Creates an AggregateCall. * + * @param pos Source position for this aggregate. + * Ideally it should only be ZERO when the aggregate + * can never fail at runtime. * @param aggFunction Aggregate function * @param distinct Whether distinct * @param approximate Whether approximate @@ -106,11 +118,12 @@ public AggregateCall( * @param type Result type * @param name Name (may be null) */ - private AggregateCall(SqlAggFunction aggFunction, boolean distinct, + private AggregateCall(SqlParserPos pos, SqlAggFunction aggFunction, boolean distinct, boolean approximate, boolean ignoreNulls, List rexList, List argList, int filterArg, @Nullable ImmutableBitSet distinctKeys, RelCollation collation, RelDataType type, @Nullable String name) { + this.pos = pos; this.type = requireNonNull(type, "type"); this.name = name; this.aggFunction = requireNonNull(aggFunction, "aggFunction"); @@ -134,7 +147,7 @@ private AggregateCall(SqlAggFunction aggFunction, boolean distinct, public static AggregateCall create(SqlAggFunction aggFunction, boolean distinct, List argList, int groupCount, RelNode input, @Nullable RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, false, false, + return create(SqlParserPos.ZERO, aggFunction, distinct, false, false, ImmutableList.of(), argList, -1, null, RelCollations.EMPTY, groupCount, input, type, name); } @@ -143,7 +156,7 @@ public static AggregateCall create(SqlAggFunction aggFunction, public static AggregateCall create(SqlAggFunction aggFunction, boolean distinct, List argList, int filterArg, int groupCount, RelNode input, @Nullable RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, false, false, + return create(SqlParserPos.ZERO, aggFunction, distinct, false, false, ImmutableList.of(), argList, filterArg, null, RelCollations.EMPTY, groupCount, input, type, name); } @@ -153,7 +166,7 @@ public static AggregateCall create(SqlAggFunction aggFunction, boolean distinct, boolean approximate, List argList, int filterArg, int groupCount, RelNode input, @Nullable RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, approximate, false, + return create(SqlParserPos.ZERO, aggFunction, distinct, approximate, false, ImmutableList.of(), argList, filterArg, null, RelCollations.EMPTY, groupCount, input, type, name); } @@ -163,7 +176,7 @@ public static AggregateCall create(SqlAggFunction aggFunction, boolean distinct, boolean approximate, List argList, int filterArg, RelCollation collation, int groupCount, RelNode input, @Nullable RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, approximate, false, + return create(SqlParserPos.ZERO, aggFunction, distinct, approximate, false, ImmutableList.of(), argList, filterArg, null, collation, groupCount, input, type, name); } @@ -175,13 +188,13 @@ public static AggregateCall create(SqlAggFunction aggFunction, @Nullable ImmutableBitSet distinctKeys, RelCollation collation, int groupCount, RelNode input, @Nullable RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, approximate, ignoreNulls, + return create(SqlParserPos.ZERO, aggFunction, distinct, approximate, ignoreNulls, ImmutableList.of(), argList, filterArg, distinctKeys, collation, groupCount, input, type, name); } /** Creates an AggregateCall, inferring its type if {@code type} is null. */ - public static AggregateCall create(SqlAggFunction aggFunction, + public static AggregateCall create(SqlParserPos pos, SqlAggFunction aggFunction, boolean distinct, boolean approximate, boolean ignoreNulls, List rexList, List argList, int filterArg, @Nullable ImmutableBitSet distinctKeys, RelCollation collation, @@ -198,7 +211,7 @@ public static AggregateCall create(SqlAggFunction aggFunction, types, groupCount, filterArg >= 0); type = aggFunction.inferReturnType(callBinding); } - return create(aggFunction, distinct, approximate, ignoreNulls, + return create(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -206,7 +219,7 @@ public static AggregateCall create(SqlAggFunction aggFunction, public static AggregateCall create(SqlAggFunction aggFunction, boolean distinct, List argList, int filterArg, RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, false, false, + return create(SqlParserPos.ZERO, aggFunction, distinct, false, false, ImmutableList.of(), argList, filterArg, null, RelCollations.EMPTY, type, name); } @@ -215,7 +228,7 @@ public static AggregateCall create(SqlAggFunction aggFunction, public static AggregateCall create(SqlAggFunction aggFunction, boolean distinct, boolean approximate, List argList, int filterArg, RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, approximate, false, + return create(SqlParserPos.ZERO, aggFunction, distinct, approximate, false, ImmutableList.of(), argList, filterArg, null, RelCollations.EMPTY, type, name); } @@ -224,7 +237,7 @@ public static AggregateCall create(SqlAggFunction aggFunction, public static AggregateCall create(SqlAggFunction aggFunction, boolean distinct, boolean approximate, List argList, int filterArg, RelCollation collation, RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, approximate, false, + return create(SqlParserPos.ZERO, aggFunction, distinct, approximate, false, ImmutableList.of(), argList, filterArg, null, collation, type, name); } @@ -234,20 +247,19 @@ public static AggregateCall create(SqlAggFunction aggFunction, boolean distinct, boolean approximate, boolean ignoreNulls, List argList, int filterArg, RelCollation collation, RelDataType type, @Nullable String name) { - return create(aggFunction, distinct, approximate, ignoreNulls, + return create(SqlParserPos.ZERO, aggFunction, distinct, approximate, ignoreNulls, ImmutableList.of(), argList, filterArg, null, collation, type, name); } - /** Creates an AggregateCall. */ - public static AggregateCall create(SqlAggFunction aggFunction, + public static AggregateCall create(SqlParserPos pos, SqlAggFunction aggFunction, boolean distinct, boolean approximate, boolean ignoreNulls, List rexList, List argList, int filterArg, @Nullable ImmutableBitSet distinctKeys, RelCollation collation, RelDataType type, @Nullable String name) { final boolean distinct2 = distinct && (aggFunction.getDistinctOptionality() != Optionality.IGNORED); - return new AggregateCall(aggFunction, distinct2, approximate, ignoreNulls, + return new AggregateCall(pos, aggFunction, distinct2, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -264,7 +276,7 @@ public final boolean isDistinct() { /** Withs {@link #isDistinct()}. */ public AggregateCall withDistinct(boolean distinct) { return distinct == this.distinct ? this - : new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + : new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -281,7 +293,7 @@ public final boolean isApproximate() { /** Withs {@link #isApproximate()}. */ public AggregateCall withApproximate(boolean approximate) { return approximate == this.approximate ? this - : new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + : new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -297,7 +309,7 @@ public final boolean ignoreNulls() { /** Withs {@link #ignoreNulls()}. */ public AggregateCall withIgnoreNulls(boolean ignoreNulls) { return ignoreNulls == this.ignoreNulls ? this - : new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + : new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -323,7 +335,7 @@ public RelCollation getCollation() { /** Withs {@link #getCollation()}. */ public AggregateCall withCollation(RelCollation collation) { return collation.equals(this.collation) ? this - : new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + : new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -341,7 +353,7 @@ public final List getArgList() { /** Withs {@link #getArgList()}. */ public AggregateCall withArgList(List argList) { return argList.equals(this.argList) ? this - : new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + : new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -349,7 +361,7 @@ public AggregateCall withArgList(List argList) { public AggregateCall withDistinctKeys( @Nullable ImmutableBitSet distinctKeys) { return Objects.equals(distinctKeys, this.distinctKeys) ? this - : new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + : new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -374,7 +386,7 @@ public final RelDataType getType() { /** Withs {@link #name}. */ public AggregateCall withName(@Nullable String name) { return Objects.equals(name, this.name) ? this - : new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + : new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -435,11 +447,16 @@ public boolean hasFilter() { /** Withs {@link #filterArg}. */ public AggregateCall withFilter(int filterArg) { return filterArg == this.filterArg ? this - : new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + : new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } + public SqlParserPos getParserPosition() { + return this.pos; + } + @Override public boolean equals(@Nullable Object o) { + // Intentionally ignore the position return o == this || o instanceof AggregateCall && aggFunction.equals(((AggregateCall) o).aggFunction) @@ -453,6 +470,7 @@ public AggregateCall withFilter(int filterArg) { } @Override public int hashCode() { + // Ignore the position! return Objects.hash(aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation); } @@ -492,7 +510,7 @@ public Aggregate.AggCallBinding createBinding( @Deprecated // to be removed before 2.0 public AggregateCall copy(List argList, int filterArg, @Nullable ImmutableBitSet distinctKeys, RelCollation collation) { - return new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + return new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -500,21 +518,21 @@ public AggregateCall copy(List argList, int filterArg, public AggregateCall copy(List argList, int filterArg, RelCollation collation) { // ignoring distinctKeys is error-prone - return new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + return new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @Deprecated // to be removed before 2.0 public AggregateCall copy(List argList, int filterArg) { // ignoring distinctKeys, collation is error-prone - return new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + return new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @Deprecated // to be removed before 2.0 public AggregateCall copy(List argList) { // ignoring filterArg, distinctKeys, collation is error-prone - return new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + return new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, type, name); } @@ -539,7 +557,7 @@ public AggregateCall adaptTo(RelNode input, List argList, && filterArg == this.filterArg ? type : null; - return create(aggFunction, distinct, approximate, ignoreNulls, + return create(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, argList, filterArg, distinctKeys, collation, newGroupKeyCount, input, newType, getName()); } @@ -547,7 +565,7 @@ public AggregateCall adaptTo(RelNode input, List argList, /** Creates a copy of this aggregate call, applying a mapping to its * arguments. */ public AggregateCall transform(Mappings.TargetMapping mapping) { - return new AggregateCall(aggFunction, distinct, approximate, ignoreNulls, + return new AggregateCall(pos, aggFunction, distinct, approximate, ignoreNulls, rexList, Mappings.apply2((Mapping) mapping, argList), hasFilter() ? Mappings.apply(mapping, filterArg) : -1, distinctKeys == null ? null : distinctKeys.permute(mapping), diff --git a/core/src/main/java/org/apache/calcite/rel/core/Window.java b/core/src/main/java/org/apache/calcite/rel/core/Window.java index 4f76256930e6..ce907643e23c 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/Window.java +++ b/core/src/main/java/org/apache/calcite/rel/core/Window.java @@ -377,7 +377,7 @@ public List getAggregateCalls(Window windowRel) { @Override public AggregateCall get(int index) { final RexWinAggCall aggCall = aggCalls.get(index); final SqlAggFunction op = (SqlAggFunction) aggCall.getOperator(); - return AggregateCall.create(op, aggCall.distinct, false, + return AggregateCall.create(aggCall.getParserPosition(), op, aggCall.distinct, false, aggCall.ignoreNulls, ImmutableList.of(), getProjectOrdinals(aggCall.getOperands()), -1, null, RelCollations.EMPTY, 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 61a86d9b5fb4..321364c5c689 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 @@ -34,6 +34,7 @@ import org.apache.calcite.runtime.SqlFunctions; import org.apache.calcite.schema.Schema; import org.apache.calcite.sql.SqlAggFunction; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; @@ -344,7 +345,7 @@ private AggregateCall toAggCall(Map jsonAggCall) { final RelDataType type = relJson.toType(cluster.getTypeFactory(), jsonAggType); final String name = (String) jsonAggCall.get("name"); - return AggregateCall.create(aggregation, distinct, false, false, + return AggregateCall.create(SqlParserPos.ZERO, aggregation, distinct, false, false, ImmutableList.of(), operands, filterOperand == null ? -1 : filterOperand, null, RelCollations.EMPTY, type, name); diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java index 242b526f8902..5d65d1ea0f41 100644 --- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java +++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java @@ -1648,7 +1648,7 @@ private JoinContext(SqlDialect dialect, Context leftContext, && ((RexInputRef) op0).getIndex() >= leftContext.fieldCount) { // Arguments were of form 'op1 = op0' final SqlOperator op2 = requireNonNull(call.getOperator().reverse()); - return (RexCall) rexBuilder.makeCall(op2, op1, op0); + return (RexCall) rexBuilder.makeCall(call.getParserPosition(), op2, op1, op0); } // fall through default: diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateCaseToFilterRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateCaseToFilterRule.java index 303b2d2c78a4..5922d0503291 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateCaseToFilterRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateCaseToFilterRule.java @@ -32,6 +32,7 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlPostfixOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilderFactory; @@ -186,7 +187,8 @@ && isThreeArgCase(project.getProjects().get(singleArg))) { && RexLiteral.isNullLiteral(arg2)) { newProjects.add(arg1); newProjects.add(filter); - return AggregateCall.create(SqlStdOperatorTable.COUNT, true, false, + return AggregateCall.create( + call.getParserPosition(), SqlStdOperatorTable.COUNT, true, false, false, call.rexList, ImmutableList.of(newProjects.size() - 2), newProjects.size() - 1, null, RelCollations.EMPTY, call.getType(), call.getName()); @@ -205,12 +207,13 @@ && isThreeArgCase(project.getProjects().get(singleArg))) { // C: COUNT(CASE WHEN x = 'foo' THEN 'dummy' END) // => COUNT() FILTER (x = 'foo') + final SqlParserPos pos = call.getParserPosition(); if (kind == SqlKind.COUNT // Case C && arg1.isA(SqlKind.LITERAL) && !RexLiteral.isNullLiteral(arg1) && RexLiteral.isNullLiteral(arg2)) { newProjects.add(filter); - return AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, + return AggregateCall.create(pos, SqlStdOperatorTable.COUNT, false, false, false, call.rexList, ImmutableList.of(), newProjects.size() - 1, null, RelCollations.EMPTY, call.getType(), call.getName()); @@ -223,7 +226,7 @@ && isIntLiteral(arg2, BigDecimal.ZERO)) { final RelDataType dataType = typeFactory.createTypeWithNullability( typeFactory.createSqlType(SqlTypeName.BIGINT), false); - return AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, + return AggregateCall.create(pos, SqlStdOperatorTable.COUNT, false, false, false, call.rexList, ImmutableList.of(), newProjects.size() - 1, null, RelCollations.EMPTY, dataType, call.getName()); } else if ((RexLiteral.isNullLiteral(arg2) // Case A1 @@ -232,7 +235,7 @@ && isIntLiteral(arg2, BigDecimal.ZERO)) { && isIntLiteral(arg2, BigDecimal.ZERO))) { newProjects.add(arg1); newProjects.add(filter); - return AggregateCall.create(call.getAggregation(), false, + return AggregateCall.create(pos, call.getAggregation(), false, false, false, call.rexList, ImmutableList.of(newProjects.size() - 2), newProjects.size() - 1, null, RelCollations.EMPTY, call.getType(), call.getName()); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandDistinctAggregatesRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandDistinctAggregatesRule.java index 56e224572c1b..33b6ed6aea46 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandDistinctAggregatesRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandDistinctAggregatesRule.java @@ -35,6 +35,7 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.fun.SqlSumEmptyIsZeroAggFunction; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilderFactory; import org.apache.calcite.util.ImmutableBitSet; @@ -331,7 +332,7 @@ private static RelBuilder convertSingletonDistinct(RelBuilder relBuilder, // as-is all the non-distinct aggregates if (!aggCall.isDistinct()) { final AggregateCall newCall = - AggregateCall.create(aggCall.getAggregation(), false, + AggregateCall.create(aggCall.getParserPosition(), aggCall.getAggregation(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), aggCall.rexList, aggCall.getArgList(), -1, aggCall.distinctKeys, aggCall.collation, bottomGroupSet.cardinality(), @@ -357,7 +358,8 @@ private static RelBuilder convertSingletonDistinct(RelBuilder relBuilder, newArgList.add(bottomGroups.headSet(arg, false).size()); } newCall = - AggregateCall.create(aggCall.getAggregation(), + AggregateCall.create(aggCall.getParserPosition(), + aggCall.getAggregation(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), @@ -377,14 +379,16 @@ private static RelBuilder convertSingletonDistinct(RelBuilder relBuilder, final List newArgs = ImmutableList.of(arg); if (aggCall.getAggregation().getKind() == SqlKind.COUNT) { newCall = - AggregateCall.create(new SqlSumEmptyIsZeroAggFunction(), false, + AggregateCall.create(aggCall.getParserPosition(), + new SqlSumEmptyIsZeroAggFunction(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), aggCall.rexList, newArgs, -1, aggCall.distinctKeys, aggCall.collation, originalGroupSet.cardinality(), relBuilder.peek(), null, aggCall.getName()); } else { newCall = - AggregateCall.create(aggCall.getAggregation(), false, + AggregateCall.create(aggCall.getParserPosition(), + aggCall.getAggregation(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), aggCall.rexList, newArgs, -1, aggCall.distinctKeys, aggCall.collation, originalGroupSet.cardinality(), @@ -480,7 +484,7 @@ private static void rewriteUsingGroupingSets(RelOptRuleCall call, } distinctAggCalls.add( - AggregateCall.create(SqlStdOperatorTable.GROUPING, false, false, false, + AggregateCall.create(SqlParserPos.ZERO, SqlStdOperatorTable.GROUPING, false, false, false, ImmutableList.of(), ImmutableIntList.copyOf(fullGroupSet), -1, null, RelCollations.EMPTY, groupSets.size(), relBuilder.peek(), null, "$g")); @@ -537,7 +541,7 @@ private static void rewriteUsingGroupingSets(RelOptRuleCall call, "filters.get(of(newGroupSet, aggCall.filterArg))"); } final AggregateCall newCall = - AggregateCall.create(aggregation, false, + AggregateCall.create(aggCall.getParserPosition(), aggregation, false, aggCall.isApproximate(), aggCall.ignoreNulls(), aggCall.rexList, newArgList, newFilterArg, aggCall.distinctKeys, aggCall.collation, @@ -752,7 +756,7 @@ private static void doRewrite(RelBuilder relBuilder, Aggregate aggregate, int n, newArgs.add(requireNonNull(sourceOf.get(arg), () -> "sourceOf.get(" + arg + ")")); } final AggregateCall newAggCall = - AggregateCall.create(aggCall.getAggregation(), false, + AggregateCall.create(aggCall.getParserPosition(), aggCall.getAggregation(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), aggCall.rexList, newArgs, -1, aggCall.distinctKeys, aggCall.collation, aggCall.getType(), aggCall.getName()); @@ -840,7 +844,7 @@ private static void rewriteAggCalls( () -> "sourceOf.get(" + arg + ")")); } final AggregateCall newAggCall = - AggregateCall.create(aggCall.getAggregation(), false, + AggregateCall.create(aggCall.getParserPosition(), aggCall.getAggregation(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), aggCall.rexList, newArgs, -1, aggCall.distinctKeys, aggCall.collation, diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java index cf5aafca48d1..81be1114c77b 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java @@ -26,6 +26,7 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.fun.SqlInternalOperators; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.ImmutableIntList; @@ -346,7 +347,7 @@ int getCount(int filterArg) { Ord.forEach(aggCallList, (c, i) -> { if (c.distinctKeys == null) { RelBuilder.AggCall aggCall = - b.aggregateCall(c.getAggregation(), b.fields(c.getArgList())); + b.aggregateCall(c.getParserPosition(), c.getAggregation(), b.fields(c.getArgList())); registrar.registerAgg(i, c.hasFilter() ? aggCall.filter(b.field(c.filterArg)) @@ -367,7 +368,7 @@ int getCount(int filterArg) { final int grouping = hasMultipleGroupSets ? registrar.registerAgg(-1, - b.aggregateCall( + b.aggregateCall(SqlParserPos.ZERO, SqlStdOperatorTable.GROUPING, b.fields(fullGroupList))) : -1; @@ -410,7 +411,7 @@ int getCount(int filterArg) { RelBuilder.AggCall aggCall; if (c.distinctKeys == null) { aggCall = - b.aggregateCall(SqlStdOperatorTable.MIN, + b.aggregateCall(c.getParserPosition(), SqlStdOperatorTable.MIN, b.field(registrar.getAgg(i))); } else { // The inputs to this aggregate are outputs from MIN() calls from the @@ -422,7 +423,7 @@ int getCount(int filterArg) { // ignore null inputs, we add a filter based on a COUNT() in the inner // aggregate. aggCall = - b.aggregateCall(c.getAggregation(), + b.aggregateCall(c.getParserPosition(), c.getAggregation(), b.fields(registrar.fields(c.getArgList(), c.filterArg))); if (mustBeCounted(c)) { diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java index 43524a2900e1..105e4096dc5e 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterTransposeRule.java @@ -145,7 +145,8 @@ public AggregateFilterTransposeRule(RelOptRuleOperand operand, return; } topAggCallList.add( - AggregateCall.create(rollup, aggregateCall.isDistinct(), + AggregateCall.create(aggregateCall.getParserPosition(), + rollup, aggregateCall.isDistinct(), aggregateCall.isApproximate(), aggregateCall.ignoreNulls(), aggregateCall.rexList, ImmutableList.of(i++), -1, aggregateCall.distinctKeys, aggregateCall.collation, diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java index ec09c77c47c8..cc61a34c4e28 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java @@ -34,6 +34,7 @@ import org.apache.calcite.sql.SqlAggFunction; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilderFactory; import org.apache.calcite.util.CompositeList; @@ -373,7 +374,8 @@ private static AggregateCall createAggregateCallWithBinding( new Aggregate.AggCallBinding(typeFactory, aggFunction, ImmutableList.of(), ImmutableList.of(operandType), oldAggRel.getGroupCount(), filter >= 0); - return AggregateCall.create(aggFunction, + return AggregateCall.create(oldCall.getParserPosition(), + aggFunction, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), @@ -394,8 +396,9 @@ private static RexNode reduceAvg( @SuppressWarnings("unused") List inputExprs) { final int nGroups = oldAggRel.getGroupCount(); final RexBuilder rexBuilder = oldAggRel.getCluster().getRexBuilder(); + final SqlParserPos pos = oldCall.getParserPosition(); final AggregateCall sumCall = - AggregateCall.create(SqlStdOperatorTable.SUM, + AggregateCall.create(pos, SqlStdOperatorTable.SUM, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), @@ -409,7 +412,7 @@ private static RexNode reduceAvg( null, null); final AggregateCall countCall = - AggregateCall.create(SqlStdOperatorTable.COUNT, + AggregateCall.create(pos, SqlStdOperatorTable.COUNT, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), @@ -442,10 +445,10 @@ private static RexNode reduceAvg( final RelDataType avgType = typeFactory.createTypeWithNullability(oldCall.getType(), numeratorRef.getType().isNullable()); - numeratorRef = rexBuilder.ensureType(avgType, numeratorRef, true); + numeratorRef = rexBuilder.ensureType(pos, avgType, numeratorRef, true); final RexNode divideRef = - rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, numeratorRef, denominatorRef); - return rexBuilder.makeCast(oldCall.getType(), divideRef); + rexBuilder.makeCall(pos, SqlStdOperatorTable.DIVIDE, numeratorRef, denominatorRef); + return rexBuilder.makeCast(pos, oldCall.getType(), divideRef); } private static RexNode reduceSum( @@ -454,16 +457,17 @@ private static RexNode reduceSum( List newCalls, Map aggCallMapping) { final int nGroups = oldAggRel.getGroupCount(); + final SqlParserPos pos = oldCall.getParserPosition(); RexBuilder rexBuilder = oldAggRel.getCluster().getRexBuilder(); final AggregateCall sumZeroCall = - AggregateCall.create(SqlStdOperatorTable.SUM0, oldCall.isDistinct(), + AggregateCall.create(pos, SqlStdOperatorTable.SUM0, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), oldCall.rexList, oldCall.getArgList(), oldCall.filterArg, oldCall.distinctKeys, oldCall.collation, oldAggRel.getGroupCount(), oldAggRel.getInput(), null, oldCall.name); final AggregateCall countCall = - AggregateCall.create(SqlStdOperatorTable.COUNT, + AggregateCall.create(pos, SqlStdOperatorTable.COUNT, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), @@ -497,8 +501,8 @@ private static RexNode reduceSum( newCalls, aggCallMapping, oldAggRel.getInput()::fieldIsNullable); - return rexBuilder.makeCall(SqlStdOperatorTable.CASE, - rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, + return rexBuilder.makeCall(pos, SqlStdOperatorTable.CASE, + rexBuilder.makeCall(pos, SqlStdOperatorTable.EQUALS, countRef, rexBuilder.makeExactLiteral(BigDecimal.ZERO)), rexBuilder.makeNullLiteral(sumZeroRef.getType()), sumZeroRef); @@ -527,6 +531,7 @@ private static RexNode reduceStddev( final RelOptCluster cluster = oldAggRel.getCluster(); final RexBuilder rexBuilder = cluster.getRexBuilder(); final RelDataTypeFactory typeFactory = cluster.getTypeFactory(); + final SqlParserPos pos = oldCall.getParserPosition(); assert oldCall.getArgList().size() == 1 : oldCall.getArgList(); final int argOrdinal = oldCall.getArgList().get(0); @@ -536,10 +541,10 @@ private static RexNode reduceStddev( fieldIsNullable.test(argOrdinal)); final RexNode argRef = - rexBuilder.ensureType(oldCallType, inputExprs.get(argOrdinal), true); + rexBuilder.ensureType(pos, oldCallType, inputExprs.get(argOrdinal), true); final RexNode argSquared = - rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, argRef, argRef); + rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, argRef, argRef); final int argSquaredOrdinal = lookupOrAdd(inputExprs, argSquared); final AggregateCall sumArgSquaredAggCall = @@ -554,7 +559,7 @@ private static RexNode reduceStddev( oldAggRel.getInput()::fieldIsNullable); final AggregateCall sumArgAggCall = - AggregateCall.create(SqlStdOperatorTable.SUM, + AggregateCall.create(pos, SqlStdOperatorTable.SUM, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), @@ -574,13 +579,13 @@ private static RexNode reduceStddev( newCalls, aggCallMapping, oldAggRel.getInput()::fieldIsNullable); - final RexNode sumArgCast = rexBuilder.ensureType(oldCallType, sumArg, true); + final RexNode sumArgCast = rexBuilder.ensureType(pos, oldCallType, sumArg, true); final RexNode sumSquaredArg = - rexBuilder.makeCall( + rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, sumArgCast, sumArgCast); final AggregateCall countArgAggCall = - AggregateCall.create(SqlStdOperatorTable.COUNT, + AggregateCall.create(pos, SqlStdOperatorTable.COUNT, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), @@ -602,20 +607,20 @@ private static RexNode reduceStddev( oldAggRel.getInput()::fieldIsNullable); final RexNode div = - divide(biased, rexBuilder, sumArgSquared, sumSquaredArg, countArg); + divide(pos, biased, rexBuilder, sumArgSquared, sumSquaredArg, countArg); final RexNode result; if (sqrt) { final RexNode half = rexBuilder.makeExactLiteral(new BigDecimal("0.5")); result = - rexBuilder.makeCall( + rexBuilder.makeCall(pos, SqlStdOperatorTable.POWER, div, half); } else { result = div; } - return rexBuilder.makeCast( + return rexBuilder.makeCast(pos, oldCall.getType(), result); } @@ -633,7 +638,7 @@ private static RexNode reduceAggCallByGrouping( if (refByGroup.getType().equals(oldCall.getType())) { return refByGroup; } else { - return rexBuilder.makeCast(oldCall.getType(), refByGroup); + return rexBuilder.makeCast(oldCall.getParserPosition(), oldCall.getType(), refByGroup); } } @@ -645,7 +650,7 @@ private static RexNode getSumAggregatedRexNode(Aggregate oldAggRel, int argOrdinal, int filterArg) { final AggregateCall aggregateCall = - AggregateCall.create(SqlStdOperatorTable.SUM, + AggregateCall.create(oldCall.getParserPosition(), SqlStdOperatorTable.SUM, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), @@ -691,7 +696,8 @@ private static RexNode getRegrCountRexNode(Aggregate oldAggRel, ImmutableIntList argOrdinals, int filterArg) { final AggregateCall countArgAggCall = - AggregateCall.create(SqlStdOperatorTable.REGR_COUNT, + AggregateCall.create(oldCall.getParserPosition(), + SqlStdOperatorTable.REGR_COUNT, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.ignoreNulls(), @@ -725,6 +731,7 @@ private static RexNode reduceRegrSzz( // sum(y * y, x) - sum(y, x) * sum(y, x) / regr_count(x, y) // + final SqlParserPos pos = oldCall.getParserPosition(); final RelOptCluster cluster = oldAggRel.getCluster(); final RexBuilder rexBuilder = cluster.getRexBuilder(); final RelDataTypeFactory typeFactory = cluster.getTypeFactory(); @@ -737,28 +744,28 @@ private static RexNode reduceRegrSzz( || fieldIsNullable.test(nullFilterIndex)); final RexNode argX = - rexBuilder.ensureType(oldCallType, inputExprs.get(xIndex), true); + rexBuilder.ensureType(pos, oldCallType, inputExprs.get(xIndex), true); final RexNode argY = - rexBuilder.ensureType(oldCallType, inputExprs.get(yIndex), true); + rexBuilder.ensureType(pos, oldCallType, inputExprs.get(yIndex), true); final RexNode argNullFilter = - rexBuilder.ensureType(oldCallType, inputExprs.get(nullFilterIndex), true); + rexBuilder.ensureType(pos, oldCallType, inputExprs.get(nullFilterIndex), true); - final RexNode argXArgY = rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, argX, argY); + final RexNode argXArgY = rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, argX, argY); final int argSquaredOrdinal = lookupOrAdd(inputExprs, argXArgY); final RexNode argXAndYNotNullFilter = - rexBuilder.makeCall(SqlStdOperatorTable.AND, - rexBuilder.makeCall(SqlStdOperatorTable.AND, - rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, argX), - rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, argY)), - rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, argNullFilter)); + rexBuilder.makeCall(pos, SqlStdOperatorTable.AND, + rexBuilder.makeCall(pos, SqlStdOperatorTable.AND, + rexBuilder.makeCall(pos, SqlStdOperatorTable.IS_NOT_NULL, argX), + rexBuilder.makeCall(pos, SqlStdOperatorTable.IS_NOT_NULL, argY)), + rexBuilder.makeCall(pos, SqlStdOperatorTable.IS_NOT_NULL, argNullFilter)); final int argXAndYNotNullFilterOrdinal = lookupOrAdd(inputExprs, argXAndYNotNullFilter); final RexNode sumXY = getSumAggregatedRexNodeWithBinding(oldAggRel, oldCall, newCalls, aggCallMapping, argXArgY.getType(), argSquaredOrdinal, argXAndYNotNullFilterOrdinal); - final RexNode sumXYCast = rexBuilder.ensureType(oldCallType, sumXY, true); + final RexNode sumXYCast = rexBuilder.ensureType(pos, oldCallType, sumXY, true); final RexNode sumX = getSumAggregatedRexNode(oldAggRel, oldCall, newCalls, aggCallMapping, @@ -769,7 +776,7 @@ private static RexNode reduceRegrSzz( aggCallMapping, rexBuilder, yIndex, argXAndYNotNullFilterOrdinal); final RexNode sumXSumY = - rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, sumX, sumY); + rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, sumX, sumY); final RexNode countArg = getRegrCountRexNode(oldAggRel, oldCall, newCalls, aggCallMapping, @@ -778,15 +785,15 @@ private static RexNode reduceRegrSzz( RexLiteral zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO); RexNode nul = rexBuilder.makeNullLiteral(zero.getType()); final RexNode avgSumXSumY = - rexBuilder.makeCall(SqlStdOperatorTable.CASE, - rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, countArg, zero), + rexBuilder.makeCall(pos, SqlStdOperatorTable.CASE, + rexBuilder.makeCall(pos, SqlStdOperatorTable.EQUALS, countArg, zero), nul, - rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, sumXSumY, countArg)); + rexBuilder.makeCall(pos, SqlStdOperatorTable.DIVIDE, sumXSumY, countArg)); final RexNode avgSumXSumYCast = - rexBuilder.ensureType(oldCallType, avgSumXSumY, true); + rexBuilder.ensureType(pos, oldCallType, avgSumXSumY, true); final RexNode result = - rexBuilder.makeCall(SqlStdOperatorTable.MINUS, sumXYCast, avgSumXSumYCast); - return rexBuilder.makeCast(oldCall.getType(), result); + rexBuilder.makeCall(pos, SqlStdOperatorTable.MINUS, sumXYCast, avgSumXSumYCast); + return rexBuilder.makeCast(pos, oldCall.getType(), result); } private static RexNode reduceCovariance( @@ -803,6 +810,7 @@ private static RexNode reduceCovariance( // covar_samp(x, y) ==> // (sum(x * y) - sum(x) * sum(y) / regr_count(x, y)) // / regr_count(count(x, y) - 1, 0) + final SqlParserPos pos = oldCall.getParserPosition(); final RelOptCluster cluster = oldAggRel.getCluster(); final RexBuilder rexBuilder = cluster.getRexBuilder(); final RelDataTypeFactory typeFactory = cluster.getTypeFactory(); @@ -814,16 +822,18 @@ private static RexNode reduceCovariance( typeFactory.createTypeWithNullability(oldCall.getType(), fieldIsNullable.test(argXOrdinal) || fieldIsNullable.test(argYOrdinal)); - final RexNode argX = rexBuilder.ensureType(oldCallType, inputExprs.get(argXOrdinal), true); - final RexNode argY = rexBuilder.ensureType(oldCallType, inputExprs.get(argYOrdinal), true); + final RexNode argX = + rexBuilder.ensureType(pos, oldCallType, inputExprs.get(argXOrdinal), true); + final RexNode argY = + rexBuilder.ensureType(pos, oldCallType, inputExprs.get(argYOrdinal), true); final RexNode argXAndYNotNullFilter = - rexBuilder.makeCall(SqlStdOperatorTable.AND, - rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, argX), - rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, argY)); + rexBuilder.makeCall(pos, SqlStdOperatorTable.AND, + rexBuilder.makeCall(pos, SqlStdOperatorTable.IS_NOT_NULL, argX), + rexBuilder.makeCall(pos, SqlStdOperatorTable.IS_NOT_NULL, argY)); final int argXAndYNotNullFilterOrdinal = lookupOrAdd(inputExprs, argXAndYNotNullFilter); final RexNode argXY = - rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, argX, argY); + rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, argX, argY); final int argXYOrdinal = lookupOrAdd(inputExprs, argXY); final RexNode sumXY = getSumAggregatedRexNodeWithBinding(oldAggRel, oldCall, newCalls, @@ -838,22 +848,22 @@ private static RexNode reduceCovariance( aggCallMapping, rexBuilder, argYOrdinal, argXAndYNotNullFilterOrdinal); final RexNode sumXSumY = - rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, sumX, sumY); + rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, sumX, sumY); final RexNode countArg = getRegrCountRexNode(oldAggRel, oldCall, newCalls, aggCallMapping, ImmutableIntList.of(argXOrdinal, argYOrdinal), argXAndYNotNullFilterOrdinal); final RexNode result = - divide(biased, rexBuilder, sumXY, sumXSumY, countArg); - return rexBuilder.makeCast(oldCall.getType(), result); + divide(pos, biased, rexBuilder, sumXY, sumXSumY, countArg); + return rexBuilder.makeCast(pos, oldCall.getType(), result); } - private static RexNode divide(boolean biased, RexBuilder rexBuilder, + private static RexNode divide(SqlParserPos pos, boolean biased, RexBuilder rexBuilder, RexNode sumXY, RexNode sumXSumY, RexNode countArg) { final RexNode avgSumSquaredArg = - rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, sumXSumY, countArg); + rexBuilder.makeCall(pos, SqlStdOperatorTable.DIVIDE, sumXSumY, countArg); final RexNode diff = - rexBuilder.makeCall(SqlStdOperatorTable.MINUS, sumXY, avgSumSquaredArg); + rexBuilder.makeCall(pos, SqlStdOperatorTable.MINUS, sumXY, avgSumSquaredArg); final RexNode denominator; if (biased) { denominator = countArg; @@ -861,14 +871,14 @@ private static RexNode divide(boolean biased, RexBuilder rexBuilder, final RexLiteral one = rexBuilder.makeExactLiteral(BigDecimal.ONE); final RexNode nul = rexBuilder.makeNullLiteral(countArg.getType()); final RexNode countMinusOne = - rexBuilder.makeCall(SqlStdOperatorTable.MINUS, countArg, one); + rexBuilder.makeCall(pos, SqlStdOperatorTable.MINUS, countArg, one); final RexNode countEqOne = - rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, countArg, one); + rexBuilder.makeCall(pos, SqlStdOperatorTable.EQUALS, countArg, one); denominator = - rexBuilder.makeCall(SqlStdOperatorTable.CASE, countEqOne, nul, + rexBuilder.makeCall(pos, SqlStdOperatorTable.CASE, countEqOne, nul, countMinusOne); } - return rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, diff, denominator); + return rexBuilder.makeCall(pos, SqlStdOperatorTable.DIVIDE, diff, denominator); } /** diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java index 64186116bb39..c4d406af2195 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateRemoveRule.java @@ -133,7 +133,7 @@ public static boolean canFlattenStatic(AggregateCall aggregateCall) { aggregate.getGroupSet(), aggregate.groupSets, aggCall); if (constant != null) { final RexNode cast = - rexBuilder.ensureType(aggCall.type, constant, false); + rexBuilder.ensureType(aggCall.getParserPosition(), aggCall.type, constant, false); projects.add(cast); continue; } @@ -143,7 +143,8 @@ public static boolean canFlattenStatic(AggregateCall aggregateCall) { final RexNode singleton = splitter.singleton(rexBuilder, input.getRowType(), aggCall); final RexNode cast = - rexBuilder.ensureType(aggCall.type, singleton, false); + rexBuilder.ensureType( + aggCall.getParserPosition(), aggCall.type, singleton, false); projects.add(cast); } 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 523c00bb8a40..5136937f6e52 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 @@ -214,7 +214,7 @@ protected void apply(RelOptRuleCall call, @Nullable Project postProject, if (roll == null) { break tryRoll; } - return AggregateCall.create(roll, false, call.isApproximate(), + return AggregateCall.create(call.getParserPosition(), roll, false, call.isApproximate(), call.ignoreNulls(), call.rexList, ImmutableList.of(offset + i), -1, call.distinctKeys, call.collation, groupCount, relBuilder.peek(), null, call.name); @@ -231,7 +231,7 @@ protected void apply(RelOptRuleCall call, @Nullable Project postProject, } newArgs.add(z); } - return AggregateCall.create(aggregation, false, + return AggregateCall.create(call.getParserPosition(), aggregation, false, call.isApproximate(), call.ignoreNulls(), call.rexList, newArgs, -1, call.distinctKeys, call.collation, groupCount, relBuilder.peek(), null, call.name); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java index 32df27a641eb..4721d6997ca9 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java @@ -213,7 +213,7 @@ public AggregateUnionTransposeRule(Class aggregateClass, aggType = origCall.getType(); } AggregateCall newCall = - AggregateCall.create(aggFun, origCall.isDistinct(), + AggregateCall.create(ord.e.getParserPosition(), aggFun, origCall.isDistinct(), origCall.isApproximate(), origCall.ignoreNulls(), origCall.rexList, ImmutableList.of(groupCount + ord.i), -1, origCall.distinctKeys, origCall.collation, diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ProjectAggregateMergeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ProjectAggregateMergeRule.java index 3c2f5e404c55..42b209fa2d39 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/ProjectAggregateMergeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/ProjectAggregateMergeRule.java @@ -164,7 +164,7 @@ && kindCount(project.getProjects(), SqlKind.CASE) == 0) { private static int findSum0(RelDataTypeFactory typeFactory, AggregateCall sum, List aggCallList) { final AggregateCall sum0 = - AggregateCall.create(SqlStdOperatorTable.SUM0, sum.isDistinct(), + AggregateCall.create(sum.getParserPosition(), SqlStdOperatorTable.SUM0, sum.isDistinct(), sum.isApproximate(), sum.ignoreNulls(), sum.rexList, sum.getArgList(), sum.filterArg, sum.distinctKeys, sum.collation, typeFactory.createTypeWithNullability(sum.type, false), null); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceDecimalsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceDecimalsRule.java index 42d8403dbc1b..ee6c3a24be2b 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceDecimalsRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceDecimalsRule.java @@ -34,6 +34,7 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.type.SqlTypeUtil; import org.apache.calcite.tools.RelBuilderFactory; @@ -415,7 +416,7 @@ protected RexNode makeApproxLiteral(BigDecimal bd) { * @param scale a value from zero to max precision - 1 * @return value * 10^scale as an exact numeric value */ - protected RexNode scaleUp(RexNode value, int scale) { + protected RexNode scaleUp(SqlParserPos pos, RexNode value, int scale) { assert scale >= 0; assert scale < builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision(); @@ -423,6 +424,7 @@ protected RexNode scaleUp(RexNode value, int scale) { return value; } return builder.makeCall( + pos, SqlStdOperatorTable.MULTIPLY, value, makeScaleFactor(scale)); @@ -439,7 +441,7 @@ protected RexNode scaleUp(RexNode value, int scale) { * @return value/10^scale, rounded away from zero and returned as an * exact numeric value */ - protected RexNode scaleDown(RexNode value, int scale) { + protected RexNode scaleDown(SqlParserPos pos, RexNode value, int scale) { final int maxPrecision = builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision(); assert scale >= 0 && scale <= maxPrecision; @@ -449,12 +451,12 @@ protected RexNode scaleDown(RexNode value, int scale) { if (scale == maxPrecision) { long half = BigInteger.TEN.pow(scale - 1).longValue() * 5; return makeCase( - builder.makeCall( + builder.makeCall(pos, SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, value, makeExactLiteral(half)), makeExactLiteral(1), - builder.makeCall( + builder.makeCall(pos, SqlStdOperatorTable.LESS_THAN_OR_EQUAL, value, makeExactLiteral(-half)), @@ -464,13 +466,13 @@ protected RexNode scaleDown(RexNode value, int scale) { RexNode roundFactor = makeRoundFactor(scale); RexNode roundValue = makeCase( - builder.makeCall( + builder.makeCall(pos, SqlStdOperatorTable.GREATER_THAN, value, makeExactLiteral(0)), - makePlus(value, roundFactor), - makeMinus(value, roundFactor)); - return makeDivide( + makePlus(pos, value, roundFactor), + makeMinus(pos, value, roundFactor)); + return makeDivide(pos, roundValue, makeScaleFactor(scale)); } @@ -484,15 +486,16 @@ protected RexNode scaleDown(RexNode value, int scale) { * @param scale a value from zero to max precision * @return value/10^scale as a double precision value */ - protected RexNode scaleDownDouble(RexNode value, int scale) { + protected RexNode scaleDownDouble(SqlParserPos pos, RexNode value, int scale) { assert scale >= 0; assert scale <= builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision(); - RexNode cast = ensureType(real8, value); + RexNode cast = ensureType(pos, real8, value); if (scale == 0) { return cast; } return makeDivide( + pos, cast, makeApproxScaleFactor(scale)); } @@ -514,7 +517,7 @@ protected RexNode scaleDownDouble(RexNode value, int scale) { * @return value * 10^scale, returned as an exact or approximate value * corresponding to the input value */ - protected RexNode ensureScale(RexNode value, int scale, int required) { + protected RexNode ensureScale(SqlParserPos pos, RexNode value, int scale, int required) { final RelDataTypeSystem typeSystem = builder.getTypeFactory().getTypeSystem(); final int maxPrecision = typeSystem.getMaxNumericPrecision(); @@ -526,6 +529,7 @@ protected RexNode ensureScale(RexNode value, int scale, int required) { int scaleDiff = required - scale; if (SqlTypeUtil.isApproximateNumeric(value.getType())) { return makeMultiply( + pos, value, makeApproxScaleFactor(scaleDiff)); } @@ -538,7 +542,7 @@ protected RexNode ensureScale(RexNode value, int scale, int required) { + "source type is too large to be encoded by the " + "target type"); } - return scaleUp(value, scaleDiff); + return scaleUp(pos, value, scaleDiff); } /** @@ -547,9 +551,9 @@ protected RexNode ensureScale(RexNode value, int scale, int required) { * @param decimalNode the decimal value as an opaque type * @return an integer representation of the decimal value */ - protected RexNode decodeValue(RexNode decimalNode) { + protected RexNode decodeValue(SqlParserPos pos, RexNode decimalNode) { assert SqlTypeUtil.isDecimal(decimalNode.getType()); - return builder.decodeIntervalOrDecimal(decimalNode); + return builder.decodeIntervalOrDecimal(pos, decimalNode); } /** @@ -563,7 +567,7 @@ protected RexNode decodeValue(RexNode decimalNode) { protected RexNode accessValue(RexNode node) { assert SqlTypeUtil.isNumeric(node.getType()); if (SqlTypeUtil.isDecimal(node.getType())) { - return decodeValue(node); + return decodeValue(SqlParserPos.ZERO, node); } return node; } @@ -578,8 +582,8 @@ protected RexNode accessValue(RexNode node) { * @param decimalType type integer will be reinterpreted as * @return the integer representation reinterpreted as a decimal type */ - protected RexNode encodeValue(RexNode value, RelDataType decimalType) { - return encodeValue(value, decimalType, false); + protected RexNode encodeValue(SqlParserPos pos, RexNode value, RelDataType decimalType) { + return encodeValue(pos, value, decimalType, false); } /** @@ -599,11 +603,12 @@ protected RexNode encodeValue(RexNode value, RelDataType decimalType) { * @return the integer reinterpreted as an opaque decimal type */ protected RexNode encodeValue( + SqlParserPos pos, RexNode value, RelDataType decimalType, boolean checkOverflow) { return builder.encodeIntervalOrDecimal( - value, decimalType, checkOverflow); + pos, value, decimalType, checkOverflow); } /** @@ -617,8 +622,8 @@ protected RexNode encodeValue( * @param node expression * @return a casted expression or the original expression */ - protected RexNode ensureType(RelDataType type, RexNode node) { - return ensureType(type, node, true); + protected RexNode ensureType(SqlParserPos pos, RelDataType type, RexNode node) { + return ensureType(pos, type, node, true); } /** @@ -634,10 +639,11 @@ protected RexNode ensureType(RelDataType type, RexNode node) { * @return a casted expression or the original expression */ protected RexNode ensureType( + SqlParserPos pos, RelDataType type, RexNode node, boolean matchNullability) { - return builder.ensureType(type, node, matchNullability); + return builder.ensureType(pos, type, node, matchNullability); } protected RexNode makeCase( @@ -667,36 +673,44 @@ protected RexNode makeCase( } protected RexNode makePlus( + SqlParserPos pos, RexNode a, RexNode b) { return builder.makeCall( + pos, SqlStdOperatorTable.PLUS, a, b); } protected RexNode makeMinus( + SqlParserPos pos, RexNode a, RexNode b) { return builder.makeCall( + pos, SqlStdOperatorTable.MINUS, a, b); } protected RexNode makeDivide( + SqlParserPos pos, RexNode a, RexNode b) { return builder.makeCall( + pos, SqlStdOperatorTable.DIVIDE_INTEGER, a, b); } protected RexNode makeMultiply( + SqlParserPos pos, RexNode a, RexNode b) { return builder.makeCall( + pos, SqlStdOperatorTable.MULTIPLY, a, b); @@ -740,26 +754,27 @@ private CastExpander(RexBuilder builder) { assert SqlTypeUtil.isDecimal(fromType) || SqlTypeUtil.isDecimal(toType); + SqlParserPos pos = call.getParserPosition(); if (SqlTypeUtil.isIntType(toType)) { // decimal to int - return ensureType( + return ensureType(pos, toType, - scaleDown( - decodeValue(operand), + scaleDown(pos, + decodeValue(pos, operand), fromType.getScale()), false); } else if (SqlTypeUtil.isApproximateNumeric(toType)) { // decimal to floating point - return ensureType( + return ensureType(pos, toType, - scaleDownDouble( - decodeValue(operand), + scaleDownDouble(pos, + decodeValue(pos, operand), fromType.getScale()), false); } else if (SqlTypeUtil.isApproximateNumeric(fromType)) { // real to decimal - return encodeValue( - ensureScale( + return encodeValue(pos, + ensureScale(pos, operand, 0, toType.getScale()), @@ -785,8 +800,8 @@ private CastExpander(RexBuilder builder) { if (SqlTypeUtil.isIntType(fromType)) { // int to decimal - return encodeValue( - ensureScale( + return encodeValue(pos, + ensureScale(pos, operand, 0, toType.getScale()), @@ -796,20 +811,20 @@ private CastExpander(RexBuilder builder) { SqlTypeUtil.isDecimal(fromType) && SqlTypeUtil.isDecimal(toType)) { // decimal to decimal - RexNode value = decodeValue(operand); + RexNode value = decodeValue(pos, operand); RexNode scaled; if (fromScale <= toScale) { - scaled = ensureScale(value, fromScale, toScale); + scaled = ensureScale(pos, value, fromScale, toScale); } else { if (toDigits == fromDigits) { // rounding away from zero may cause an overflow // for example: cast(9.99 as decimal(2,1)) checkOverflow = true; } - scaled = scaleDown(value, fromScale - toScale); + scaled = scaleDown(pos, value, fromScale - toScale); } - return encodeValue(scaled, toType, checkOverflow); + return encodeValue(pos, scaled, toType, checkOverflow); } else { throw Util.needToImplement( "Reduce decimal cast from " + fromType + " to " + toType); @@ -831,6 +846,7 @@ private BinaryArithmeticExpander(RexBuilder builder) { } @Override public RexNode expand(RexCall call) { + final SqlParserPos pos = call.getParserPosition(); List operands = call.operands; assert operands.size() == 2; RelDataType typeA = operands.get(0).getType(); @@ -844,13 +860,13 @@ private BinaryArithmeticExpander(RexBuilder builder) { if (SqlTypeUtil.isApproximateNumeric(typeA)) { newOperands = ImmutableList.of(operands.get(0), - ensureType(real8, operands.get(1))); + ensureType(pos, real8, operands.get(1))); } else { newOperands = - ImmutableList.of(ensureType(real8, operands.get(0)), + ImmutableList.of(ensureType(pos, real8, operands.get(0)), operands.get(1)); } - return builder.makeCall( + return builder.makeCall(pos, call.getOperator(), newOperands); } @@ -897,15 +913,16 @@ private void analyzeOperands(List operands) { private RexNode expandPlusMinus(RexCall call, List operands) { RelDataType outType = call.getType(); + final SqlParserPos pos = call.getParserPosition(); int outScale = outType.getScale(); - return encodeValue( - builder.makeCall( + return encodeValue(pos, + builder.makeCall(pos, call.getOperator(), - ensureScale( + ensureScale(pos, accessValue(operands.get(0)), scaleA, outScale), - ensureScale( + ensureScale(pos, accessValue(operands.get(1)), scaleB, outScale)), @@ -914,22 +931,24 @@ private RexNode expandPlusMinus(RexCall call, List operands) { private RexNode expandDivide(RexCall call, List operands) { RelDataType outType = call.getType(); + final SqlParserPos pos = call.getParserPosition(); RexNode dividend = - builder.makeCall( + builder.makeCall(pos, call.getOperator(), - ensureType( + ensureType(pos, real8, accessValue(operands.get(0))), ensureType( + pos, real8, accessValue(operands.get(1)))); int scaleDifference = outType.getScale() - scaleA + scaleB; RexNode rescale = - builder.makeCall( + builder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, dividend, makeApproxScaleFactor(scaleDifference)); - return encodeValue(rescale, outType); + return encodeValue(pos, rescale, outType); } private RexNode expandTimes(RexCall call, List operands) { @@ -937,6 +956,7 @@ private RexNode expandTimes(RexCall call, List operands) { // a number with scale = scaleA + scaleB. If the result type has // a lower scale, then the number should be scaled down. int divisor = scaleA + scaleB - call.getType().getScale(); + final SqlParserPos pos = call.getParserPosition(); if (builder.getTypeFactory().getTypeSystem().shouldUseDoubleMultiplication( builder.getTypeFactory(), @@ -946,17 +966,17 @@ private RexNode expandTimes(RexCall call, List operands) { // cast (a as double) * cast (b as double) // / 10^divisor RexNode division = - makeDivide( - makeMultiply( - ensureType(real8, accessValue(operands.get(0))), - ensureType(real8, accessValue(operands.get(1)))), + makeDivide(pos, + makeMultiply(pos, + ensureType(pos, real8, accessValue(operands.get(0))), + ensureType(pos, real8, accessValue(operands.get(1)))), makeApproxLiteral(BigDecimal.TEN.pow(divisor))); - return encodeValue(division, call.getType(), true); + return encodeValue(pos, division, call.getType(), true); } else { // Exact implementation: scaleDown(a * b) - return encodeValue( - scaleDown( - builder.makeCall( + return encodeValue(pos, + scaleDown(pos, + builder.makeCall(pos, call.getOperator(), accessValue(operands.get(0)), accessValue(operands.get(1))), @@ -966,20 +986,22 @@ private RexNode expandTimes(RexCall call, List operands) { } private RexNode expandComparison(RexCall call, List operands) { + final SqlParserPos pos = call.getParserPosition(); int commonScale = Math.max(scaleA, scaleB); - return builder.makeCall( + return builder.makeCall(pos, call.getOperator(), - ensureScale( + ensureScale(pos, accessValue(operands.get(0)), scaleA, commonScale), - ensureScale( + ensureScale(pos, accessValue(operands.get(1)), scaleB, commonScale)); } private RexNode expandMod(RexCall call, List operands) { + final SqlParserPos pos = call.getParserPosition(); assert SqlTypeUtil.isExactNumeric(requireNonNull(typeA, "typeA")); assert SqlTypeUtil.isExactNumeric(requireNonNull(typeB, "typeB")); if (scaleA != 0 || scaleB != 0) { @@ -987,15 +1009,15 @@ private RexNode expandMod(RexCall call, List operands) { .ex(); } RexNode result = - builder.makeCall( + builder.makeCall(pos, call.getOperator(), accessValue(operands.get(0)), accessValue(operands.get(1))); RelDataType retType = call.getType(); if (SqlTypeUtil.isDecimal(retType)) { - return encodeValue(result, retType); + return encodeValue(pos, result, retType); } - return ensureType( + return ensureType(pos, call.getType(), result); } @@ -1019,9 +1041,10 @@ private FloorExpander(RexBuilder rexBuilder) { @Override public RexNode expand(RexCall call) { assert call.getOperator() == SqlStdOperatorTable.FLOOR; + final SqlParserPos pos = call.getParserPosition(); RexNode decValue = call.operands.get(0); int scale = decValue.getType().getScale(); - RexNode value = decodeValue(decValue); + RexNode value = decodeValue(pos, decValue); final RelDataTypeSystem typeSystem = builder.getTypeFactory().getTypeSystem(); @@ -1040,12 +1063,12 @@ private FloorExpander(RexBuilder rexBuilder) { rewrite = makeCase( makeIsNegative(value), - makeDivide( - makePlus(value, round), + makeDivide(pos, + makePlus(pos, value, round), scaleFactor), - makeDivide(value, scaleFactor)); + makeDivide(pos, value, scaleFactor)); } - return encodeValue( + return encodeValue(pos, rewrite, call.getType()); } @@ -1069,9 +1092,10 @@ private CeilExpander(RexBuilder rexBuilder) { @Override public RexNode expand(RexCall call) { assert call.getOperator() == SqlStdOperatorTable.CEIL; + final SqlParserPos pos = call.getParserPosition(); RexNode decValue = call.operands.get(0); int scale = decValue.getType().getScale(); - RexNode value = decodeValue(decValue); + RexNode value = decodeValue(pos, decValue); final RelDataTypeSystem typeSystem = builder.getTypeFactory().getTypeSystem(); @@ -1090,12 +1114,12 @@ private CeilExpander(RexBuilder rexBuilder) { rewrite = makeCase( makeIsPositive(value), - makeDivide( - makePlus(value, round), + makeDivide(pos, + makePlus(pos, value, round), scaleFactor), - makeDivide(value, scaleFactor)); + makeDivide(pos, value, scaleFactor)); } - return encodeValue( + return encodeValue(pos, rewrite, call.getType()); } @@ -1119,7 +1143,8 @@ private CaseExpander(RexBuilder rexBuilder) { } @Override public RexNode expand(RexCall call) { - RelDataType retType = call.getType(); + final SqlParserPos pos = call.getParserPosition(); + final RelDataType retType = call.getType(); int argCount = call.operands.size(); ImmutableList.Builder opBuilder = ImmutableList.builder(); @@ -1129,17 +1154,17 @@ private CaseExpander(RexBuilder rexBuilder) { opBuilder.add(call.operands.get(i)); continue; } - RexNode expr = ensureType(retType, call.operands.get(i), false); + RexNode expr = ensureType(pos, retType, call.operands.get(i), false); if (SqlTypeUtil.isDecimal(retType)) { - expr = decodeValue(expr); + expr = decodeValue(pos, expr); } opBuilder.add(expr); } RexNode newCall = - builder.makeCall(retType, call.getOperator(), opBuilder.build()); + builder.makeCall(pos, retType, call.getOperator(), opBuilder.build()); if (SqlTypeUtil.isDecimal(retType)) { - newCall = encodeValue(newCall, retType); + newCall = encodeValue(pos, newCall, retType); } return newCall; } @@ -1160,6 +1185,7 @@ private PassThroughExpander(RexBuilder builder) { } @Override public RexNode expand(RexCall call) { + final SqlParserPos pos = call.getParserPosition(); ImmutableList.Builder opBuilder = ImmutableList.builder(); for (RexNode operand : call.operands) { if (SqlTypeUtil.isNumeric(operand.getType())) { @@ -1170,10 +1196,10 @@ private PassThroughExpander(RexBuilder builder) { } RexNode newCall = - builder.makeCall(call.getType(), call.getOperator(), + builder.makeCall(pos, call.getType(), call.getOperator(), opBuilder.build()); if (SqlTypeUtil.isDecimal(call.getType())) { - return encodeValue( + return encodeValue(pos, newCall, call.getType()); } else { @@ -1213,24 +1239,25 @@ private CastArgAsTypeExpander(RexBuilder builder) { public abstract RelDataType getArgType(RexCall call, int ordinal); @Override public RexNode expand(RexCall call) { + final SqlParserPos pos = call.getParserPosition(); ImmutableList.Builder opBuilder = ImmutableList.builder(); for (Ord operand : Ord.zip(call.operands)) { RelDataType targetType = getArgType(call, operand.i); if (SqlTypeUtil.isDecimal(operand.e.getType())) { - opBuilder.add(ensureType(targetType, operand.e, true)); + opBuilder.add(ensureType(pos, targetType, operand.e, true)); } else { opBuilder.add(operand.e); } } RexNode ret = - builder.makeCall( + builder.makeCall(pos, call.getType(), call.getOperator(), opBuilder.build()); ret = - ensureType( + ensureType(pos, call.getType(), ret, true); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java index 579efc3336e0..d5864fa49f0f 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java @@ -49,6 +49,7 @@ import org.apache.calcite.sql.SqlFunction; import org.apache.calcite.sql.fun.SqlMinMaxAggFunction; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilder.AggCall; @@ -323,6 +324,7 @@ public abstract class MaterializedViewAggregateRule exprs) { - return new RexCall(returnType, op, exprs); + return new RexCall(pos, returnType, op, exprs); + } + + /** + * Creates a call with a list of arguments and a predetermined type. + */ + public RexNode makeCall( + RelDataType returnType, + SqlOperator op, + List exprs) { + return makeCall(SqlParserPos.ZERO, returnType, op, exprs); } /** * Creates a call with an array of arguments. * + * @param pos should be different from ZERO if the call can + * fail at runtime. + * *

If you already know the return type of the call, then - * {@link #makeCall(org.apache.calcite.rel.type.RelDataType, org.apache.calcite.sql.SqlOperator, java.util.List)} + * {@link #makeCall(SqlParserPos, RelDataType, SqlOperator, List)} * is preferred. */ public RexNode makeCall( - SqlOperator op, + SqlParserPos pos, SqlOperator op, List exprs) { final RelDataType type = deriveReturnType(op, exprs); - return new RexCall(type, op, exprs); + return new RexCall(pos, type, op, exprs); + } + + /** + * Creates a call with an array of arguments. + * + *

If you already know the return type of the call, then + * {@link #makeCall(SqlParserPos, RelDataType, SqlOperator, List)} + * is preferred. + */ + public RexNode makeCall( + SqlOperator op, + List exprs) { + return makeCall(SqlParserPos.ZERO, op, exprs); + } + + /** + * Creates a call with a list of arguments. + * + * @param pos should be different from ZERO if the call can + * fail at runtime. + * + *

Equivalent to + * makeCall(pos, op, exprList.toArray(new RexNode[exprList.size()])). + */ + public final RexNode makeCall( + SqlParserPos pos, + SqlOperator op, + RexNode... exprs) { + return makeCall(pos, op, ImmutableList.copyOf(exprs)); } /** * Creates a call with a list of arguments. * *

Equivalent to - * makeCall(op, exprList.toArray(new RexNode[exprList.size()])). + * makeCall(ZERO, op, exprList.toArray(new RexNode[exprList.size()])). */ public final RexNode makeCall( SqlOperator op, RexNode... exprs) { - return makeCall(op, ImmutableList.copyOf(exprs)); + return makeCall(SqlParserPos.ZERO, op, exprs); } /** @@ -417,7 +464,7 @@ public RexNode makeOver( window, distinct, ignoreNulls), makeLiteral(BigDecimal.ZERO, bigintType, SqlTypeName.DECIMAL)), - ensureType(type, // SUM0 is non-nullable, thus need a cast + ensureType(SqlParserPos.ZERO, type, // SUM0 is non-nullable, thus need a cast new RexOver(typeFactory.createTypeWithNullability(type, false), operator, exprs, window, distinct, ignoreNulls), false), @@ -526,14 +573,29 @@ public RexNode makeNewInvocation( /** * Creates a call to the CAST operator. * + * @param pos Parser position of the cast. * @param type Type to cast to * @param exp Expression being cast * @return Call to CAST operator */ public RexNode makeCast( + SqlParserPos pos, RelDataType type, RexNode exp) { - return makeCast(type, exp, false, false); + return makeCast(pos, type, exp, false, false); + } + + /** + * Creates a call to the CAST operator. + * + * @param type Type to cast to + * @param exp Expression being cast + * @return Call to CAST operator + */ + public RexNode makeCast( + RelDataType type, + RexNode exp) { + return makeCast(SqlParserPos.ZERO, type, exp, false, false); } @Deprecated // to be removed before 2.0 @@ -564,6 +626,31 @@ public RexNode makeCast( RexNode exp, boolean matchNullability, boolean safe) { + return makeCast(SqlParserPos.ZERO, type, exp, matchNullability, safe); + } + + /** + * Creates a call to the CAST operator, expanding if possible, and optionally + * also preserving nullability, and optionally in safe mode. + * + *

Tries to expand the cast, and therefore the result may be something + * other than a {@link RexCall} to the CAST operator, such as a + * {@link RexLiteral}. + * + * @param pos Parser position + * @param type Type to cast to + * @param exp Expression being cast + * @param matchNullability Whether to ensure the result has the same + * nullability as {@code type} + * @param safe Whether to return NULL if cast fails + * @return Call to CAST operator + */ + public RexNode makeCast( + SqlParserPos pos, + RelDataType type, + RexNode exp, + boolean matchNullability, + boolean safe) { final SqlTypeName sqlType = type.getSqlTypeName(); if (exp instanceof RexLiteral) { RexLiteral literal = (RexLiteral) exp; @@ -630,13 +717,13 @@ public RexNode makeCast( if (type.isNullable() && !literal2.getType().isNullable() && matchNullability) { - return makeAbstractCast(type, literal2, safe); + return makeAbstractCast(pos, type, literal2, safe); } return literal2; } } else if (SqlTypeUtil.isExactNumeric(type) && SqlTypeUtil.isInterval(exp.getType())) { - return makeCastIntervalToExact(type, exp); + return makeCastIntervalToExact(pos, type, exp); } else if (sqlType == SqlTypeName.BOOLEAN && SqlTypeUtil.isExactNumeric(exp.getType())) { return makeCastExactToBoolean(type, exp); @@ -644,7 +731,7 @@ public RexNode makeCast( && SqlTypeUtil.isExactNumeric(type)) { return makeCastBooleanToExact(type, exp); } - return makeAbstractCast(type, exp, safe); + return makeAbstractCast(pos, type, exp, safe); } /** Returns the lowest granularity unit for the given unit. @@ -742,17 +829,17 @@ private RexNode makeCastBooleanToExact(RelDataType toType, RexNode exp) { casted, makeNullLiteral(toType))); } - private RexNode makeCastIntervalToExact(RelDataType toType, RexNode exp) { + private RexNode makeCastIntervalToExact(SqlParserPos pos, RelDataType toType, RexNode exp) { final TimeUnit endUnit = exp.getType().getSqlTypeName().getEndUnit(); final TimeUnit baseUnit = baseUnit(exp.getType().getSqlTypeName()); final BigDecimal multiplier = baseUnit.multiplier; final BigDecimal divider = endUnit.multiplier; RexNode value = - multiplyDivide(decodeIntervalOrDecimal(exp), multiplier, divider); - return ensureType(toType, value, false); + multiplyDivide(pos, decodeIntervalOrDecimal(pos, exp), multiplier, divider); + return ensureType(pos, toType, value, false); } - public RexNode multiplyDivide(RexNode e, BigDecimal multiplier, + public RexNode multiplyDivide(SqlParserPos pos, RexNode e, BigDecimal multiplier, BigDecimal divider) { assert multiplier.signum() > 0; assert divider.signum() > 0; @@ -761,12 +848,12 @@ public RexNode multiplyDivide(RexNode e, BigDecimal multiplier, return e; case 1: // E.g. multiplyDivide(e, 1000, 10) ==> e * 100 - return makeCall(SqlStdOperatorTable.MULTIPLY, e, + return makeCall(pos, SqlStdOperatorTable.MULTIPLY, e, makeExactLiteral( multiplier.divide(divider, RoundingMode.UNNECESSARY))); case -1: // E.g. multiplyDivide(e, 10, 1000) ==> e / 100 - return makeCall(SqlStdOperatorTable.DIVIDE_INTEGER, e, + return makeCall(pos, SqlStdOperatorTable.DIVIDE_INTEGER, e, makeExactLiteral( divider.divide(multiplier, RoundingMode.UNNECESSARY))); default: @@ -791,13 +878,14 @@ public RexNode multiplyDivide(RexNode e, BigDecimal multiplier, * @return the integer reinterpreted as an opaque decimal type */ public RexNode encodeIntervalOrDecimal( + SqlParserPos pos, RexNode value, RelDataType type, boolean checkOverflow) { RelDataType bigintType = typeFactory.createSqlType(SqlTypeName.BIGINT); - RexNode cast = ensureType(bigintType, value, true); - return makeReinterpretCast(type, cast, makeLiteral(checkOverflow)); + RexNode cast = ensureType(pos, bigintType, value, true); + return makeReinterpretCast(pos, type, cast, makeLiteral(checkOverflow)); } /** @@ -806,11 +894,11 @@ public RexNode encodeIntervalOrDecimal( * @param node the interval or decimal value as an opaque type * @return an integer representation of the decimal value */ - public RexNode decodeIntervalOrDecimal(RexNode node) { + public RexNode decodeIntervalOrDecimal(SqlParserPos pos, RexNode node) { assert SqlTypeUtil.isDecimal(node.getType()) || SqlTypeUtil.isInterval(node.getType()); RelDataType bigintType = typeFactory.createSqlType(SqlTypeName.BIGINT); - return makeReinterpretCast( + return makeReinterpretCast(pos, matchNullability(bigintType, node), node, makeLiteral(false)); } @@ -822,27 +910,45 @@ public RexNode makeAbstractCast(RelDataType type, RexNode exp) { /** * Creates a call to CAST or SAFE_CAST operator. * + * @param pos Parser position. * @param type Type to cast to * @param exp Expression being cast * @param safe Whether to return NULL if cast fails * @return Call to CAST operator + * Casts can fail at runtime, so we expect position information. */ - public RexNode makeAbstractCast(RelDataType type, RexNode exp, boolean safe) { + public RexNode makeAbstractCast(SqlParserPos pos, RelDataType type, RexNode exp, boolean safe) { SqlOperator operator = safe ? SqlLibraryOperators.SAFE_CAST : SqlStdOperatorTable.CAST; - return new RexCall(type, operator, ImmutableList.of(exp)); + return new RexCall(pos, type, operator, ImmutableList.of(exp)); + } + + /** + * Creates a call to CAST or SAFE_CAST operator. + * + * @param type Type to cast to + * @param exp Expression being cast + * @param safe Whether to return NULL if cast fails + * @return Call to CAST operator + * Casts can fail at runtime, so we expect position information. + */ + public RexNode makeAbstractCast(RelDataType type, RexNode exp, boolean safe) { + return makeAbstractCast(SqlParserPos.ZERO, type, exp, safe); } + /** * Makes a reinterpret cast. * + * @param pos parser position * @param type type returned by the cast * @param exp expression to be casted * @param checkOverflow whether an overflow check is required * @return a RexCall with two operands and a special return type */ public RexNode makeReinterpretCast( + SqlParserPos pos, RelDataType type, RexNode exp, RexNode checkOverflow) { @@ -853,6 +959,7 @@ public RexNode makeReinterpretCast( args = ImmutableList.of(exp); } return new RexCall( + pos, type, SqlStdOperatorTable.REINTERPRET, args); @@ -1188,6 +1295,7 @@ protected RexLiteral makePreciseStringLiteral(ByteString value, * Ensures expression is interpreted as a specified type. The returned * expression may be wrapped with a cast. * + * @param pos parser position * @param type desired type * @param node expression * @param matchNullability whether to correct nullability of specified @@ -1197,6 +1305,7 @@ protected RexLiteral makePreciseStringLiteral(ByteString value, * @return a casted expression or the original expression */ public RexNode ensureType( + SqlParserPos pos, RelDataType type, RexNode node, boolean matchNullability) { @@ -1212,7 +1321,7 @@ public RexNode ensureType( } if (!node.getType().equals(targetType)) { - return makeCast(targetType, node); + return makeCast(pos, targetType, node); } return node; } diff --git a/core/src/main/java/org/apache/calcite/rex/RexCall.java b/core/src/main/java/org/apache/calcite/rex/RexCall.java index c2d7b332d398..9d78cd915aea 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexCall.java +++ b/core/src/main/java/org/apache/calcite/rex/RexCall.java @@ -21,6 +21,7 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSyntax; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.type.SqlTypeUtil; import org.apache.calcite.util.Litmus; @@ -56,6 +57,12 @@ public class RexCall extends RexNode { //~ Instance fields -------------------------------------------------------- + /** In the calls which can produce runtime errors we carry + * the source position, so the backend can produce runtime error messages + * pointing to the original source position. + * For calls that are can never generate runtime failures, this field may + * be ZERO. Note that some optimizations may "lost" position information. */ + public final SqlParserPos pos; public final SqlOperator op; public final ImmutableList operands; public final RelDataType type; @@ -74,9 +81,11 @@ public class RexCall extends RexNode { //~ Constructors ----------------------------------------------------------- protected RexCall( + SqlParserPos pos, RelDataType type, SqlOperator operator, List operands) { + this.pos = pos; this.type = requireNonNull(type, "type"); this.op = requireNonNull(operator, "operator"); this.operands = ImmutableList.copyOf(operands); @@ -86,6 +95,13 @@ protected RexCall( assert operator.kind != SqlKind.IN || this instanceof RexSubQuery; } + protected RexCall( + RelDataType type, + SqlOperator operator, + List operands) { + this(SqlParserPos.ZERO, type, operator, operands); + } + //~ Methods ---------------------------------------------------------------- /** @@ -177,6 +193,10 @@ protected String computeDigest(boolean withType) { return sb.toString(); } + public SqlParserPos getParserPosition() { + return this.pos; + } + @Override public final String toString() { return computeDigest(digestWithType()); } @@ -212,7 +232,7 @@ private boolean digestWithType() { case CAST: return operands.get(0).isAlwaysTrue(); case SEARCH: - final Sarg sarg = ((RexLiteral) operands.get(1)).getValueAs(Sarg.class); + final Sarg sarg = ((RexLiteral) operands.get(1)).getValueAs(Sarg.class); return requireNonNull(sarg, "sarg").isAll() && (sarg.nullAs == RexUnknownAs.TRUE || !operands.get(0).getType().isNullable()); @@ -234,7 +254,7 @@ private boolean digestWithType() { case CAST: return operands.get(0).isAlwaysFalse(); case SEARCH: - final Sarg sarg = ((RexLiteral) operands.get(1)).getValueAs(Sarg.class); + final Sarg sarg = ((RexLiteral) operands.get(1)).getValueAs(Sarg.class); return requireNonNull(sarg, "sarg").isNone() && (sarg.nullAs == RexUnknownAs.FALSE || !operands.get(0).getType().isNullable()); @@ -267,7 +287,7 @@ public SqlOperator getOperator() { * @return New call */ public RexCall clone(RelDataType type, List operands) { - return new RexCall(type, op, operands); + return new RexCall(pos, type, op, operands); } private Pair> getNormalized() { diff --git a/core/src/main/java/org/apache/calcite/rex/RexCopier.java b/core/src/main/java/org/apache/calcite/rex/RexCopier.java index e73a68d5f6f5..1f5700e48208 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexCopier.java +++ b/core/src/main/java/org/apache/calcite/rex/RexCopier.java @@ -57,7 +57,7 @@ private RelDataType copy(RelDataType type) { @Override public RexNode visitCall(final RexCall call) { final boolean[] update = null; - return builder.makeCall(copy(call.getType()), + return builder.makeCall(call.getParserPosition(), copy(call.getType()), call.getOperator(), visitList(call.getOperands(), update)); } diff --git a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java index c81a72543f36..6f02f95e3ce0 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java +++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java @@ -396,7 +396,7 @@ private RexNode simplifyGenericNode(RexCall e) { if (e.operands.equals(operands)) { return e; } - return rexBuilder.makeCall(e.getType(), e.getOperator(), operands); + return rexBuilder.makeCall(e.getParserPosition(), e.getType(), e.getOperator(), operands); } /** @@ -446,7 +446,7 @@ private RexNode simplifyPlus(RexCall e) { // return the other operand. RexNode other = e.getOperands().get((zeroIndex + 1) % 2); return other.getType().equals(e.getType()) - ? other : rexBuilder.makeCast(e.getType(), other); + ? other : rexBuilder.makeCast(e.getParserPosition(), e.getType(), other); } return simplifyGenericNode(e); } @@ -456,7 +456,7 @@ private RexNode simplifyMinus(RexCall e) { if (zeroIndex == 1) { RexNode leftOperand = e.getOperands().get(0); return leftOperand.getType().equals(e.getType()) - ? leftOperand : rexBuilder.makeCast(e.getType(), leftOperand); + ? leftOperand : rexBuilder.makeCast(e.getParserPosition(), e.getType(), leftOperand); } return simplifyGenericNode(e); } @@ -467,7 +467,7 @@ private RexNode simplifyMultiply(RexCall e) { // return the other operand. RexNode other = e.getOperands().get((oneIndex + 1) % 2); return other.getType().equals(e.getType()) - ? other : rexBuilder.makeCast(e.getType(), other); + ? other : rexBuilder.makeCast(e.getParserPosition(), e.getType(), other); } return simplifyGenericNode(e); } @@ -477,7 +477,7 @@ private RexNode simplifyDivide(RexCall e) { if (oneIndex == 1) { RexNode leftOperand = e.getOperands().get(0); return leftOperand.getType().equals(e.getType()) - ? leftOperand : rexBuilder.makeCast(e.getType(), leftOperand); + ? leftOperand : rexBuilder.makeCast(e.getParserPosition(), e.getType(), leftOperand); } return simplifyGenericNode(e); } @@ -488,8 +488,9 @@ private RexNode simplifyLike(RexCall e, RexUnknownAs unknownAs) { if ("%".equals(literal.getValueAs(String.class))) { // "x LIKE '%'" simplifies to "x = x" final RexNode x = e.operands.get(0); - return simplify(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, x, x), - unknownAs); + return simplify( + rexBuilder.makeCall( + e.getParserPosition(), SqlStdOperatorTable.EQUALS, x, x), unknownAs); } } return simplifyGenericNode(e); @@ -519,18 +520,18 @@ private > RexNode simplifyComparison(RexCall e, case LESS_THAN_OR_EQUAL: // "x = x" simplifies to "null or x is not null" (similarly <= and >=) newExpr = - rexBuilder.makeCall(SqlStdOperatorTable.OR, + rexBuilder.makeCall(e.getParserPosition(), SqlStdOperatorTable.OR, rexBuilder.makeNullLiteral(e.getType()), - rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, o0)); + rexBuilder.makeCall(e.getParserPosition(), SqlStdOperatorTable.IS_NOT_NULL, o0)); return simplify(newExpr, unknownAs); case NOT_EQUALS: case LESS_THAN: case GREATER_THAN: // "x != x" simplifies to "null and x is null" (similarly < and >) newExpr = - rexBuilder.makeCall(SqlStdOperatorTable.AND, + rexBuilder.makeCall(e.getParserPosition(), SqlStdOperatorTable.AND, rexBuilder.makeNullLiteral(e.getType()), - rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, o0)); + rexBuilder.makeCall(e.getParserPosition(), SqlStdOperatorTable.IS_NULL, o0)); return simplify(newExpr, unknownAs); default: // unknown kind @@ -538,7 +539,9 @@ private > RexNode simplifyComparison(RexCall e, } if (o0.getType().getSqlTypeName() == SqlTypeName.BOOLEAN) { - Comparison cmp = Comparison.of(rexBuilder.makeCall(e.getOperator(), o0, o1), node -> true); + Comparison cmp = + Comparison.of( + rexBuilder.makeCall(e.getParserPosition(), e.getOperator(), o0, o1), node -> true); if (cmp != null) { if (cmp.literal.isAlwaysTrue()) { switch (cmp.kind) { @@ -632,7 +635,7 @@ private > RexNode simplifyComparison(RexCall e, if (operands.equals(e.operands)) { e2 = e; } else { - e2 = rexBuilder.makeCall(e.op, operands); + e2 = rexBuilder.makeCall(e.getParserPosition(), e.op, operands); } return simplifyUsingPredicates(e2, clazz); } @@ -771,7 +774,8 @@ private RexNode simplifyNot(RexCall call, RexUnknownAs unknownAs) { newOperands.add(simplify(not(operand), unknownAs)); } return simplify( - rexBuilder.makeCall(SqlStdOperatorTable.OR, newOperands), unknownAs); + rexBuilder.makeCall( + call.getParserPosition(), SqlStdOperatorTable.OR, newOperands), unknownAs); case OR: // NOT distributivity for OR @@ -780,7 +784,8 @@ private RexNode simplifyNot(RexCall call, RexUnknownAs unknownAs) { newOperands.add(simplify(not(operand), unknownAs)); } return simplify( - rexBuilder.makeCall(SqlStdOperatorTable.AND, newOperands), unknownAs); + rexBuilder.makeCall( + call.getParserPosition(), SqlStdOperatorTable.AND, newOperands), unknownAs); case CASE: newOperands = new ArrayList<>(); @@ -794,7 +799,8 @@ private RexNode simplifyNot(RexCall call, RexUnknownAs unknownAs) { } } return simplify( - rexBuilder.makeCall(SqlStdOperatorTable.CASE, newOperands), unknownAs); + rexBuilder.makeCall( + call.getParserPosition(), SqlStdOperatorTable.CASE, newOperands), unknownAs); case IN: case NOT_IN: @@ -805,13 +811,14 @@ private RexNode simplifyNot(RexCall call, RexUnknownAs unknownAs) { final SqlKind negateKind = a.getKind().negate(); if (a.getKind() != negateKind) { return simplify( - rexBuilder.makeCall(RexUtil.op(negateKind), + rexBuilder.makeCall( + call.getParserPosition(), RexUtil.op(negateKind), ((RexCall) a).getOperands()), unknownAs); } final SqlKind negateKind2 = a.getKind().negateNullSafe(); if (a.getKind() != negateKind2) { return simplify( - rexBuilder.makeCall(RexUtil.op(negateKind2), + rexBuilder.makeCall(call.getParserPosition(), RexUtil.op(negateKind2), ((RexCall) a).getOperands()), unknownAs); } } @@ -1212,7 +1219,7 @@ && isSafeExpression(newCond)) { if (sameTypeOrNarrowsNullability(caseType, value.getType())) { return value; } else { - return rexBuilder.makeAbstractCast(caseType, value, false); + return rexBuilder.makeAbstractCast(call.getParserPosition(), caseType, value, false); } } @@ -1227,7 +1234,7 @@ && isSafeExpression(newCond)) { if (!simplified.getType().isNullable()) { return simplified; } else { - return rexBuilder.makeCast(call.getType(), simplified); + return rexBuilder.makeCast(call.getParserPosition(), call.getType(), simplified); } } } @@ -1236,7 +1243,7 @@ && isSafeExpression(newCond)) { if (newOperands.equals(call.getOperands())) { return call; } - return rexBuilder.makeCall(SqlStdOperatorTable.CASE, newOperands); + return rexBuilder.makeCall(call.getParserPosition(), SqlStdOperatorTable.CASE, newOperands); } /** @@ -1439,7 +1446,8 @@ static boolean isSafeExpression(RexNode r) { final RexNode cond = isTrue(branch.cond); final RexNode value; if (!branchType.equals(branch.value.getType())) { - value = rexBuilder.makeAbstractCast(branchType, branch.value, false); + value = + rexBuilder.makeAbstractCast(branchType, branch.value, false); } else { value = branch.value; } @@ -2235,7 +2243,7 @@ && sameTypeOrNarrowsNullability(e.getType(), intExpr.getType())) { || operand.getType().getSqlTypeName() != SqlTypeName.CHAR) && SqlTypeCoercionRule.instance() .canApplyFrom(intExpr.getType().getSqlTypeName(), e.getType().getSqlTypeName())) { - return rexBuilder.makeCast(e.getType(), intExpr); + return rexBuilder.makeCast(e.getParserPosition(), e.getType(), intExpr); } } final boolean safe = e.getKind() == SqlKind.SAFE_CAST; @@ -2249,7 +2257,7 @@ && sameTypeOrNarrowsNullability(e.getType(), intExpr.getType())) { // makeCast and canRemoveCastFromLiteral have the same logic, so we are // sure to be able to remove the cast. if (rexBuilder.canRemoveCastFromLiteral(e.getType(), value, typeName)) { - return rexBuilder.makeCast(e.getType(), operand); + return rexBuilder.makeCast(e.getParserPosition(), e.getType(), operand); } // Next, try to convert the value to a different type, @@ -2268,7 +2276,7 @@ && sameTypeOrNarrowsNullability(e.getType(), intExpr.getType())) { } final List reducedValues = new ArrayList<>(); final RexNode simplifiedExpr = - rexBuilder.makeCast(e.getType(), operand, safe, safe); + rexBuilder.makeCast(e.getParserPosition(), e.getType(), operand, safe, safe); executor.reduce(rexBuilder, ImmutableList.of(simplifiedExpr), reducedValues); return requireNonNull( Iterables.getOnlyElement(reducedValues)); @@ -2276,7 +2284,7 @@ && sameTypeOrNarrowsNullability(e.getType(), intExpr.getType())) { if (operand == e.getOperands().get(0)) { return e; } else { - return rexBuilder.makeCast(e.getType(), operand, safe, safe); + return rexBuilder.makeCast(e.getParserPosition(), e.getType(), operand, safe, safe); } } } 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 5d7f473a2013..48ecb00d2109 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java +++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java @@ -35,6 +35,7 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeFamily; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.type.SqlTypeUtil; @@ -1590,7 +1591,7 @@ public static RexNode flatten(RexBuilder rexBuilder, RexNode node) { final SqlOperator op = call.getOperator(); final List flattenedOperands = flatten(call.getOperands(), op); if (!isFlat(call.getOperands(), op)) { - return rexBuilder.makeCall(call.getType(), op, flattenedOperands); + return rexBuilder.makeCall(call.getParserPosition(), call.getType(), op, flattenedOperands); } } return node; @@ -2033,8 +2034,7 @@ public static RexNode not(RexNode e) { } private static RexNode addNot(RexNode e) { - return new RexCall(e.getType(), SqlStdOperatorTable.NOT, - ImmutableList.of(e)); + return new RexCall(e.getType(), SqlStdOperatorTable.NOT, ImmutableList.of(e)); } @API(since = "1.27.0", status = API.Status.EXPERIMENTAL) @@ -2111,7 +2111,7 @@ public static RexNode simplifyAnd2ForUnknownAsFalse(RexBuilder rexBuilder, case LESS_THAN_OR_EQUAL: case GREATER_THAN_OR_EQUAL: final SqlOperator op = op(call.getKind().negateNullSafe()); - return rexBuilder.makeCall(op, call.getOperands()); + return rexBuilder.makeCall(call.getParserPosition(), op, call.getOperands()); default: break; } @@ -2127,7 +2127,7 @@ public static RexNode simplifyAnd2ForUnknownAsFalse(RexBuilder rexBuilder, case LESS_THAN_OR_EQUAL: case GREATER_THAN_OR_EQUAL: final SqlOperator op = requireNonNull(call.getOperator().reverse()); - return rexBuilder.makeCall(op, Lists.reverse(call.getOperands())); + return rexBuilder.makeCall(call.getParserPosition(), op, Lists.reverse(call.getOperands())); default: return null; } @@ -3013,7 +3013,7 @@ public ExprSimplifier(RexSimplify simplify, RexUnknownAs unknownAs, if (simplifiedNode.getType().equals(call.getType())) { return simplifiedNode; } - return simplify.rexBuilder.makeCast(call.getType(), simplifiedNode, + return simplify.rexBuilder.makeCast(call.getParserPosition(), call.getType(), simplifiedNode, matchNullability, false); } } @@ -3089,8 +3089,8 @@ private void addAnd(RexNode... nodes) { list.add(rexBuilder.makeCall(SqlStdOperatorTable.AND, nodes)); } - private RexNode op(SqlOperator op, C value) { - return rexBuilder.makeCall(op, ref, + private RexNode op(SqlParserPos pos, SqlOperator op, C value) { + return rexBuilder.makeCall(pos, op, ref, rexBuilder.makeLiteral(value, type, true, true)); } @@ -3099,43 +3099,43 @@ private RexNode op(SqlOperator op, C value) { } @Override public void atLeast(C lower) { - list.add(op(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, lower)); + list.add(op(SqlParserPos.ZERO, SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, lower)); } @Override public void atMost(C upper) { - list.add(op(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, upper)); + list.add(op(SqlParserPos.ZERO, SqlStdOperatorTable.LESS_THAN_OR_EQUAL, upper)); } @Override public void greaterThan(C lower) { - list.add(op(SqlStdOperatorTable.GREATER_THAN, lower)); + list.add(op(SqlParserPos.ZERO, SqlStdOperatorTable.GREATER_THAN, lower)); } @Override public void lessThan(C upper) { - list.add(op(SqlStdOperatorTable.LESS_THAN, upper)); + list.add(op(SqlParserPos.ZERO, SqlStdOperatorTable.LESS_THAN, upper)); } @Override public void singleton(C value) { - list.add(op(SqlStdOperatorTable.EQUALS, value)); + list.add(op(SqlParserPos.ZERO, SqlStdOperatorTable.EQUALS, value)); } @Override public void closed(C lower, C upper) { - addAnd(op(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, lower), - op(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, upper)); + addAnd(op(SqlParserPos.ZERO, SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, lower), + op(SqlParserPos.ZERO, SqlStdOperatorTable.LESS_THAN_OR_EQUAL, upper)); } @Override public void closedOpen(C lower, C upper) { - addAnd(op(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, lower), - op(SqlStdOperatorTable.LESS_THAN, upper)); + addAnd(op(SqlParserPos.ZERO, SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, lower), + op(SqlParserPos.ZERO, SqlStdOperatorTable.LESS_THAN, upper)); } @Override public void openClosed(C lower, C upper) { - addAnd(op(SqlStdOperatorTable.GREATER_THAN, lower), - op(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, upper)); + addAnd(op(SqlParserPos.ZERO, SqlStdOperatorTable.GREATER_THAN, lower), + op(SqlParserPos.ZERO, SqlStdOperatorTable.LESS_THAN_OR_EQUAL, upper)); } @Override public void open(C lower, C upper) { - addAnd(op(SqlStdOperatorTable.GREATER_THAN, lower), - op(SqlStdOperatorTable.LESS_THAN, upper)); + addAnd(op(SqlParserPos.ZERO, SqlStdOperatorTable.GREATER_THAN, lower), + op(SqlParserPos.ZERO, SqlStdOperatorTable.LESS_THAN, upper)); } } diff --git a/core/src/main/java/org/apache/calcite/runtime/Resources.java b/core/src/main/java/org/apache/calcite/runtime/Resources.java index a015541a382e..f3c53b3d7ab6 100644 --- a/core/src/main/java/org/apache/calcite/runtime/Resources.java +++ b/core/src/main/java/org/apache/calcite/runtime/Resources.java @@ -54,8 +54,6 @@ import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; -import static java.lang.reflect.Modifier.isStatic; - import static org.apache.calcite.linq4j.Nullness.castNonNull; import static java.util.Objects.requireNonNull; diff --git a/core/src/main/java/org/apache/calcite/schema/impl/ModifiableViewTable.java b/core/src/main/java/org/apache/calcite/schema/impl/ModifiableViewTable.java index 99f81d4d2681..93837a13adcb 100644 --- a/core/src/main/java/org/apache/calcite/schema/impl/ModifiableViewTable.java +++ b/core/src/main/java/org/apache/calcite/schema/impl/ModifiableViewTable.java @@ -32,6 +32,7 @@ import org.apache.calcite.schema.Table; import org.apache.calcite.schema.Wrapper; import org.apache.calcite.sql.SqlFunction; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql2rel.InitializerContext; import org.apache.calcite.sql2rel.InitializerExpressionFactory; import org.apache.calcite.sql2rel.NullInitializerExpressionFactory; @@ -241,7 +242,7 @@ private ModifiableViewTableInitializerExpressionFactory() { final int mappedOrdinal = viewTable.columnMapping.get(iColumn); final RexNode viewConstraint = projectMap.get(mappedOrdinal); if (viewConstraint != null) { - return rexBuilder.ensureType(iType, viewConstraint, true); + return rexBuilder.ensureType(SqlParserPos.ZERO, iType, viewConstraint, true); } // Otherwise use the default value of the underlying table. @@ -253,7 +254,7 @@ private ModifiableViewTableInitializerExpressionFactory() { final RexNode tableConstraint = initializerExpressionFactory.newColumnDefaultValue(table, iColumn, context); - return rexBuilder.ensureType(iType, tableConstraint, true); + return rexBuilder.ensureType(SqlParserPos.ZERO, iType, tableConstraint, true); } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlSplittableAggFunction.java b/core/src/main/java/org/apache/calcite/sql/SqlSplittableAggFunction.java index da4b31085c29..4e78d183310a 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlSplittableAggFunction.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlSplittableAggFunction.java @@ -26,6 +26,7 @@ import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexUtil; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.ImmutableIntList; import org.apache.calcite.util.mapping.Mappings; @@ -114,7 +115,7 @@ class CountSplitter implements SqlSplittableAggFunction { @Override public @Nullable AggregateCall other(RelDataTypeFactory typeFactory, AggregateCall e) { final RelDataType type = typeFactory.createSqlType(SqlTypeName.BIGINT); - return AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, + return AggregateCall.create(e.getParserPosition(), SqlStdOperatorTable.COUNT, false, false, false, ImmutableList.of(), ImmutableIntList.of(), -1, null, RelCollations.EMPTY, type, null); } @@ -123,6 +124,7 @@ class CountSplitter implements SqlSplittableAggFunction { Registry extra, int offset, RelDataType inputRowType, AggregateCall aggregateCall, int leftSubTotal, int rightSubTotal) { final List merges = new ArrayList<>(); + final SqlParserPos pos = aggregateCall.getParserPosition(); if (leftSubTotal >= 0) { merges.add( rexBuilder.makeInputRef(aggregateCall.type, leftSubTotal)); @@ -137,13 +139,13 @@ class CountSplitter implements SqlSplittableAggFunction { node = merges.get(0); break; case 2: - node = rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, merges); + node = rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, merges); break; default: throw new AssertionError("unexpected count " + merges); } int ordinal = extra.register(node); - return AggregateCall.create(SqlStdOperatorTable.SUM0, false, false, + return AggregateCall.create(pos, SqlStdOperatorTable.SUM0, false, false, false, aggregateCall.rexList, ImmutableList.of(ordinal), -1, aggregateCall.distinctKeys, aggregateCall.collation, aggregateCall.type, aggregateCall.name); @@ -183,7 +185,7 @@ class CountSplitter implements SqlSplittableAggFunction { if (bottom.getAggregation().getKind() == SqlKind.COUNT && (top.getAggregation().getKind() == SqlKind.SUM || top.getAggregation().getKind() == SqlKind.SUM0)) { - return AggregateCall.create(bottom.getAggregation(), + return AggregateCall.create(top.getParserPosition(), bottom.getAggregation(), bottom.isDistinct(), bottom.isApproximate(), false, bottom.rexList, bottom.getArgList(), bottom.filterArg, bottom.distinctKeys, bottom.getCollation(), @@ -228,7 +230,7 @@ class SelfSplitter implements SqlSplittableAggFunction { @Override public @Nullable AggregateCall merge(AggregateCall top, AggregateCall bottom) { if (top.getAggregation().getKind() == bottom.getAggregation().getKind()) { - return AggregateCall.create(bottom.getAggregation(), + return AggregateCall.create(top.getParserPosition(), bottom.getAggregation(), bottom.isDistinct(), bottom.isApproximate(), false, bottom.rexList, bottom.getArgList(), bottom.filterArg, bottom.distinctKeys, bottom.getCollation(), @@ -258,7 +260,7 @@ abstract class AbstractSumSplitter implements SqlSplittableAggFunction { @Override public @Nullable AggregateCall other(RelDataTypeFactory typeFactory, AggregateCall e) { final RelDataType type = typeFactory.createSqlType(SqlTypeName.BIGINT); - return AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, + return AggregateCall.create(e.getParserPosition(), SqlStdOperatorTable.COUNT, false, false, false, ImmutableList.of(), ImmutableIntList.of(), -1, null, RelCollations.EMPTY, type, null); } @@ -267,6 +269,7 @@ abstract class AbstractSumSplitter implements SqlSplittableAggFunction { Registry extra, int offset, RelDataType inputRowType, AggregateCall aggregateCall, int leftSubTotal, int rightSubTotal) { final List merges = new ArrayList<>(); + final SqlParserPos pos = aggregateCall.getParserPosition(); final List fieldList = inputRowType.getFieldList(); if (leftSubTotal >= 0) { final RelDataType type = fieldList.get(leftSubTotal).getType(); @@ -282,14 +285,14 @@ abstract class AbstractSumSplitter implements SqlSplittableAggFunction { node = merges.get(0); break; case 2: - node = rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, merges); - node = rexBuilder.makeAbstractCast(aggregateCall.type, node, false); + node = rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, merges); + node = rexBuilder.makeAbstractCast(pos, aggregateCall.type, node, false); break; default: throw new AssertionError("unexpected count " + merges); } int ordinal = extra.register(node); - return AggregateCall.create(getMergeAggFunctionOfTopSplit(), false, false, + return AggregateCall.create(pos, getMergeAggFunctionOfTopSplit(), false, false, false, aggregateCall.rexList, ImmutableList.of(ordinal), -1, aggregateCall.distinctKeys, aggregateCall.collation, aggregateCall.type, aggregateCall.name); @@ -300,7 +303,7 @@ abstract class AbstractSumSplitter implements SqlSplittableAggFunction { if (topKind == bottom.getAggregation().getKind() && (topKind == SqlKind.SUM || topKind == SqlKind.SUM0)) { - return AggregateCall.create(bottom.getAggregation(), + return AggregateCall.create(top.getParserPosition(), bottom.getAggregation(), bottom.isDistinct(), bottom.isApproximate(), false, bottom.rexList, bottom.getArgList(), bottom.filterArg, bottom.distinctKeys, bottom.getCollation(), diff --git a/core/src/main/java/org/apache/calcite/sql2rel/AggConverter.java b/core/src/main/java/org/apache/calcite/sql2rel/AggConverter.java index fb05f9377d6a..3d3ebdf95875 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/AggConverter.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/AggConverter.java @@ -521,6 +521,7 @@ private void translateAgg(SqlCall call, @Nullable SqlNode filter, } final AggregateCall aggCall = AggregateCall.create( + call.getParserPosition(), aggFunction, distinct, approximate, 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 f084d279b75b..b59ab152279f 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java @@ -1841,6 +1841,7 @@ private RexNode createCaseExpression( } newCall = rexBuilder.makeCall( + call.getParserPosition(), newType, operator, clonedOperands); 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 3a3a5494885d..b98ed76dcce9 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java @@ -685,8 +685,9 @@ private void flattenProjection(RewriteRexShuttle shuttle, // NOTE jvs 10-Feb-2005: This is a lame hack to keep special // functions which return row types working. RexNode newExp = exp; - List operands = ((RexCall) exp).getOperands(); - SqlOperator operator = ((RexCall) exp).getOperator(); + RexCall expCall = (RexCall) exp; + List operands = expCall.getOperands(); + SqlOperator operator = expCall.getOperator(); if (operator == SqlStdOperatorTable.ITEM && operands.get(0).getType().isStruct() @@ -732,7 +733,7 @@ private void flattenProjection(RewriteRexShuttle shuttle, } } else { newExp = - rexBuilder.makeCall(exp.getType(), operator, + rexBuilder.makeCall(expCall.getParserPosition(), exp.getType(), operator, shuttle.visitList(operands)); // flatten call result type flattenResultTypeOfRexCall(newExp, fieldName, flattenedExps); @@ -968,6 +969,7 @@ private RelDataType removeDistinct(RelDataType type) { RexNode input = rexCall.getOperands().get(0).accept(this); RelDataType targetType = removeDistinct(rexCall.getType()); return rexBuilder.makeCast( + rexCall.getParserPosition(), targetType, input); } 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 2b79213838a1..c892e7a7b813 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java @@ -1269,10 +1269,10 @@ private void substituteSubQuery(Blackboard bb, SubQuery subQuery) { ImmutableBitSet.of(), null, ImmutableList.of( - AggregateCall.create(SqlStdOperatorTable.COUNT, false, + AggregateCall.create(call.getParserPosition(), SqlStdOperatorTable.COUNT, false, false, false, ImmutableList.of(), ImmutableList.of(), -1, null, RelCollations.EMPTY, longType, null), - AggregateCall.create(SqlStdOperatorTable.COUNT, false, + AggregateCall.create(call.getParserPosition(), SqlStdOperatorTable.COUNT, false, false, false, ImmutableList.of(), args, -1, null, RelCollations.EMPTY, longType, null))); LogicalJoin join = @@ -1735,7 +1735,7 @@ public RelNode convertToSingleValueSubq( rexComparison = rexBuilder.makeCall(comparisonOp, leftKeys.get(0), - ensureSqlType(leftKeys.get(0).getType(), + ensureSqlType(rightVals.getParserPosition(), leftKeys.get(0).getType(), bb.convertExpression(rightVals))); } else { assert rightVals instanceof SqlCall; @@ -1746,9 +1746,11 @@ public RelNode convertToSingleValueSubq( RexUtil.composeConjunction(rexBuilder, Util.transform( Pair.zip(leftKeys, call.getOperandList()), - pair -> rexBuilder.makeCall(comparisonOp, pair.left, + pair -> rexBuilder.makeCall( + call.getParserPosition(), comparisonOp, pair.left, // TODO: remove requireNonNull when checkerframework issue resolved - ensureSqlType(requireNonNull(pair.left, "pair.left").getType(), + ensureSqlType(call.getParserPosition(), + requireNonNull(pair.left, "pair.left").getType(), bb.convertExpression(pair.right))))); } comparisons.add(rexComparison); @@ -1771,13 +1773,13 @@ public RelNode convertToSingleValueSubq( /** Ensures that an expression has a given {@link SqlTypeName}, applying a * cast if necessary. If the expression already has the right type family, * returns the expression unchanged. */ - private RexNode ensureSqlType(RelDataType type, RexNode node) { + private RexNode ensureSqlType(SqlParserPos pos, RelDataType type, RexNode node) { if (type.getSqlTypeName() == node.getType().getSqlTypeName() || (type.getSqlTypeName() == SqlTypeName.VARCHAR && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) { return node; } - return rexBuilder.ensureType(type, node, true); + return rexBuilder.ensureType(pos, type, node, true); } /** @@ -2302,7 +2304,7 @@ private RexNode convertOver(Blackboard bb, SqlNode node) { bb.window = window; RexNode rexAgg = exprConverter.convertCall(bb, aggCall); rexAgg = - rexBuilder.ensureType( + rexBuilder.ensureType(call.getParserPosition(), validator().getValidatedNodeType(call), rexAgg, false); // Walk over the tree and apply 'over' to all agg functions. This is @@ -2575,7 +2577,7 @@ protected void convertMatchRecognize(Blackboard bb, RexNode arg = requireNonNull(node.accept(this), node::toString); newOperands.add(arg); } - return rexBuilder.makeCall( + return rexBuilder.makeCall(call.getParserPosition(), validator().getUnknownType(), call.getOperator(), newOperands); } @@ -2623,15 +2625,16 @@ protected void convertMatchRecognize(Blackboard bb, final RexNode after; if (afterMatch instanceof SqlCall) { - List operands = ((SqlCall) afterMatch).getOperandList(); - SqlOperator operator = ((SqlCall) afterMatch).getOperator(); + final SqlCall afterCall = (SqlCall) afterMatch; + List operands = afterCall.getOperandList(); + SqlOperator operator = afterCall.getOperator(); assert operands.size() == 1; SqlIdentifier id = (SqlIdentifier) operands.get(0); assert patternVarsSet.contains(id.getSimple()) : id.getSimple() + " not defined in pattern"; RexNode rex = rexBuilder.makeLiteral(id.getSimple()); after = - rexBuilder.makeCall(validator().getUnknownType(), operator, + rexBuilder.makeCall(afterCall.getParserPosition(), validator().getUnknownType(), operator, ImmutableList.of(rex)); } else { after = matchBb.convertExpression(afterMatch); @@ -3959,7 +3962,7 @@ private RelNode createSource(RelOptTable targetTable, RelNode source, if (node == null) { node = rexBuilder.makeNullLiteral(field.getType()); } - projects.add(rexBuilder.ensureType(field.getType(), node, false), + projects.add(rexBuilder.ensureType(SqlParserPos.ZERO, field.getType(), node, false), field.getName()); } @@ -5597,7 +5600,8 @@ ImmutableList retrieveCursors() { } assert subQuery != null; rex = requireNonNull(subQuery.expr); - return StandardConvertletTable.castToValidatedType(expr, rex, + return StandardConvertletTable.castToValidatedType( + expr.getParserPosition(), expr, rex, validator(), rexBuilder, false); case SELECT: @@ -6023,13 +6027,15 @@ private class HistogramShuttle extends RexShuttle { exprs.set( 0, reinterpretCast - ? rexBuilder.makeReinterpretCast(histogramType, exprs.get(0), + ? rexBuilder.makeReinterpretCast( + call.getParserPosition(), histogramType, exprs.get(0), rexBuilder.makeLiteral(false)) - : rexBuilder.makeCast(histogramType, exprs.get(0))); + : rexBuilder.makeCast(call.getParserPosition(), histogramType, exprs.get(0))); } RexNode over = - relBuilder.aggregateCall(SqlStdOperatorTable.HISTOGRAM_AGG, exprs) + relBuilder.aggregateCall( + call.getParserPosition(), SqlStdOperatorTable.HISTOGRAM_AGG, exprs) .distinct(distinct) .ignoreNulls(ignoreNulls) .over() @@ -6042,7 +6048,7 @@ private class HistogramShuttle extends RexShuttle { .toRex(); RexNode histogramCall = - rexBuilder.makeCall( + rexBuilder.makeCall(call.getParserPosition(), histogramType, histogramOp, ImmutableList.of(over)); @@ -6052,13 +6058,13 @@ private class HistogramShuttle extends RexShuttle { if (histogramType != type) { if (reinterpretCast) { histogramCall = - rexBuilder.makeReinterpretCast( + rexBuilder.makeReinterpretCast(call.getParserPosition(), type, histogramCall, rexBuilder.makeLiteral(false)); } else { histogramCall = - rexBuilder.makeCast(type, histogramCall); + rexBuilder.makeCast(call.getParserPosition(), type, histogramCall); } } @@ -6069,7 +6075,7 @@ private class HistogramShuttle extends RexShuttle { SqlAggFunction aggOpToUse = needSum0 ? SqlStdOperatorTable.SUM0 : aggOp; - return relBuilder.aggregateCall(aggOpToUse, exprs) + return relBuilder.aggregateCall(call.getParserPosition(), aggOpToUse, exprs) .distinct(distinct) .ignoreNulls(ignoreNulls) .over() @@ -6476,7 +6482,8 @@ private class JsonFunctionRexRewriter extends RexShuttle { builder.add(call.operands.get(i)); } } - return rexBuilder.makeCall(SqlStdOperatorTable.JSON_OBJECT, builder.build()); + return rexBuilder.makeCall( + call.getParserPosition(), SqlStdOperatorTable.JSON_OBJECT, builder.build()); } if (call.getOperator() == SqlStdOperatorTable.JSON_ARRAY) { final ImmutableList.Builder builder = ImmutableList.builder(); @@ -6484,7 +6491,8 @@ private class JsonFunctionRexRewriter extends RexShuttle { for (int i = 1; i < call.operands.size(); ++i) { builder.add(forceChildJsonType(call.operands.get(i))); } - return rexBuilder.makeCall(SqlStdOperatorTable.JSON_ARRAY, builder.build()); + return rexBuilder.makeCall( + call.getParserPosition(), SqlStdOperatorTable.JSON_ARRAY, builder.build()); } return super.visitCall(call); } diff --git a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java index 9211f9778c99..fc30d4181978 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java @@ -174,7 +174,8 @@ private StandardConvertletTable() { (RexCall) StandardConvertletTable.this.convertCall(cx, call); if (e.getOperands().size() == 1 && SqlTypeUtil.isString(e.getOperands().get(0).getType())) { - return cx.getRexBuilder().makeCast(e.type, e.getOperands().get(0)); + return cx.getRexBuilder().makeCast( + e.getParserPosition(), e.type, e.getOperands().get(0)); } return e; }); @@ -390,7 +391,8 @@ private static RexNode convertQuantifyOperator(SqlRexContext cx, SqlCall call) { cx.getTypeFactory().createTypeWithNullability( cx.getTypeFactory().createSqlType(SqlTypeName.BOOLEAN), right.getType().isNullable() || left.getType().isNullable() || rightComponentType.isNullable()); - return rexBuilder.makeCall(returnType, call.getOperator(), ImmutableList.of(left, right)); + return rexBuilder.makeCall(call.getParserPosition(), returnType, + call.getOperator(), ImmutableList.of(left, right)); } /** Converts a call to the {@code NVL} function (and also its synonym, @@ -404,15 +406,15 @@ private static RexNode convertNvl(SqlRexContext cx, SqlCall call) { final RelDataType type = cx.getValidator().getValidatedNodeType(call); // Preserve Operand Nullability - return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, + return rexBuilder.makeCall(call.getParserPosition(), type, SqlStdOperatorTable.CASE, ImmutableList.of( - rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, + rexBuilder.makeCall(call.getParserPosition(), SqlStdOperatorTable.IS_NOT_NULL, operand0), - rexBuilder.makeCast( + rexBuilder.makeCast(call.getParserPosition(), cx.getTypeFactory() .createTypeWithNullability(type, operand0.getType().isNullable()), operand0), - rexBuilder.makeCast( + rexBuilder.makeCast(call.getParserPosition(), cx.getTypeFactory() .createTypeWithNullability(type, operand1.getType().isNullable()), operand1))); @@ -449,7 +451,7 @@ private static RexNode convertInstr(SqlRexContext cx, SqlCall call) { throw new UnsupportedOperationException("Position does not accept " + call.operandCount() + " operands"); } - return rexBuilder.makeCall(type, SqlStdOperatorTable.POSITION, exprs); + return rexBuilder.makeCall(call.getParserPosition(), type, SqlStdOperatorTable.POSITION, exprs); } /** Converts a call to the DECODE function. */ @@ -471,7 +473,7 @@ private static RexNode convertDecode(SqlRexContext cx, SqlCall call) { } else { exprs.add(rexBuilder.makeNullLiteral(type)); } - return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, exprs); + return rexBuilder.makeCall(call.getParserPosition(), type, SqlStdOperatorTable.CASE, exprs); } /** Converts a call to the IF function. @@ -483,7 +485,7 @@ private static RexNode convertIf(SqlRexContext cx, SqlCall call) { convertOperands(cx, call, SqlOperandTypeChecker.Consistency.NONE); final RelDataType type = cx.getValidator().getValidatedNodeType(call); - return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, operands); + return rexBuilder.makeCall(call.getParserPosition(), type, SqlStdOperatorTable.CASE, operands); } /** Converts an interval expression to a numeric multiplied by an interval @@ -524,22 +526,22 @@ private static RexNode and(RexBuilder rexBuilder, RexNode a0, RexNode a1) { return rexBuilder.makeCall(SqlStdOperatorTable.AND, a0, a1); } - private static RexNode divideInt(RexBuilder rexBuilder, RexNode a0, + private static RexNode divideInt(SqlParserPos pos, RexBuilder rexBuilder, RexNode a0, RexNode a1) { - return rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE_INTEGER, a0, a1); + return rexBuilder.makeCall(pos, SqlStdOperatorTable.DIVIDE_INTEGER, a0, a1); } - private static RexNode plus(RexBuilder rexBuilder, RexNode a0, RexNode a1) { - return rexBuilder.makeCall(SqlStdOperatorTable.PLUS, a0, a1); + private static RexNode plus(SqlParserPos pos, RexBuilder rexBuilder, RexNode a0, RexNode a1) { + return rexBuilder.makeCall(pos, SqlStdOperatorTable.PLUS, a0, a1); } - private static RexNode minus(RexBuilder rexBuilder, RexNode a0, RexNode a1) { - return rexBuilder.makeCall(SqlStdOperatorTable.MINUS, a0, a1); + private static RexNode minus(SqlParserPos pos, RexBuilder rexBuilder, RexNode a0, RexNode a1) { + return rexBuilder.makeCall(pos, SqlStdOperatorTable.MINUS, a0, a1); } - private static RexNode multiply(RexBuilder rexBuilder, RexNode a0, + private static RexNode multiply(SqlParserPos pos, RexBuilder rexBuilder, RexNode a0, RexNode a1) { - return rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, a0, a1); + return rexBuilder.makeCall(pos, SqlStdOperatorTable.MULTIPLY, a0, a1); } private static RexNode case_(RexBuilder rexBuilder, RexNode... args) { @@ -592,9 +594,10 @@ public RexNode convertCase( rexBuilder.deriveReturnType(call.getOperator(), exprList); for (int i : elseArgs(exprList.size())) { exprList.set(i, - rexBuilder.ensureType(type, exprList.get(i), false)); + rexBuilder.ensureType( + call.getParserPosition(), type, exprList.get(i), false)); } - return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, exprList); + return rexBuilder.makeCall(call.getParserPosition(), type, SqlStdOperatorTable.CASE, exprList); } public RexNode convertMultiset( @@ -622,7 +625,8 @@ public RexNode convertMultiset( // then '$SLICE() has type 'INTEGER MULTISET'. // This will be removed as the expression is translated. expr = - cx.getRexBuilder().makeCall(originalType, SqlStdOperatorTable.SLICE, + cx.getRexBuilder().makeCall( + call.getParserPosition(), originalType, SqlStdOperatorTable.SLICE, ImmutableList.of(expr)); } return expr; @@ -695,8 +699,8 @@ protected RexNode convertCast( RexLiteral castedInterval = rexBuilder.makeIntervalLiteral(sourceValue, intervalQualifier); - return castToValidatedType(call, castedInterval, validator, rexBuilder, - safe); + return castToValidatedType( + call.getParserPosition(), call, castedInterval, validator, rexBuilder, safe); } else if (left instanceof SqlNumericLiteral) { RexLiteral sourceInterval = (RexLiteral) cx.convertExpression(left); @@ -708,11 +712,12 @@ protected RexNode convertCast( rexBuilder.makeIntervalLiteral( SqlFunctions.multiply(sourceValue, multiplier), intervalQualifier); - return castToValidatedType(call, castedInterval, validator, rexBuilder, - safe); + return castToValidatedType( + call.getParserPosition(), call, castedInterval, validator, rexBuilder, safe); } RexNode value = cx.convertExpression(left); - return castToValidatedType(call, value, validator, rexBuilder, safe); + return castToValidatedType( + call.getParserPosition(), call, value, validator, rexBuilder, safe); } final RexNode arg = cx.convertExpression(left); @@ -751,11 +756,12 @@ protected RexNode convertCast( type = typeFactory.createTypeWithNullability(type, isn); } } - return rexBuilder.makeCast(type, arg, safe, safe); + return rexBuilder.makeCast(call.getParserPosition(), type, arg, safe, safe); } protected RexNode convertFloorCeil(SqlRexContext cx, SqlCall call) { final boolean floor = call.getKind() == SqlKind.FLOOR; + final SqlParserPos pos = call.getParserPosition(); // Rewrite floor, ceil of interval if (call.operandCount() == 1 && call.operand(0) instanceof SqlIntervalLiteral) { @@ -773,19 +779,19 @@ protected RexNode convertFloorCeil(SqlRexContext cx, SqlCall call) { RexNode pad = rexBuilder.makeExactLiteral(val.subtract(BigDecimal.ONE)); RexNode cast = - rexBuilder.makeReinterpretCast(rexInterval.getType(), pad, + rexBuilder.makeReinterpretCast(pos, rexInterval.getType(), pad, rexBuilder.makeLiteral(false)); RexNode sum = - floor ? minus(rexBuilder, rexInterval, cast) - : plus(rexBuilder, rexInterval, cast); + floor ? minus(pos, rexBuilder, rexInterval, cast) + : plus(pos, rexBuilder, rexInterval, cast); RexNode kase = floor ? case_(rexBuilder, rexInterval, cond, sum) : case_(rexBuilder, sum, cond, rexInterval); RexNode factor = rexBuilder.makeExactLiteral(val); - RexNode div = divideInt(rexBuilder, kase, factor); - return multiply(rexBuilder, div, factor); + RexNode div = divideInt(pos, rexBuilder, kase, factor); + return multiply(pos, rexBuilder, div, factor); } // normal floor, ceil function @@ -795,11 +801,12 @@ protected RexNode convertFloorCeil(SqlRexContext cx, SqlCall call) { protected RexNode convertCharset( @UnknownInitialization StandardConvertletTable this, SqlRexContext cx, SqlCall call) { + final SqlParserPos pos = call.getParserPosition(); final SqlNode expr = call.operand(0); final String srcCharset = call.operand(1).toString(); final String destCharset = call.operand(2).toString(); final RexBuilder rexBuilder = cx.getRexBuilder(); - return rexBuilder.makeCall(SqlStdOperatorTable.CONVERT, + return rexBuilder.makeCall(pos, SqlStdOperatorTable.CONVERT, cx.convertExpression(expr), rexBuilder.makeLiteral(srcCharset), rexBuilder.makeLiteral(destCharset)); @@ -808,10 +815,11 @@ protected RexNode convertCharset( protected RexNode translateCharset( @UnknownInitialization StandardConvertletTable this, SqlRexContext cx, SqlCall call) { + final SqlParserPos pos = call.getParserPosition(); final SqlNode expr = call.operand(0); final String transcodingName = call.operand(1).toString(); final RexBuilder rexBuilder = cx.getRexBuilder(); - return rexBuilder.makeCall(SqlStdOperatorTable.TRANSLATE, + return rexBuilder.makeCall(pos, SqlStdOperatorTable.TRANSLATE, cx.convertExpression(expr), rexBuilder.makeLiteral(transcodingName)); } @@ -829,16 +837,17 @@ public RexNode convertExtract( } @SuppressWarnings("unused") - private static RexNode mod(RexBuilder rexBuilder, RelDataType resType, RexNode res, + private static RexNode mod(SqlParserPos pos, RexBuilder rexBuilder, + RelDataType resType, RexNode res, BigDecimal val) { if (val.equals(BigDecimal.ONE)) { return res; } - return rexBuilder.makeCall(SqlStdOperatorTable.MOD, res, + return rexBuilder.makeCall(pos, SqlStdOperatorTable.MOD, res, rexBuilder.makeExactLiteral(val, resType)); } - private static RexNode divide(RexBuilder rexBuilder, RexNode res, + private static RexNode divide(SqlParserPos pos, RexBuilder rexBuilder, RexNode res, BigDecimal val) { if (val.equals(BigDecimal.ONE)) { return res; @@ -850,13 +859,13 @@ private static RexNode divide(RexBuilder rexBuilder, RexNode res, try { final BigDecimal reciprocal = BigDecimal.ONE.divide(val, RoundingMode.UNNECESSARY); - return multiply(rexBuilder, res, + return multiply(pos, rexBuilder, res, rexBuilder.makeExactLiteral(reciprocal)); } catch (ArithmeticException e) { // ignore - reciprocal is not an integer } } - return divideInt(rexBuilder, res, rexBuilder.makeExactLiteral(val)); + return divideInt(pos, rexBuilder, res, rexBuilder.makeExactLiteral(val)); } public RexNode convertDatetimeMinus( @@ -871,7 +880,7 @@ public RexNode convertDatetimeMinus( final RelDataType resType = cx.getValidator().getValidatedNodeType(call); - return rexBuilder.makeCall(resType, op, exprs.subList(0, 2)); + return rexBuilder.makeCall(call.getParserPosition(), resType, op, exprs.subList(0, 2)); } public RexNode convertFunction( @@ -888,7 +897,7 @@ public RexNode convertFunction( if (returnType == null) { returnType = cx.getRexBuilder().deriveReturnType(fun, exprs); } - return cx.getRexBuilder().makeCall(returnType, fun, exprs); + return cx.getRexBuilder().makeCall(call.getParserPosition(), returnType, fun, exprs); } public RexNode convertWindowFunction( @@ -905,7 +914,7 @@ public RexNode convertWindowFunction( if (returnType == null) { returnType = cx.getRexBuilder().deriveReturnType(fun, exprs); } - return cx.getRexBuilder().makeCall(returnType, fun, exprs); + return cx.getRexBuilder().makeCall(call.getParserPosition(), returnType, fun, exprs); } public RexNode convertJsonValueFunction( @@ -923,7 +932,7 @@ public RexNode convertJsonValueFunction( RelDataType returnType = cx.getValidator().getValidatedNodeTypeIfKnown(call); requireNonNull(returnType, () -> "Unable to get type of " + call); - return cx.getRexBuilder().makeCall(returnType, fun, exprs); + return cx.getRexBuilder().makeCall(call.getParserPosition(), returnType, fun, exprs); } public RexNode convertSequenceValue( @@ -937,7 +946,7 @@ public RexNode convertSequenceValue( final String key = Util.listToString(id.names); RelDataType returnType = cx.getValidator().getValidatedNodeType(call); - return cx.getRexBuilder().makeCall(returnType, fun, + return cx.getRexBuilder().makeCall(call.getParserPosition(), returnType, fun, ImmutableList.of(cx.getRexBuilder().makeLiteral(key))); } @@ -964,7 +973,7 @@ public RexNode convertAggregateFunction( }; returnType = fun.inferReturnType(binding); } - return cx.getRexBuilder().makeCall(returnType, fun, exprs); + return cx.getRexBuilder().makeCall(call.getParserPosition(), returnType, fun, exprs); } private static RexNode makeConstructorCall( @@ -1038,7 +1047,7 @@ private RexNode convertItem( } } RelDataType type = rexBuilder.deriveReturnType(op, exprs); - return rexBuilder.makeCall(type, op, RexUtil.flatten(exprs, op)); + return rexBuilder.makeCall(call.getParserPosition(), type, op, RexUtil.flatten(exprs, op)); } /** @@ -1075,11 +1084,11 @@ public RexNode convertCall( final RexCall call1 = (RexCall) expr1; final List eqList = new ArrayList<>(); Pair.forEach(call0.getOperands(), call1.getOperands(), (x, y) -> - eqList.add(rexBuilder.makeCall(op, x, y))); + eqList.add(rexBuilder.makeCall(call.getParserPosition(), op, x, y))); return RexUtil.composeConjunction(rexBuilder, eqList); } } - return rexBuilder.makeCall(type, op, RexUtil.flatten(exprs, op)); + return rexBuilder.makeCall(call.getParserPosition(), type, op, RexUtil.flatten(exprs, op)); } private static List elseArgs(int count) { @@ -1125,7 +1134,7 @@ private static List convertOperands(SqlRexContext cx, final List oldExprs = new ArrayList<>(exprs); exprs.clear(); Pair.forEach(oldExprs, operandTypes, (expr, type) -> - exprs.add(cx.getRexBuilder().ensureType(type, expr, true))); + exprs.add(cx.getRexBuilder().ensureType(call.getParserPosition(), type, expr, true))); } if (exprs.size() > 1) { final RelDataType type = @@ -1134,7 +1143,7 @@ private static List convertOperands(SqlRexContext cx, final List oldExprs = new ArrayList<>(exprs); exprs.clear(); for (RexNode expr : oldExprs) { - exprs.add(cx.getRexBuilder().ensureType(type, expr, true)); + exprs.add(cx.getRexBuilder().ensureType(call.getParserPosition(), type, expr, true)); } } } @@ -1218,7 +1227,7 @@ private RexNode convertPlus( break; } } - return rexBuilder.makeCall(rex.getType(), + return rexBuilder.makeCall(call.getParserPosition(), rex.getType(), SqlStdOperatorTable.DATETIME_PLUS, operands); default: return rex; @@ -1280,7 +1289,7 @@ public RexNode convertBetween( final SqlBetweenOperator betweenOp = (SqlBetweenOperator) call.getOperator(); if (betweenOp.isNegated()) { - res = rexBuilder.makeCall(SqlStdOperatorTable.NOT, res); + res = rexBuilder.makeCall(call.getParserPosition(), SqlStdOperatorTable.NOT, res); } return res; } @@ -1353,7 +1362,8 @@ public RexNode convertRow( } final RelDataType type = rexBuilder.deriveReturnType(SqlStdOperatorTable.COLUMN_LIST, columns); - return rexBuilder.makeCall(type, SqlStdOperatorTable.COLUMN_LIST, columns); + return rexBuilder.makeCall( + call.getParserPosition(), type, SqlStdOperatorTable.COLUMN_LIST, columns); } /** @@ -1445,14 +1455,14 @@ public RexNode castToValidatedType( SqlRexContext cx, SqlCall call, RexNode value) { - return castToValidatedType(call, value, cx.getValidator(), + return castToValidatedType(call.getParserPosition(), call, value, cx.getValidator(), cx.getRexBuilder(), false); } @Deprecated // to be removed before 2.0 public static RexNode castToValidatedType(SqlNode node, RexNode e, SqlValidator validator, RexBuilder rexBuilder) { - return castToValidatedType(node, e, validator, rexBuilder, false); + return castToValidatedType(node.getParserPosition(), node, e, validator, rexBuilder, false); } /** @@ -1460,13 +1470,13 @@ public static RexNode castToValidatedType(SqlNode node, RexNode e, * was already of the validated type, then the value is returned without an * additional cast. */ - public static RexNode castToValidatedType(SqlNode node, RexNode e, + public static RexNode castToValidatedType(SqlParserPos pos, SqlNode node, RexNode e, SqlValidator validator, RexBuilder rexBuilder, boolean safe) { final RelDataType type = validator.getValidatedNodeType(node); if (e.getType() == type) { return e; } - return rexBuilder.makeCast(type, e, safe, safe); + return rexBuilder.makeCast(pos, type, e, safe, safe); } /** Convertlet that handles {@code COVAR_POP}, {@code COVAR_SAMP}, @@ -1503,7 +1513,7 @@ private static class RegrCovarianceConvertlet implements SqlRexConvertlet { throw Util.unexpected(kind); } RexNode rex = cx.convertExpression(expr); - return cx.getRexBuilder().ensureType(type, rex, true); + return cx.getRexBuilder().ensureType(call.getParserPosition(), type, rex, true); } private static SqlNode expandRegrSzz( @@ -1634,7 +1644,7 @@ private static class AvgVarianceConvertlet implements SqlRexConvertlet { throw Util.unexpected(kind); } RexNode rex = cx.convertExpression(expr); - return cx.getRexBuilder().ensureType(type, rex, true); + return cx.getRexBuilder().ensureType(call.getParserPosition(), type, rex, true); } private static SqlNode expandAvg( @@ -1763,7 +1773,7 @@ private static class TrimConvertlet implements SqlRexConvertlet { final RexBuilder rexBuilder = cx.getRexBuilder(); final RexNode operand = cx.convertExpression(call.getOperandList().get(0)); - return rexBuilder.makeCall(SqlStdOperatorTable.TRIM, + return rexBuilder.makeCall(call.getParserPosition(), SqlStdOperatorTable.TRIM, rexBuilder.makeFlag(flag), rexBuilder.makeLiteral(" "), operand); } } @@ -1804,7 +1814,8 @@ private static class GreatestConvertlet implements SqlRexConvertlet { final List list = new ArrayList<>(); final List orList = new ArrayList<>(); for (RexNode expr : exprs) { - orList.add(rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, expr)); + orList.add( + rexBuilder.makeCall(call.getParserPosition(), SqlStdOperatorTable.IS_NULL, expr)); } list.add(RexUtil.composeDisjunction(rexBuilder, orList)); list.add(rexBuilder.makeNullLiteral(type)); @@ -1813,13 +1824,13 @@ private static class GreatestConvertlet implements SqlRexConvertlet { final List andList = new ArrayList<>(); for (int j = i + 1; j < exprs.size(); j++) { final RexNode expr2 = exprs.get(j); - andList.add(rexBuilder.makeCall(op, expr, expr2)); + andList.add(rexBuilder.makeCall(call.getParserPosition(), op, expr, expr2)); } list.add(RexUtil.composeConjunction(rexBuilder, andList)); list.add(expr); } list.add(exprs.get(exprs.size() - 1)); - return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, list); + return rexBuilder.makeCall(call.getParserPosition(), type, SqlStdOperatorTable.CASE, list); } } @@ -1893,6 +1904,7 @@ private static class SubstrConvertlet implements SqlRexConvertlet { // FOR CASE WHEN length < 0 THEN 0 ELSE length END) final RexBuilder rexBuilder = cx.getRexBuilder(); + final SqlParserPos pos = call.getParserPosition(); final List exprs = convertOperands(cx, call, SqlOperandTypeChecker.Consistency.NONE); final RexNode value = exprs.get(0); @@ -1902,10 +1914,10 @@ private static class SubstrConvertlet implements SqlRexConvertlet { final RexLiteral oneLiteral = rexBuilder.makeLiteral(1, startType); final RexNode valueLength = SqlTypeUtil.isBinary(value.getType()) - ? rexBuilder.makeCall(SqlStdOperatorTable.OCTET_LENGTH, value) - : rexBuilder.makeCall(SqlStdOperatorTable.CHAR_LENGTH, value); + ? rexBuilder.makeCall(pos, SqlStdOperatorTable.OCTET_LENGTH, value) + : rexBuilder.makeCall(pos, SqlStdOperatorTable.CHAR_LENGTH, value); final RexNode valueLengthPlusOne = - rexBuilder.makeCall(SqlStdOperatorTable.PLUS, valueLength, + rexBuilder.makeCall(pos, SqlStdOperatorTable.PLUS, valueLength, oneLiteral); final RexNode newStart; @@ -1913,8 +1925,8 @@ private static class SubstrConvertlet implements SqlRexConvertlet { case POSTGRESQL: if (call.operandCount() == 2) { newStart = - rexBuilder.makeCall(SqlStdOperatorTable.CASE, - rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, start, + rexBuilder.makeCall(pos, SqlStdOperatorTable.CASE, + rexBuilder.makeCall(pos, SqlStdOperatorTable.LESS_THAN, start, oneLiteral), oneLiteral, start); } else { @@ -1923,37 +1935,37 @@ private static class SubstrConvertlet implements SqlRexConvertlet { break; case BIG_QUERY: newStart = - rexBuilder.makeCall(SqlStdOperatorTable.CASE, - rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, start, + rexBuilder.makeCall(pos, SqlStdOperatorTable.CASE, + rexBuilder.makeCall(pos, SqlStdOperatorTable.EQUALS, start, zeroLiteral), oneLiteral, - rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, start, + rexBuilder.makeCall(pos, SqlStdOperatorTable.LESS_THAN, start, zeroLiteral), - rexBuilder.makeCall(SqlStdOperatorTable.PLUS, start, + rexBuilder.makeCall(pos, SqlStdOperatorTable.PLUS, start, valueLengthPlusOne), start); break; default: newStart = - rexBuilder.makeCall(SqlStdOperatorTable.CASE, - rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, start, + rexBuilder.makeCall(pos, SqlStdOperatorTable.CASE, + rexBuilder.makeCall(pos, SqlStdOperatorTable.EQUALS, start, zeroLiteral), library == SqlLibrary.MYSQL ? valueLengthPlusOne : oneLiteral, - rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, - rexBuilder.makeCall(SqlStdOperatorTable.PLUS, start, + rexBuilder.makeCall(pos, SqlStdOperatorTable.LESS_THAN, + rexBuilder.makeCall(pos, SqlStdOperatorTable.PLUS, start, valueLengthPlusOne), oneLiteral), valueLengthPlusOne, - rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, start, + rexBuilder.makeCall(pos, SqlStdOperatorTable.LESS_THAN, start, zeroLiteral), - rexBuilder.makeCall(SqlStdOperatorTable.PLUS, start, + rexBuilder.makeCall(pos, SqlStdOperatorTable.PLUS, start, valueLengthPlusOne), start); break; } if (call.operandCount() == 2) { - return rexBuilder.makeCall(SqlStdOperatorTable.SUBSTRING, value, + return rexBuilder.makeCall(pos, SqlStdOperatorTable.SUBSTRING, value, newStart); } @@ -1966,19 +1978,19 @@ private static class SubstrConvertlet implements SqlRexConvertlet { break; default: newLength = - rexBuilder.makeCall(SqlStdOperatorTable.CASE, - rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, length, + rexBuilder.makeCall(pos, SqlStdOperatorTable.CASE, + rexBuilder.makeCall(pos, SqlStdOperatorTable.LESS_THAN, length, zeroLiteral), zeroLiteral, length); } final RexNode substringCall = - rexBuilder.makeCall(SqlStdOperatorTable.SUBSTRING, value, newStart, + rexBuilder.makeCall(pos, SqlStdOperatorTable.SUBSTRING, value, newStart, newLength); switch (library) { case BIG_QUERY: - return rexBuilder.makeCall(SqlStdOperatorTable.CASE, - rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, - rexBuilder.makeCall(SqlStdOperatorTable.PLUS, start, + return rexBuilder.makeCall(pos, SqlStdOperatorTable.CASE, + rexBuilder.makeCall(pos, SqlStdOperatorTable.LESS_THAN, + rexBuilder.makeCall(pos, SqlStdOperatorTable.PLUS, start, valueLengthPlusOne), oneLiteral), value, substringCall); default: @@ -1997,6 +2009,7 @@ private static class TimestampAddConvertlet implements SqlRexConvertlet { // => timestamp + interval // "timestamp" may be of type TIMESTAMP or TIMESTAMP WITH LOCAL TIME ZONE. final RexBuilder rexBuilder = cx.getRexBuilder(); + final SqlParserPos pos = call.getParserPosition(); SqlIntervalQualifier qualifier; final RexNode op1; final RexNode op2; @@ -2027,8 +2040,8 @@ private static class TimestampAddConvertlet implements SqlRexConvertlet { // If the TIMESTAMPADD call has type TIMESTAMP and op2 has type DATE // (which can happen for sub-day time frames such as HOUR), cast op2 to // TIMESTAMP. - final RexNode op2b = rexBuilder.makeCast(type, op2); - return rexBuilder.makeCall(type, SqlStdOperatorTable.TIMESTAMP_ADD, + final RexNode op2b = rexBuilder.makeCast(pos, type, op2); + return rexBuilder.makeCall(pos, type, SqlStdOperatorTable.TIMESTAMP_ADD, ImmutableList.of(timeFrameName, op1, op2b)); } @@ -2043,19 +2056,19 @@ private static class TimestampAddConvertlet implements SqlRexConvertlet { case MICROSECOND: case NANOSECOND: interval2Add = - divide(rexBuilder, - multiply(rexBuilder, + divide(pos, rexBuilder, + multiply(pos, rexBuilder, rexBuilder.makeIntervalLiteral(BigDecimal.ONE, qualifier), op1), BigDecimal.ONE.divide(unit.multiplier, RoundingMode.UNNECESSARY)); break; default: interval2Add = - multiply(rexBuilder, + multiply(pos, rexBuilder, rexBuilder.makeIntervalLiteral(unit.multiplier, qualifier), op1); } - return rexBuilder.makeCall(SqlStdOperatorTable.DATETIME_PLUS, + return rexBuilder.makeCall(pos, SqlStdOperatorTable.DATETIME_PLUS, op2, interval2Add); } } @@ -2066,13 +2079,14 @@ private static class TimestampAddConvertlet implements SqlRexConvertlet { private static class TruncConvertlet implements SqlRexConvertlet { @Override public RexNode convertCall(SqlRexContext cx, SqlCall call) { final RexBuilder rexBuilder = cx.getRexBuilder(); + final SqlParserPos pos = call.getParserPosition(); RexNode op1 = cx.convertExpression(call.operand(0)); RexNode op2 = cx.convertExpression(call.operand(1)); if (op1.getType().getSqlTypeName() == SqlTypeName.DATE) { RelDataType type = cx.getValidator().getValidatedNodeType(call); - op1 = cx.getRexBuilder().makeCast(type, op1); + op1 = cx.getRexBuilder().makeCast(pos, type, op1); } - return rexBuilder.makeCall(call.getOperator(), op1, op2); + return rexBuilder.makeCall(pos, call.getOperator(), op1, op2); } } @@ -2082,6 +2096,7 @@ private static class TimestampSubConvertlet implements SqlRexConvertlet { // TIMESTAMP_SUB(timestamp, interval) // => timestamp - count * INTERVAL '1' UNIT final RexBuilder rexBuilder = cx.getRexBuilder(); + final SqlParserPos pos = call.getParserPosition(); final SqlBasicCall operandCall = call.operand(1); SqlIntervalQualifier qualifier = operandCall.operand(1); final RexNode op1 = cx.convertExpression(operandCall.operand(0)); @@ -2095,19 +2110,19 @@ private static class TimestampSubConvertlet implements SqlRexConvertlet { case MICROSECOND: case NANOSECOND: interval2Sub = - divide(rexBuilder, - multiply(rexBuilder, + divide(pos, rexBuilder, + multiply(pos, rexBuilder, rexBuilder.makeIntervalLiteral(BigDecimal.ONE, qualifier), op1), BigDecimal.ONE.divide(unit.multiplier, RoundingMode.UNNECESSARY)); break; default: interval2Sub = - multiply(rexBuilder, + multiply(pos, rexBuilder, rexBuilder.makeIntervalLiteral(unit.multiplier, qualifier), op1); } - return rexBuilder.makeCall(SqlInternalOperators.MINUS_DATE2, + return rexBuilder.makeCall(pos, SqlInternalOperators.MINUS_DATE2, op2, interval2Sub); } } @@ -2139,6 +2154,7 @@ private static class TimestampDiffConvertlet implements SqlRexConvertlet { final boolean preTruncate; final RexNode op1; final RexNode op2; + final SqlParserPos pos = call.getParserPosition(); if (call.operand(0).getKind() == SqlKind.INTERVAL_QUALIFIER) { qualifier = call.operand(0); preTruncate = false; @@ -2165,11 +2181,11 @@ private static class TimestampDiffConvertlet implements SqlRexConvertlet { // computing the difference. if (preTruncate) { truncateFn = e -> - rexBuilder.makeCall(e.getType(), + rexBuilder.makeCall(pos, e.getType(), SqlLibraryOperators.TIMESTAMP_TRUNC, ImmutableList.of(e, timeFrameName)); } - return rexBuilder.makeCall(cx.getValidator().getValidatedNodeType(call), + return rexBuilder.makeCall(pos, cx.getValidator().getValidatedNodeType(call), SqlStdOperatorTable.TIMESTAMP_DIFF, ImmutableList.of(timeFrameName, truncateFn.apply(op1), truncateFn.apply(op2))); @@ -2181,7 +2197,7 @@ private static class TimestampDiffConvertlet implements SqlRexConvertlet { // should be returned. final RexNode timeUnit = cx.convertExpression(qualifier); truncateFn = e -> - rexBuilder.makeCall(e.getType(), + rexBuilder.makeCall(call.getParserPosition(), e.getType(), SqlLibraryOperators.TIMESTAMP_TRUNC, ImmutableList.of(e, timeUnit)); } @@ -2222,15 +2238,15 @@ private static class TimestampDiffConvertlet implements SqlRexConvertlet { typeFactory.createSqlIntervalType(qualifier), op1.getType().isNullable() || op2.getType().isNullable()); final RexNode call2 = - rexBuilder.makeCall(intervalType, + rexBuilder.makeCall(pos, intervalType, SqlStdOperatorTable.MINUS_DATE, ImmutableList.of(truncateFn.apply(op2), truncateFn.apply(op1))); final RelDataType intType = typeFactory.createTypeWithNullability( typeFactory.createSqlType(sqlTypeName), SqlTypeUtil.containsNullable(call2.getType())); - RexNode e = rexBuilder.makeCast(intType, call2); - return rexBuilder.multiplyDivide(e, multiplier, divider); + RexNode e = rexBuilder.makeCast(pos, intType, call2); + return rexBuilder.multiplyDivide(pos, e, multiplier, divider); } } } 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 8d8d48bd078a..a7da7d01000d 100644 --- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java +++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java @@ -100,6 +100,7 @@ import org.apache.calcite.sql.fun.SqlLikeOperator; import org.apache.calcite.sql.fun.SqlQuantifyOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlReturnTypeInference; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.type.TableFunctionReturnTypeInference; @@ -726,7 +727,7 @@ public RexNode call(SqlOperator operator, RexNode... operands) { } /** Creates a call to a scalar operator. */ - private RexCall call(SqlOperator operator, List operandList) { + private RexCall call(SqlParserPos pos, SqlOperator operator, List operandList) { switch (operator.getKind()) { case LIKE: case SIMILAR: @@ -745,13 +746,13 @@ private RexCall call(SqlOperator operator, List operandList) { } final RexBuilder builder = cluster.getRexBuilder(); final RelDataType type = builder.deriveReturnType(operator, operandList); - return (RexCall) builder.makeCall(type, operator, operandList); + return (RexCall) builder.makeCall(pos, type, operator, operandList); } /** Creates a call to a scalar operator. */ public RexNode call(SqlOperator operator, Iterable operands) { - return call(operator, ImmutableList.copyOf(operands)); + return call(SqlParserPos.ZERO, operator, ImmutableList.copyOf(operands)); } /** Creates an IN predicate with a list of values. @@ -1152,6 +1153,12 @@ public RexNode isNotNull(RexNode operand) { return call(SqlStdOperatorTable.IS_NOT_NULL, operand); } + /** Creates an expression that casts an expression to a given type. */ + public RexNode cast(SqlParserPos pos, RexNode expr, SqlTypeName typeName) { + final RelDataType type = cluster.getTypeFactory().createSqlType(typeName); + return cluster.getRexBuilder().makeCast(pos, type, expr); + } + /** Creates an expression that casts an expression to a given type. */ public RexNode cast(RexNode expr, SqlTypeName typeName) { final RelDataType type = cluster.getTypeFactory().createSqlType(typeName); @@ -1160,19 +1167,19 @@ public RexNode cast(RexNode expr, SqlTypeName typeName) { /** Creates an expression that casts an expression to a type with a given name * and precision or length. */ - public RexNode cast(RexNode expr, SqlTypeName typeName, int precision) { + public RexNode cast(SqlParserPos pos, RexNode expr, SqlTypeName typeName, int precision) { final RelDataType type = cluster.getTypeFactory().createSqlType(typeName, precision); - return cluster.getRexBuilder().makeCast(type, expr); + return cluster.getRexBuilder().makeCast(pos, type, expr); } /** Creates an expression that casts an expression to a type with a given * name, precision and scale. */ - public RexNode cast(RexNode expr, SqlTypeName typeName, int precision, + public RexNode cast(SqlParserPos pos, RexNode expr, SqlTypeName typeName, int precision, int scale) { final RelDataType type = cluster.getTypeFactory().createSqlType(typeName, precision, scale); - return cluster.getRexBuilder().makeCast(type, expr); + return cluster.getRexBuilder().makeCast(pos, type, expr); } /** @@ -1369,38 +1376,18 @@ private GroupKey groupKey_(ImmutableBitSet groupSet, return groupKey_(nodes, Util.transform(groupSets, this::fields)); } - @Deprecated // to be removed before 2.0 - public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct, - RexNode filter, @Nullable String alias, RexNode... operands) { - return aggregateCall(aggFunction, distinct, false, false, filter, null, - ImmutableList.of(), alias, ImmutableList.of(), - ImmutableList.copyOf(operands)); - } - - @Deprecated // to be removed before 2.0 - public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct, - boolean approximate, RexNode filter, @Nullable String alias, - RexNode... operands) { - return aggregateCall(aggFunction, distinct, approximate, false, filter, - null, ImmutableList.of(), alias, ImmutableList.of(), - ImmutableList.copyOf(operands)); - } - - @Deprecated // to be removed before 2.0 - public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct, - RexNode filter, @Nullable String alias, - Iterable operands) { - return aggregateCall(aggFunction, distinct, false, false, filter, null, - ImmutableList.of(), alias, ImmutableList.of(), - ImmutableList.copyOf(operands)); - } - - @Deprecated // to be removed before 2.0 - public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct, - boolean approximate, RexNode filter, @Nullable String alias, + /** Creates a call to an aggregate function. + * + *

To add other operands, apply + * {@link AggCall#distinct()}, + * {@link AggCall#approximate(boolean)}, + * {@link AggCall#filter(RexNode...)}, + * {@link AggCall#sort}, + * {@link AggCall#as} to the result. */ + public AggCall aggregateCall(SqlParserPos pos, SqlAggFunction aggFunction, Iterable operands) { - return aggregateCall(aggFunction, distinct, approximate, false, filter, - null, ImmutableList.of(), alias, ImmutableList.of(), + return aggregateCall(pos, aggFunction, false, false, false, null, null, + ImmutableList.of(), null, ImmutableList.of(), ImmutableList.copyOf(operands)); } @@ -1412,9 +1399,9 @@ public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct, * {@link AggCall#filter(RexNode...)}, * {@link AggCall#sort}, * {@link AggCall#as} to the result. */ - public AggCall aggregateCall(SqlAggFunction aggFunction, - Iterable operands) { - return aggregateCall(aggFunction, false, false, false, null, null, + public AggCall aggregateCall(SqlParserPos pos, SqlAggFunction aggFunction, + RexNode... operands) { + return aggregateCall(pos, aggFunction, false, false, false, null, null, ImmutableList.of(), null, ImmutableList.of(), ImmutableList.copyOf(operands)); } @@ -1429,7 +1416,7 @@ public AggCall aggregateCall(SqlAggFunction aggFunction, * {@link AggCall#as} to the result. */ public AggCall aggregateCall(SqlAggFunction aggFunction, RexNode... operands) { - return aggregateCall(aggFunction, false, false, false, null, null, + return aggregateCall(SqlParserPos.ZERO, aggFunction, false, false, false, null, null, ImmutableList.of(), null, ImmutableList.of(), ImmutableList.copyOf(operands)); } @@ -1437,7 +1424,8 @@ public AggCall aggregateCall(SqlAggFunction aggFunction, /** Creates a call to an aggregate function as a copy of an * {@link AggregateCall}. */ public AggCall aggregateCall(AggregateCall a) { - return aggregateCall(a.getAggregation(), a.isDistinct(), a.isApproximate(), + return aggregateCall(a.getParserPosition(), + a.getAggregation(), a.isDistinct(), a.isApproximate(), a.ignoreNulls(), a.filterArg < 0 ? null : field(a.filterArg), a.distinctKeys == null ? null : fields(a.distinctKeys), fields(a.collation), a.name, ImmutableList.copyOf(a.rexList), @@ -1447,7 +1435,8 @@ public AggCall aggregateCall(AggregateCall a) { /** Creates a call to an aggregate function as a copy of an * {@link AggregateCall}, applying a mapping. */ public AggCall aggregateCall(AggregateCall a, Mapping mapping) { - return aggregateCall(a.getAggregation(), a.isDistinct(), a.isApproximate(), + return aggregateCall(a.getParserPosition(), + a.getAggregation(), a.isDistinct(), a.isApproximate(), a.ignoreNulls(), a.filterArg < 0 ? null : field(Mappings.apply(mapping, a.filterArg)), a.distinctKeys == null ? null @@ -1458,12 +1447,12 @@ public AggCall aggregateCall(AggregateCall a, Mapping mapping) { } /** Creates a call to an aggregate function with all applicable operands. */ - protected AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct, + protected AggCall aggregateCall(SqlParserPos pos, SqlAggFunction aggFunction, boolean distinct, boolean approximate, boolean ignoreNulls, @Nullable RexNode filter, @Nullable ImmutableList distinctKeys, ImmutableList orderKeys, @Nullable String alias, ImmutableList preOperands, ImmutableList operands) { - return new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + return new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, filter, alias, preOperands, operands, distinctKeys, orderKeys); } @@ -1481,7 +1470,7 @@ public AggCall count(Iterable operands) { * optionally distinct and with an alias. */ public AggCall count(boolean distinct, @Nullable String alias, RexNode... operands) { - return aggregateCall(SqlStdOperatorTable.COUNT, distinct, false, false, null, + return aggregateCall(SqlParserPos.ZERO, SqlStdOperatorTable.COUNT, distinct, false, false, null, null, ImmutableList.of(), alias, ImmutableList.of(), ImmutableList.copyOf(operands)); } @@ -1490,7 +1479,7 @@ public AggCall count(boolean distinct, @Nullable String alias, * optionally distinct and with an alias. */ public AggCall count(boolean distinct, @Nullable String alias, Iterable operands) { - return aggregateCall(SqlStdOperatorTable.COUNT, distinct, false, false, null, + return aggregateCall(SqlParserPos.ZERO, SqlStdOperatorTable.COUNT, distinct, false, false, null, null, ImmutableList.of(), alias, ImmutableList.of(), ImmutableList.copyOf(operands)); } @@ -1501,29 +1490,29 @@ public AggCall countStar(@Nullable String alias) { } /** Creates a call to the {@code SUM} aggregate function. */ - public AggCall sum(RexNode operand) { - return sum(false, null, operand); + public AggCall sum(SqlParserPos pos, RexNode operand) { + return sum(pos, false, null, operand); } /** Creates a call to the {@code SUM} aggregate function, * optionally distinct and with an alias. */ - public AggCall sum(boolean distinct, @Nullable String alias, + public AggCall sum(SqlParserPos pos, boolean distinct, @Nullable String alias, RexNode operand) { - return aggregateCall(SqlStdOperatorTable.SUM, distinct, false, false, null, + return aggregateCall(pos, SqlStdOperatorTable.SUM, distinct, false, false, null, null, ImmutableList.of(), alias, ImmutableList.of(), ImmutableList.of(operand)); } /** Creates a call to the {@code AVG} aggregate function. */ - public AggCall avg(RexNode operand) { - return avg(false, null, operand); + public AggCall avg(SqlParserPos pos, RexNode operand) { + return avg(pos, false, null, operand); } /** Creates a call to the {@code AVG} aggregate function, * optionally distinct and with an alias. */ - public AggCall avg(boolean distinct, @Nullable String alias, + public AggCall avg(SqlParserPos pos, boolean distinct, @Nullable String alias, RexNode operand) { - return aggregateCall(SqlStdOperatorTable.AVG, distinct, false, false, null, + return aggregateCall(pos, SqlStdOperatorTable.AVG, distinct, false, false, null, null, ImmutableList.of(), alias, ImmutableList.of(), ImmutableList.of(operand)); } @@ -1536,7 +1525,7 @@ public AggCall min(RexNode operand) { /** Creates a call to the {@code MIN} aggregate function, * optionally with an alias. */ public AggCall min(@Nullable String alias, RexNode operand) { - return aggregateCall(SqlStdOperatorTable.MIN, false, false, false, null, + return aggregateCall(SqlParserPos.ZERO, SqlStdOperatorTable.MIN, false, false, false, null, null, ImmutableList.of(), alias, ImmutableList.of(), ImmutableList.of(operand)); } @@ -1549,14 +1538,14 @@ public AggCall max(RexNode operand) { /** Creates a call to the {@code MAX} aggregate function. */ public AggCall max(@Nullable String alias, RexNode operand) { - return aggregateCall(SqlStdOperatorTable.MAX, false, false, false, null, + return aggregateCall(SqlParserPos.ZERO, SqlStdOperatorTable.MAX, false, false, false, null, null, ImmutableList.of(), alias, ImmutableList.of(), ImmutableList.of(operand)); } /** Creates a call to the {@code LITERAL_AGG} aggregate function. */ public AggCall literalAgg(@Nullable Object value) { - return aggregateCall(SqlInternalOperators.LITERAL_AGG) + return aggregateCall(SqlParserPos.ZERO, SqlInternalOperators.LITERAL_AGG) .preOperands(literal(value)); } @@ -1756,7 +1745,7 @@ public RelBuilder functionScan(SqlOperator operator, inputs.add(0, build()); } - final RexCall call = call(operator, ImmutableList.copyOf(operands)); + final RexCall call = call(SqlParserPos.ZERO, operator, ImmutableList.copyOf(operands)); final RelNode functionScan = struct.tableFunctionScanFactory.createTableFunctionScan(cluster, inputs, call, null, getColumnMappings(operator)); @@ -3971,6 +3960,8 @@ public void clear() { * * @see RelBuilder#aggregateCall */ public interface AggCall { + SqlParserPos getPosition(); + /** Returns a copy of this AggCall that applies a filter before aggregating * values. */ AggCall filter(@Nullable RexNode condition); @@ -4137,6 +4128,7 @@ private boolean checkIfCorrelated(Set variablesSet, /** Implementation of {@link AggCall}. */ private class AggCallImpl implements AggCallPlus { + private final SqlParserPos pos; private final SqlAggFunction aggFunction; private final boolean distinct; private final boolean approximate; @@ -4148,12 +4140,13 @@ private class AggCallImpl implements AggCallPlus { private final @Nullable ImmutableList distinctKeys; // may be empty or null private final ImmutableList orderKeys; // may be empty - AggCallImpl(SqlAggFunction aggFunction, boolean distinct, + AggCallImpl(SqlParserPos pos, SqlAggFunction aggFunction, boolean distinct, boolean approximate, boolean ignoreNulls, @Nullable RexNode filter, @Nullable String alias, ImmutableList preOperands, ImmutableList operands, @Nullable ImmutableList distinctKeys, ImmutableList orderKeys) { + this.pos = pos; this.aggFunction = requireNonNull(aggFunction, "aggFunction"); // If the aggregate function ignores DISTINCT, // make the DISTINCT flag FALSE. @@ -4177,6 +4170,10 @@ private class AggCallImpl implements AggCallPlus { this.filter = filter; } + @Override public SqlParserPos getPosition() { + return pos; + } + @Override public String toString() { final StringBuilder b = new StringBuilder(); b.append(aggFunction.getName()) @@ -4224,7 +4221,7 @@ private class AggCallImpl implements AggCallPlus { final RelCollation collation = RelCollations.EMPTY; final RelDataType type = getTypeFactory().createSqlType(SqlTypeName.BOOLEAN); - return AggregateCall.create(aggFunction, distinct, approximate, + return AggregateCall.create(pos, aggFunction, distinct, approximate, ignoreNulls, preOperands, ImmutableList.of(), -1, null, collation, type, alias); } @@ -4260,7 +4257,7 @@ private class AggCallImpl implements AggCallPlus { .collect(toImmutableList()); } - return AggregateCall.create(aggFunction, distinct, approximate, + return AggregateCall.create(pos, aggFunction, distinct, approximate, ignoreNulls, preOperands, args, filterArg, distinctKeys, collation, groupSet.cardinality(), r, null, alias); } @@ -4282,7 +4279,7 @@ private class AggCallImpl implements AggCallPlus { ImmutableList.copyOf(preOperands); return preOperandList.equals(this.preOperands) ? this - : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + : new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, filter, alias, preOperandList, operands, distinctKeys, orderKeys); } @@ -4296,7 +4293,7 @@ private class AggCallImpl implements AggCallPlus { ImmutableList.copyOf(orderKeys); return orderKeyList.equals(this.orderKeys) ? this - : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + : new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, filter, alias, preOperands, operands, distinctKeys, orderKeyList); } @@ -4309,42 +4306,42 @@ private class AggCallImpl implements AggCallPlus { distinctKeys == null ? null : ImmutableList.copyOf(distinctKeys); return Objects.equals(distinctKeyList, this.distinctKeys) ? this - : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + : new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, filter, alias, preOperands, operands, distinctKeyList, orderKeys); } @Override public AggCall approximate(boolean approximate) { return approximate == this.approximate ? this - : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + : new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, filter, alias, preOperands, operands, distinctKeys, orderKeys); } @Override public AggCall filter(@Nullable RexNode condition) { return Objects.equals(condition, this.filter) ? this - : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + : new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, condition, alias, preOperands, operands, distinctKeys, orderKeys); } @Override public AggCall as(@Nullable String alias) { return Objects.equals(alias, this.alias) ? this - : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + : new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, filter, alias, preOperands, operands, distinctKeys, orderKeys); } @Override public AggCall distinct(boolean distinct) { return distinct == this.distinct ? this - : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + : new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, filter, alias, preOperands, operands, distinctKeys, orderKeys); } @Override public AggCall ignoreNulls(boolean ignoreNulls) { return ignoreNulls == this.ignoreNulls ? this - : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls, + : new AggCallImpl(pos, aggFunction, distinct, approximate, ignoreNulls, filter, alias, preOperands, operands, distinctKeys, orderKeys); } } @@ -4366,6 +4363,10 @@ private class AggCallImpl2 implements AggCallPlus { aggregateCall.name); } + @Override public SqlParserPos getPosition() { + return this.aggregateCall.getParserPosition(); + } + @Override public String toString() { return aggregateCall.toString(); } diff --git a/core/src/test/java/org/apache/calcite/examples/RelBuilderExample.java b/core/src/test/java/org/apache/calcite/examples/RelBuilderExample.java index 5b4aa6633937..6cffaec71d74 100644 --- a/core/src/test/java/org/apache/calcite/examples/RelBuilderExample.java +++ b/core/src/test/java/org/apache/calcite/examples/RelBuilderExample.java @@ -20,6 +20,7 @@ import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.test.RelBuilderTest; import org.apache.calcite.tools.FrameworkConfig; import org.apache.calcite.tools.RelBuilder; @@ -121,7 +122,7 @@ private RelBuilder example3(RelBuilder builder) { .scan("EMP") .aggregate(builder.groupKey("DEPTNO"), builder.count(false, "C"), - builder.sum(false, "S", builder.field("SAL"))) + builder.sum(SqlParserPos.ZERO, false, "S", builder.field("SAL"))) .filter( builder.call(SqlStdOperatorTable.GREATER_THAN, builder.field("C"), builder.literal(10))); diff --git a/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java b/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java index c53b822b213a..06cb1c5de90b 100644 --- a/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java +++ b/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java @@ -84,7 +84,7 @@ public static Frameworks.ConfigBuilder config() { final ImmutableBitSet groupSet = ImmutableBitSet.of(4); final AggregateCall count = aggregate.getAggCallList().get(0); final AggregateCall call = - AggregateCall.create(count.getAggregation(), + AggregateCall.create(count.getParserPosition(), count.getAggregation(), count.isDistinct(), count.isApproximate(), count.ignoreNulls(), count.rexList, ImmutableList.of(3), count.filterArg, null, count.collation, 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 ccb375503d74..36f551ef4ea7 100644 --- a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java +++ b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java @@ -544,11 +544,11 @@ private static Fixture relFn(Function relFn) { ImmutableBitSet.of(0), null, ImmutableList.of( - AggregateCall.create(SqlStdOperatorTable.COUNT, + AggregateCall.create(SqlParserPos.ZERO, SqlStdOperatorTable.COUNT, true, false, false, ImmutableList.of(), ImmutableList.of(1), -1, null, RelCollations.EMPTY, bigIntType, "c"), - AggregateCall.create(SqlStdOperatorTable.COUNT, + AggregateCall.create(SqlParserPos.ZERO, SqlStdOperatorTable.COUNT, false, false, false, ImmutableList.of(), ImmutableList.of(), -1, null, RelCollations.EMPTY, bigIntType, "d"))); 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 0caa7ec3e598..dba1ddfdf7e6 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 @@ -64,6 +64,7 @@ import org.apache.calcite.sql.SqlExplainFormat; import org.apache.calcite.sql.SqlExplainLevel; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.tools.FrameworkConfig; import org.apache.calcite.tools.Frameworks; @@ -170,7 +171,7 @@ public RelDataType getRowType(RelDataTypeFactory typeFactory) { // aggregate on s, count AggregateCall aggCall = - AggregateCall.create(SqlStdOperatorTable.COUNT, + AggregateCall.create(SqlParserPos.ZERO, SqlStdOperatorTable.COUNT, false, false, false, ImmutableList.of(), Collections.singletonList(1), -1, null, RelCollations.EMPTY, sqlBigInt, "cnt"); diff --git a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java index 6affbf4a7788..3fbc4d1788fd 100644 --- a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java +++ b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java @@ -66,6 +66,7 @@ import org.apache.calcite.sql.fun.SqlLibrary; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.parser.SqlParser; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeFactoryImpl; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.util.SqlShuttle; @@ -672,7 +673,7 @@ private static String toSql(RelNode root, SqlDialect dialect, b.groupKey(ImmutableBitSet.of(0, 1, 2), ImmutableList.of(ImmutableBitSet.of(0, 1), ImmutableBitSet.of(0))), b.count(false, "C"), - b.sum(false, "S", b.field("SAL"))) + b.sum(SqlParserPos.ZERO, false, "S", b.field("SAL"))) .filter(b.equals(b.field("JOB"), b.literal("DEVELOP"))) .project(b.field("JOB")) .build(); @@ -696,7 +697,7 @@ private static String toSql(RelNode root, SqlDialect dialect, b.groupKey(ImmutableBitSet.of(0, 1, 2), ImmutableList.of(ImmutableBitSet.of(0, 1), ImmutableBitSet.of(0))), b.count(false, "C"), - b.sum(false, "S", b.field("SAL"))) + b.sum(SqlParserPos.ZERO, false, "S", b.field("SAL"))) .filter( b.call(SqlStdOperatorTable.GREATER_THAN, b.field("C"), b.literal(10))) @@ -729,7 +730,7 @@ private static String toSql(RelNode root, SqlDialect dialect, ImmutableBitSet.of(0), ImmutableBitSet.of())), b.count(false, "C"), - b.sum(false, "S", b.field("SAL"))) + b.sum(SqlParserPos.ZERO, false, "S", b.field("SAL"))) .filter( b.or( b.greaterThan(b.field("C"), b.literal(10)), @@ -760,7 +761,7 @@ private static String toSql(RelNode root, SqlDialect dialect, b.groupKey(ImmutableBitSet.of(0, 1, 2), ImmutableList.of(ImmutableBitSet.of(0, 1), ImmutableBitSet.of(0))), b.count(false, "C"), - b.sum(false, "S", b.field("SAL"))) + b.sum(SqlParserPos.ZERO, false, "S", b.field("SAL"))) .project(b.field("JOB")) .build(); final String expectedSql = "SELECT \"JOB\"\n" @@ -780,7 +781,7 @@ private static String toSql(RelNode root, SqlDialect dialect, b.groupKey(ImmutableBitSet.of(0, 1, 2), ImmutableList.of(ImmutableBitSet.of(0, 1), ImmutableBitSet.of(0))), b.count(false, "C"), - b.sum(false, "S", b.field("SAL"))) + b.sum(SqlParserPos.ZERO, false, "S", b.field("SAL"))) .sort(b.field("C")) .build(); final String expectedSql = "SELECT \"EMPNO\", \"ENAME\", \"JOB\"," @@ -803,7 +804,7 @@ private static String toSql(RelNode root, SqlDialect dialect, ImmutableBitSet.of(0), ImmutableBitSet.of())), b.count(false, "C"), - b.sum(false, "S", b.field("SAL"))) + b.sum(SqlParserPos.ZERO, false, "S", b.field("SAL"))) .filter( b.lessThan( b.call(SqlStdOperatorTable.GROUP_ID, b.field("EMPNO")), diff --git a/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java b/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java index 9db5f8ed076b..d1575ec368c6 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java @@ -31,6 +31,7 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.fun.SqlLibraryOperators; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.BasicSqlType; import org.apache.calcite.sql.type.SqlTypeFactoryImpl; import org.apache.calcite.sql.type.SqlTypeName; @@ -115,7 +116,7 @@ private static class MySqlTypeFactoryImpl extends SqlTypeFactoryImpl { new RexLiteral(Boolean.TRUE, typeFactory.createSqlType(SqlTypeName.BOOLEAN), SqlTypeName.BOOLEAN); RexNode ensuredNode = - builder.ensureType(typeFactory.createSqlType(SqlTypeName.ANY), node, + builder.ensureType(SqlParserPos.ZERO, typeFactory.createSqlType(SqlTypeName.ANY), node, true); assertEquals(node, ensuredNode); @@ -132,7 +133,7 @@ private static class MySqlTypeFactoryImpl extends SqlTypeFactoryImpl { new RexLiteral(Boolean.TRUE, typeFactory.createSqlType(SqlTypeName.BOOLEAN), SqlTypeName.BOOLEAN); RexNode ensuredNode = - builder.ensureType(typeFactory.createSqlType(SqlTypeName.BOOLEAN), node, + builder.ensureType(SqlParserPos.ZERO, typeFactory.createSqlType(SqlTypeName.BOOLEAN), node, true); assertEquals(node, ensuredNode); @@ -149,7 +150,7 @@ private static class MySqlTypeFactoryImpl extends SqlTypeFactoryImpl { new RexLiteral(Boolean.TRUE, typeFactory.createSqlType(SqlTypeName.BOOLEAN), SqlTypeName.BOOLEAN); RexNode ensuredNode = - builder.ensureType(typeFactory.createSqlType(SqlTypeName.INTEGER), node, + builder.ensureType(SqlParserPos.ZERO, typeFactory.createSqlType(SqlTypeName.INTEGER), node, true); assertNotEquals(node, ensuredNode); diff --git a/core/src/test/java/org/apache/calcite/rex/RexProgramBuilderBase.java b/core/src/test/java/org/apache/calcite/rex/RexProgramBuilderBase.java index 36fec90759de..e890a7838539 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexProgramBuilderBase.java +++ b/core/src/test/java/org/apache/calcite/rex/RexProgramBuilderBase.java @@ -25,6 +25,7 @@ import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeSystem; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; import com.google.common.collect.ImmutableList; @@ -238,7 +239,7 @@ protected RexNode case_(Iterable nodes) { * *

This method enables to create {@code CAST(42 nullable int)} expressions. * - * @param e input node + * @param e input node * @param type type to cast to * @return call to CAST operator */ @@ -246,6 +247,22 @@ protected RexNode abstractCast(RexNode e, RelDataType type) { return rexBuilder.makeAbstractCast(type, e, false); } + /** + * Creates a call to the CAST operator, expanding if possible, and not + * preserving nullability. + * + *

Tries to expand the cast, and therefore the result may be something + * other than a {@link RexCall} to the CAST operator, such as a + * {@link RexLiteral}. + * + * @param e input node + * @param type type to cast to + * @return input node converted to given type + */ + protected RexNode cast(SqlParserPos pos, RexNode e, RelDataType type) { + return rexBuilder.makeCast(pos, type, e); + } + /** * Creates a call to the CAST operator, expanding if possible, and not * preserving nullability. 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 7f8f42c51b24..c527af23debf 100644 --- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java @@ -1279,7 +1279,7 @@ private RexNode caseCall(RelBuilder b, RexNode ref, RexNode... nodes) { builder.field(3)), builder.field(1)), builder.countStar("C"), - builder.sum( + builder.sum(SqlParserPos.ZERO, builder.call(SqlStdOperatorTable.PLUS, builder.field(3), builder.literal(1))).as("S")) .build(); @@ -1395,7 +1395,7 @@ private RexNode caseCall(RelBuilder b, RexNode ref, RexNode... nodes) { .project(builder.field("EMPNO"), builder.field("ENAME"), builder.field("SAL")) .aggregate(builder.groupKey(builder.field("ENAME")), - builder.sum(builder.field("SAL"))) + builder.sum(SqlParserPos.ZERO, builder.field("SAL"))) // Before [CALCITE-3839] was fixed, the following line gave // 'field [ENAME] not found' .project(builder.field("ENAME")) @@ -1456,10 +1456,10 @@ private RelNode buildRelWithDuplicateAggregates( final RelBuilder builder = createBuilder(transform); return builder.scan("EMP") .aggregate(builder.groupKey(groupFieldOrdinals), - builder.sum(builder.field(1)).as("S1"), + builder.sum(SqlParserPos.ZERO, builder.field(1)).as("S1"), builder.count().as("C"), - builder.sum(builder.field(2)).as("S2"), - builder.sum(builder.field(1)).as("S1b")) + builder.sum(SqlParserPos.ZERO, builder.field(2)).as("S2"), + builder.sum(SqlParserPos.ZERO, builder.field(1)).as("S1b")) .build(); } @@ -1473,13 +1473,13 @@ private RelNode buildRelWithDuplicateAggregates( final RelBuilder builder = RelBuilder.create(config().build()); RelNode root = builder.scan("EMP") .aggregate(builder.groupKey(2), - builder.sum(builder.field(1)).as("S1"), - builder.sum(builder.field(1)).distinct().as("SD1"), + builder.sum(SqlParserPos.ZERO, builder.field(1)).as("S1"), + builder.sum(SqlParserPos.ZERO, builder.field(1)).distinct().as("SD1"), builder.count().as("C"), builder.min(builder.field(2)).distinct().as("MD2"), builder.min(builder.field(2)).as("M2"), builder.min(builder.field(2)).distinct().as("MD2b"), - builder.sum(builder.field(1)).distinct().as("S1b")) + builder.sum(SqlParserPos.ZERO, builder.field(1)).distinct().as("S1b")) .build(); final String expected = "" + "LogicalProject(JOB=[$0], S1=[$1], SD1=[$2], C=[$3], MD2=[$4], " @@ -1512,9 +1512,9 @@ private RelNode buildRelWithDuplicateAggregates( .aggregate( builder.groupKey(builder.field("MGR")), // duplicate avg() agg calls - builder.avg(false, "SALARY_AVG", builder.field("SAL")), - builder.sum(false, "SALARY_SUM", builder.field("SAL")), - builder.avg(false, "SALARY_MEAN", builder.field("SAL"))) + builder.avg(SqlParserPos.ZERO, false, "SALARY_AVG", builder.field("SAL")), + builder.sum(SqlParserPos.ZERO, false, "SALARY_SUM", builder.field("SAL")), + builder.avg(SqlParserPos.ZERO, false, "SALARY_MEAN", builder.field("SAL"))) .build(); final String expected = "" + "LogicalProject(MGR=[$0], SALARY_AVG=[$1], SALARY_SUM=[$2], SALARY_MEAN=[$1])\n" @@ -1594,7 +1594,7 @@ private RelNode buildRelWithDuplicateAggregates( builder.scan("EMP") .aggregate( builder.groupKey(builder.field("DEPTNO")), - builder.sum(builder.field("SAL")) + builder.sum(SqlParserPos.ZERO, builder.field("SAL")) .filter(builder.field("COMM")) .as("C")) .build(); @@ -1614,7 +1614,7 @@ private RelNode buildRelWithDuplicateAggregates( builder.scan("EMP") .aggregate( builder.groupKey(builder.field("DEPTNO")), - builder.sum(builder.field("SAL")) + builder.sum(SqlParserPos.ZERO, builder.field("SAL")) .filter( builder.lessThan(builder.field("COMM"), builder.literal(100))) @@ -1708,7 +1708,7 @@ private RelNode buildRelWithDuplicateAggregates( builder.field("JOB")) .aggregate( builder.groupKey(builder.field("DEPTNO")), - builder.sum(builder.field("SAL")) + builder.sum(SqlParserPos.ZERO, builder.field("SAL")) .filter( builder.equals(builder.field("JOB"), builder.literal("CLERK")))) @@ -1832,7 +1832,7 @@ private RelNode buildRelWithDuplicateAggregates( ImmutableBitSet.of(0, 1, 2), ImmutableList.of(ImmutableBitSet.of(0, 1), ImmutableBitSet.of(0))), builder.count(false, "C"), - builder.sum(false, "S", builder.field("SAL"))) + builder.sum(SqlParserPos.ZERO, false, "S", builder.field("SAL"))) .filter( builder.call( SqlStdOperatorTable.GREATER_THAN, @@ -1990,9 +1990,9 @@ private static RelNode groupIdRel(RelBuilder builder, boolean extra) { RelNode root = builder.scan("EMP") .aggregate(builder.groupKey(), - builder.avg(builder.field("SAL")) + builder.avg(SqlParserPos.ZERO, builder.field("SAL")) .as("g"), - builder.avg(builder.field("SAL")) + builder.avg(SqlParserPos.ZERO, builder.field("SAL")) .unique(builder.field("DEPTNO")) .as("g2")) .build(); @@ -2751,7 +2751,7 @@ private static RelBuilder assertSize(RelBuilder b, b.scalarQuery(b2 -> b2.scan("EMP") .aggregate(b2.groupKey(), - b2.avg(b2.field("SAL"))) + b2.avg(SqlParserPos.ZERO, b2.field("SAL"))) .build()))) .build(); @@ -3048,7 +3048,7 @@ private static RelBuilder assertSize(RelBuilder b, .project(builder.field("DEPTNO"), builder.literal(20)) .aggregate(builder.groupKey(builder.field("EMP_alias", "DEPTNO")), - builder.sum(builder.field(1))) + builder.sum(SqlParserPos.ZERO, builder.field(1))) .project(builder.alias(builder.field(1), "sum"), builder.field("EMP_alias", "DEPTNO")) .build(); @@ -3945,7 +3945,7 @@ private static RelBuilder assertSize(RelBuilder b, b.scan("EMP") .pivot(b.groupKey("MGR"), Arrays.asList( - b.sum(b.field("SAL")).as("SS"), + b.sum(SqlParserPos.ZERO, b.field("SAL")).as("SS"), b.count().as("C")), b.fields(Arrays.asList("JOB", "DEPTNO")), ImmutableMap.>builder() 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 d9733486bd6a..52b7da4e0e68 100644 --- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java @@ -98,6 +98,7 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.test.SqlTestFactory; import org.apache.calcite.sql.type.OperandTypes; import org.apache.calcite.sql.type.ReturnTypes; @@ -2321,7 +2322,7 @@ private void checkAverageRowSize(RelOptCluster cluster, RelOptTable empTable, bitSetOf(2, 0), ImmutableList.of(), ImmutableList.of( - AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, + AggregateCall.create(SqlParserPos.ZERO, SqlStdOperatorTable.COUNT, false, false, false, ImmutableList.of(), ImmutableIntList.of(), -1, null, RelCollations.EMPTY, 2, join, null, null))); rowSize = mq.getAverageRowSize(aggregate); diff --git a/core/src/test/java/org/apache/calcite/test/fuzzer/RexShrinker.java b/core/src/test/java/org/apache/calcite/test/fuzzer/RexShrinker.java index 9cf470fdd1dd..84272d0de61d 100644 --- a/core/src/test/java/org/apache/calcite/test/fuzzer/RexShrinker.java +++ b/core/src/test/java/org/apache/calcite/test/fuzzer/RexShrinker.java @@ -76,7 +76,7 @@ public class RexShrinker extends RexShuttle { if (res != null) { didWork = true; if (!res.getType().equals(type)) { - return rexBuilder.makeCast(type, res); + return rexBuilder.makeCast(call.getParserPosition(), type, res); } return res; } diff --git a/piglet/src/main/java/org/apache/calcite/piglet/PigToSqlAggregateRule.java b/piglet/src/main/java/org/apache/calcite/piglet/PigToSqlAggregateRule.java index 71f206d09afc..973d2cb5e8c1 100644 --- a/piglet/src/main/java/org/apache/calcite/piglet/PigToSqlAggregateRule.java +++ b/piglet/src/main/java/org/apache/calcite/piglet/PigToSqlAggregateRule.java @@ -33,6 +33,7 @@ import org.apache.calcite.sql.SqlAggFunction; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.tools.RelBuilder; import org.immutables.value.Value; @@ -153,7 +154,7 @@ private static class RexCallReplacer extends RexShuttle { newOperands.add(operand.accept(this)); } } - return builder.makeCall(call.type, call.op, newOperands); + return builder.makeCall(call.getParserPosition(), call.type, call.op, newOperands); } @Override public RexNode visitInputRef(RexInputRef inputRef) { @@ -275,7 +276,7 @@ private static class RexCallReplacer extends RexShuttle { if (aggOperands.size() == 1) { // Project single column aggCalls.add( - relBuilder.aggregateCall(SqlStdOperatorTable.COLLECT, + relBuilder.aggregateCall(SqlParserPos.ZERO, SqlStdOperatorTable.COLLECT, aggOperands)); } else { // Project more than one column, need to construct a record (ROW) @@ -290,7 +291,7 @@ private static class RexCallReplacer extends RexShuttle { } else { final SqlAggFunction udf = PigRelUdfConverter.getSqlAggFuncForPigUdf(rexCall); - aggCalls.add(relBuilder.aggregateCall(udf, aggOperands)); + aggCalls.add(relBuilder.aggregateCall(SqlParserPos.ZERO, udf, aggOperands)); } } relBuilder.aggregate(groupKey, aggCalls); diff --git a/plus/src/test/java/org/apache/calcite/adapter/tpcds/TpcdsTest.java b/plus/src/test/java/org/apache/calcite/adapter/tpcds/TpcdsTest.java index 3d4595ca67bf..399d5d3b096c 100644 --- a/plus/src/test/java/org/apache/calcite/adapter/tpcds/TpcdsTest.java +++ b/plus/src/test/java/org/apache/calcite/adapter/tpcds/TpcdsTest.java @@ -22,6 +22,7 @@ import org.apache.calcite.runtime.Hook; import org.apache.calcite.schema.SchemaPlus; import org.apache.calcite.sql.parser.SqlParser; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.test.CalciteAssert; import org.apache.calcite.tools.Frameworks; import org.apache.calcite.tools.Program; @@ -376,10 +377,10 @@ public Frameworks.ConfigBuilder config() throws Exception { builder.literal("OK"), builder.literal("MD"))) .aggregate(builder.groupKey("I_ITEM_ID", "S_STATE"), - builder.avg(false, "AGG1", builder.field("SS_QUANTITY")), - builder.avg(false, "AGG2", builder.field("SS_LIST_PRICE")), - builder.avg(false, "AGG3", builder.field("SS_COUPON_AMT")), - builder.avg(false, "AGG4", builder.field("SS_SALES_PRICE"))) + builder.avg(SqlParserPos.ZERO, false, "AGG1", builder.field("SS_QUANTITY")), + builder.avg(SqlParserPos.ZERO, false, "AGG2", builder.field("SS_LIST_PRICE")), + builder.avg(SqlParserPos.ZERO, false, "AGG3", builder.field("SS_COUPON_AMT")), + builder.avg(SqlParserPos.ZERO, false, "AGG4", builder.field("SS_SALES_PRICE"))) .sortLimit(0, 100, builder.field("I_ITEM_ID"), builder.field("S_STATE")) .build(); String expectResult = ""