content: /*
   * 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.config.NullCollation;
  import org.apache.calcite.rel.type.RelDataType;
  import org.apache.calcite.rel.type.RelDataTypeFactory;
  import org.apache.calcite.rel.type.RelDataTypeField;
  import org.apache.calcite.rel.type.TimeFrame;
  import org.apache.calcite.rel.type.TimeFrameSet;
  import org.apache.calcite.runtime.CalciteContextException;
  import org.apache.calcite.runtime.CalciteException;
  import org.apache.calcite.runtime.Resources;
  import org.apache.calcite.sql.SqlCall;
  import org.apache.calcite.sql.SqlDataTypeSpec;
  import org.apache.calcite.sql.SqlDelete;
  import org.apache.calcite.sql.SqlDynamicParam;
  import org.apache.calcite.sql.SqlFunction;
  import org.apache.calcite.sql.SqlIdentifier;
  import org.apache.calcite.sql.SqlInsert;
  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;
  import org.apache.calcite.sql.SqlOperator;
  import org.apache.calcite.sql.SqlOperatorTable;
  import org.apache.calcite.sql.SqlSelect;
  import org.apache.calcite.sql.SqlUpdate;
  import org.apache.calcite.sql.SqlWindow;
  import org.apache.calcite.sql.SqlWith;
  import org.apache.calcite.sql.SqlWithItem;
  import org.apache.calcite.sql.type.SqlTypeCoercionRule;
  import org.apache.calcite.sql.type.SqlTypeMappingRule;
  import org.apache.calcite.sql.validate.implicit.TypeCoercion;
  import org.apache.calcite.sql.validate.implicit.TypeCoercionFactory;
  import org.apache.calcite.sql.validate.implicit.TypeCoercions;
  
  import org.apiguardian.api.API;
  import org.checkerframework.checker.nullness.qual.Nullable;
  import org.checkerframework.dataflow.qual.Pure;
  import org.immutables.value.Value;
  
  import java.util.List;
  import java.util.Map;
  import java.util.function.UnaryOperator;
  
  /**
   * Validates the parse tree of a SQL statement, and provides semantic
   * information about the parse tree.
   *
   * <p>To create an instance of the default validator implementation, call
   * {@link SqlValidatorUtil#newValidator}.
   *
   * <h2>Visitor pattern</h2>
   *
   * <p>The validator interface is an instance of the
   * {@link org.apache.calcite.util.Glossary#VISITOR_PATTERN visitor pattern}.
   * Implementations
   * of the {@link SqlNode#validate} method call the <code>validateXxx</code>
   * method appropriate to the kind of node:
   * <ul>
   * <li>{@link SqlLiteral#validate(SqlValidator, SqlValidatorScope)}
   *     calls
   *     {@link #validateLiteral(org.apache.calcite.sql.SqlLiteral)};
   * <li>{@link SqlCall#validate(SqlValidator, SqlValidatorScope)}
   *     calls
   *     {@link #validateCall(SqlCall, SqlValidatorScope)};
   * <li>and so forth.</ul>
   *
   * <p>The {@link SqlNode#validateExpr(SqlValidator, SqlValidatorScope)} method
   * is as {@link SqlNode#validate(SqlValidator, SqlValidatorScope)} but is called
   * when the node is known to be a scalar expression.
   *
   * <h2>Scopes and namespaces</h2>
   *
   * <p>In order to resolve names to objects, the validator builds a map of the
   * structure of the query. This map consists of two types of objects. A
   * {@link SqlValidatorScope} describes the tables and columns accessible at a
   * particular point in the query; and a {@link SqlValidatorNamespace} is a
   * description of a data source used in a query.
   *
   * <p>There are different kinds of namespace for different parts of the query.
   * for example {@link IdentifierNamespace} for table names,
   * {@link SelectNamespace} for SELECT queries,
   * {@link SetopNamespace} for UNION, EXCEPT
   * and INTERSECT. A validator is allowed to wrap namespaces in other objects
   * which implement {@link SqlValidatorNamespace}, so don't try to cast your
   * namespace or use <code>instanceof</code>; use
   * {@link SqlValidatorNamespace#unwrap(Class)} and
   * {@link SqlValidatorNamespace#isWrapperFor(Class)} instead.
   *
   * <p>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.
   *
   * <p>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 {
    //~ Methods ----------------------------------------------------------------
  
    /**
     * Returns the catalog reader used by this validator.
     *
     * @return catalog reader
     */
    @Pure
    SqlValidatorCatalogReader getCatalogReader();
  
    /**
     * Returns the operator table used by this validator.
     *
     * @return operator table
     */
    @Pure
    SqlOperatorTable getOperatorTable();
  
    /**
     * Validates an expression tree. You can call this method multiple times,
     * but not reentrantly.
     *
     * @param topNode top of expression tree to be validated
     * @return validated tree (possibly rewritten)
     */
    SqlNode validate(SqlNode topNode);
  
    /**
     * Validates an expression tree. You can call this method multiple times,
     * but not reentrantly.
     *
     * @param topNode       top of expression tree to be validated
     * @param nameToTypeMap map of simple name to {@link RelDataType}; used to
     *                      resolve {@link SqlIdentifier} references
     * @return validated tree (possibly rewritten)
     */
    SqlNode validateParameterizedExpression(
        SqlNode topNode,
        Map<String, RelDataType> nameToTypeMap);
  
    /**
     * Checks that a query is valid.
     *
     * <p>Valid queries include:
     *
     * <ul>
     * <li><code>SELECT</code> statement,
     * <li>set operation (<code>UNION</code>, <code>INTERSECT</code>, <code>
     * EXCEPT</code>)
     * <li>identifier (e.g. representing use of a table in a FROM clause)
     * <li>query aliased with the <code>AS</code> operator
     * </ul>
     *
     * @param node  Query node
     * @param scope Scope in which the query occurs
     * @param targetRowType Desired row type, must not be null, may be the data
     *                      type 'unknown'.
     * @throws RuntimeException if the query is not valid
     */
    void validateQuery(SqlNode node, SqlValidatorScope scope,
        RelDataType targetRowType);
  
    /**
     * Returns the type assigned to a node by validation.
     *
     * @param node the node of interest
     * @return validated type, never null
     */
    RelDataType getValidatedNodeType(SqlNode node);
  
    /**
     * Returns the type assigned to a node by validation, or null if unknown.
     * This allows for queries against nodes such as aliases, which have no type
     * of their own. If you want to assert that the node of interest must have a
     * type, use {@link #getValidatedNodeType} instead.
     *
     * @param node the node of interest
     * @return validated type, or null if unknown or not applicable
     */
    @Nullable RelDataType getValidatedNodeTypeIfKnown(SqlNode node);
  
    /**
     * Returns the types of a call's operands.
     *
     * <p>Returns null if the call has not been validated, or if the operands'
     * types do not differ from their types as expressions.
     *
     * <p>This method is most useful when some of the operands are of type ANY,
     * or if they need to be coerced to be consistent with other operands, or
     * with the needs of the function.
     *
     * @param call Call
     * @return List of operands' types, or null if not known or 'obvious'
     */
    @Nullable List<RelDataType> getValidatedOperandTypes(SqlCall call);
  
    /**
     * Resolves an identifier to a fully-qualified name.
     *
     * @param id    Identifier
     * @param scope Naming scope
     */
    void validateIdentifier(SqlIdentifier id, SqlValidatorScope scope);
  
    /**
     * Validates a literal.
     *
     * @param literal Literal
     */
    void validateLiteral(SqlLiteral literal);
  
    /**
     * Validates a {@link SqlIntervalQualifier}.
     *
     * @param qualifier Interval qualifier
     */
    void validateIntervalQualifier(SqlIntervalQualifier qualifier);
  
    /**
     * Validates an INSERT statement.
     *
     * @param insert INSERT statement
     */
    void validateInsert(SqlInsert insert);
  
    /**
     * Validates an UPDATE statement.
     *
     * @param update UPDATE statement
     */
    void validateUpdate(SqlUpdate update);
  
    /**
     * Validates a DELETE statement.
     *
     * @param delete DELETE statement
     */
    void validateDelete(SqlDelete delete);
  
    /**
     * Validates a MERGE statement.
     *
     * @param merge MERGE statement
     */
    void validateMerge(SqlMerge merge);
  
    /**
     * Validates a data type expression.
     *
     * @param dataType Data type
     */
    void validateDataType(SqlDataTypeSpec dataType);
  
    /**
     * Validates a dynamic parameter.
     *
     * @param dynamicParam Dynamic parameter
     */
    void validateDynamicParam(SqlDynamicParam dynamicParam);
  
    /**
     * Validates the right-hand side of an OVER expression. It might be either
     * an {@link SqlIdentifier identifier} referencing a window, or an
     * {@link SqlWindow inline window specification}.
     *
     * @param windowOrId SqlNode that can be either SqlWindow with all the
     *                   components of a window spec or a SqlIdentifier with the
     *                   name of a window spec.
     * @param scope      Naming scope
     * @param call       the SqlNode if a function call if the window is attached
     *                   to one.
     */
    void validateWindow(
        SqlNode windowOrId,
        SqlValidatorScope scope,
        @Nullable SqlCall call);
  
    /**
     * Validates a MATCH_RECOGNIZE clause.
     *
     * @param pattern MATCH_RECOGNIZE clause
     */
    void validateMatchRecognize(SqlCall pattern);
  
    /**
     * Validates a lambda expression. lambda expression will be validated twice
     * during the validation process. The first time is validate lambda expression
     * namespace, the second time is when validating higher order function operands
     * type check.
     *
     * @param lambdaExpr Lambda expression
     */
    void validateLambda(SqlLambda lambdaExpr);
  
    /**
     * Validates a call to an operator.
     *
     * @param call  Operator call
     * @param scope Naming scope
     */
    void validateCall(
        SqlCall call,
        SqlValidatorScope scope);
  
    /**
     * Validates parameters for aggregate function.
     *
     * @param aggCall      Call to aggregate function
     * @param filter       Filter ({@code FILTER (WHERE)} clause), or null
     * @param distinctList Distinct specification ({@code WITHIN DISTINCT}
     *                     clause), or null
     * @param orderList    Ordering specification ({@code WITHIN GROUP} clause),
     *                     or null
     * @param scope        Syntactic scope
     */
    void validateAggregateParams(SqlCall aggCall, @Nullable SqlNode filter,
        @Nullable SqlNodeList distinctList, @Nullable SqlNodeList orderList,
        SqlValidatorScope scope);
  
    /**
     * If an identifier is a legitimate call to a function that has no
     * arguments and requires no parentheses (for example "CURRENT_USER"),
     * returns a call to that function, otherwise returns null.
     */
    @Nullable SqlCall makeNullaryCall(SqlIdentifier id);
  
    /**
     * Derives the type of a node in a given scope. If the type has already been
     * inferred, returns the previous type.
     *
     * @param scope   Syntactic scope
     * @param operand Parse tree node
     * @return Type of the SqlNode. Should never return <code>NULL</code>
     */
    RelDataType deriveType(
        SqlValidatorScope scope,
        SqlNode operand);
  
    /**
     * Adds "line x, column y" context to a validator exception.
     *
     * <p>Note that the input exception is checked (it derives from
     * {@link Exception}) and the output exception is unchecked (it derives from
     * {@link RuntimeException}). This is intentional -- it should remind code
     * authors to provide context for their validation errors.
     *
     * @param node The place where the exception occurred, not null
     * @param e    The validation error
     * @return Exception containing positional information, never null
     */
    CalciteContextException newValidationError(
        SqlNode node,
        Resources.ExInst<SqlValidatorException> e);
  
    /**
     * Returns whether a SELECT statement is an aggregation. Criteria are: (1)
     * contains GROUP BY, or (2) contains HAVING, or (3) SELECT or ORDER BY
     * clause contains aggregate functions. (Windowed aggregate functions, such
     * as <code>SUM(x) OVER w</code>, don't count.)
     *
     * @param select SELECT statement
     * @return whether SELECT statement is an aggregation
     */
    boolean isAggregate(SqlSelect select);
  
    /**
     * Returns whether a select list expression is an aggregate function.
     *
     * @param selectNode Expression in SELECT clause
     * @return whether expression is an aggregate function
     */
    @Deprecated // to be removed before 2.0
    boolean isAggregate(SqlNode selectNode);
  
    /**
     * Converts a window specification or window name into a fully-resolved
     * window specification. For example, in <code>SELECT sum(x) OVER (PARTITION
     * BY x ORDER BY y), sum(y) OVER w1, sum(z) OVER (w ORDER BY y) FROM t
     * WINDOW w AS (PARTITION BY x)</code> all aggregations have the same
     * resolved window specification <code>(PARTITION BY x ORDER BY y)</code>.
     *
     * @param windowOrRef    Either the name of a window (a {@link SqlIdentifier})
     *                       or a window specification (a {@link SqlWindow}).
     * @param scope          Scope in which to resolve window names
     * @return A window
     * @throws RuntimeException Validation exception if window does not exist
     */
    SqlWindow resolveWindow(
        SqlNode windowOrRef,
        SqlValidatorScope scope);
  
    /**
     * Converts a window specification or window name into a fully-resolved
     * window specification.
     *
     * @deprecated Use {@link #resolveWindow(SqlNode, SqlValidatorScope)}, which
     * does not have the deprecated {@code populateBounds} parameter.
     *
     * @param populateBounds Whether to populate bounds. Doing so may alter the
     *                       definition of the window. It is recommended that
     *                       populate bounds when translating to physical algebra,
     *                       but not when validating.
     */
    @Deprecated // to be removed before 2.0
    default SqlWindow resolveWindow(
        SqlNode windowOrRef,
        SqlValidatorScope scope,
        boolean populateBounds) {
      return resolveWindow(windowOrRef, scope);
    };
  
    /**
     * Finds the namespace corresponding to a given node.
     *
     * <p>For example, in the query <code>SELECT * FROM (SELECT * FROM t), t1 AS
     * alias</code>, the both items in the FROM clause have a corresponding
     * namespace.
     *
     * @param node Parse tree node
     * @return namespace of node
     */
    @Nullable SqlValidatorNamespace getNamespace(SqlNode node);
  
    /**
     * Derives an alias for an expression. If no alias can be derived, returns
     * null if <code>ordinal</code> is less than zero, otherwise generates an
     * alias <code>EXPR$<i>ordinal</i></code>.
     *
     * @param node    Expression
     * @param ordinal Ordinal of expression
     * @return derived alias, or null if no alias can be derived and ordinal is
     * less than zero
     */
    @Nullable String deriveAlias(
        SqlNode node,
        int ordinal);
  
    /**
     * Returns a list of expressions, with every occurrence of "&#42;" or
     * "TABLE.&#42;" expanded.
     *
     * @param selectList        Select clause to be expanded
     * @param query             Query
     * @param includeSystemVars Whether to include system variables
     * @return expanded select clause
     */
    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.
     *
     * @return type factory
     */
    @Pure
    RelDataTypeFactory getTypeFactory();
  
    /**
     * Saves the type of a {@link SqlNode}, now that it has been validated.
     *
     * <p>This method is only for internal use. The validator should drive the
     * type-derivation process, and store nodes' types when they have been derived.
     *
     * @param node A SQL parse tree node, never null
     * @param type Its type; must not be null
     */
    @API(status = API.Status.INTERNAL, since = "1.24")
    void setValidatedNodeType(SqlNode node, RelDataType type);
  
    /**
     * Removes a node from the set of validated nodes.
     *
     * @param node node to be removed
     */
    void removeValidatedNodeType(SqlNode node);
  
    /**
     * Returns an object representing the "unknown" type.
     *
     * @return unknown type
     */
    RelDataType getUnknownType();
  
    /**
     * Returns the appropriate scope for validating a particular clause of a
     * SELECT statement.
     *
     * <p>Consider
     *
     * <blockquote><pre><code>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)</code></pre></blockquote>
     *
     * <p>What objects can be seen in each part of the sub-query?
     *
     * <ul>
     * <li>In FROM ({@link #getFromScope} , you can only see 'foo'.
     *
     * <li>In WHERE ({@link #getWhereScope}), GROUP BY ({@link #getGroupScope}),
     * SELECT ({@code getSelectScope}), and the ON clause of the JOIN
     * ({@link #getJoinScope}) you can see 'emp', 'dept', and 'foo'.
     *
     * <li>In ORDER BY ({@link #getOrderScope}), you can see the column alias 'x';
     * and tables 'emp', 'dept', and 'foo'.
     *
     * </ul>
     *
     * @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();
  
    /**
     * Declares a SELECT expression as a cursor.
     *
     * @param select select expression associated with the cursor
     * @param scope  scope of the parent query associated with the cursor
     */
    void declareCursor(SqlSelect select, SqlValidatorScope scope);
  
    /**
     * Pushes a new instance of a function call on to a function call stack.
     */
    void pushFunctionCall();
  
    /**
     * Removes the topmost entry from the function call stack.
     */
    void popFunctionCall();
  
    /**
     * Retrieves the name of the parent cursor referenced by a column list
     * parameter.
     *
     * @param columnListParamName name of the column list parameter
     * @return name of the parent cursor
     */
    @Nullable String getParentCursor(String columnListParamName);
  
    /**
     * Derives the type of a constructor.
     *
     * @param scope                 Scope
     * @param call                  Call
     * @param unresolvedConstructor TODO
     * @param resolvedConstructor   TODO
     * @param argTypes              Types of arguments
     * @return Resolved type of constructor
     */
    RelDataType deriveConstructorType(
        SqlValidatorScope scope,
        SqlCall call,
        SqlFunction unresolvedConstructor,
        @Nullable SqlFunction resolvedConstructor,
        List<RelDataType> argTypes);
  
    /**
     * Handles a call to a function which cannot be resolved. Returns an
     * appropriately descriptive error, which caller must throw.
     *
     * @param call               Call
     * @param unresolvedFunction Overloaded function which is the target of the
     *                           call
     * @param argTypes           Types of arguments
     * @param argNames           Names of arguments, or null if call by position
     */
    CalciteException handleUnresolvedFunction(SqlCall call,
        SqlOperator unresolvedFunction, List<RelDataType> argTypes,
        @Nullable List<String> argNames);
  
    /**
     * Expands an expression in the ORDER BY clause into an expression with the
     * same semantics as expressions in the SELECT clause.
     *
     * <p>This is made necessary by a couple of dialect 'features':
     *
     * <ul>
     * <li><b>ordinal expressions</b>: In "SELECT x, y FROM t ORDER BY 2", the
     * expression "2" is shorthand for the 2nd item in the select clause, namely
     * "y".
     * <li><b>alias references</b>: In "SELECT x AS a, y FROM t ORDER BY a", the
     * expression "a" is shorthand for the item in the select clause whose alias
     * is "a"
     * </ul>
     *
     * @param select    Select statement which contains ORDER BY
     * @param orderExpr Expression in the ORDER BY clause.
     * @return Expression translated into SELECT clause semantics
     */
    SqlNode expandOrderExpr(SqlSelect select, SqlNode orderExpr);
  
    /**
     * Expands an expression.
     *
     * @param expr  Expression
     * @param scope Scope
     * @return Expanded expression
     */
    SqlNode expand(SqlNode expr, SqlValidatorScope scope);
  
    /** Resolves a literal.
     *
     * <p>Usually returns the literal unchanged, but if the literal is of type
     * {@link org.apache.calcite.sql.type.SqlTypeName#UNKNOWN} looks up its type
     * and converts to the appropriate literal subclass. */
    SqlLiteral resolveLiteral(SqlLiteral literal);
  
    /**
     * Returns whether a field is a system field. Such fields may have
     * particular properties such as sortedness and nullability.
     *
     * <p>In the default implementation, always returns {@code false}.
     *
     * @param field Field
     * @return whether field is a system field
     */
    boolean isSystemField(RelDataTypeField field);
  
    /**
     * Returns a description of how each field in the row type maps to a
     * catalog, schema, table and column in the schema.
     *
     * <p>The returned list is never null, and has one element for each field
     * in the row type. Each element is a list of four elements (catalog,
     * schema, table, column), or may be null if the column is an expression.
     *
     * @param sqlQuery Query
     * @return Description of how each field in the row type maps to a schema
     * object
     */
    List<@Nullable List<String>> getFieldOrigins(SqlNode sqlQuery);
  
    /**
     * Returns a record type that contains the name and type of each parameter.
     * Returns a record type with no fields if there are no parameters.
     *
     * @param sqlQuery Query
     * @return Record type
     */
    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).
     *
     * @param select Query
     * @param modality Modality (streaming or relational)
     * @param fail Whether to throw a user error if does not support required
     *             modality
     * @return whether query supports the given modality
     */
    boolean validateModality(SqlSelect select, SqlModality modality,
        boolean fail);
  
    void validateWith(SqlWith with, SqlValidatorScope scope);
  
    void validateWithItem(SqlWithItem withItem);
  
    void validateSequenceValue(SqlValidatorScope scope, SqlIdentifier id);
  
    SqlValidatorScope getWithScope(SqlNode withItem);
  
    /** Get the type coercion instance. */
    TypeCoercion getTypeCoercion();
  
    /** Returns the type mapping rule. */
    default SqlTypeMappingRule getTypeMappingRule() {
      return config().conformance().allowLenientCoercion()
          ? SqlTypeCoercionRule.lenientInstance()
          : SqlTypeCoercionRule.instance();
    }
  
    /** Returns the config of the validator. */
    Config config();
  
    /**
     * Returns this SqlValidator, with the same state, applying
     * a transform to the config.
     *
     * <p>This is mainly used for tests, otherwise constructs a {@link Config} directly
     * through the constructor.
     */
    @API(status = API.Status.INTERNAL, since = "1.23")
    SqlValidator transform(UnaryOperator<SqlValidator.Config> transform);
  
    /** Returns the set of allowed time frames. */
    TimeFrameSet getTimeFrameSet();
  
    /** Validates a time frame.
     *
     * <p>A time frame is either a built-in time frame based on a time unit such
     * as {@link org.apache.calcite.avatica.util.TimeUnitRange#HOUR},
     * or is a custom time frame represented by a name in
     * {@link SqlIntervalQualifier#timeFrameName}. A custom time frame is
     * validated against {@link #getTimeFrameSet()}.
     *
     * <p>Returns a time frame, or throws.
     */
    TimeFrame validateTimeFrame(SqlIntervalQualifier intervalQualifier);
  
    //~ Inner Class ------------------------------------------------------------
  
    /**
     * Interface to define the configuration for a SqlValidator.
     * Provides methods to set each configuration option.
     */
    @Value.Immutable(singleton = false)
    interface Config {
      /** Default configuration. */
      SqlValidator.Config DEFAULT = ImmutableSqlValidator.Config.builder()
          .withTypeCoercionFactory(TypeCoercions::createTypeCoercion)
          .build();
  
      /**
       * Returns whether to enable rewrite of "macro-like" calls such as COALESCE.
       */
      @Value.Default default boolean callRewrite() {
        return true;
      }
  
      /**
       * Sets whether to enable rewrite of "macro-like" calls such as COALESCE.
       */
      Config withCallRewrite(boolean rewrite);
  
      /** Returns how NULL values should be collated if an ORDER BY item does not
       * contain NULLS FIRST or NULLS LAST. */
      @Value.Default default NullCollation defaultNullCollation() {
        return NullCollation.HIGH;
      }
  
      /** Sets how NULL values should be collated if an ORDER BY item does not
       * contain NULLS FIRST or NULLS LAST. */
      Config withDefaultNullCollation(NullCollation nullCollation);
  
      /** Returns whether column reference expansion is enabled. */
      @Value.Default default boolean columnReferenceExpansion() {
        return true;
      }
  
      /**
       * Sets whether to enable expansion of column references. (Currently this does
       * not apply to the ORDER BY clause; may be fixed in the future.)
       */
      Config withColumnReferenceExpansion(boolean expand);
  
      /**
       * Returns whether to expand identifiers other than column
       * references.
       *
       * <p>REVIEW jvs 30-June-2006: subclasses may override shouldExpandIdentifiers
       * in a way that ignores this; we should probably get rid of the protected
       * method and always use this variable (or better, move preferences like
       * this to a separate "parameter" class).
       */
      @Value.Default default boolean identifierExpansion() {
        return false;
      }
  
      /**
       * Sets whether to enable expansion of identifiers other than column
       * references.
       */
      Config withIdentifierExpansion(boolean expand);
  
      /**
       * Returns whether to treat the query being validated as embedded
       * (as opposed to top-level).
       *
       * <p>The default, false, treats the query as top-level;
       * a value of true treats it as a query inside another, as would be the case
       * for a view or common table expression.
       *
       * <p>Possible behavior differences include ignoring the {@code ORDER BY}
       * clause of an embedded query, or converting measure expressions of a
       * non-embedded query into values. */
      @Value.Default default boolean embeddedQuery() {
        return false;
      }
  
      /**
       * Sets whether to treat the query being validated as embedded
       * (as opposed to top-level).
       */
      Config withEmbeddedQuery(boolean embedded);
  
      /**
       * Returns whether this validator should be lenient upon encountering an
       * unknown function, default false.
       *
       * <p>If true, if a statement contains a call to a function that is not
       * present in the operator table, or if the call does not have the required
       * number or types of operands, the validator nevertheless regards the
       * statement as valid. The type of the function call will be
       * {@link #getUnknownType() UNKNOWN}.
       *
       * <p>If false (the default behavior), an unknown function call causes a
       * validation error to be thrown.
       */
      @Value.Default default boolean lenientOperatorLookup() {
        return false;
      }
  
      /**
       * Sets whether this validator should be lenient upon encountering an unknown
       * function.
       *
       * @param lenient Whether to be lenient when encountering an unknown function
       */
      Config withLenientOperatorLookup(boolean lenient);
  
      /** 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 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() {
        return true;
      }
  
      /**
       * Sets whether to enable implicit type coercion for validation, default true.
       *
       * @see org.apache.calcite.sql.validate.implicit.TypeCoercionImpl TypeCoercionImpl
       */
      Config withTypeCoercionEnabled(boolean enabled);
  
      /** Returns the type coercion factory. */
      TypeCoercionFactory typeCoercionFactory();
  
      /**
       * Sets a factory to create type coercion instance that overrides the
       * default coercion rules defined in
       * {@link org.apache.calcite.sql.validate.implicit.TypeCoercionImpl}.
       *
       * @param factory Factory to create {@link TypeCoercion} instance
       */
      Config withTypeCoercionFactory(TypeCoercionFactory factory);
  
      /** Returns the type coercion rules for explicit type coercion. */
      @Nullable SqlTypeCoercionRule typeCoercionRules();
  
      /**
       * Sets the {@link SqlTypeCoercionRule} instance which defines the type conversion matrix
       * for the explicit type coercion.
       *
       * <p>The {@code rules} setting should be thread safe. In the default implementation,
       * it is set to a ThreadLocal variable.
       *
       * @param rules The {@link SqlTypeCoercionRule} instance,
       *              see its documentation for how to customize the rules
       */
      Config withTypeCoercionRules(@Nullable SqlTypeCoercionRule rules);
  
      /** Returns the dialect of SQL (SQL:2003, etc.) this validator recognizes.
       * Default is {@link SqlConformanceEnum#DEFAULT}. */
      @Value.Default default SqlConformance conformance() {
        return SqlConformanceEnum.DEFAULT;
      }
  
      /** Returns the SQL conformance.
       *
       * @deprecated Use {@link #conformance()} */
      @Deprecated // to be removed before 2.0
      default SqlConformance sqlConformance() {
        return conformance();
      }
  
      /** Sets the SQL conformance of the validator. */
      Config withConformance(SqlConformance conformance);
  
      /** Sets the SQL conformance of the validator.
       *
       * @deprecated Use {@link #conformance()} */
      @Deprecated // to be removed before 2.0
      default Config withSqlConformance(SqlConformance conformance) {
        return withConformance(conformance);
      }
    }
  }
  