OmniSciDB  ca0c39ec8f
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SqlOperator.java
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to you under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 // clang-format off
19 
20 package org.apache.calcite.sql;
21 
22 import org.apache.calcite.linq4j.Ord;
23 import org.apache.calcite.plan.Strong;
24 import org.apache.calcite.rel.type.RelDataType;
25 import org.apache.calcite.rel.type.RelDataTypeFactory;
26 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
27 import org.apache.calcite.sql.parser.SqlParserPos;
28 import org.apache.calcite.sql.type.SqlOperandTypeChecker;
29 import org.apache.calcite.sql.type.SqlOperandTypeInference;
30 import org.apache.calcite.sql.type.SqlReturnTypeInference;
31 import org.apache.calcite.sql.type.SqlTypeName;
32 import org.apache.calcite.sql.util.SqlBasicVisitor;
33 import org.apache.calcite.sql.util.SqlVisitor;
34 import org.apache.calcite.sql.validate.SqlMonotonicity;
35 import org.apache.calcite.sql.validate.SqlValidator;
37 import org.apache.calcite.sql.validate.SqlValidatorScope;
38 import org.apache.calcite.sql.validate.SqlValidatorUtil;
39 import org.apache.calcite.util.Litmus;
40 import org.apache.calcite.util.Util;
41 
42 import com.google.common.collect.ImmutableList;
43 
44 import java.util.Arrays;
45 import java.util.List;
46 import java.util.Objects;
47 import java.util.function.Supplier;
48 
49 import static org.apache.calcite.util.Static.RESOURCE;
50 
74 public abstract class SqlOperator {
75  //~ Static fields/initializers ---------------------------------------------
76 
77  public static final String NL = System.getProperty("line.separator");
78 
82  public static final int MDX_PRECEDENCE = 200;
83 
84  //~ Instance fields --------------------------------------------------------
85 
89  private final String name;
90 
95  public final SqlKind kind;
96 
102  private final int leftPrec;
103 
109  private final int rightPrec;
110 
112  private final SqlReturnTypeInference returnTypeInference;
113 
115  private final SqlOperandTypeInference operandTypeInference;
116 
118  private final SqlOperandTypeChecker operandTypeChecker;
119 
120  //~ Constructors -----------------------------------------------------------
121 
125  protected SqlOperator(
126  String name,
127  SqlKind kind,
128  int leftPrecedence,
129  int rightPrecedence,
130  SqlReturnTypeInference returnTypeInference,
131  SqlOperandTypeInference operandTypeInference,
132  SqlOperandTypeChecker operandTypeChecker) {
133  assert kind != null;
134  this.name = name;
135  this.kind = kind;
136  this.leftPrec = leftPrecedence;
137  this.rightPrec = rightPrecedence;
138  this.returnTypeInference = returnTypeInference;
139  this.operandTypeInference = operandTypeInference;
140  this.operandTypeChecker = operandTypeChecker;
141  }
142 
146  protected SqlOperator(
147  String name,
148  SqlKind kind,
149  int prec,
150  boolean leftAssoc,
151  SqlReturnTypeInference returnTypeInference,
152  SqlOperandTypeInference operandTypeInference,
153  SqlOperandTypeChecker operandTypeChecker) {
154  this(
155  name,
156  kind,
157  leftPrec(prec, leftAssoc),
158  rightPrec(prec, leftAssoc),
162  }
163 
164  //~ Methods ----------------------------------------------------------------
165 
166  protected static int leftPrec(int prec, boolean leftAssoc) {
167  assert (prec % 2) == 0;
168  if (!leftAssoc) {
169  ++prec;
170  }
171  return prec;
172  }
173 
174  protected static int rightPrec(int prec, boolean leftAssoc) {
175  assert (prec % 2) == 0;
176  if (leftAssoc) {
177  ++prec;
178  }
179  return prec;
180  }
181 
182  public SqlOperandTypeChecker getOperandTypeChecker() {
183  return operandTypeChecker;
184  }
185 
194  public SqlOperandCountRange getOperandCountRange() {
195  if (operandTypeChecker != null) {
196  return operandTypeChecker.getOperandCountRange();
197  }
198 
199  // If you see this error you need to override this method
200  // or give operandTypeChecker a value.
201  throw Util.needToImplement(this);
202  }
203 
204  // This only exists to allow us to identify if a UDF will add // HEAVY.AI new
205  // default values to the operand list during a later phase // HEAVY.AI new
206  // and therefore require special handling ... to be recreated // HEAVY.AI new
207  // // HEAVY.AI new
208  public boolean requiresCreate(List<SqlNode> operands) { // HEAVY.AI new
209  return false; // HEAVY.AI new
210  } // HEAVY.AI new
211 
212  public String getName() {
213  return name;
214  }
215 
219  public SqlIdentifier getNameAsId() {
220  return new SqlIdentifier(getName(), SqlParserPos.ZERO);
221  }
222 
223  public SqlKind getKind() {
224  return kind;
225  }
226 
227  public String toString() {
228  return name;
229  }
230 
231  public int getLeftPrec() {
232  return leftPrec;
233  }
234 
235  public int getRightPrec() {
236  return rightPrec;
237  }
238 
242  public abstract SqlSyntax getSyntax();
243 
254  public SqlCall createCall(
255  SqlLiteral functionQualifier,
256  SqlParserPos pos,
257  SqlNode... operands) {
258  pos = pos.plusAll(Arrays.asList(operands));
259  return new SqlBasicCall(this, operands, pos, false, functionQualifier);
260  }
261 
272  public final SqlCall createCall(
273  SqlParserPos pos,
274  SqlNode... operands) {
275  return createCall(null, pos, operands);
276  }
277 
287  public final SqlCall createCall(
288  SqlNodeList nodeList) {
289  return createCall(
290  null,
291  nodeList.getParserPosition(),
292  nodeList.toArray());
293  }
294 
301  public final SqlCall createCall(
302  SqlParserPos pos,
303  List<? extends SqlNode> operandList) {
304  return createCall(
305  null,
306  pos,
307  operandList.toArray(new SqlNode[0]));
308  }
309 
323  public SqlNode rewriteCall(SqlValidator validator, SqlCall call) {
324  return call;
325  }
326 
335  public void unparse(
336  SqlWriter writer,
337  SqlCall call,
338  int leftPrec,
339  int rightPrec) {
340  getSyntax().unparse(writer, this, call, leftPrec, rightPrec);
341  }
342 
343  @Deprecated // to be removed before 2.0
344  protected void unparseListClause(SqlWriter writer, SqlNode clause) {
345  final SqlNodeList nodeList =
346  clause instanceof SqlNodeList
347  ? (SqlNodeList) clause
348  : SqlNodeList.of(clause);
349  writer.list(SqlWriter.FrameTypeEnum.SIMPLE, SqlWriter.COMMA, nodeList);
350  }
351 
352  @Deprecated // to be removed before 2.0
353  protected void unparseListClause(
354  SqlWriter writer,
355  SqlNode clause,
356  SqlKind sepKind) {
357  final SqlNodeList nodeList =
358  clause instanceof SqlNodeList
359  ? (SqlNodeList) clause
360  : SqlNodeList.of(clause);
361  final SqlBinaryOperator sepOp;
362  if (sepKind == null) {
363  sepOp = SqlWriter.COMMA;
364  } else {
365  switch (sepKind) {
366  case AND:
367  sepOp = SqlStdOperatorTable.AND;
368  break;
369  case OR:
370  sepOp = SqlStdOperatorTable.OR;
371  break;
372  default:
373  throw new AssertionError();
374  }
375  }
376  writer.list(SqlWriter.FrameTypeEnum.SIMPLE, sepOp, nodeList);
377  }
378 
379  // override Object
380  public boolean equals(Object obj) {
381  if (!(obj instanceof SqlOperator)) {
382  return false;
383  }
384  if (!obj.getClass().equals(this.getClass())) {
385  return false;
386  }
387  SqlOperator other = (SqlOperator) obj;
388  return name.equals(other.name) && kind == other.kind;
389  }
390 
391  public boolean isName(String testName, boolean caseSensitive) {
392  return caseSensitive ? name.equals(testName) : name.equalsIgnoreCase(testName);
393  }
394 
395  @Override public int hashCode() {
396  return Objects.hash(kind, name);
397  }
398 
423  public void validateCall(
424  SqlCall call,
425  SqlValidator validator,
426  SqlValidatorScope scope,
427  SqlValidatorScope operandScope) {
428  assert call.getOperator() == this;
429  for (SqlNode operand : call.getOperandList()) {
430  operand.validateExpr(validator, operandScope);
431  }
432  }
433 
443  public final RelDataType validateOperands(
444  SqlValidator validator,
445  SqlValidatorScope scope,
446  SqlCall call) {
447  // Let subclasses know what's up.
448  preValidateCall(validator, scope, call);
449 
450  // Check the number of operands
451  checkOperandCount(validator, operandTypeChecker, call);
452 
453  SqlCallBinding opBinding = new SqlCallBinding(validator, scope, call);
454 
456  opBinding,
457  true);
458 
459  // Now infer the result type.
460  RelDataType ret = inferReturnType(opBinding);
461  ((SqlValidatorImpl) validator).setValidatedNodeType(call, ret);
462  return ret;
463  }
464 
474  protected void preValidateCall(
475  SqlValidator validator,
476  SqlValidatorScope scope,
477  SqlCall call) {
478  }
479 
490  public RelDataType inferReturnType(
491  SqlOperatorBinding opBinding) {
492  if (returnTypeInference != null) {
493  RelDataType returnType = returnTypeInference.inferReturnType(opBinding);
494  if (returnType == null) {
495  throw new IllegalArgumentException("Cannot infer return type for "
496  + opBinding.getOperator() + "; operand types: "
497  + opBinding.collectOperandTypes());
498  }
499  return returnType;
500  }
501 
502  // Derived type should have overridden this method, since it didn't
503  // supply a type inference rule.
504  throw Util.needToImplement(this);
505  }
506 
519  public RelDataType deriveType(
520  SqlValidator validator,
521  SqlValidatorScope scope,
522  SqlCall call) {
523  for (SqlNode operand : call.getOperandList()) {
524  RelDataType nodeType = validator.deriveType(scope, operand);
525  assert nodeType != null;
526  }
527 
528  final List<SqlNode> args = constructOperandList(validator, call, null);
529 
530  final List<RelDataType> argTypes = constructArgTypeList(validator, scope,
531  call, args, false);
532 
533  // Always disable type coercion for builtin operator operands,
534  // they are handled by the TypeCoercion specifically.
535  final SqlOperator sqlOperator =
536  SqlUtil.lookupRoutine(validator.getOperatorTable(), getNameAsId(),
537  argTypes, null, null, getSyntax(), getKind(),
538  validator.getCatalogReader().nameMatcher(), false);
539 
540  ((SqlBasicCall) call).setOperator(sqlOperator);
541  RelDataType type = call.getOperator().validateOperands(validator, scope, call);
542 
543  // Validate and determine coercibility and resulting collation
544  // name of binary operator if needed.
545  type = adjustType(validator, call, type);
546  SqlValidatorUtil.checkCharsetAndCollateConsistentIfCharType(type);
547  return type;
548  }
549 
550  protected List<String> constructArgNameList(SqlCall call) {
551  // If any arguments are named, construct a map.
552  final ImmutableList.Builder<String> nameBuilder = ImmutableList.builder();
553  for (SqlNode operand : call.getOperandList()) {
554  if (operand.getKind() == SqlKind.ARGUMENT_ASSIGNMENT) {
555  final List<SqlNode> operandList = ((SqlCall) operand).getOperandList();
556  nameBuilder.add(((SqlIdentifier) operandList.get(1)).getSimple());
557  }
558  }
559  ImmutableList<String> argNames = nameBuilder.build();
560 
561  if (argNames.isEmpty()) {
562  return null;
563  } else {
564  return argNames;
565  }
566  }
567 
568  protected List<SqlNode> constructOperandList(
569  SqlValidator validator,
570  SqlCall call,
571  List<String> argNames) {
572  if (argNames == null) {
573  return call.getOperandList();
574  }
575  if (argNames.size() < call.getOperandList().size()) {
576  throw validator.newValidationError(call,
577  RESOURCE.someButNotAllArgumentsAreNamed());
578  }
579  final int duplicate = Util.firstDuplicate(argNames);
580  if (duplicate >= 0) {
581  throw validator.newValidationError(call,
582  RESOURCE.duplicateArgumentName(argNames.get(duplicate)));
583  }
584  final ImmutableList.Builder<SqlNode> argBuilder = ImmutableList.builder();
585  for (SqlNode operand : call.getOperandList()) {
586  if (operand.getKind() == SqlKind.ARGUMENT_ASSIGNMENT) {
587  final List<SqlNode> operandList = ((SqlCall) operand).getOperandList();
588  argBuilder.add(operandList.get(0));
589  }
590  }
591  return argBuilder.build();
592  }
593 
594  protected List<RelDataType> constructArgTypeList(
595  SqlValidator validator,
596  SqlValidatorScope scope,
597  SqlCall call,
598  List<SqlNode> args,
599  boolean convertRowArgToColumnList) {
600  // Scope for operands. Usually the same as 'scope'.
601  final SqlValidatorScope operandScope = scope.getOperandScope(call);
602 
603  final ImmutableList.Builder<RelDataType> argTypeBuilder =
604  ImmutableList.builder();
605  for (SqlNode operand : args) {
606  RelDataType nodeType;
607  // for row arguments that should be converted to ColumnList
608  // types, set the nodeType to a ColumnList type but defer
609  // validating the arguments of the row constructor until we know
610  // for sure that the row argument maps to a ColumnList type
611  if (operand.getKind() == SqlKind.ROW && convertRowArgToColumnList) {
612  RelDataTypeFactory typeFactory = validator.getTypeFactory();
613  nodeType = typeFactory.createSqlType(SqlTypeName.COLUMN_LIST);
614  ((SqlValidatorImpl) validator).setValidatedNodeType(operand, nodeType);
615  } else {
616  nodeType = validator.deriveType(operandScope, operand);
617  }
618  argTypeBuilder.add(nodeType);
619  }
620 
621  return argTypeBuilder.build();
622  }
623 
630  boolean needsSpace() {
631  return true;
632  }
633 
638  protected RelDataType adjustType(
639  SqlValidator validator,
640  final SqlCall call,
641  RelDataType type) {
642  return type;
643  }
644 
649  public final RelDataType inferReturnType(
650  RelDataTypeFactory typeFactory,
651  List<RelDataType> operandTypes) {
652  return inferReturnType(
653  new ExplicitOperatorBinding(
654  typeFactory,
655  this,
656  operandTypes));
657  }
658 
669  public boolean checkOperandTypes(
670  SqlCallBinding callBinding,
671  boolean throwOnFailure) {
672  // Check that all of the operands are of the right type.
673  if (null == operandTypeChecker) {
674  // If you see this you must either give operandTypeChecker a value
675  // or override this method.
676  throw Util.needToImplement(this);
677  }
678 
679  if (kind != SqlKind.ARGUMENT_ASSIGNMENT) {
680  for (Ord<SqlNode> operand : Ord.zip(callBinding.operands())) {
681  if (operand.e != null
682  && operand.e.getKind() == SqlKind.DEFAULT
683  && !operandTypeChecker.isOptional(operand.i)) {
684  throw callBinding.newValidationError(RESOURCE.defaultForOptionalParameter());
685  }
686  }
687  }
688 
689  return operandTypeChecker.checkOperandTypes(
690  callBinding,
691  throwOnFailure);
692  }
693 
694  protected void checkOperandCount(
695  SqlValidator validator,
696  SqlOperandTypeChecker argType,
697  SqlCall call) {
698  SqlOperandCountRange od = call.getOperator().getOperandCountRange();
699  if (od.isValidCount(call.operandCount())) {
700  return;
701  }
702  if (od.getMin() == od.getMax()) {
703  throw validator.newValidationError(call,
704  RESOURCE.invalidArgCount(call.getOperator().getName(), od.getMin()));
705  } else {
706  throw validator.newValidationError(call, RESOURCE.wrongNumOfArguments());
707  }
708  }
709 
719  public boolean validRexOperands(int count, Litmus litmus) {
720  return true;
721  }
722 
733  public String getSignatureTemplate(final int operandsCount) {
734  return null;
735  }
736 
741  public final String getAllowedSignatures() {
742  return getAllowedSignatures(name);
743  }
744 
750  public String getAllowedSignatures(String opNameToUse) {
751  assert operandTypeChecker != null
752  : "If you see this, assign operandTypeChecker a value "
753  + "or override this function";
754  return operandTypeChecker.getAllowedSignatures(this, opNameToUse)
755  .trim();
756  }
757 
758  public SqlOperandTypeInference getOperandTypeInference() {
759  return operandTypeInference;
760  }
761 
782  public boolean isAggregator() {
783  return false;
784  }
785 
799  public boolean requiresOver() {
800  return false;
801  }
802 
812  public boolean requiresOrder() {
813  return false;
814  }
815 
820  public boolean allowsFraming() {
821  return true;
822  }
823 
834  public boolean isGroup() {
835  return false;
836  }
837 
846  public boolean isGroupAuxiliary() {
847  return false;
848  }
849 
857  public <R> R acceptCall(SqlVisitor<R> visitor, SqlCall call) {
858  for (SqlNode operand : call.getOperandList()) {
859  if (operand == null) {
860  continue;
861  }
862  operand.accept(visitor);
863  }
864  return null;
865  }
866 
882  public <R> void acceptCall(
883  SqlVisitor<R> visitor,
884  SqlCall call,
885  boolean onlyExpressions,
886  SqlBasicVisitor.ArgHandler<R> argHandler) {
887  List<SqlNode> operands = call.getOperandList();
888  for (int i = 0; i < operands.size(); i++) {
889  argHandler.visitChild(visitor, call, i, operands.get(i));
890  }
891  }
892 
895  public SqlReturnTypeInference getReturnTypeInference() {
896  return returnTypeInference;
897  }
898 
906  public Supplier<Strong.Policy> getStrongPolicyInference() {
907  return null;
908  }
909 
920  @Deprecated // to be removed before 2.0
921  public SqlMonotonicity getMonotonicity(
922  SqlCall call,
923  SqlValidatorScope scope) {
924  return getMonotonicity(
925  new SqlCallBinding(scope.getValidator(), scope, call));
926  }
927 
936  public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
937  return SqlMonotonicity.NOT_MONOTONIC;
938  }
939 
944  public boolean isDeterministic() {
945  return true;
946  }
947 
955  public boolean isSymmetrical() {
956  return SqlKind.SYMMETRICAL.contains(kind);
957  }
958 
963  public boolean isDynamicFunction() {
964  return false;
965  }
966 
971  public boolean requiresDecimalExpansion() {
972  return true;
973  }
974 
986  public boolean argumentMustBeScalar(int ordinal) {
987  return true;
988  }
989 }
SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNode...operands)
Supplier< Strong.Policy > getStrongPolicyInference()
void unparseListClause(SqlWriter writer, SqlNode clause)
SqlReturnTypeInference getReturnTypeInference()
boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure)
boolean requiresCreate(List< SqlNode > operands)
SqlOperator(String name, SqlKind kind, int prec, boolean leftAssoc, SqlReturnTypeInference returnTypeInference, SqlOperandTypeInference operandTypeInference, SqlOperandTypeChecker operandTypeChecker)
RelDataType adjustType(SqlValidator validator, final SqlCall call, RelDataType type)
String getSignatureTemplate(final int operandsCount)
final SqlOperandTypeChecker operandTypeChecker
SqlOperator(String name, SqlKind kind, int leftPrecedence, int rightPrecedence, SqlReturnTypeInference returnTypeInference, SqlOperandTypeInference operandTypeInference, SqlOperandTypeChecker operandTypeChecker)
final SqlCall createCall(SqlParserPos pos, SqlNode...operands)
public< R > void acceptCall(SqlVisitor< R > visitor, SqlCall call, boolean onlyExpressions, SqlBasicVisitor.ArgHandler< R > argHandler)
final RelDataType inferReturnType(RelDataTypeFactory typeFactory, List< RelDataType > operandTypes)
SqlOperandTypeInference getOperandTypeInference()
SqlMonotonicity getMonotonicity(SqlCall call, SqlValidatorScope scope)
static int rightPrec(int prec, boolean leftAssoc)
void preValidateCall(SqlValidator validator, SqlValidatorScope scope, SqlCall call)
void validateCall(SqlCall call, SqlValidator validator, SqlValidatorScope scope, SqlValidatorScope operandScope)
final SqlCall createCall(SqlParserPos pos, List<?extends SqlNode > operandList)
List< RelDataType > constructArgTypeList(SqlValidator validator, SqlValidatorScope scope, SqlCall call, List< SqlNode > args, boolean convertRowArgToColumnList)
SqlMonotonicity getMonotonicity(SqlOperatorBinding call)
boolean isName(String testName, boolean caseSensitive)
public< R > R acceptCall(SqlVisitor< R > visitor, SqlCall call)
abstract SqlSyntax getSyntax()
final SqlCall createCall(SqlNodeList nodeList)
void unparse(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec)
SqlNode rewriteCall(SqlValidator validator, SqlCall call)
static int leftPrec(int prec, boolean leftAssoc)
RelDataType deriveType(SqlValidator validator, SqlValidatorScope scope, SqlCall call)
void checkOperandCount(SqlValidator validator, SqlOperandTypeChecker argType, SqlCall call)
String getAllowedSignatures(String opNameToUse)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
final SqlReturnTypeInference returnTypeInference
List< SqlNode > constructOperandList(SqlValidator validator, SqlCall call, List< String > argNames)
boolean argumentMustBeScalar(int ordinal)
List< String > constructArgNameList(SqlCall call)
void unparseListClause(SqlWriter writer, SqlNode clause, SqlKind sepKind)
final SqlOperandTypeInference operandTypeInference
SqlOperandTypeChecker getOperandTypeChecker()
string name
Definition: setup.in.py:72
SqlOperandCountRange getOperandCountRange()
final RelDataType validateOperands(SqlValidator validator, SqlValidatorScope scope, SqlCall call)
boolean validRexOperands(int count, Litmus litmus)