blob: 37a56edcb7ecf0509aa57937ea724fcf57c83c0f [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.fun;
import org.apache.calcite.rex.RexCall;
import org.apache.calcite.sql.SqlAggFunction;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlInternalOperator;
import org.apache.calcite.sql.SqlKind;
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.SqlSyntax;
import org.apache.calcite.sql.SqlWriter;
import org.apache.calcite.sql.type.InferTypes;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.type.ReturnTypes;
import org.apache.calcite.util.Litmus;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
/**
* Contains internal operators.
*
* <p>These operators are always created directly, not by looking up a function
* or operator by name or syntax, and therefore this class does not implement
* interface {@link SqlOperatorTable}.
*/
public abstract class SqlInternalOperators {
private SqlInternalOperators() {
}
/** Similar to {@link SqlStdOperatorTable#ROW}, but does not print "ROW".
*
* <p>For arguments [1, TRUE], ROW would print "{@code ROW (1, TRUE)}",
* but this operator prints "{@code (1, TRUE)}". */
public static final SqlRowOperator ANONYMOUS_ROW =
new SqlRowOperator("$ANONYMOUS_ROW") {
@Override public void unparse(SqlWriter writer, SqlCall call,
int leftPrec, int rightPrec) {
@SuppressWarnings("assignment.type.incompatible")
List<@Nullable SqlNode> operandList = call.getOperandList();
writer.list(SqlWriter.FrameTypeEnum.PARENTHESES, SqlWriter.COMMA,
SqlNodeList.of(call.getParserPosition(), operandList));
}
};
/** Similar to {@link #ANONYMOUS_ROW}, but does not print "ROW" or
* parentheses.
*
* <p>For arguments [1, TRUE], prints "{@code 1, TRUE}". It is used in
* contexts where parentheses have been printed (because we thought we were
* about to print "{@code (ROW (1, TRUE))}") and we wish we had not. */
public static final SqlRowOperator ANONYMOUS_ROW_NO_PARENTHESES =
new SqlRowOperator("$ANONYMOUS_ROW_NO_PARENTHESES") {
@Override public void unparse(SqlWriter writer, SqlCall call,
int leftPrec, int rightPrec) {
final SqlWriter.Frame frame =
writer.startList(SqlWriter.FrameTypeEnum.FUN_CALL);
for (SqlNode operand : call.getOperandList()) {
writer.sep(",");
operand.unparse(writer, leftPrec, rightPrec);
}
writer.endList(frame);
}
};
/** "$THROW_UNLESS(condition, message)" throws an error with the given message
* if condition is not TRUE, otherwise returns TRUE. */
public static final SqlInternalOperator THROW_UNLESS =
new SqlInternalOperator("$THROW_UNLESS", SqlKind.OTHER);
/** An IN operator for Druid.
*
* <p>Unlike the regular
* {@link SqlStdOperatorTable#IN} operator it may
* be used in {@link RexCall}. It does not require that
* its operands have consistent types. */
public static final SqlInOperator DRUID_IN =
new SqlInOperator(SqlKind.DRUID_IN);
/** A NOT IN operator for Druid, analogous to {@link #DRUID_IN}. */
public static final SqlInOperator DRUID_NOT_IN =
new SqlInOperator(SqlKind.DRUID_NOT_IN);
/** A BETWEEN operator for Druid, analogous to {@link #DRUID_IN}. */
public static final SqlBetweenOperator DRUID_BETWEEN =
new SqlBetweenOperator(SqlBetweenOperator.Flag.SYMMETRIC, false) {
@Override public SqlKind getKind() {
return SqlKind.DRUID_BETWEEN;
}
@Override public boolean validRexOperands(int count, Litmus litmus) {
return litmus.succeed();
}
};
/** Separator expression inside GROUP_CONCAT, e.g. '{@code SEPARATOR ','}'. */
public static final SqlOperator SEPARATOR =
new SqlInternalOperator("SEPARATOR", SqlKind.SEPARATOR, 20, false,
ReturnTypes.ARG0, InferTypes.RETURN_TYPE, OperandTypes.ANY);
/** {@code DISTINCT} operator, occurs within {@code GROUP BY} clause. */
public static final SqlInternalOperator GROUP_BY_DISTINCT =
new SqlRollupOperator("GROUP BY DISTINCT", SqlKind.GROUP_BY_DISTINCT);
/** Fetch operator is ONLY used for its precedence during unparsing. */
public static final SqlOperator FETCH =
SqlBasicOperator.create("FETCH")
.withPrecedence(SqlStdOperatorTable.UNION.getLeftPrec() - 2, true);
/** 2-argument form of the special minus-date operator
* to be used with BigQuery subtraction functions. It differs from
* the standard MINUS_DATE operator in that it has 2 arguments,
* and subtracts an interval from a datetime. */
public static final SqlDatetimeSubtractionOperator MINUS_DATE2 =
new SqlDatetimeSubtractionOperator("MINUS_DATE2", ReturnTypes.ARG0_NULLABLE);
/** Offset operator is ONLY used for its precedence during unparsing. */
public static final SqlOperator OFFSET =
SqlBasicOperator.create("OFFSET")
.withPrecedence(SqlStdOperatorTable.UNION.getLeftPrec() - 2, true);
/** Aggregate function that always returns a given literal. */
public static final SqlAggFunction LITERAL_AGG =
SqlLiteralAggFunction.INSTANCE;
/** Subject to change. */
private static class SqlBasicOperator extends SqlOperator {
@Override public SqlSyntax getSyntax() {
return SqlSyntax.SPECIAL;
}
/** Private constructor. Use {@link #create}. */
private SqlBasicOperator(String name, int leftPrecedence, int rightPrecedence) {
super(name, SqlKind.OTHER, leftPrecedence, rightPrecedence,
ReturnTypes.BOOLEAN, InferTypes.RETURN_TYPE, OperandTypes.ANY);
}
static SqlBasicOperator create(String name) {
return new SqlBasicOperator(name, 0, 0);
}
SqlBasicOperator withPrecedence(int prec, boolean leftAssoc) {
return new SqlBasicOperator(getName(), leftPrec(prec, leftAssoc),
rightPrec(prec, leftAssoc));
}
}
}