blob: 2f27837b7675bee9f5af472e1e49714129ae4f03 [file] [log] [blame]
/*
* 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);
/**
* 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 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);
}
}
}