This is an automated email from the ASF dual-hosted git repository.
tanner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new 14ade3a720 [CALCITE-6337] Distinguish naked measure support between
inside and outside aggregation
14ade3a720 is described below
commit 14ade3a72032986731239068963e4716dc7fe6af
Author: Barry Kelly <[email protected]>
AuthorDate: Mon Nov 20 15:59:46 2023 +0000
[CALCITE-6337] Distinguish naked measure support between inside and outside
aggregation
Split nakedMeasures flag into two flags:
- nakedMeasuresInsideAggregatingQuery : allowed in group-by queries
- nakedMeasuresOutsideAggregatingQuery : allowed in non-group-by queries
The existing nakedMeasures flag is marked as deprecated. Its functionality
is equivalent to setting the above two flags to the same value.
---
.../apache/calcite/sql/validate/AggChecker.java | 2 +-
.../apache/calcite/sql/validate/SqlValidator.java | 34 +++++++++++++++++---
.../calcite/sql/validate/SqlValidatorImpl.java | 10 +++---
.../org/apache/calcite/test/SqlValidatorTest.java | 37 +++++++++++++++++-----
4 files changed, 64 insertions(+), 19 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/AggChecker.java
b/core/src/main/java/org/apache/calcite/sql/validate/AggChecker.java
index 9a93718c38..43ccc3453b 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/AggChecker.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/AggChecker.java
@@ -106,7 +106,7 @@ class AggChecker extends SqlBasicVisitor<Void> {
return null;
}
- if (!validator.config().nakedMeasures()
+ if (!validator.config().nakedMeasuresInAggregateQuery()
&& isMeasureExp(id)) {
SqlNode originalExpr = validator.getOriginal(id);
throw validator.newValidationError(originalExpr,
diff --git
a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidator.java
b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidator.java
index 80d1734d9c..2f27837b76 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidator.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidator.java
@@ -912,15 +912,39 @@ public interface SqlValidator {
*/
Config withLenientOperatorLookup(boolean lenient);
- /** Returns whether the validator allows measures to be used without the
- * AGGREGATE function. Default is true. */
- @Value.Default default boolean nakedMeasures() {
+ /** Returns whether the validator allows measures to be used without
+ * AGGREGATE function in a non-aggregate query. Default is true.
+ */
+ @Value.Default default boolean nakedMeasuresInNonAggregateQuery() {
return true;
}
+ /** Sets whether the validator allows measures to be used without AGGREGATE
+ * function in a non-aggregate query.
+ */
+ Config withNakedMeasuresInNonAggregateQuery(boolean value);
+
+ /** Returns whether the validator allows measures to be used without
+ * AGGREGATE function in an aggregate query. Default is true.
+ */
+ @Value.Default default boolean nakedMeasuresInAggregateQuery() {
+ return true;
+ }
+
+ /** Sets whether the validator allows measures to be used without AGGREGATE
+ * function in an aggregate query.
+ */
+ Config withNakedMeasuresInAggregateQuery(boolean value);
+
/** Sets whether the validator allows measures to be used without the
- * AGGREGATE function. */
- Config withNakedMeasures(boolean nakedMeasures);
+ * AGGREGATE function inside or outside aggregate queries.
+ * Deprecated: use the inside / outside variants instead.
+ */
+ @Deprecated // to be removed before 1.38
+ default Config withNakedMeasures(boolean nakedMeasures) {
+ return withNakedMeasuresInAggregateQuery(nakedMeasures)
+ .withNakedMeasuresInNonAggregateQuery(nakedMeasures);
+ }
/** Returns whether the validator supports implicit type coercion. */
@Value.Default default boolean typeCoercionEnabled() {
diff --git
a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index 9572cf4ebd..a0e970fadb 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -2852,7 +2852,7 @@ public class SqlValidatorImpl implements
SqlValidatorWithHints {
}
}
- // If this is an aggregating query, the SELECT list and HAVING
+ // If this is an aggregate query, the SELECT list and HAVING
// clause use a different scope, where you can only reference
// columns which are in the GROUP BY clause.
SqlValidatorScope aggScope = selectScope;
@@ -2888,7 +2888,7 @@ public class SqlValidatorImpl implements
SqlValidatorWithHints {
registerSubQueries(orderScope, orderList);
if (!isAggregate(select)) {
- // Since this is not an aggregating query,
+ // Since this is not an aggregate query,
// there cannot be any aggregates in the ORDER BY clause.
SqlNode agg = aggFinder.findAgg(orderList);
if (agg != null) {
@@ -4826,10 +4826,10 @@ public class SqlValidatorImpl implements
SqlValidatorWithHints {
}
}
- // Unless 'naked measures' are enabled, a non-aggregating query cannot
- // reference measure columns. (An aggregating query can use them as
+ // Unless 'naked measures' are enabled, a non-aggregate query cannot
+ // reference measure columns. (An aggregate query can use them as
// argument to the AGGREGATE function.)
- if (!config.nakedMeasures()
+ if (!config.nakedMeasuresInNonAggregateQuery()
&& !(scope instanceof AggregatingScope)
&& scope.isMeasureRef(expr)) {
throw newValidationError(expr,
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index 11c2edf7a7..192b65fef5 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -2866,7 +2866,7 @@ public class SqlValidatorTest extends
SqlValidatorTestCase {
.fails("OVER clause is necessary for window functions");
// With [CALCITE-1340], the validator would see RANK without OVER,
- // mistakenly think this is an aggregating query, and wrongly complain
+ // mistakenly think this is an aggregate query, and wrongly complain
// about the PARTITION BY: "Expression 'DEPTNO' is not being grouped"
winSql("select cume_dist() over w , ^rank()^\n"
+ "from emp\n"
@@ -3874,8 +3874,19 @@ public class SqlValidatorTest extends
SqlValidatorTestCase {
SqlValidatorFixture f =
fixture().withExtendedCatalog()
.withOperatorTable(operatorTableFor(SqlLibrary.CALCITE));
- SqlValidatorFixture f2 =
- f.withValidatorConfig(c -> c.withNakedMeasures(false));
+
+ SqlValidatorFixture fNakedInsideOnly =
+ f.withValidatorConfig(c ->
+ c.withNakedMeasuresInAggregateQuery(true)
+ .withNakedMeasuresInNonAggregateQuery(false));
+ SqlValidatorFixture fNakedOutsideOnly =
+ f.withValidatorConfig(c ->
+ c.withNakedMeasuresInNonAggregateQuery(true)
+ .withNakedMeasuresInAggregateQuery(false));
+ SqlValidatorFixture fNoNakedMeasures =
+ f.withValidatorConfig(c ->
+ c.withNakedMeasuresInNonAggregateQuery(false)
+ .withNakedMeasuresInAggregateQuery(false));
final String measureIllegal =
"Measure expressions can only occur within AGGREGATE function";
@@ -3890,28 +3901,36 @@ public class SqlValidatorTest extends
SqlValidatorTestCase {
.ok();
// Same SQL is invalid if naked measures are not enabled
- f2.withSql(sql0).fails(measureIllegal);
+ fNoNakedMeasures.withSql(sql0).fails(measureIllegal);
+ fNakedOutsideOnly.withSql(sql0).fails(measureIllegal);
+ fNakedInsideOnly.withSql(sql0).isAggregate(is(true)).ok();
// Similarly, with alias
final String sql1b = "select deptno, ^count_plus_100^ as x\n"
+ "from empm\n"
+ "group by deptno";
f.withSql(sql1b).isAggregate(is(true)).ok();
- f2.withSql(sql1b).fails(measureIllegal);
+ fNoNakedMeasures.withSql(sql1b).fails(measureIllegal);
+ fNakedOutsideOnly.withSql(sql1b).fails(measureIllegal);
+ fNakedInsideOnly.withSql(sql1b).isAggregate(is(true)).ok();
// Similarly, in an expression
final String sql1c = "select deptno, deptno + ^count_plus_100^ * 2 as x\n"
+ "from empm\n"
+ "group by deptno";
f.withSql(sql1c).isAggregate(is(true)).ok();
- f2.withSql(sql1c).fails(measureIllegal);
+ fNoNakedMeasures.withSql(sql1c).fails(measureIllegal);
+ fNakedOutsideOnly.withSql(sql1c).fails(measureIllegal);
+ fNakedInsideOnly.withSql(sql1c).isAggregate(is(true)).ok();
// Similarly, for a query that is an aggregate query because of another
// aggregate function.
final String sql1 = "select count(*), ^count_plus_100^\n"
+ "from empm";
f.withSql(sql1).isAggregate(is(true)).ok();
- f2.withSql(sql1).fails(measureIllegal);
+ fNoNakedMeasures.withSql(sql1).fails(measureIllegal);
+ fNakedInsideOnly.withSql(sql1).isAggregate(is(true)).ok();
+ fNakedOutsideOnly.withSql(sql1).fails(measureIllegal);
// A measure in a non-aggregate query.
// Using a measure should not make it an aggregate query.
@@ -3924,7 +3943,9 @@ public class SqlValidatorTest extends
SqlValidatorTestCase {
+ "MEASURE<INTEGER NOT NULL> NOT NULL COUNT_PLUS_100, "
+ "VARCHAR(20) NOT NULL ENAME) NOT NULL")
.isAggregate(is(false));
- f2.withSql(sql2).fails(measureIllegal2);
+ fNoNakedMeasures.withSql(sql2).fails(measureIllegal2);
+ fNakedInsideOnly.withSql(sql2).fails(measureIllegal2);
+ fNakedOutsideOnly.withSql(sql2).isAggregate(is(false)).ok();
// as above, wrapping the measure in AGGREGATE
final String sql3 = "select deptno, aggregate(count_plus_100) as x,
ename\n"