diff --git a/core/src/main/java/org/apache/calcite/sql/advise/SqlAdvisorValidator.java b/core/src/main/java/org/apache/calcite/sql/advise/SqlAdvisorValidator.java index ddcfe9a6a9b6..92bbf9b7b030 100644 --- a/core/src/main/java/org/apache/calcite/sql/advise/SqlAdvisorValidator.java +++ b/core/src/main/java/org/apache/calcite/sql/advise/SqlAdvisorValidator.java @@ -169,11 +169,11 @@ private void registerId(SqlIdentifier id, SqlValidatorScope scope) { @Override protected void validateOver(SqlCall call, SqlValidatorScope scope) { try { - final OverScope overScope = (OverScope) getOverScope(call); + final OverScope overScope = (OverScope) getSqlQueryScopes().getOverScope(call); final SqlNode relation = call.operand(0); validateFrom(relation, unknownType, scope); final SqlNode window = call.operand(1); - SqlValidatorScope opScope = scopes.get(relation); + SqlValidatorScope opScope = getSqlQueryScopes().getScope(relation); if (opScope == null) { opScope = overScope; } diff --git a/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java b/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java index a9544ca463ec..b664a904b309 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java +++ b/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java @@ -1732,7 +1732,7 @@ private static class LambdaFamilyOperandTypeChecker && !argFamilies.stream().allMatch(f -> f == SqlTypeFamily.ANY)) { // Replace the parameter types in the lambda expression. final SqlLambdaScope scope = - (SqlLambdaScope) validator.getLambdaScope(lambdaExpr); + (SqlLambdaScope) validator.getSqlQueryScopes().getLambdaScope(lambdaExpr); for (int i = 0; i < argFamilies.size(); i++) { final SqlNode param = lambdaExpr.getParameters().get(i); final RelDataType type = @@ -1794,7 +1794,7 @@ private static class LambdaRelOperandTypeChecker // Replace the parameter types in the lambda expression. final SqlValidator validator = callBinding.getValidator(); final SqlLambdaScope scope = - (SqlLambdaScope) validator.getLambdaScope(lambdaExpr); + (SqlLambdaScope) validator.getSqlQueryScopes().getLambdaScope(lambdaExpr); for (int i = 0; i < argTypes.size(); i++) { final SqlNode param = lambdaExpr.getParameters().get(i); final RelDataType type = argTypes.get(i); 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 43ccc3453b19..47b6b3187a55 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 @@ -147,7 +147,7 @@ && isMeasureExp(id)) { if (scope instanceof AggregatingSelectScope) { final SqlSelect select = (SqlSelect) scope.getNode(); SelectScope selectScope = - requireNonNull(validator.getRawSelectScope(select), + requireNonNull(validator.getSqlQueryScopes().getRawSelectScope(select), () -> "rawSelectScope for " + scope.getNode()); List selectList = requireNonNull(selectScope.getExpandedSelectList(), diff --git a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java index 5153d3160e50..207dd5140219 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java @@ -234,9 +234,9 @@ protected void addColumnNames( @Override public SqlValidatorScope getOperandScope(SqlCall call) { if (call instanceof SqlSelect) { - return validator.getSelectScope((SqlSelect) call); + return validator.getSqlQueryScopes().getSelectScope((SqlSelect) call); } else if (call instanceof SqlLambda) { - return validator.getLambdaScope((SqlLambda) call); + return validator.getSqlQueryScopes().getLambdaScope((SqlLambda) call); } return this; } diff --git a/core/src/main/java/org/apache/calcite/sql/validate/OrderByScope.java b/core/src/main/java/org/apache/calcite/sql/validate/OrderByScope.java index b8e58222ad97..3bdcd740ffe7 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/OrderByScope.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/OrderByScope.java @@ -87,7 +87,7 @@ public class OrderByScope extends DelegatingScope { if (field != null) { return field.getType(); } - final SqlValidatorScope selectScope = validator.getSelectScope(select); + final SqlValidatorScope selectScope = validator.getSqlQueryScopes().getSelectScope(select); return selectScope.resolveColumn(name, ctx); } diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SelectNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/SelectNamespace.java index 9819d28a584e..0141fb91fb7a 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/SelectNamespace.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/SelectNamespace.java @@ -71,11 +71,11 @@ public SelectNamespace( final RelDataType rowType = this.getRowTypeSansSystemColumns(); final int field = SqlTypeUtil.findField(rowType, columnName); SelectScope selectScope = - requireNonNull(validator.getRawSelectScope(select), + requireNonNull(validator.getSqlQueryScopes().getRawSelectScope(select), () -> "rawSelectScope for " + select); final SqlNode selectItem = requireNonNull(selectScope.getExpandedSelectList(), () -> "expandedSelectList for selectScope of " + select).get(field); - return validator.getSelectScope(select).getMonotonicity(selectItem); + return validator.getSqlQueryScopes().getSelectScope(select).getMonotonicity(selectItem); } } diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SetopNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/SetopNamespace.java index 58c381e80c31..58c140fea24f 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/SetopNamespace.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/SetopNamespace.java @@ -103,7 +103,7 @@ private static SqlMonotonicity combine(@Nullable SqlMonotonicity m0, case INTERSECT: case EXCEPT: final SqlValidatorScope scope = - requireNonNull(validator.scopes.get(call), + requireNonNull(validator.getSqlQueryScopes().getScope(call), () -> "scope for " + call); for (SqlNode operand : call.getOperandList()) { if (!operand.isA(SqlKind.QUERY)) { diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlQueryScopes.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlQueryScopes.java new file mode 100644 index 000000000000..35aff576b74b --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlQueryScopes.java @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.calcite.sql.validate; + +import org.apache.calcite.sql.SqlLambda; +import org.apache.calcite.sql.SqlMatchRecognize; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlSelect; +import org.apache.calcite.util.Util; + +import org.checkerframework.checker.nullness.qual.Nullable; + +/** + * Contains mapping of SqlNodes to SqlValidatorScope. + * + *

The methods {@link #getSelectScope}, {@link #getFromScope}, + * {@link #getWhereScope}, {@link #getGroupScope}, {@link #getHavingScope}, + * {@link #getOrderScope} and {@link #getJoinScope} get the correct scope + * to resolve names in a particular clause of a SQL statement. + */ +public interface SqlQueryScopes { + SqlValidatorScope getCursorScope(SqlSelect select); + + /** + * Returns a scope containing the objects visible from the FROM clause of a + * query. + * + * @param select SELECT statement + * @return naming scope for FROM clause + */ + SqlValidatorScope getFromScope(SqlSelect select); + + /** + * Returns a scope containing the objects visible from the GROUP BY clause + * of a query. + * + * @param select SELECT statement + * @return naming scope for GROUP BY clause + */ + SqlValidatorScope getGroupScope(SqlSelect select); + + /** + * Returns a scope containing the objects visible from the HAVING clause of + * a query. + * + * @param select SELECT statement + * @return naming scope for HAVING clause + */ + SqlValidatorScope getHavingScope(SqlSelect select); + + /** + * Returns a scope containing the objects visible from the ON and USING + * sections of a JOIN clause. + * + * @param node The item in the FROM clause which contains the ON or USING + * expression + * @return naming scope for JOIN clause + * @see #getFromScope + */ + SqlValidatorScope getJoinScope(SqlNode node); + + /** + * Returns the lambda expression scope. + * + * @param node Lambda expression + * @return naming scope for lambda expression + */ + SqlValidatorScope getLambdaScope(SqlLambda node); + + /** + * Returns a scope match recognize clause. + * + * @param node Match recognize + * @return naming scope for Match recognize clause + */ + SqlValidatorScope getMatchRecognizeScope(SqlMatchRecognize node); + + SqlValidatorScope getMeasureScope(SqlSelect select); + + /** + * Returns the scope that expressions in the SELECT and HAVING clause of + * this query should use. This scope consists of the FROM clause and the + * enclosing scope. If the query is aggregating, only columns in the GROUP + * BY clause may be used. + * + * @param select SELECT statement + * @return naming scope for ORDER BY clause + */ + SqlValidatorScope getOrderScope(SqlSelect select); + + /** + * Returns the scope of an OVER or VALUES node. + * + * @param node Node + * @return Scope + */ + SqlValidatorScope getOverScope(SqlNode node); + + /** + * Returns the appropriate scope for validating a particular clause of a + * SELECT statement. + * + *

Consider + * + *

SELECT *
+   * FROM foo
+   * WHERE EXISTS (
+   *    SELECT deptno AS x
+   *    FROM emp
+   *       JOIN dept ON emp.deptno = dept.deptno
+   *    WHERE emp.deptno = 5
+   *    GROUP BY deptno
+   *    ORDER BY x)
+ * + *

What objects can be seen in each part of the sub-query? + * + *

+ * + * @param select SELECT statement + * @return naming scope for SELECT statement + */ + SqlValidatorScope getSelectScope(SqlSelect select); + /** + * Returns the scope that expressions in the WHERE and GROUP BY clause of + * this query should use. This scope consists of the tables in the FROM + * clause, and the enclosing scope. + * + * @param select Query + * @return naming scope of WHERE clause + */ + SqlValidatorScope getWhereScope(SqlSelect select); + SqlValidatorScope getWithScope(SqlNode withItem); + + SqlValidatorScope getScopeOrThrow(SqlNode node); + + SqlValidatorScope getScope(SqlNode sqlNode); + + SelectScope getRawSelectScopeNonNull(SqlSelect select); + + @Nullable + TableScope getTableScope(); + + + /** + * Returns the scope for resolving the SELECT, GROUP BY and HAVING clauses. + * Always a {@link SelectScope}; if this is an aggregation query, the + * {@link AggregatingScope} is stripped away. + * + * @param select SELECT statement + * @return naming scope for SELECT statement, sans any aggregating scope + */ + @Nullable SelectScope getRawSelectScope(SqlSelect select); + + + /** Allows {@link SqlQueryScopesImpl#clauseScopes} to have multiple values per SELECT. */ + enum Clause { + WHERE, + GROUP_BY, + SELECT, + MEASURE, + ORDER, + CURSOR, + HAVING, + QUALIFY; + + /** + * Determines if the extender should replace aliases with expanded values. + * For example: + * + *
{@code
+     * SELECT a + a as twoA
+     * GROUP BY twoA
+     * }
+ * + *

turns into + * + *

{@code
+     * SELECT a + a as twoA
+     * GROUP BY a + a
+     * }
+ * + *

This is determined both by the clause and the config. + * + * @param config The configuration + * @return Whether we should replace the alias with its expanded value + */ + public boolean shouldReplaceAliases(SqlValidator.Config config) { + switch (this) { + case GROUP_BY: + return config.conformance().isGroupByAlias(); + + case HAVING: + return config.conformance().isHavingAlias(); + + case QUALIFY: + return true; + + default: + throw Util.unexpected(this); + } + } + } +} diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlQueryScopesImpl.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlQueryScopesImpl.java new file mode 100644 index 000000000000..f0dc53b6a689 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlQueryScopesImpl.java @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.calcite.sql.validate; + +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLambda; +import org.apache.calcite.sql.SqlMatchRecognize; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlSelect; +import org.apache.calcite.sql.util.IdPair; + +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Map; + +import static org.apache.calcite.sql.SqlUtil.stripAs; + +import static java.util.Objects.requireNonNull; + +/** + * An implementation of SqlQueryScopes with helper methods for building up the mapping. + */ +public class SqlQueryScopesImpl implements SqlQueryScopes { + + /** + * Maps {@link SqlNode query node} objects to the {@link SqlValidatorScope} + * scope created from them. + */ + protected final IdentityHashMap scopes = + new IdentityHashMap<>(); + + + /** + * Maps a {@link SqlSelect} and a {@link Clause} to the scope used by that + * clause. + */ + private final Map, SqlValidatorScope> + clauseScopes = new HashMap<>(); + + /** + * The name-resolution scope of a LATERAL TABLE clause. + */ + private @Nullable TableScope tableScope = null; + + @Override public SqlValidatorScope getCursorScope(SqlSelect select) { + return getScope(select, Clause.CURSOR); + } + + public @Nullable SqlValidatorScope putCursorScope( + SqlSelect select, SelectScope selectScope) { + return putScope(select, Clause.CURSOR, selectScope); + } + + @Override public SqlValidatorScope getFromScope(SqlSelect select) { + return requireNonNull(scopes.get(select), + () -> "no scope for " + select); + } + + @Override public SqlValidatorScope getGroupScope(SqlSelect select) { + // Yes, it's the same as getWhereScope + return getScope(select, Clause.WHERE); + } + + + public @Nullable SqlValidatorScope putGroupByScope( + SqlSelect select, SqlValidatorScope sqlValidatorScope) { + // Why is the group by, but the get is where? + return putScope(select, Clause.GROUP_BY, sqlValidatorScope); + } + + + @Override public SqlValidatorScope getHavingScope(SqlSelect select) { + // Yes, it's the same as getSelectScope + return getScope(select, Clause.SELECT); + } + + @Override public SqlValidatorScope getJoinScope(SqlNode node) { + return requireNonNull(scopes.get(stripAs(node)), + () -> "scope for " + node); + } + + @Override public SqlValidatorScope getLambdaScope(SqlLambda node) { + return getScopeOrThrow(node); + } + + @Override public SqlValidatorScope getMatchRecognizeScope(SqlMatchRecognize node) { + return getScopeOrThrow(node); + } + + @Override public SqlValidatorScope getMeasureScope(SqlSelect select) { + return getScope(select, Clause.MEASURE); + } + + public @Nullable SqlValidatorScope putMeasureScope( + SqlSelect select, SqlValidatorScope sqlValidatorScope) { + return putScope(select, Clause.MEASURE, sqlValidatorScope); + } + + @Override public SqlValidatorScope getOrderScope(SqlSelect select) { + return getScope(select, Clause.ORDER); + } + + public @Nullable SqlValidatorScope putOrderScope( + SqlSelect select, SqlValidatorScope sqlValidatorScope) { + return putScope(select, Clause.ORDER, sqlValidatorScope); + } + + @Override public SqlValidatorScope getOverScope(SqlNode node) { + return getScopeOrThrow(node); + } + + @Override public SqlValidatorScope getSelectScope(SqlSelect select) { + return getScope(select, Clause.SELECT); + } + + public @Nullable SqlValidatorScope putSelectScope( + SqlSelect select, SqlValidatorScope sqlValidatorScope) { + return putScope(select, Clause.SELECT, sqlValidatorScope); + } + + @Override public SqlValidatorScope getWhereScope(SqlSelect select) { + return getScope(select, Clause.WHERE); + } + + public @Nullable SqlValidatorScope putWhereScope( + SqlSelect sqlNode, SelectScope selectScope) { + return putScope(sqlNode, Clause.WHERE, selectScope); + } + + @Override public SqlValidatorScope getWithScope(SqlNode withItem) { + assert withItem.getKind() == SqlKind.WITH_ITEM; + return getScopeOrThrow(withItem); + } + + @Override public SqlValidatorScope getScopeOrThrow(SqlNode node) { + return requireNonNull(scopes.get(node), () -> "scope for " + node); + } + + @Override public SqlValidatorScope getScope(SqlNode sqlNode) { + return scopes.get(sqlNode); + } + + public @Nullable SqlValidatorScope putScope(SqlNode sqlNode, + SqlValidatorScope sqlValidatorScope) { + return scopes.put(sqlNode, sqlValidatorScope); + } + + public @Nullable SqlValidatorScope putIfAbsent(SqlNode sqlNode, + SqlValidatorScope sqlValidatorScope) { + return scopes.putIfAbsent(sqlNode, sqlValidatorScope); + } + + private @Nullable SqlValidatorScope putScope(SqlSelect select, Clause clause, + SqlValidatorScope sqlValidatorScope) { + return clauseScopes.put(IdPair.of(select, clause), sqlValidatorScope); + } + + @Override public @Nullable SelectScope getRawSelectScope(SqlSelect select) { + SqlValidatorScope scope = clauseScopes.get(IdPair.of(select, Clause.SELECT)); + if (scope instanceof AggregatingSelectScope) { + scope = ((AggregatingSelectScope) scope).getParent(); + } + return (SelectScope) scope; + } + + @Override public SelectScope getRawSelectScopeNonNull(SqlSelect select) { + return requireNonNull(getRawSelectScope(select), + () -> "getRawSelectScope for " + select); + } + + @Override public @Nullable TableScope getTableScope() { + return tableScope; + } + + public void setTableScope(@Nullable TableScope tableScope) { + this.tableScope = tableScope; + } + + private SqlValidatorScope getScope(SqlSelect select, Clause clause) { + return requireNonNull( + clauseScopes.get(IdPair.of(select, clause)), + () -> "no " + clause + " scope for " + select); + } +} 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 b113dec80f23..59601c3d574e 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 @@ -35,7 +35,6 @@ import org.apache.calcite.sql.SqlIntervalQualifier; import org.apache.calcite.sql.SqlLambda; import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlMatchRecognize; import org.apache.calcite.sql.SqlMerge; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; @@ -59,6 +58,7 @@ import java.util.List; import java.util.Map; +import java.util.function.Supplier; import java.util.function.UnaryOperator; /** @@ -109,12 +109,6 @@ *

The validator builds the map by making a quick scan over the query when * the root {@link SqlNode} is first provided. Thereafter, it supplies the * correct scope or namespace object when it calls validation methods. - * - *

The methods {@link #getSelectScope}, {@link #getFromScope}, - * {@link #getWhereScope}, {@link #getGroupScope}, {@link #getHavingScope}, - * {@link #getOrderScope} and {@link #getJoinScope} get the correct scope - * to resolve - * names in a particular clause of a SQL statement. */ @Value.Enclosing public interface SqlValidator { @@ -136,6 +130,14 @@ public interface SqlValidator { @Pure SqlOperatorTable getOperatorTable(); + /** + * Returns a mapping of sql nodes to scopes. + * + * @return sql query scopes + */ + @Pure + SqlQueryScopes getSqlQueryScopes(); + /** * Validates an expression tree. You can call this method multiple times, * but not reentrantly. @@ -467,18 +469,6 @@ default SqlWindow resolveWindow( SqlNodeList expandStar(SqlNodeList selectList, SqlSelect query, boolean includeSystemVars); - /** - * Returns the scope that expressions in the WHERE and GROUP BY clause of - * this query should use. This scope consists of the tables in the FROM - * clause, and the enclosing scope. - * - * @param select Query - * @return naming scope of WHERE clause - */ - SqlValidatorScope getWhereScope(SqlSelect select); - - SqlValidatorScope getMeasureScope(SqlSelect select); - /** * Returns the type factory used by this validator. * @@ -513,120 +503,10 @@ SqlNodeList expandStar(SqlNodeList selectList, SqlSelect query, */ RelDataType getUnknownType(); - /** - * Returns the appropriate scope for validating a particular clause of a - * SELECT statement. - * - *

Consider - * - *

SELECT *
-   * FROM foo
-   * WHERE EXISTS (
-   *    SELECT deptno AS x
-   *    FROM emp
-   *       JOIN dept ON emp.deptno = dept.deptno
-   *    WHERE emp.deptno = 5
-   *    GROUP BY deptno
-   *    ORDER BY x)
- * - *

What objects can be seen in each part of the sub-query? - * - *

- * - * @param select SELECT statement - * @return naming scope for SELECT statement - */ - SqlValidatorScope getSelectScope(SqlSelect select); - - /** - * Returns the scope for resolving the SELECT, GROUP BY and HAVING clauses. - * Always a {@link SelectScope}; if this is an aggregation query, the - * {@link AggregatingScope} is stripped away. - * - * @param select SELECT statement - * @return naming scope for SELECT statement, sans any aggregating scope - */ - @Nullable SelectScope getRawSelectScope(SqlSelect select); - - /** - * Returns a scope containing the objects visible from the FROM clause of a - * query. - * - * @param select SELECT statement - * @return naming scope for FROM clause - */ - SqlValidatorScope getFromScope(SqlSelect select); - - /** - * Returns a scope containing the objects visible from the ON and USING - * sections of a JOIN clause. - * - * @param node The item in the FROM clause which contains the ON or USING - * expression - * @return naming scope for JOIN clause - * @see #getFromScope - */ - SqlValidatorScope getJoinScope(SqlNode node); - - /** - * Returns a scope containing the objects visible from the GROUP BY clause - * of a query. - * - * @param select SELECT statement - * @return naming scope for GROUP BY clause - */ - SqlValidatorScope getGroupScope(SqlSelect select); - - /** - * Returns a scope containing the objects visible from the HAVING clause of - * a query. - * - * @param select SELECT statement - * @return naming scope for HAVING clause - */ - SqlValidatorScope getHavingScope(SqlSelect select); - - /** - * Returns the scope that expressions in the SELECT and HAVING clause of - * this query should use. This scope consists of the FROM clause and the - * enclosing scope. If the query is aggregating, only columns in the GROUP - * BY clause may be used. - * - * @param select SELECT statement - * @return naming scope for ORDER BY clause - */ - SqlValidatorScope getOrderScope(SqlSelect select); - - /** - * Returns a scope match recognize clause. - * - * @param node Match recognize - * @return naming scope for Match recognize clause - */ - SqlValidatorScope getMatchRecognizeScope(SqlMatchRecognize node); - - /** - * Returns the lambda expression scope. - * - * @param node Lambda expression - * @return naming scope for lambda expression - */ - SqlValidatorScope getLambdaScope(SqlLambda node); - /** * Returns a scope that cannot see anything. */ - SqlValidatorScope getEmptyScope(); + SqlValidatorScope createEmptyScope(); /** * Declares a SELECT expression as a cursor. @@ -757,14 +637,6 @@ CalciteException handleUnresolvedFunction(SqlCall call, */ RelDataType getParameterRowType(SqlNode sqlQuery); - /** - * Returns the scope of an OVER or VALUES node. - * - * @param node Node - * @return Scope - */ - SqlValidatorScope getOverScope(SqlNode node); - /** * Validates that a query is capable of producing a return of given modality * (relational or streaming). @@ -784,8 +656,6 @@ boolean validateModality(SqlSelect select, SqlModality modality, void validateSequenceValue(SqlValidatorScope scope, SqlIdentifier id); - SqlValidatorScope getWithScope(SqlNode withItem); - /** Get the type coercion instance. */ TypeCoercion getTypeCoercion(); @@ -1014,6 +884,15 @@ default Config withNakedMeasures(boolean nakedMeasures) { return SqlConformanceEnum.DEFAULT; } + /** Set a supplier for query scopes to allow for custom behavior downstream. */ + Config withSqlQueryScopeSupplier(Supplier supplier); + + /** Returns a supplier of SqlQueryScopes. */ + @Value.Default default Supplier sqlQueryScopeSupplier() { + return SqlQueryScopesImpl::new; + } + + /** Returns the SQL conformance. * * @deprecated Use {@link #conformance()} */ 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 706c8e6be0e5..4b93ec9d8e58 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 @@ -104,10 +104,10 @@ import org.apache.calcite.sql.type.SqlTypeFamily; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.type.SqlTypeUtil; -import org.apache.calcite.sql.util.IdPair; import org.apache.calcite.sql.util.SqlBasicVisitor; import org.apache.calcite.sql.util.SqlShuttle; import org.apache.calcite.sql.util.SqlVisitor; +import org.apache.calcite.sql.validate.SqlQueryScopes.Clause; import org.apache.calcite.sql.validate.implicit.TypeCoercion; import org.apache.calcite.util.BitString; import org.apache.calcite.util.Bug; @@ -214,24 +214,6 @@ public class SqlValidatorImpl implements SqlValidatorWithHints { */ protected final Map idPositions = new HashMap<>(); - /** - * Maps {@link SqlNode query node} objects to the {@link SqlValidatorScope} - * scope created from them. - */ - protected final IdentityHashMap scopes = - new IdentityHashMap<>(); - - /** - * Maps a {@link SqlSelect} and a {@link Clause} to the scope used by that - * clause. - */ - private final Map, SqlValidatorScope> - clauseScopes = new HashMap<>(); - - /** - * The name-resolution scope of a LATERAL TABLE clause. - */ - private @Nullable TableScope tableScope = null; /** * Maps a {@link SqlNode node} to the @@ -298,6 +280,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints { // TypeCoercion instance used for implicit type coercion. private final TypeCoercion typeCoercion; + private final SqlQueryScopesImpl sqlQueryScopes; //~ Constructors ----------------------------------------------------------- @@ -339,6 +322,7 @@ protected SqlValidatorImpl( @SuppressWarnings("argument.type.incompatible") TypeCoercion typeCoercion = config.typeCoercionFactory().create(typeFactory, this); this.typeCoercion = typeCoercion; + this.sqlQueryScopes = config.sqlQueryScopeSupplier().get(); if (config.conformance().allowLenientCoercion()) { final SqlTypeCoercionRule rules = @@ -406,7 +390,7 @@ public SqlConformance getConformance() { list, catalogReader.nameMatcher().createSet(), types, includeSystemVars); } - getRawSelectScopeNonNull(select).setExpandedSelectList(list); + sqlQueryScopes.getRawSelectScopeNonNull(select).setExpandedSelectList(list); return new SqlNodeList(list, SqlParserPos.ZERO); } @@ -426,8 +410,8 @@ public SqlConformance getConformance() { // that is the argument to the cursor constructor; register it // with a scope corresponding to the cursor SelectScope cursorScope = - new SelectScope(parentScope, getEmptyScope(), select); - clauseScopes.put(IdPair.of(select, Clause.CURSOR), cursorScope); + new SelectScope(parentScope, createEmptyScope(), select); + sqlQueryScopes.putCursorScope(select, cursorScope); final SelectNamespace selectNs = createSelectNamespace(select, select); final String alias = SqlValidatorUtil.alias(select, nextGeneratedId++); registerNamespace(cursorScope, alias, selectNs, false); @@ -468,10 +452,10 @@ private boolean expandSelectItem(final SqlNode selectItem, SqlSelect select, final SqlValidatorScope selectScope; SqlNode expanded; if (SqlValidatorUtil.isMeasure(selectItem)) { - selectScope = getMeasureScope(select); + selectScope = sqlQueryScopes.getMeasureScope(select); expanded = selectItem; } else { - final SelectScope scope = (SelectScope) getWhereScope(select); + final SelectScope scope = (SelectScope) sqlQueryScopes.getWhereScope(select); if (expandStar(selectItems, aliases, fields, includeSystemVars, scope, selectItem)) { return true; @@ -480,7 +464,7 @@ private boolean expandSelectItem(final SqlNode selectItem, SqlSelect select, // Expand the select item: fully-qualify columns, and convert // parentheses-free functions such as LOCALTIME into explicit function // calls. - selectScope = getSelectScope(select); + selectScope = sqlQueryScopes.getSelectScope(select); expanded = expandSelectExpr(selectItem, scope, select); } final String alias = @@ -905,7 +889,7 @@ void lookupSelectHints( IdInfo info = idPositions.get(pos.toString()); if (info == null) { SqlNode fromNode = select.getFrom(); - final SqlValidatorScope fromScope = getFromScope(select); + final SqlValidatorScope fromScope = sqlQueryScopes.getFromScope(select); lookupFromHints(fromNode, fromScope, pos, hintList); } else { lookupNameCompletionHints(info.scope, info.id.names, @@ -984,7 +968,7 @@ private void lookupJoinHints( case ON: requireNonNull(condition, () -> "join.getCondition() for " + join) .findValidOptions(this, - getScopeOrThrow(join), + sqlQueryScopes.getScopeOrThrow(join), pos, hintList); return; default: @@ -1235,89 +1219,15 @@ protected void validateNamespace(final SqlValidatorNamespace namespace, } } - @Override public SqlValidatorScope getEmptyScope() { - return new EmptyScope(this); - } - - private SqlValidatorScope getScope(SqlSelect select, Clause clause) { - return requireNonNull( - clauseScopes.get(IdPair.of(select, clause)), - () -> "no " + clause + " scope for " + select); - } - - public SqlValidatorScope getCursorScope(SqlSelect select) { - return getScope(select, Clause.CURSOR); - } - - @Override public SqlValidatorScope getWhereScope(SqlSelect select) { - return getScope(select, Clause.WHERE); - } - - @Override public SqlValidatorScope getSelectScope(SqlSelect select) { - return getScope(select, Clause.SELECT); - } - - @Override public SqlValidatorScope getMeasureScope(SqlSelect select) { - return getScope(select, Clause.MEASURE); - } - - @Override public @Nullable SelectScope getRawSelectScope(SqlSelect select) { - SqlValidatorScope scope = clauseScopes.get(IdPair.of(select, Clause.SELECT)); - if (scope instanceof AggregatingSelectScope) { - scope = ((AggregatingSelectScope) scope).getParent(); - } - return (SelectScope) scope; - } - - private SelectScope getRawSelectScopeNonNull(SqlSelect select) { - return requireNonNull(getRawSelectScope(select), - () -> "getRawSelectScope for " + select); - } - - @Override public SqlValidatorScope getHavingScope(SqlSelect select) { - // Yes, it's the same as getSelectScope - return getScope(select, Clause.SELECT); - } - - @Override public SqlValidatorScope getGroupScope(SqlSelect select) { - // Yes, it's the same as getWhereScope - return getScope(select, Clause.WHERE); - } - - @Override public SqlValidatorScope getFromScope(SqlSelect select) { - return requireNonNull(scopes.get(select), - () -> "no scope for " + select); - } - - @Override public SqlValidatorScope getOrderScope(SqlSelect select) { - return getScope(select, Clause.ORDER); - } - - @Override public SqlValidatorScope getMatchRecognizeScope(SqlMatchRecognize node) { - return getScopeOrThrow(node); - } - @Override public SqlValidatorScope getLambdaScope(SqlLambda node) { - return getScopeOrThrow(node); - } - - @Override public SqlValidatorScope getJoinScope(SqlNode node) { - return requireNonNull(scopes.get(stripAs(node)), - () -> "scope for " + node); - } - - @Override public SqlValidatorScope getOverScope(SqlNode node) { - return getScopeOrThrow(node); + @Override public SqlValidatorScope createEmptyScope() { + return new EmptyScope(this); } - @Override public SqlValidatorScope getWithScope(SqlNode withItem) { - assert withItem.getKind() == SqlKind.WITH_ITEM; - return getScopeOrThrow(withItem); + @Override public SqlQueryScopes getSqlQueryScopes() { + return sqlQueryScopes; } - private SqlValidatorScope getScopeOrThrow(SqlNode node) { - return requireNonNull(scopes.get(node), () -> "scope for " + node); - } private @Nullable SqlValidatorNamespace getNamespace(SqlNode node, SqlValidatorScope scope) { @@ -2103,7 +2013,7 @@ protected void inferUnknownTypes( requireNonNull(inferredType, "inferredType"); requireNonNull(scope, "scope"); requireNonNull(node, "node"); - final SqlValidatorScope newScope = scopes.get(node); + final SqlValidatorScope newScope = sqlQueryScopes.getScope(node); if (newScope != null) { scope = newScope; } @@ -2186,7 +2096,7 @@ protected void inferUnknownTypes( // For MEASURE operator, use the measure scope (which has additional // aliases available) if (scope instanceof SelectScope) { - scope = getMeasureScope(((SelectScope) scope).getNode()); + scope = sqlQueryScopes.getMeasureScope(((SelectScope) scope).getNode()); } inferUnknownTypes(inferredType, scope, ((SqlCall) node).operand(0)); } else if (node instanceof SqlCall) { @@ -2262,7 +2172,7 @@ private void registerMatchRecognize( final MatchRecognizeScope matchRecognizeScope = new MatchRecognizeScope(parentScope, call); - scopes.put(call, matchRecognizeScope); + sqlQueryScopes.putScope(call, matchRecognizeScope); // parse input query SqlNode expr = call.getTableRef(); @@ -2293,7 +2203,7 @@ private void registerPivot( final SqlValidatorScope scope = new PivotScope(parentScope, pivot); - scopes.put(pivot, scope); + sqlQueryScopes.putScope(pivot, scope); // parse input query SqlNode expr = pivot.query; @@ -2323,7 +2233,7 @@ private void registerUnpivot( final SqlValidatorScope scope = new UnpivotScope(parentScope, call); - scopes.put(call, scope); + sqlQueryScopes.putScope(call, scope); // parse input query SqlNode expr = call.query; @@ -2558,7 +2468,7 @@ private SqlNode registerFrom( final SqlJoin join = (SqlJoin) node; final JoinScope joinScope = new JoinScope(parentScope, usingScope, join); - scopes.put(join, joinScope); + sqlQueryScopes.putScope(join, joinScope); final SqlNode left = join.getLeft(); final SqlNode right = join.getRight(); boolean forceLeftNullable = forceNullable; @@ -2606,8 +2516,8 @@ private SqlNode registerFrom( if (newRight != right) { join.setRight(newRight); } - scopes.putIfAbsent(stripAs(join.getRight()), parentScope); - scopes.putIfAbsent(stripAs(join.getLeft()), parentScope); + sqlQueryScopes.putIfAbsent(stripAs(join.getRight()), parentScope); + sqlQueryScopes.putIfAbsent(stripAs(join.getLeft()), parentScope); registerSubQueries(joinScope, join.getCondition()); final JoinNamespace joinNamespace = new JoinNamespace(this, join); registerNamespace(null, null, joinNamespace, forceNullable); @@ -2621,10 +2531,11 @@ private SqlNode registerFrom( parentScope); registerNamespace(register ? usingScope : null, alias, newNs, forceNullable); - if (tableScope == null) { - tableScope = new TableScope(parentScope, node); + if (sqlQueryScopes.getTableScope() == null) { + sqlQueryScopes.setTableScope(new TableScope(parentScope, node)); } - tableScope.addChild(newNs, requireNonNull(alias, "alias"), forceNullable); + sqlQueryScopes.getTableScope() + .addChild(newNs, requireNonNull(alias, "alias"), forceNullable); if (extendList != null && !extendList.isEmpty()) { return enclosingNode; } @@ -2665,14 +2576,14 @@ private SqlNode registerFrom( final SqlOperator op = call1.getOperator(); if (op instanceof SqlWindowTableFunction && call1.operand(0).getKind() == SqlKind.SELECT) { - scopes.put(node, getSelectScope(call1.operand(0))); + sqlQueryScopes.putScope(node, sqlQueryScopes.getSelectScope(call1.operand(0))); return newNode; } } // Put the usingScope which can be a JoinScope // or a SelectScope, in order to see the left items // of the JOIN tree. - scopes.put(node, usingScope); + sqlQueryScopes.putScope(node, usingScope); return newNode; case UNNEST: @@ -2706,7 +2617,7 @@ private SqlNode registerFrom( } call = (SqlCall) node; final OverScope overScope = new OverScope(usingScope, call); - scopes.put(call, overScope); + sqlQueryScopes.putScope(call, overScope); operand = call.operand(0); newOperand = registerFrom( @@ -2777,7 +2688,7 @@ private SqlNode registerFrom( // Put the usingScope which can be a JoinScope // or a SelectScope, in order to see the left items // of the JOIN tree. - scopes.put(node, usingScope); + sqlQueryScopes.putScope(node, usingScope); return newNode; default: @@ -2883,10 +2794,10 @@ private void registerQuery( first(usingScope, parentScope); SelectScope selectScope = new SelectScope(parentScope, windowParentScope, select); - scopes.put(select, selectScope); + sqlQueryScopes.putScope(select, selectScope); // Start by registering the WHERE clause - clauseScopes.put(IdPair.of(select, Clause.WHERE), selectScope); + sqlQueryScopes.putWhereScope(select, selectScope); registerOperandSubQueries( selectScope, select, @@ -2926,13 +2837,12 @@ private void registerQuery( isAggregate(select) ? new AggregatingSelectScope(selectScope, select, false) : selectScope; - clauseScopes.put(IdPair.of(select, Clause.SELECT), selectScope2); - clauseScopes.put(IdPair.of(select, Clause.MEASURE), - new MeasureScope(selectScope, select)); + sqlQueryScopes.putSelectScope(select, selectScope2); + sqlQueryScopes.putMeasureScope(select, new MeasureScope(selectScope, select)); if (select.getGroup() != null) { GroupByScope groupByScope = new GroupByScope(selectScope, select.getGroup(), select); - clauseScopes.put(IdPair.of(select, Clause.GROUP_BY), groupByScope); + sqlQueryScopes.putGroupByScope(select, groupByScope); registerSubQueries(groupByScope, select.getGroup()); } registerOperandSubQueries( @@ -2951,7 +2861,7 @@ private void registerQuery( : selectScope2; OrderByScope orderScope = new OrderByScope(selectScope3, orderList, select); - clauseScopes.put(IdPair.of(select, Clause.ORDER), orderScope); + sqlQueryScopes.putOrderScope(select, orderScope); registerSubQueries(orderScope, orderList); if (!isAggregate(select)) { @@ -3001,7 +2911,7 @@ private void registerQuery( call = (SqlCall) node; SqlLambdaScope lambdaScope = new SqlLambdaScope(parentScope, (SqlLambda) call); - scopes.put(call, lambdaScope); + sqlQueryScopes.putScope(call, lambdaScope); final LambdaNamespace lambdaNamespace = new LambdaNamespace(this, (SqlLambda) call, node); registerNamespace( @@ -3022,7 +2932,7 @@ private void registerQuery( case VALUES: call = (SqlCall) node; - scopes.put(call, parentScope); + sqlQueryScopes.putScope(call, parentScope); final TableConstructorNamespace tableConstructorNamespace = new TableConstructorNamespace( this, @@ -3128,7 +3038,7 @@ private void registerQuery( SqlUpdate mergeUpdateCall = mergeCall.getUpdateCall(); if (mergeUpdateCall != null) { registerQuery( - getScope(SqlNonNullableAccessors.getSourceSelect(mergeCall), Clause.WHERE), + sqlQueryScopes.getWhereScope(SqlNonNullableAccessors.getSourceSelect(mergeCall)), null, mergeUpdateCall, enclosingNode, @@ -3158,7 +3068,7 @@ private void registerQuery( unnestNs, forceNullable); registerOperandSubQueries(parentScope, call, 0); - scopes.put(node, parentScope); + sqlQueryScopes.putScope(node, parentScope); break; case OTHER_FUNCTION: call = (SqlCall) node; @@ -3213,7 +3123,7 @@ private void registerSetop( registerNamespace(usingScope, alias, setopNamespace, forceNullable); // A setop is in the same scope as its parent. - scopes.put(call, parentScope); + sqlQueryScopes.putScope(call, parentScope); @NonNull SqlValidatorScope recursiveScope = parentScope; if (enclosingNode.getKind() == SqlKind.WITH_ITEM) { if (node.getKind() != SqlKind.UNION) { @@ -3221,7 +3131,7 @@ private void registerSetop( } else if (call.getOperandList().size() > 2) { throw newValidationError(node, RESOURCE.recursiveWithMustHaveTwoChildUnionSetOp()); } - final WithScope scope = (WithScope) scopes.get(enclosingNode); + final WithScope scope = (WithScope) sqlQueryScopes.getScope(enclosingNode); // recursive scope is only set for the recursive queries. recursiveScope = scope != null && scope.recursiveScope != null ? requireNonNull(scope.recursiveScope) : parentScope; @@ -3250,7 +3160,7 @@ private void registerWith( final WithNamespace withNamespace = new WithNamespace(this, with, enclosingNode); registerNamespace(usingScope, alias, withNamespace, forceNullable); - scopes.put(with, parentScope); + sqlQueryScopes.putScope(with, parentScope); SqlValidatorScope scope = parentScope; for (SqlNode withItem_ : with.withList) { @@ -3260,7 +3170,7 @@ private void registerWith( final SqlValidatorScope withScope = new WithScope(scope, withItem, isRecursiveWith ? new WithRecursiveScope(scope, withItem) : null); - scopes.put(withItem, withScope); + sqlQueryScopes.putScope(withItem, withScope); registerQuery(scope, null, withItem.query, withItem.recursive.booleanValue() ? withItem : with, withItem.name.getSimple(), @@ -3323,7 +3233,7 @@ protected boolean isOverAggregateWindow(SqlNode node) { /** If there is at least one call to an aggregate function, returns the * first. */ private @Nullable SqlNode getAgg(SqlSelect select) { - final SelectScope selectScope = getRawSelectScope(select); + final SelectScope selectScope = sqlQueryScopes.getRawSelectScope(select); if (selectScope != null) { final List selectList = selectScope.getExpandedSelectList(); if (selectList != null) { @@ -3708,7 +3618,7 @@ protected void validateJoin(SqlJoin join, SqlValidatorScope scope) { final boolean natural = join.isNatural(); final JoinType joinType = join.getJoinType(); final JoinConditionType conditionType = join.getConditionType(); - final SqlValidatorScope joinScope = getScopeOrThrow(join); // getJoinScope? + final SqlValidatorScope joinScope = sqlQueryScopes.getScopeOrThrow(join); // getJoinScope? validateFrom(left, unknownType, joinScope); validateFrom(right, unknownType, joinScope); @@ -4056,7 +3966,7 @@ protected void validateSelect( } // Make sure that items in FROM clause have distinct aliases. - final SelectScope fromScope = (SelectScope) getFromScope(select); + final SelectScope fromScope = (SelectScope) sqlQueryScopes.getFromScope(select); List<@Nullable String> names = fromScope.getChildNames(); if (!catalogReader.nameMatcher().isCaseSensitive()) { //noinspection RedundantTypeArguments @@ -4115,11 +4025,11 @@ protected void validateSelect( } if (!qualifieds.isEmpty()) { if (select.getWhere() != null) { - forEachQualified(select.getWhere(), getWhereScope(select), + forEachQualified(select.getWhere(), sqlQueryScopes.getWhereScope(select), qualifieds::remove); } if (select.getHaving() != null) { - forEachQualified(select.getHaving(), getHavingScope(select), + forEachQualified(select.getHaving(), sqlQueryScopes.getHavingScope(select), qualifieds::remove); } @@ -4164,8 +4074,8 @@ protected void validateSelect( if (shouldCheckForRollUp(from)) { checkRollUpInSelectList(select); - checkRollUp(null, select, select.getWhere(), getWhereScope(select)); - checkRollUp(null, select, select.getHaving(), getHavingScope(select)); + checkRollUp(null, select, select.getWhere(), sqlQueryScopes.getWhereScope(select)); + checkRollUp(null, select, select.getHaving(), sqlQueryScopes.getHavingScope(select)); checkRollUpInWindowDecl(select); checkRollUpInGroupBy(select); checkRollUpInOrderBy(select); @@ -4186,7 +4096,7 @@ private static void forEachQualified(SqlNode node, SqlValidatorScope scope, } private void checkRollUpInSelectList(SqlSelect select) { - SqlValidatorScope scope = getSelectScope(select); + SqlValidatorScope scope = sqlQueryScopes.getSelectScope(select); for (SqlNode item : SqlNonNullableAccessors.getSelectList(select)) { if (SqlValidatorUtil.isMeasure(item)) { continue; @@ -4199,7 +4109,8 @@ private void checkRollUpInGroupBy(SqlSelect select) { SqlNodeList group = select.getGroup(); if (group != null) { for (SqlNode node : group) { - checkRollUp(null, select, node, getGroupScope(select), "GROUP BY"); + SqlValidatorScope groupScope = sqlQueryScopes.getGroupScope(select); + checkRollUp(null, select, node, groupScope, "GROUP BY"); } } } @@ -4208,7 +4119,8 @@ private void checkRollUpInOrderBy(SqlSelect select) { SqlNodeList orderList = select.getOrderList(); if (orderList != null) { for (SqlNode node : orderList) { - checkRollUp(null, select, node, getOrderScope(select), "ORDER BY"); + SqlValidatorScope orderScope = sqlQueryScopes.getOrderScope(select); + checkRollUp(null, select, node, orderScope, "ORDER BY"); } } } @@ -4227,7 +4139,7 @@ private void checkRollUpInWindow(@Nullable SqlWindow window, SqlValidatorScope s private void checkRollUpInWindowDecl(SqlSelect select) { for (SqlNode decl : select.getWindowList()) { - checkRollUpInWindow((SqlWindow) decl, getSelectScope(select)); + checkRollUpInWindow((SqlWindow) decl, sqlQueryScopes.getSelectScope(select)); } } @@ -4436,7 +4348,7 @@ private static SqlModality deduceModality(SqlNode query) { @Override public boolean validateModality(SqlSelect select, SqlModality modality, boolean fail) { - final SelectScope scope = getRawSelectScopeNonNull(select); + final SelectScope scope = sqlQueryScopes.getRawSelectScopeNonNull(select); switch (modality) { case STREAM: @@ -4561,7 +4473,7 @@ protected void validateWindowClause(SqlSelect select) { return; } - final SelectScope windowScope = (SelectScope) getFromScope(select); + final SelectScope windowScope = (SelectScope) sqlQueryScopes.getFromScope(select); // 1. ensure window names are simple // 2. ensure they are unique within this scope @@ -4614,7 +4526,7 @@ protected void validateQualifyClause(SqlSelect select) { return; } - SqlValidatorScope qualifyScope = getSelectScope(select); + SqlValidatorScope qualifyScope = sqlQueryScopes.getSelectScope(select); qualifyNode = extendedExpand(qualifyNode, qualifyScope, select, Clause.QUALIFY); select.setQualify(qualifyNode); @@ -4722,7 +4634,7 @@ protected void validateOrderList(SqlSelect select) { throw newValidationError(select, RESOURCE.invalidOrderByPos()); } } - final SqlValidatorScope orderScope = getOrderScope(select); + final SqlValidatorScope orderScope = sqlQueryScopes.getOrderScope(select); requireNonNull(orderScope, "orderScope"); List expandList = new ArrayList<>(); @@ -4747,7 +4659,7 @@ protected void validateOrderList(SqlSelect select) { * @param groupByItem GROUP BY clause item */ private void validateGroupByItem(SqlSelect select, SqlNode groupByItem) { - final SqlValidatorScope groupByScope = getGroupScope(select); + final SqlValidatorScope groupByScope = sqlQueryScopes.getGroupScope(select); validateGroupByExpr(groupByItem, groupByScope); groupByScope.validateExpr(groupByItem); } @@ -4792,7 +4704,7 @@ private void validateOrderItem(SqlSelect select, SqlNode orderItem) { break; } - final SqlValidatorScope orderScope = getOrderScope(select); + final SqlValidatorScope orderScope = sqlQueryScopes.getOrderScope(select); validateExpr(orderItem, orderScope); } @@ -4803,7 +4715,7 @@ private void validateOrderItem(SqlSelect select, SqlNode orderItem) { return orderExpr2; } - final SqlValidatorScope scope = getOrderScope(select); + final SqlValidatorScope scope = sqlQueryScopes.getOrderScope(select); inferUnknownTypes(unknownType, scope, orderExpr2); final RelDataType type = deriveType(scope, orderExpr2); setValidatedNodeType(orderExpr2, type); @@ -4835,7 +4747,7 @@ protected void validateGroupClause(SqlSelect select) { } final String clause = "GROUP BY"; validateNoAggs(aggOrOverFinder, groupList, clause); - final SqlValidatorScope groupScope = getGroupScope(select); + final SqlValidatorScope groupScope = sqlQueryScopes.getGroupScope(select); // expand the expression in group list. List expandedList = new ArrayList<>(); @@ -4870,7 +4782,7 @@ protected void validateGroupClause(SqlSelect select) { // Derive the type of each GROUP BY item. We don't need the type, but // it resolves functions, and that is necessary for deducing // monotonicity. - final SqlValidatorScope selectScope = getSelectScope(select); + final SqlValidatorScope selectScope = sqlQueryScopes.getSelectScope(select); AggregatingSelectScope aggregatingScope = null; if (selectScope instanceof AggregatingSelectScope) { aggregatingScope = (AggregatingSelectScope) selectScope; @@ -4925,7 +4837,7 @@ protected void validateWhereClause(SqlSelect select) { if (where == null) { return; } - final SqlValidatorScope whereScope = getWhereScope(select); + final SqlValidatorScope whereScope = sqlQueryScopes.getWhereScope(select); final SqlNode expandedWhere = expand(where, whereScope); select.setWhere(expandedWhere); validateWhereOrOn(whereScope, expandedWhere, "WHERE"); @@ -4970,7 +4882,7 @@ protected void validateHavingClause(SqlSelect select) { } SqlNode originalHaving = having; final AggregatingScope havingScope = - (AggregatingScope) getSelectScope(select); + (AggregatingScope) sqlQueryScopes.getSelectScope(select); if (config.conformance().isHavingAlias()) { SqlNode newExpr = extendedExpand(having, havingScope, select, Clause.HAVING); if (having != newExpr) { @@ -4996,7 +4908,7 @@ protected RelDataType validateSelectList(final SqlNodeList selectItems, // are ignored. // Validate SELECT list. Expand terms of the form "*" or "TABLE.*". - final SqlValidatorScope selectScope = getSelectScope(select); + final SqlValidatorScope selectScope = sqlQueryScopes.getSelectScope(select); final List expandedSelectItems = new ArrayList<>(); final Set aliases = new HashSet<>(); final PairList fieldList = PairList.of(); @@ -5027,7 +4939,7 @@ protected RelDataType validateSelectList(final SqlNodeList selectItems, if (config.identifierExpansion()) { select.setSelectList(newSelectList); } - getRawSelectScopeNonNull(select).setExpandedSelectList(expandedSelectItems); + sqlQueryScopes.getRawSelectScopeNonNull(select).setExpandedSelectList(expandedSelectItems); // TODO: when SELECT appears as a value sub-query, should be using // something other than unknownType for targetRowType @@ -5075,7 +4987,7 @@ private void validateExpr(SqlNode expr, SqlValidatorScope scope) { } if (SqlValidatorUtil.isMeasure(expr) && scope instanceof SelectScope) { - scope = getMeasureScope(((SelectScope) scope).getNode()); + scope = sqlQueryScopes.getMeasureScope(((SelectScope) scope).getNode()); } // Call on the expression to validate itself. @@ -5114,7 +5026,7 @@ private void handleScalarSubQuery(SqlSelect parentSelect, SqlValidatorUtil.alias(selectItem, aliasList.size()); aliasList.add(alias); - final SelectScope scope = (SelectScope) getWhereScope(parentSelect); + final SelectScope scope = (SelectScope) sqlQueryScopes.getWhereScope(parentSelect); final RelDataType type = deriveType(scope, selectItem); setValidatedNodeType(selectItem, type); @@ -5199,7 +5111,7 @@ protected RelDataType createTargetRowType( final SqlSelect sqlSelect = (SqlSelect) source; validateSelect(sqlSelect, targetRowType); } else { - final SqlValidatorScope scope = scopes.get(source); + final SqlValidatorScope scope = sqlQueryScopes.getScope(source); requireNonNull(scope, "scope"); validateQuery(source, scope, targetRowType); } @@ -5235,7 +5147,7 @@ protected RelDataType createTargetRowType( targetRowTypeToValidate, realTargetRowType, source, logicalSourceRowType, logicalTargetRowType); - checkTypeAssignment(scopes.get(source), + checkTypeAssignment(sqlQueryScopes.getScope(source), table, logicalSourceRowType, targetRowTypeToValidate, @@ -5619,7 +5531,7 @@ private static SqlNode getNthExpr(SqlNode query, int ordinal, int sourceCount) { validateSelect(select, targetRowType); final RelDataType sourceRowType = getValidatedNodeType(select); - checkTypeAssignment(scopes.get(select), table, sourceRowType, targetRowType, + checkTypeAssignment(sqlQueryScopes.getScope(select), table, sourceRowType, targetRowType, call); checkConstraint(table, call, targetRowType); @@ -5982,7 +5894,7 @@ public void setOriginal(SqlNode expr, SqlNode original) { } @Override public void validateLambda(SqlLambda lambdaExpr) { - final SqlLambdaScope scope = (SqlLambdaScope) scopes.get(lambdaExpr); + final SqlLambdaScope scope = (SqlLambdaScope) sqlQueryScopes.getScope(lambdaExpr); requireNonNull(scope, "scope"); final LambdaNamespace ns = getNamespaceOrThrow(lambdaExpr).unwrap(LambdaNamespace.class); @@ -5996,7 +5908,7 @@ public void setOriginal(SqlNode expr, SqlNode original) { @Override public void validateMatchRecognize(SqlCall call) { final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call; final MatchRecognizeScope scope = - (MatchRecognizeScope) getMatchRecognizeScope(matchRecognize); + (MatchRecognizeScope) sqlQueryScopes.getMatchRecognizeScope(matchRecognize); final MatchRecognizeNamespace ns = getNamespaceOrThrow(call).unwrap(MatchRecognizeNamespace.class); @@ -6251,7 +6163,7 @@ private static String alias(SqlNode item) { } public void validatePivot(SqlPivot pivot) { - final PivotScope scope = (PivotScope) getJoinScope(pivot); + final PivotScope scope = (PivotScope) sqlQueryScopes.getJoinScope(pivot); final PivotNamespace ns = getNamespaceOrThrow(pivot).unwrap(PivotNamespace.class); @@ -6327,7 +6239,7 @@ public void validatePivot(SqlPivot pivot) { } public void validateUnpivot(SqlUnpivot unpivot) { - final UnpivotScope scope = (UnpivotScope) getJoinScope(unpivot); + final UnpivotScope scope = (UnpivotScope) sqlQueryScopes.getJoinScope(unpivot); final UnpivotNamespace ns = getNamespaceOrThrow(unpivot).unwrap(UnpivotNamespace.class); @@ -6705,7 +6617,7 @@ public SqlNode extendedExpandGroupBy(SqlNode expr, private @Nullable List getFieldOrigin(SqlNode sqlQuery, int i) { if (sqlQuery instanceof SqlSelect) { SqlSelect sqlSelect = (SqlSelect) sqlQuery; - final SelectScope scope = getRawSelectScopeNonNull(sqlSelect); + final SelectScope scope = sqlQueryScopes.getRawSelectScopeNonNull(sqlSelect); final List selectList = requireNonNull(scope.getExpandedSelectList(), () -> "expandedSelectList for " + scope); @@ -7146,7 +7058,7 @@ class OrderExpressionExpander extends SqlScopedShuttle { private final SqlNode root; OrderExpressionExpander(SqlSelect select, SqlNode root) { - super(getOrderScope(select)); + super(sqlQueryScopes.getOrderScope(select)); this.select = select; this.root = root; this.aliasList = getNamespaceOrThrow(select).getRowType().getFieldNames(); @@ -7289,7 +7201,7 @@ static class ExtendedExpander extends Expander { final boolean replaceAliases = clause.shouldReplaceAliases(validator.config); if (!replaceAliases) { - final SelectScope scope = validator.getRawSelectScopeNonNull(select); + final SelectScope scope = validator.sqlQueryScopes.getRawSelectScopeNonNull(select); SqlNode node = expandCommonColumn(select, id, scope, validator); if (node != id) { return node; @@ -7877,52 +7789,5 @@ public enum Status { VALID } - /** Allows {@link #clauseScopes} to have multiple values per SELECT. */ - private enum Clause { - WHERE, - GROUP_BY, - SELECT, - MEASURE, - ORDER, - CURSOR, - HAVING, - QUALIFY; - /** - * Determines if the extender should replace aliases with expanded values. - * For example: - * - *
{@code
-     * SELECT a + a as twoA
-     * GROUP BY twoA
-     * }
- * - *

turns into - * - *

{@code
-     * SELECT a + a as twoA
-     * GROUP BY a + a
-     * }
- * - *

This is determined both by the clause and the config. - * - * @param config The configuration - * @return Whether we should replace the alias with its expanded value - */ - boolean shouldReplaceAliases(Config config) { - switch (this) { - case GROUP_BY: - return config.conformance().isGroupByAlias(); - - case HAVING: - return config.conformance().isHavingAlias(); - - case QUALIFY: - return true; - - default: - throw Util.unexpected(this); - } - } - } } diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorScope.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorScope.java index 4d59c96d1507..70e8c61af067 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorScope.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorScope.java @@ -317,7 +317,8 @@ class ResolvedImpl implements Resolved { boolean nullable, SqlValidatorScope scope, Path path, List remainingNames) { if (scope instanceof TableScope) { - scope = scope.getValidator().getSelectScope((SqlSelect) scope.getNode()); + scope = scope.getValidator().getSqlQueryScopes() + .getSelectScope((SqlSelect) scope.getNode()); } if (scope instanceof AggregatingSelectScope) { scope = ((AggregatingSelectScope) scope).parent; diff --git a/core/src/main/java/org/apache/calcite/sql/validate/TableScope.java b/core/src/main/java/org/apache/calcite/sql/validate/TableScope.java index 2bba7a22bb14..5af293e8c985 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/TableScope.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/TableScope.java @@ -54,7 +54,7 @@ class TableScope extends ListScope { if (this == scope2) { return true; } - SqlValidatorScope s = getValidator().getSelectScope((SqlSelect) node); + SqlValidatorScope s = getValidator().getSqlQueryScopes().getSelectScope((SqlSelect) node); return s.isWithin(scope2); } } diff --git a/core/src/main/java/org/apache/calcite/sql/validate/WithNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/WithNamespace.java index bec57b715b1d..a4ac664e835c 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/WithNamespace.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/WithNamespace.java @@ -57,7 +57,7 @@ public class WithNamespace extends AbstractNamespace { validator.validateWithItem((SqlWithItem) withItem); } final SqlValidatorScope scope2 = - validator.getWithScope(Util.last(with.withList)); + validator.getSqlQueryScopes().getWithScope(Util.last(with.withList)); final SqlValidatorNamespace bodyNamespace = requireNonNull(validator.getNamespace(with.body), "namespace"); diff --git a/core/src/main/java/org/apache/calcite/sql/validate/implicit/TypeCoercionImpl.java b/core/src/main/java/org/apache/calcite/sql/validate/implicit/TypeCoercionImpl.java index 73de170e5c12..9f798b474c0e 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/implicit/TypeCoercionImpl.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/implicit/TypeCoercionImpl.java @@ -98,7 +98,7 @@ public TypeCoercionImpl(RelDataTypeFactory typeFactory, SqlValidator validator) switch (kind) { case SELECT: SqlSelect selectNode = (SqlSelect) query; - SqlValidatorScope scope1 = validator.getSelectScope(selectNode); + SqlValidatorScope scope1 = validator.getSqlQueryScopes().getSelectScope(selectNode); if (!coerceColumnType(scope1, getSelectList(selectNode), columnIndex, targetType)) { return false; } @@ -118,7 +118,8 @@ public TypeCoercionImpl(RelDataTypeFactory typeFactory, SqlValidator validator) return coerceValues; case WITH: SqlNode body = ((SqlWith) query).body; - return rowTypeCoercion(validator.getOverScope(query), body, columnIndex, targetType); + return rowTypeCoercion( + validator.getSqlQueryScopes().getOverScope(query), body, columnIndex, targetType); case UNION: case INTERSECT: case EXCEPT: @@ -563,7 +564,7 @@ protected boolean booleanEquality(SqlCallBinding binding, } else { // Another sub-query. SqlValidatorScope scope1 = node2 instanceof SqlSelect - ? validator.getSelectScope((SqlSelect) node2) + ? validator.getSqlQueryScopes().getSelectScope((SqlSelect) node2) : scope; coerced = rowTypeCoercion(scope1, node2, i, desired) || coerced; } 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 12222b218b09..3d8a58466eeb 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java @@ -169,6 +169,7 @@ import org.apache.calcite.sql.validate.SqlMonotonicity; import org.apache.calcite.sql.validate.SqlNameMatcher; import org.apache.calcite.sql.validate.SqlQualified; +import org.apache.calcite.sql.validate.SqlQueryScopes; import org.apache.calcite.sql.validate.SqlUserDefinedTableFunction; import org.apache.calcite.sql.validate.SqlUserDefinedTableMacro; import org.apache.calcite.sql.validate.SqlValidator; @@ -386,6 +387,10 @@ private SqlValidator validator() { return requireNonNull(validator, "validator"); } + private SqlQueryScopes sqlQueryScopes() { + return requireNonNull(validator().getSqlQueryScopes(), "sqlQueryScopes"); + } + private T getNamespace(SqlNode node) { return requireNonNull(getNamespaceOrNull(node), () -> "Namespace is not found for " + node); @@ -727,9 +732,9 @@ private static RelCollation requiredCollation(RelNode r) { * Converts a SELECT statement's parse tree into a relational expression. */ public RelNode convertSelect(SqlSelect select, boolean top) { - final SqlValidatorScope selectScope = validator().getWhereScope(select); + final SqlValidatorScope selectScope = sqlQueryScopes().getWhereScope(select); final MeasureScope measureScope = - (MeasureScope) validator().getMeasureScope(select); + (MeasureScope) sqlQueryScopes().getMeasureScope(select); final Blackboard bb = createBlackboard(selectScope, null, top); final Blackboard measureBb = new MeasureBlackboard(measureScope, bb); convertSelectImpl(bb, measureBb, select); @@ -1362,8 +1367,8 @@ private void substituteSubQuery(Blackboard bb, SubQuery subQuery) { query = call.operand(0); final SqlValidatorScope seekScope = (query instanceof SqlSelect) - ? validator().getSelectScope((SqlSelect) query) - : validator().getEmptyScope(); + ? sqlQueryScopes().getSelectScope((SqlSelect) query) + : validator().createEmptyScope(); final Blackboard seekBb = createBlackboard(seekScope, null, false); final RelNode seekRel = convertQueryOrInList(seekBb, query, null); requireNonNull(seekRel, () -> "seekRel is null for query " + query); @@ -1444,8 +1449,8 @@ private void substituteSubQueryOfSetSemanticsInputTable( query = call.operand(0); final SqlValidatorScope innerTableScope = (query instanceof SqlSelect) - ? validator().getSelectScope((SqlSelect) query) - : validator().getEmptyScope(); + ? sqlQueryScopes().getSelectScope((SqlSelect) query) + : validator().createEmptyScope(); final Blackboard setSemanticsTableBb = createBlackboard(innerTableScope, null, false); final RelNode inputOfSetSemanticsTable = @@ -1846,8 +1851,8 @@ private RelOptUtil.Exists convertExists( @Nullable RelDataType targetDataType) { final SqlValidatorScope seekScope = (seek instanceof SqlSelect) - ? validator().getSelectScope((SqlSelect) seek) - : validator().getEmptyScope(); + ? sqlQueryScopes().getSelectScope((SqlSelect) seek) + : validator().createEmptyScope(); final Blackboard seekBb = createBlackboard(seekScope, null, false); RelNode seekRel = convertQueryOrInList(seekBb, seek, targetDataType); requireNonNull(seekRel, () -> "seekRel is null for query " + seek); @@ -2220,7 +2225,7 @@ public RexNode convertExpression( */ private RexNode convertLambda(Blackboard bb, SqlNode node) { final SqlLambda call = (SqlLambda) node; - final SqlLambdaScope scope = (SqlLambdaScope) validator().getLambdaScope(call); + final SqlLambdaScope scope = (SqlLambdaScope) sqlQueryScopes().getLambdaScope(call); final Map nameToNodeMap = new HashMap<>(); final List parameters = new ArrayList<>(scope.getParameterTypes().size()); @@ -2553,7 +2558,7 @@ private void convertUnnest(Blackboard bb, SqlCall call, @Nullable List f protected void convertMatchRecognize(Blackboard bb, SqlMatchRecognize matchRecognize) { final SqlValidatorNamespace ns = getNamespace(matchRecognize); - final SqlValidatorScope scope = validator().getMatchRecognizeScope(matchRecognize); + final SqlValidatorScope scope = sqlQueryScopes().getMatchRecognizeScope(matchRecognize); final Blackboard matchBb = createBlackboard(scope, null, false); final RelDataType rowType = ns.getRowType(); @@ -2712,7 +2717,7 @@ protected void convertMatchRecognize(Blackboard bb, } protected void convertPivot(Blackboard bb, SqlPivot pivot) { - final SqlValidatorScope scope = validator().getJoinScope(pivot); + final SqlValidatorScope scope = sqlQueryScopes().getJoinScope(pivot); final Blackboard pivotBb = createBlackboard(scope, null, false); // Convert input @@ -2794,7 +2799,7 @@ protected void convertPivot(Blackboard bb, SqlPivot pivot) { } protected void convertUnpivot(Blackboard bb, SqlUnpivot unpivot) { - final SqlValidatorScope scope = validator().getJoinScope(unpivot); + final SqlValidatorScope scope = sqlQueryScopes().getJoinScope(unpivot); final Blackboard unpivotBb = createBlackboard(scope, null, false); // Convert input @@ -3268,17 +3273,16 @@ protected List getSystemFields() { } private void convertJoin(Blackboard bb, SqlJoin join) { - SqlValidator validator = validator(); - final SqlValidatorScope scope = validator.getJoinScope(join); + final SqlValidatorScope scope = sqlQueryScopes().getJoinScope(join); final Blackboard fromBlackboard = createBlackboard(scope, null, false); SqlNode left = join.getLeft(); SqlNode right = join.getRight(); JoinType joinType = join.getJoinType(); - final SqlValidatorScope leftScope = validator.getJoinScope(left); + final SqlValidatorScope leftScope = sqlQueryScopes().getJoinScope(left); final Blackboard leftBlackboard = createBlackboard(leftScope, null, false); - final SqlValidatorScope rightScope = validator.getJoinScope(right); + final SqlValidatorScope rightScope = sqlQueryScopes().getJoinScope(right); final Blackboard rightBlackboard = createBlackboard(rightScope, null, false); convertFrom(leftBlackboard, left); @@ -3492,7 +3496,7 @@ protected void convertAgg(Blackboard bb, SqlSelect select, final AggConverter aggConverter = AggConverter.create(bb, - (AggregatingSelectScope) validator().getSelectScope(select)); + (AggregatingSelectScope) sqlQueryScopes().getSelectScope(select)); createAggImpl(bb, aggConverter, selectList, groupList, having, orderExprList); } @@ -3818,7 +3822,7 @@ protected RelFieldCollation convertOrderItem( // Scan the select list and order exprs for an identical expression. final SelectScope selectScope = - requireNonNull(validator.getRawSelectScope(select), + requireNonNull(sqlQueryScopes().getRawSelectScope(select), () -> "getRawSelectScope is not found for " + select); int ordinal = -1; List expandedSelectList = selectScope.getExpandedSelectList(); @@ -4219,7 +4223,7 @@ private Blackboard createInsertBlackboard(RelOptTable targetTable, rexBuilder.makeFieldAccess(sourceRef, j++)); } } - return createBlackboard(validator().getEmptyScope(), nameToNodeMap, false); + return createBlackboard(validator().createEmptyScope(), nameToNodeMap, false); } private static InitializerExpressionFactory getInitializerFactory( @@ -4341,7 +4345,7 @@ private RelNode convertUpdate(SqlUpdate call) { final SqlSelect sourceSelect = requireNonNull(call.getSourceSelect(), () -> "sourceSelect for " + call); - final SqlValidatorScope scope = validator().getWhereScope(sourceSelect); + final SqlValidatorScope scope = sqlQueryScopes().getWhereScope(sourceSelect); Blackboard bb = createBlackboard(scope, null, false); replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN); @@ -4936,7 +4940,7 @@ public RelNode convertValues( SqlCall values, @Nullable RelDataType targetRowType) { final SqlValidatorScope scope = - requireNonNull(validator().getOverScope(values)); + requireNonNull(sqlQueryScopes().getOverScope(values)); final Blackboard bb = createBlackboard(scope, null, false); convertValuesImpl(bb, values, targetRowType); return bb.root(); diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java index 41619a9d9200..7edc42b28b02 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -15873,7 +15873,7 @@ void testCastTruncates(CastType castType, SqlOperatorFixture f) { final SqlOperatorFixture f = fixture(); final SqlValidatorImpl validator = (SqlValidatorImpl) f.getFactory().createValidator(); - final SqlValidatorScope scope = validator.getEmptyScope(); + final SqlValidatorScope scope = validator.createEmptyScope(); final RelDataTypeFactory typeFactory = validator.getTypeFactory(); final Builder builder = new Builder(typeFactory); builder.add0(SqlTypeName.BOOLEAN, true, false);