All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.apache.calcite.sql.SqlOperator Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * 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 com.hazelcast.org.apache.calcite.sql;

import com.hazelcast.org.apache.calcite.linq4j.Ord;
import com.hazelcast.org.apache.calcite.plan.Strong;
import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeFactory;
import com.hazelcast.org.apache.calcite.sql.fun.SqlStdOperatorTable;
import com.hazelcast.org.apache.calcite.sql.parser.SqlParserPos;
import com.hazelcast.org.apache.calcite.sql.type.SqlOperandTypeChecker;
import com.hazelcast.org.apache.calcite.sql.type.SqlOperandTypeInference;
import com.hazelcast.org.apache.calcite.sql.type.SqlReturnTypeInference;
import com.hazelcast.org.apache.calcite.sql.type.SqlTypeName;
import com.hazelcast.org.apache.calcite.sql.util.SqlBasicVisitor;
import com.hazelcast.org.apache.calcite.sql.util.SqlVisitor;
import com.hazelcast.org.apache.calcite.sql.validate.SqlMonotonicity;
import com.hazelcast.org.apache.calcite.sql.validate.SqlValidator;
import com.hazelcast.org.apache.calcite.sql.validate.SqlValidatorImpl;
import com.hazelcast.org.apache.calcite.sql.validate.SqlValidatorScope;
import com.hazelcast.org.apache.calcite.sql.validate.SqlValidatorUtil;
import com.hazelcast.org.apache.calcite.util.ImmutableNullableList;
import com.hazelcast.org.apache.calcite.util.Litmus;
import com.hazelcast.org.apache.calcite.util.Util;

import com.hazelcast.com.google.common.collect.ImmutableList;
import com.hazelcast.com.google.common.collect.Iterables;

import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;
import com.hazelcast.org.checkerframework.dataflow.qual.Pure;

import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

import static com.hazelcast.org.apache.calcite.linq4j.Nullness.castNonNull;
import static com.hazelcast.org.apache.calcite.util.Static.RESOURCE;

import static java.util.Objects.requireNonNull;

/**
 * A SqlOperator is a type of node in a SQL parse tree (it is NOT a
 * node in a SQL parse tree). It includes functions, operators such as '=', and
 * syntactic constructs such as 'case' statements. Operators may represent
 * query-level expressions (e.g. {@link SqlSelectOperator} or row-level
 * expressions (e.g. {@link com.hazelcast.org.apache.calcite.sql.fun.SqlBetweenOperator}.
 *
 * 

Operators have formal operands, meaning ordered (and optionally * named) placeholders for the values they operate on. For example, the division * operator takes two operands; the first is the numerator and the second is the * denominator. In the context of subclass {@link SqlFunction}, formal operands * are referred to as parameters. * *

When an operator is instantiated via a {@link SqlCall}, it is supplied * with actual operands. For example, in the expression 3 / * 5, the literal expression 3 is the actual operand * corresponding to the numerator, and 5 is the actual operand * corresponding to the denominator. In the context of SqlFunction, actual * operands are referred to as arguments * *

In many cases, the formal/actual distinction is clear from context, in * which case we drop these qualifiers. */ public abstract class SqlOperator { //~ Static fields/initializers --------------------------------------------- public static final String NL = System.getProperty("line.separator"); /** * Maximum precedence. */ public static final int MDX_PRECEDENCE = 200; //~ Instance fields -------------------------------------------------------- /** * The name of the operator/function. Ex. "OVERLAY" or "TRIM" */ private final String name; /** * See {@link SqlKind}. It's possible to have a name that doesn't match the * kind */ public final SqlKind kind; /** * The precedence with which this operator binds to the expression to the * left. This is less than the right precedence if the operator is * left-associative. */ private final int leftPrec; /** * The precedence with which this operator binds to the expression to the * right. This is more than the left precedence if the operator is * left-associative. */ private final int rightPrec; /** Used to infer the return type of a call to this operator. */ private final @Nullable SqlReturnTypeInference returnTypeInference; /** Used to infer types of unknown operands. */ private final @Nullable SqlOperandTypeInference operandTypeInference; /** Used to validate operand types. */ private final @Nullable SqlOperandTypeChecker operandTypeChecker; //~ Constructors ----------------------------------------------------------- /** * Creates an operator. */ protected SqlOperator( String name, SqlKind kind, int leftPrecedence, int rightPrecedence, @Nullable SqlReturnTypeInference returnTypeInference, @Nullable SqlOperandTypeInference operandTypeInference, @Nullable SqlOperandTypeChecker operandTypeChecker) { assert kind != null; this.name = name; this.kind = kind; this.leftPrec = leftPrecedence; this.rightPrec = rightPrecedence; this.returnTypeInference = returnTypeInference; if (operandTypeInference == null && operandTypeChecker != null) { operandTypeInference = operandTypeChecker.typeInference(); } this.operandTypeInference = operandTypeInference; this.operandTypeChecker = operandTypeChecker; } /** * Creates an operator specifying left/right associativity. */ protected SqlOperator( String name, SqlKind kind, int prec, boolean leftAssoc, @Nullable SqlReturnTypeInference returnTypeInference, @Nullable SqlOperandTypeInference operandTypeInference, @Nullable SqlOperandTypeChecker operandTypeChecker) { this( name, kind, leftPrec(prec, leftAssoc), rightPrec(prec, leftAssoc), returnTypeInference, operandTypeInference, operandTypeChecker); } //~ Methods ---------------------------------------------------------------- protected static int leftPrec(int prec, boolean leftAssoc) { assert (prec % 2) == 0; if (!leftAssoc) { ++prec; } return prec; } protected static int rightPrec(int prec, boolean leftAssoc) { assert (prec % 2) == 0; if (leftAssoc) { ++prec; } return prec; } public @Nullable SqlOperandTypeChecker getOperandTypeChecker() { return operandTypeChecker; } /** * Returns a constraint on the number of operands expected by this operator. * Subclasses may override this method; when they don't, the range is * derived from the {@link SqlOperandTypeChecker} associated with this * operator. * * @return acceptable range */ public SqlOperandCountRange getOperandCountRange() { if (operandTypeChecker != null) { return operandTypeChecker.getOperandCountRange(); } // If you see this error you need to override this method // or give operandTypeChecker a value. throw Util.needToImplement(this); } public String getName() { return name; } /** * Returns the fully-qualified name of this operator. */ public SqlIdentifier getNameAsId() { return new SqlIdentifier(getName(), SqlParserPos.ZERO); } @Pure public SqlKind getKind() { return kind; } @Override public String toString() { return name; } public int getLeftPrec() { return leftPrec; } public int getRightPrec() { return rightPrec; } /** * Returns the syntactic type of this operator, never null. */ public abstract SqlSyntax getSyntax(); /** * Creates a call to this operator with a list of operands. * *

The position of the resulting call is the union of the {@code pos} * and the positions of all of the operands. * * @param functionQualifier Function qualifier (e.g. "DISTINCT"), or null * @param pos Parser position of the identifier of the call * @param operands List of operands */ public final SqlCall createCall( @Nullable SqlLiteral functionQualifier, SqlParserPos pos, Iterable operands) { return createCall(functionQualifier, pos, Iterables.toArray(operands, SqlNode.class)); } /** * Creates a call to this operator with an array of operands. * *

The position of the resulting call is the union of the {@code pos} * and the positions of all of the operands. * * @param functionQualifier Function qualifier (e.g. "DISTINCT"), or null * @param pos Parser position of the identifier of the call * @param operands Array of operands */ public SqlCall createCall( @Nullable SqlLiteral functionQualifier, SqlParserPos pos, @Nullable SqlNode... operands) { pos = pos.plusAll(operands); return new SqlBasicCall(this, ImmutableNullableList.copyOf(operands), pos, functionQualifier); } /** Not supported. Choose between * {@link #createCall(SqlLiteral, SqlParserPos, SqlNode...)} and * {@link #createCall(SqlParserPos, List)}. The ambiguity arises because * {@link SqlNodeList} extends {@link SqlNode} * and also implements {@code List}. */ @Deprecated public static SqlCall createCall( @Nullable SqlLiteral functionQualifier, SqlParserPos pos, SqlNodeList operands) { throw new UnsupportedOperationException(); } /** * Creates a call to this operator with an array of operands. * *

The position of the resulting call is the union of the * pos and the positions of all of the operands. * * @param pos Parser position * @param operands List of arguments * @return call to this operator */ public final SqlCall createCall( SqlParserPos pos, @Nullable SqlNode... operands) { return createCall(null, pos, operands); } /** * Creates a call to this operator with a list of operands contained in a * {@link SqlNodeList}. * *

The position of the resulting call is inferred from the SqlNodeList. * * @param nodeList List of arguments * @return call to this operator */ public final SqlCall createCall( SqlNodeList nodeList) { return createCall( null, nodeList.getParserPosition(), nodeList.toArray(new SqlNode[0])); } /** * Creates a call to this operator with a list of operands. * *

The position of the resulting call is the union of the {@code pos} * and the positions of all of the operands. */ public final SqlCall createCall( SqlParserPos pos, List operandList) { return createCall( null, pos, operandList.toArray(new SqlNode[0])); } /** Not supported. Choose between * {@link #createCall(SqlParserPos, SqlNode...)} and * {@link #createCall(SqlParserPos, List)}. The ambiguity arises because * {@link SqlNodeList} extends {@link SqlNode} * and also implements {@code List}. */ @Deprecated public SqlCall createCall( SqlParserPos pos, SqlNodeList operands) { throw new UnsupportedOperationException(); } /** * Rewrites a call to this operator. Some operators are implemented as * trivial rewrites (e.g. NULLIF becomes CASE). However, we don't do this at * createCall time because we want to preserve the original SQL syntax as * much as possible; instead, we do this before the call is validated (so * the trivial operator doesn't need its own implementation of type * derivation methods). The default implementation is to just return the * original call without any rewrite. * * @param validator Validator * @param call Call to be rewritten * @return rewritten call */ public SqlNode rewriteCall(SqlValidator validator, SqlCall call) { return call; } /** * Writes a SQL representation of a call to this operator to a writer, * including parentheses if the operators on either side are of greater * precedence. * *

The default implementation of this method delegates to * {@link SqlSyntax#unparse}. */ public void unparse( SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) { getSyntax().unparse(writer, this, call, leftPrec, rightPrec); } @Deprecated // to be removed before 2.0 protected void unparseListClause(SqlWriter writer, SqlNode clause) { final SqlNodeList nodeList = clause instanceof SqlNodeList ? (SqlNodeList) clause : SqlNodeList.of(clause); writer.list(SqlWriter.FrameTypeEnum.SIMPLE, SqlWriter.COMMA, nodeList); } @Deprecated // to be removed before 2.0 protected void unparseListClause( SqlWriter writer, SqlNode clause, @Nullable SqlKind sepKind) { final SqlNodeList nodeList = clause instanceof SqlNodeList ? (SqlNodeList) clause : SqlNodeList.of(clause); final SqlBinaryOperator sepOp; if (sepKind == null) { sepOp = SqlWriter.COMMA; } else { switch (sepKind) { case AND: sepOp = SqlStdOperatorTable.AND; break; case OR: sepOp = SqlStdOperatorTable.OR; break; default: throw new AssertionError(); } } writer.list(SqlWriter.FrameTypeEnum.SIMPLE, sepOp, nodeList); } @Override public boolean equals(@Nullable Object obj) { if (!(obj instanceof SqlOperator)) { return false; } if (!obj.getClass().equals(this.getClass())) { return false; } SqlOperator other = (SqlOperator) obj; return name.equals(other.name) && kind == other.kind; } public boolean isName(String testName, boolean caseSensitive) { return caseSensitive ? name.equals(testName) : name.equalsIgnoreCase(testName); } @Override public int hashCode() { return Objects.hash(kind, name); } /** * Validates a call to this operator. * *

This method should not perform type-derivation or perform validation * related related to types. That is done later, by * {@link #deriveType(SqlValidator, SqlValidatorScope, SqlCall)}. This method * should focus on structural validation. * *

A typical implementation of this method first validates the operands, * then performs some operator-specific logic. The default implementation * just validates the operands. * *

This method is the default implementation of {@link SqlCall#validate}; * but note that some sub-classes of {@link SqlCall} never call this method. * * @param call the call to this operator * @param validator the active validator * @param scope validator scope * @param operandScope validator scope in which to validate operands to this * call; usually equal to scope, but not always because * some operators introduce new scopes * @see SqlNode#validateExpr(SqlValidator, SqlValidatorScope) * @see #deriveType(SqlValidator, SqlValidatorScope, SqlCall) */ public void validateCall( SqlCall call, SqlValidator validator, SqlValidatorScope scope, SqlValidatorScope operandScope) { assert call.getOperator() == this; for (SqlNode operand : call.getOperandList()) { operand.validateExpr(validator, operandScope); } } /** * Validates the operands of a call, inferring the return type in the * process. * * @param validator active validator * @param scope validation scope * @param call call to be validated * @return inferred type */ public final RelDataType validateOperands( SqlValidator validator, @Nullable SqlValidatorScope scope, SqlCall call) { // Let subclasses know what's up. preValidateCall(validator, scope, call); // Check the number of operands checkOperandCount(validator, operandTypeChecker, call); SqlCallBinding opBinding = new SqlCallBinding(validator, scope, call); checkOperandTypes( opBinding, true); // Now infer the result type. RelDataType ret = inferReturnType(opBinding); validator.setValidatedNodeType(call, ret); return ret; } /** * Receives notification that validation of a call to this operator is * beginning. Subclasses can supply custom behavior; default implementation * does nothing. * * @param validator invoking validator * @param scope validation scope * @param call the call being validated */ protected void preValidateCall( SqlValidator validator, @Nullable SqlValidatorScope scope, SqlCall call) { } /** * Infers the return type of an invocation of this operator; only called * after the number and types of operands have already been validated. * Subclasses must either override this method or supply an instance of * {@link SqlReturnTypeInference} to the constructor. * * @param opBinding description of invocation (not necessarily a * {@link SqlCall}) * @return inferred return type */ public RelDataType inferReturnType( SqlOperatorBinding opBinding) { if (returnTypeInference != null) { RelDataType returnType = returnTypeInference.inferReturnType(opBinding); if (returnType == null) { throw new IllegalArgumentException("Cannot infer return type for " + opBinding.getOperator() + "; operand types: " + opBinding.collectOperandTypes()); } if (operandTypeInference != null && opBinding instanceof SqlCallBinding && this instanceof SqlFunction) { final SqlCallBinding callBinding = (SqlCallBinding) opBinding; final List operandTypes = opBinding.collectOperandTypes(); if (operandTypes.stream().anyMatch(t -> t.getSqlTypeName() == SqlTypeName.ANY)) { final RelDataType[] operandTypes2 = operandTypes.toArray(new RelDataType[0]); operandTypeInference.inferOperandTypes(callBinding, returnType, operandTypes2); ((SqlValidatorImpl) callBinding.getValidator()) .callToOperandTypesMap .put(callBinding.getCall(), ImmutableList.copyOf(operandTypes2)); } } return returnType; } // Derived type should have overridden this method, since it didn't // supply a type inference rule. throw Util.needToImplement(this); } /** * Derives the type of a call to this operator. * *

This method is an intrinsic part of the validation process so, unlike * {@link #inferReturnType}, specific operators would not typically override * this method. * * @param validator Validator * @param scope Scope of validation * @param call Call to this operator * @return Type of call */ public RelDataType deriveType( SqlValidator validator, SqlValidatorScope scope, SqlCall call) { for (SqlNode operand : call.getOperandList()) { RelDataType nodeType = validator.deriveType(scope, operand); assert nodeType != null; } final List args = constructOperandList(validator, call, null); final List argTypes = constructArgTypeList(validator, scope, call, args, false); // Always disable type coercion for builtin operator operands, // they are handled by the TypeCoercion specifically. final SqlOperator sqlOperator = SqlUtil.lookupRoutine(validator.getOperatorTable(), validator.getTypeFactory(), getNameAsId(), argTypes, null, null, getSyntax(), getKind(), validator.getCatalogReader().nameMatcher(), false); if (sqlOperator == null) { throw validator.handleUnresolvedFunction(call, this, argTypes, null); } ((SqlBasicCall) call).setOperator(castNonNull(sqlOperator)); RelDataType type = call.getOperator().validateOperands(validator, scope, call); // Validate and determine coercibility and resulting collation // name of binary operator if needed. type = adjustType(validator, call, type); SqlValidatorUtil.checkCharsetAndCollateConsistentIfCharType(type); return type; } protected @Nullable List constructArgNameList(SqlCall call) { // If any arguments are named, construct a map. final ImmutableList.Builder nameBuilder = ImmutableList.builder(); for (SqlNode operand : call.getOperandList()) { if (operand.getKind() == SqlKind.ARGUMENT_ASSIGNMENT) { final List operandList = ((SqlCall) operand).getOperandList(); nameBuilder.add(((SqlIdentifier) operandList.get(1)).getSimple()); } } ImmutableList argNames = nameBuilder.build(); if (argNames.isEmpty()) { return null; } else { return argNames; } } protected List constructOperandList( SqlValidator validator, SqlCall call, @Nullable List argNames) { if (argNames == null) { return call.getOperandList(); } if (argNames.size() < call.getOperandList().size()) { throw validator.newValidationError(call, RESOURCE.someButNotAllArgumentsAreNamed()); } final int duplicate = Util.firstDuplicate(argNames); if (duplicate >= 0) { throw validator.newValidationError(call, RESOURCE.duplicateArgumentName(argNames.get(duplicate))); } final ImmutableList.Builder argBuilder = ImmutableList.builder(); for (SqlNode operand : call.getOperandList()) { if (operand.getKind() == SqlKind.ARGUMENT_ASSIGNMENT) { final List operandList = ((SqlCall) operand).getOperandList(); argBuilder.add(operandList.get(0)); } } return argBuilder.build(); } protected List constructArgTypeList( SqlValidator validator, SqlValidatorScope scope, SqlCall call, List args, boolean convertRowArgToColumnList) { // Scope for operands. Usually the same as 'scope'. final SqlValidatorScope operandScope = scope.getOperandScope(call); final ImmutableList.Builder argTypeBuilder = ImmutableList.builder(); for (SqlNode operand : args) { RelDataType nodeType; // for row arguments that should be converted to ColumnList // types, set the nodeType to a ColumnList type but defer // validating the arguments of the row constructor until we know // for sure that the row argument maps to a ColumnList type if (operand.getKind() == SqlKind.ROW && convertRowArgToColumnList) { RelDataTypeFactory typeFactory = validator.getTypeFactory(); nodeType = typeFactory.createSqlType(SqlTypeName.COLUMN_LIST); validator.setValidatedNodeType(operand, nodeType); } else { nodeType = validator.deriveType(operandScope, operand); } argTypeBuilder.add(nodeType); } return argTypeBuilder.build(); } /** * Returns whether this operator should be surrounded by space when * unparsed. * * @return whether this operator should be surrounded by space */ boolean needsSpace() { return true; } /** * Validates and determines coercibility and resulting collation name of * binary operator if needed. */ protected RelDataType adjustType( SqlValidator validator, final SqlCall call, RelDataType type) { return type; } /** * Infers the type of a call to this operator with a given set of operand * types. Shorthand for {@link #inferReturnType(SqlOperatorBinding)}. */ public final RelDataType inferReturnType( RelDataTypeFactory typeFactory, List operandTypes) { return inferReturnType( new ExplicitOperatorBinding( typeFactory, this, operandTypes)); } /** * Checks that the operand values in a {@link SqlCall} to this operator are * valid. Subclasses must either override this method or supply an instance * of {@link SqlOperandTypeChecker} to the constructor. * * @param callBinding description of call * @param throwOnFailure whether to throw an exception if check fails * (otherwise returns false in that case) * @return whether check succeeded */ public boolean checkOperandTypes( SqlCallBinding callBinding, boolean throwOnFailure) { // Check that all of the operands are of the right type. if (null == operandTypeChecker) { // If you see this you must either give operandTypeChecker a value // or override this method. throw Util.needToImplement(this); } if (kind != SqlKind.ARGUMENT_ASSIGNMENT) { for (Ord operand : Ord.zip(callBinding.operands())) { if (operand.e != null && operand.e.getKind() == SqlKind.DEFAULT && !operandTypeChecker.isOptional(operand.i)) { throw callBinding.newValidationError(RESOURCE.defaultForOptionalParameter()); } } } return operandTypeChecker.checkOperandTypes( callBinding, throwOnFailure); } protected void checkOperandCount( SqlValidator validator, @Nullable SqlOperandTypeChecker argType, SqlCall call) { SqlOperandCountRange od = call.getOperator().getOperandCountRange(); if (od.isValidCount(call.operandCount())) { return; } if (od.getMin() == od.getMax()) { throw validator.newValidationError(call, RESOURCE.invalidArgCount(call.getOperator().getName(), od.getMin())); } else { throw validator.newValidationError(call, RESOURCE.wrongNumOfArguments()); } } /** * Returns whether the given operands are valid. If not valid and * {@code fail}, throws an assertion error. * *

Similar to {@link #checkOperandCount}, but some operators may have * different valid operands in {@link SqlNode} and {@code RexNode} formats * (some examples are CAST and AND), and this method throws internal errors, * not user errors.

*/ public boolean validRexOperands(int count, Litmus litmus) { return true; } /** * Returns a template describing how the operator signature is to be built. * E.g for the binary + operator the template looks like "{1} {0} {2}" {0} * is the operator, subsequent numbers are operands. * * @param operandsCount is used with functions that can take a variable * number of operands * @return signature template, or null to indicate that a default template * will suffice */ public @Nullable String getSignatureTemplate(final int operandsCount) { return null; } /** * Returns a string describing the expected operand types of a call, e.g. * "SUBSTR(VARCHAR, INTEGER, INTEGER)". */ public final String getAllowedSignatures() { return getAllowedSignatures(name); } /** * Returns a string describing the expected operand types of a call, e.g. * "SUBSTRING(VARCHAR, INTEGER, INTEGER)" where the name (SUBSTRING in this * example) can be replaced by a specified name. */ public String getAllowedSignatures(String opNameToUse) { requireNonNull(operandTypeChecker, "If you see this, assign operandTypeChecker a value " + "or override this function"); return operandTypeChecker.getAllowedSignatures(this, opNameToUse) .trim(); } public @Nullable SqlOperandTypeInference getOperandTypeInference() { return operandTypeInference; } /** * Returns whether this operator is an aggregate function. By default, * subclass type is used (an instance of SqlAggFunction is assumed to be an * aggregator; anything else is not). * *

Per SQL:2011, there are aggregate functions and * window functions. * Every aggregate function (e.g. SUM) is also a window function. * There are window functions that are not aggregate functions, e.g. RANK, * NTILE, LEAD, FIRST_VALUE.

* *

Collectively, aggregate and window functions are called analytic * functions. Despite its name, this method returns true for every * analytic function.

* * @see #requiresOrder() * * @return whether this operator is an analytic function (aggregate function * or window function) */ @Pure public boolean isAggregator() { return false; } /** Returns whether this is a window function that requires an OVER clause. * *

For example, returns true for {@code RANK}, {@code DENSE_RANK} and * other ranking functions; returns false for {@code SUM}, {@code COUNT}, * {@code MIN}, {@code MAX}, {@code AVG} (they can be used as non-window * aggregate functions). * *

If {@code requiresOver} returns true, then {@link #isAggregator()} must * also return true. * * @see #allowsFraming() * @see #requiresOrder() */ public boolean requiresOver() { return false; } /** * Returns whether this is a window function that requires ordering. * *

Per SQL:2011, 2, 6.10: "If <ntile function>, <lead or lag * function>, RANK or DENSE_RANK is specified, then the window ordering * clause shall be present."

* * @see #isAggregator() */ public boolean requiresOrder() { return false; } /** * Returns whether this is a window function that allows framing (i.e. a * ROWS or RANGE clause in the window specification). */ public boolean allowsFraming() { return true; } /** * Returns whether this is a group function. * *

Group functions can only appear in the GROUP BY clause. * *

Examples are {@code HOP}, {@code TUMBLE}, {@code SESSION}. * *

Group functions have auxiliary functions, e.g. {@code HOP_START}, but * these are not group functions. */ public boolean isGroup() { return false; } /** * Returns whether this is an group auxiliary function. * *

Examples are {@code HOP_START} and {@code HOP_END} (both auxiliary to * {@code HOP}). * * @see #isGroup() */ public boolean isGroupAuxiliary() { return false; } /** * Accepts a {@link SqlVisitor}, visiting each operand of a call. Returns * null. * * @param visitor Visitor * @param call Call to visit */ public @Nullable R acceptCall(SqlVisitor visitor, SqlCall call) { for (SqlNode operand : call.getOperandList()) { if (operand == null) { continue; } operand.accept(visitor); } return null; } /** * Accepts a {@link SqlVisitor}, directing an * {@link com.hazelcast.org.apache.calcite.sql.util.SqlBasicVisitor.ArgHandler} * to visit an operand of a call. * *

The argument handler allows fine control about how the operands are * visited, and how the results are combined. * * @param visitor Visitor * @param call Call to visit * @param onlyExpressions If true, ignores operands which are not * expressions. For example, in the call to the * AS operator * @param argHandler Called for each operand */ public void acceptCall( SqlVisitor visitor, SqlCall call, boolean onlyExpressions, SqlBasicVisitor.ArgHandler argHandler) { List operands = call.getOperandList(); for (int i = 0; i < operands.size(); i++) { argHandler.visitChild(visitor, call, i, operands.get(i)); } } /** Returns the return type inference strategy for this operator, or null if * return type inference is implemented by a subclass override. */ public @Nullable SqlReturnTypeInference getReturnTypeInference() { return returnTypeInference; } /** Returns the operator that is the logical inverse of this operator. * *

For example, {@code SqlStdOperatorTable.LIKE.not()} returns * {@code SqlStdOperatorTable.NOT_LIKE}, and vice versa. * *

By default, returns {@code null}, which means there is no inverse * operator. * * @see #reverse */ public @Nullable SqlOperator not() { return null; } /** Returns the operator that has the same effect as this operator * if its arguments are reversed. * *

For example, {@code SqlStdOperatorTable.GREATER_THAN.reverse()} returns * {@code SqlStdOperatorTable.LESS_THAN}, and vice versa, * because {@code a > b} is equivalent to {@code b < a}. * *

{@code SqlStdOperatorTable.EQUALS.reverse()} returns itself. * *

By default, returns {@code null}, which means there is no inverse * operator. * * @see SqlOperator#not() * @see SqlKind#reverse() */ public @Nullable SqlOperator reverse() { return null; } /** * Returns the {@link Strong.Policy} strategy for this operator, or null if * there is no particular strategy, in which case this policy will be deducted * from the operator's {@link SqlKind}. * * @see Strong */ @Pure public @Nullable Supplier getStrongPolicyInference() { return null; } /** * Returns whether this operator is monotonic. * *

Default implementation returns {@link SqlMonotonicity#NOT_MONOTONIC}. * * @param call Call to this operator * @param scope Scope in which the call occurs * * @deprecated Use {@link #getMonotonicity(SqlOperatorBinding)} */ @Deprecated // to be removed before 2.0 public SqlMonotonicity getMonotonicity( SqlCall call, SqlValidatorScope scope) { return getMonotonicity( new SqlCallBinding(scope.getValidator(), scope, call)); } /** * Returns whether a call to this operator is monotonic. * *

Default implementation returns {@link SqlMonotonicity#NOT_MONOTONIC}. * * @param call Call to this operator with particular arguments and information * about the monotonicity of the arguments */ public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) { return SqlMonotonicity.NOT_MONOTONIC; } /** * Returns whether a call to this operator is guaranteed to always return * the same result given the same operands; true is assumed by default. */ public boolean isDeterministic() { return true; } /** * Returns whether a call to this operator is not sensitive to the operands input order. * An operator is symmetrical if the call returns the same result when * the operands are shuffled. * *

By default, returns true for {@link SqlKind#SYMMETRICAL}. */ public boolean isSymmetrical() { return SqlKind.SYMMETRICAL.contains(kind); } /** * Returns whether it is unsafe to cache query plans referencing this * operator; false is assumed by default. */ public boolean isDynamicFunction() { return false; } /** * Method to check if call requires expansion when it has decimal operands. * The default implementation is to return true. */ public boolean requiresDecimalExpansion() { return true; } /** * Returns whether the ordinalth argument to this operator must * be scalar (as opposed to a query). * *

If true (the default), the validator will attempt to convert the * argument into a scalar sub-query, which must have one column and return at * most one row. * *

Operators such as SELECT and EXISTS override * this method. */ public boolean argumentMustBeScalar(int ordinal) { return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy