OmniSciDB  c1a53651b2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HeavyDBSqlOperatorTable.java
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.mapd.calcite.parser;
18 
20 
21 import static org.apache.calcite.util.Static.RESOURCE;
22 
23 import com.google.common.base.Predicate;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.Multimap;
29 
30 import org.apache.calcite.rel.metadata.RelColumnMapping;
31 import org.apache.calcite.rel.type.RelDataType;
32 import org.apache.calcite.rel.type.RelDataTypeFactory;
33 import org.apache.calcite.rel.type.RelDataTypeFactory.FieldInfoBuilder;
34 import org.apache.calcite.rel.type.RelDataTypeFamily;
35 import org.apache.calcite.schema.FunctionParameter;
36 import org.apache.calcite.schema.TranslatableTable;
37 import org.apache.calcite.sql.SqlAggFunction;
38 import org.apache.calcite.sql.SqlCall;
39 import org.apache.calcite.sql.SqlCallBinding;
40 import org.apache.calcite.sql.SqlDynamicParam;
41 import org.apache.calcite.sql.SqlFunction;
42 import org.apache.calcite.sql.SqlFunctionCategory;
43 import org.apache.calcite.sql.SqlIdentifier;
44 import org.apache.calcite.sql.SqlIntervalQualifier;
45 import org.apache.calcite.sql.SqlKind;
46 import org.apache.calcite.sql.SqlLiteral;
47 import org.apache.calcite.sql.SqlNode;
48 import org.apache.calcite.sql.SqlOperandCountRange;
50 import org.apache.calcite.sql.SqlOperatorBinding;
51 import org.apache.calcite.sql.SqlOperatorTable;
52 import org.apache.calcite.sql.SqlSyntax;
53 import org.apache.calcite.sql.SqlTableFunction;
54 import org.apache.calcite.sql.SqlUtil;
55 import org.apache.calcite.sql.SqlWriter;
56 import org.apache.calcite.sql.fun.SqlArrayValueConstructor;
57 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
58 import org.apache.calcite.sql.parser.SqlParserPos;
59 import org.apache.calcite.sql.type.ArraySqlType;
60 import org.apache.calcite.sql.type.InferTypes;
61 import org.apache.calcite.sql.type.OperandTypes;
62 import org.apache.calcite.sql.type.ReturnTypes;
63 import org.apache.calcite.sql.type.SameOperandTypeChecker;
64 import org.apache.calcite.sql.type.SqlOperandCountRanges;
65 import org.apache.calcite.sql.type.SqlReturnTypeInference;
66 import org.apache.calcite.sql.type.SqlTypeFamily;
67 import org.apache.calcite.sql.type.SqlTypeName;
68 import org.apache.calcite.sql.type.SqlTypeTransforms;
69 import org.apache.calcite.sql.type.SqlTypeUtil;
70 import org.apache.calcite.sql.util.ChainedSqlOperatorTable;
71 import org.apache.calcite.sql.util.ListSqlOperatorTable;
72 import org.apache.calcite.sql.util.ReflectiveSqlOperatorTable;
73 import org.apache.calcite.sql.validate.SqlNameMatcher;
75 import org.apache.calcite.util.Optionality;
76 import org.checkerframework.checker.nullness.qual.Nullable;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
79 
80 import java.lang.reflect.Field;
81 import java.util.Arrays;
82 import java.util.HashSet;
83 import java.util.Iterator;
84 import java.util.List;
85 import java.util.Locale;
86 import java.util.Map;
87 import java.util.Set;
88 import java.util.stream.Collectors;
89 
90 class CaseInsensitiveListSqlOperatorTable extends ListSqlOperatorTable {
91  @Override
92  public void lookupOperatorOverloads(SqlIdentifier opName,
93  SqlFunctionCategory category,
94  SqlSyntax syntax,
95  List<SqlOperator> operatorList,
96  SqlNameMatcher nameMatcher) {
97  for (SqlOperator operator : this.getOperatorList()) {
98  if (operator.getSyntax() != syntax) {
99  continue;
100  }
101  if (!opName.isSimple()
102  || !nameMatcher.matches(operator.getName(), opName.getSimple())) {
103  continue;
104  }
105  SqlFunctionCategory functionCategory;
106  if (operator instanceof SqlFunction) {
107  functionCategory = ((SqlFunction) operator).getFunctionType();
108  } else {
109  functionCategory = SqlFunctionCategory.SYSTEM;
110  }
111  if (category != functionCategory
112  && category != SqlFunctionCategory.USER_DEFINED_FUNCTION) {
113  continue;
114  }
115  operatorList.add(operator);
116  }
117  }
118 }
119 
120 public class HeavyDBSqlOperatorTable extends ChainedSqlOperatorTable {
123  public static final SqlFunction TRY_CAST = new TryCast();
124 
125  static {
126  try {
127  // some nasty bit to remove the std APPROX_COUNT_DISTINCT function definition
128  {
129  Field f = ReflectiveSqlOperatorTable.class.getDeclaredField(
130  "caseSensitiveOperators");
131  f.setAccessible(true);
132  Multimap operators = (Multimap) f.get(SqlStdOperatorTable.instance());
133  for (Iterator i = operators.entries().iterator(); i.hasNext();) {
134  Map.Entry entry = (Map.Entry) i.next();
135  if (entry.getValue() == SqlStdOperatorTable.APPROX_COUNT_DISTINCT
136  || entry.getValue() == SqlStdOperatorTable.AVG
137  || entry.getValue() == SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR) {
138  i.remove();
139  }
140  }
141  }
142 
143  {
144  Field f = ReflectiveSqlOperatorTable.class.getDeclaredField(
145  "caseInsensitiveOperators");
146  f.setAccessible(true);
147  Multimap operators = (Multimap) f.get(SqlStdOperatorTable.instance());
148  for (Iterator i = operators.entries().iterator(); i.hasNext();) {
149  Map.Entry entry = (Map.Entry) i.next();
150  if (entry.getValue() == SqlStdOperatorTable.APPROX_COUNT_DISTINCT
151  || entry.getValue() == SqlStdOperatorTable.AVG
152  || entry.getValue() == SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR) {
153  i.remove();
154  }
155  }
156  }
157 
158  SqlStdOperatorTable.instance().register(ARRAY_VALUE_CONSTRUCTOR);
159 
160  } catch (Exception e) {
161  throw new RuntimeException(e);
162  }
163 
164  // register our approx count distinct against std table
165  // SqlStdOperatorTable.instance().register(new ApproxCountDistinct());
166  }
167 
168  final static Logger HEAVYDBLOGGER =
169  LoggerFactory.getLogger(HeavyDBSqlOperatorTable.class);
170 
175  // ~ Instance fields --------------------------------------------------------
176  private final ListSqlOperatorTable listOpTab;
177 
178  // ~ Constructors -----------------------------------------------------------
179  public HeavyDBSqlOperatorTable(SqlOperatorTable parentTable) {
180  super(ImmutableList.of(parentTable, new CaseInsensitiveListSqlOperatorTable()));
181  listOpTab = (ListSqlOperatorTable) tableList.get(1);
182  }
183 
189  public void addOperator(SqlOperator op) {
190  listOpTab.add(op);
191  }
192 
193  public void addUDF(final Map<String, ExtensionFunction> extSigs) {
194  // Don't use anonymous inner classes. They can't be instantiated
195  // using reflection when we are deserializing from JSON.
196  addOperator(new MyUDFFunction());
197  addOperator(new PgUnnest());
198  addOperator(new Any());
199  addOperator(new All());
200  addOperator(new Now());
201  addOperator(new Datetime());
202  addOperator(new PgExtract());
203  addOperator(new Dateadd());
204  addOperator(new Datediff());
205  addOperator(new Datepart());
206  addOperator(new PgDateTrunc());
207  addOperator(new Length());
208  addOperator(new CharLength());
209  addOperator(new KeyForString());
210  addOperator(new SampleRatio());
211  addOperator(new WidthBucket());
212  addOperator(new ArrayLength());
213  addOperator(new PgILike());
214  addOperator(new LTrim());
215  addOperator(new RTrim());
216  addOperator(new LPad());
217  addOperator(new RPad());
218  addOperator(new Replace());
219  addOperator(new Reverse());
220  addOperator(new Repeat());
221  addOperator(new SplitPart());
222  addOperator(new RegexpLike());
223  addOperator(new RegexpReplace());
224  addOperator(new RegexpSubstr());
225  addOperator(new RegexpMatch());
226  addOperator(new Base64Encode());
227  addOperator(new Base64Decode());
228  addOperator(new Likely());
229  addOperator(new Unlikely());
230  addOperator(new Sign());
231  addOperator(new Truncate());
232  addOperator(new TryCast());
233  addOperator(new ST_IsEmpty());
234  addOperator(new ST_IsValid());
235  addOperator(new ST_Contains());
236  addOperator(new ST_Equals());
237  addOperator(new ST_Intersects());
238  addOperator(new ST_Overlaps());
240  addOperator(new ST_Disjoint());
241  addOperator(new ST_Within());
242  addOperator(new ST_DWithin());
244  addOperator(new ST_Distance());
248  addOperator(new ST_Transform());
249  addOperator(new ST_X());
250  addOperator(new ST_Y());
251  addOperator(new ST_XMin());
252  addOperator(new ST_XMax());
253  addOperator(new ST_YMin());
254  addOperator(new ST_YMax());
255  addOperator(new ST_PointN());
256  addOperator(new ST_StartPoint());
257  addOperator(new ST_EndPoint());
258  addOperator(new ST_Length());
259  addOperator(new ST_Perimeter());
260  addOperator(new ST_Area());
261  addOperator(new ST_NPoints());
262  addOperator(new ST_NRings());
264  addOperator(new ST_SRID());
265  addOperator(new ST_SetSRID());
266  addOperator(new ST_Point());
267  addOperator(new ST_Centroid());
268  addOperator(new ST_Buffer());
270  addOperator(new ST_ConvexHull());
272  addOperator(new ST_Union());
273  addOperator(new ST_Difference());
275  addOperator(new EncodeText());
278  addOperator(new ApproxMedian());
281  addOperator(new MapDAvg());
282  addOperator(new Mode());
283  addOperator(new Sample());
284  addOperator(new LastSample());
285 
286  // window functions on window frame
288  addOperator(new LagInFrame());
289  addOperator(new LeadInFrame());
290 
291  // conditional window aggregate functions
292  addOperator(new CountIf());
293  addOperator(new SumIf());
294 
304  addOperator(new usTimestamp());
305  addOperator(new nsTimestamp());
306 
307  if (extSigs == null) {
308  return;
309  }
310  HashSet<String> demangledNames = new HashSet<String>();
311  for (Map.Entry<String, ExtensionFunction> extSig : extSigs.entrySet()) {
312  final String demangledName = dropSuffix(extSig.getKey());
313  final String demangledNameArity = extSig.getValue().isTableUdf()
314  ? String.format("%s-%s-%s",
315  demangledName,
316  extSig.getValue().getArgs(),
317  extSig.getValue().getCursorFieldTypes())
318  : String.format("%s-%d", demangledName, extSig.getValue().getArgs().size());
319  if (demangledNames.contains(demangledNameArity)) {
320  continue;
321  }
322  demangledNames.add(demangledNameArity);
323  if (extSig.getValue().isRowUdf()) {
324  addOperator(new ExtFunction(demangledName, extSig.getValue()));
325  } else {
326  addOperator(new ExtTableFunction(demangledName, extSig.getValue()));
327  }
328  }
329  }
330 
331  private static String dropSuffix(final String str) {
332  int suffix_idx = str.indexOf("__");
333  if (suffix_idx == -1) {
334  return str;
335  }
336  assert suffix_idx > 0;
337  return str.substring(0, suffix_idx);
338  }
339 
340  //@Deprecated // to be removed before 2.0
341  // public static final SqlFunction LTRIM = SqlLibraryOperators.LTRIM;
342 
343  //@Deprecated // to be removed before 2.0
344  // public static final SqlFunction RTRIM = SqlLibraryOperators.RTRIM;
345 
347  extends SqlArrayValueConstructor {
348  @Override
349  protected RelDataType getComponentType(
350  RelDataTypeFactory typeFactory, List<RelDataType> argTypes) {
351  if (argTypes.isEmpty()) {
352  return typeFactory.createSqlType(SqlTypeName.NULL);
353  }
354  return super.getComponentType(typeFactory, argTypes);
355  }
356 
357  @Override
358  public boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure) {
359  if (callBinding.operands().isEmpty()) {
360  return true;
361  }
362  return super.checkOperandTypes(callBinding, throwOnFailure);
363  }
364  }
365 
369  public static class RampFunction extends SqlFunction {
370  public RampFunction() {
371  super("RAMP",
372  SqlKind.OTHER_FUNCTION,
373  null,
374  null,
375  OperandTypes.NUMERIC,
376  SqlFunctionCategory.USER_DEFINED_FUNCTION);
377  }
378 
379  @Override
380  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
381  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
382  return typeFactory.builder().add("I", SqlTypeName.INTEGER).build();
383  }
384  }
385 
389  public static class DedupFunction extends SqlFunction {
390  public DedupFunction() {
391  super("DEDUP",
392  SqlKind.OTHER_FUNCTION,
393  null,
394  null,
395  OperandTypes.VARIADIC,
396  SqlFunctionCategory.USER_DEFINED_FUNCTION);
397  }
398 
399  @Override
400  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
401  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
402  return typeFactory.builder().add("NAME", SqlTypeName.VARCHAR, 1024).build();
403  }
404  }
405 
410  public static class MyUDFFunction extends SqlFunction {
411  public MyUDFFunction() {
412  super("MyUDF",
413  SqlKind.OTHER_FUNCTION,
414  null,
415  null,
416  OperandTypes.STRING_STRING,
417  SqlFunctionCategory.SYSTEM);
418  }
419 
420  @Override
421  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
422  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
423  return typeFactory.createSqlType(SqlTypeName.BIGINT);
424  }
425  }
426 
427  /* Postgres-style UNNEST */
428  public static class PgUnnest extends SqlFunction {
429  public PgUnnest() {
430  super("PG_UNNEST",
431  SqlKind.OTHER_FUNCTION,
432  null,
433  null,
434  OperandTypes.ARRAY,
435  SqlFunctionCategory.SYSTEM);
436  }
437 
438  @Override
439  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
440  assert opBinding.getOperandCount() == 1;
441  RelDataType elem_type = opBinding.getOperandType(0).getComponentType();
442  assert elem_type != null;
443  return elem_type;
444  }
445  }
446 
447  /* ANY qualifier */
448  public static class Any extends SqlFunction {
449  public Any() {
450  super("PG_ANY",
451  SqlKind.OTHER_FUNCTION,
452  null,
453  null,
454  OperandTypes.ARRAY,
455  SqlFunctionCategory.SYSTEM);
456  }
457 
458  @Override
459  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
460  assert opBinding.getOperandCount() == 1;
461  RelDataType elem_type = opBinding.getOperandType(0).getComponentType();
462  assert elem_type != null;
463  return elem_type;
464  }
465  }
466 
467  /* ALL qualifier */
468  public static class All extends SqlFunction {
469  public All() {
470  super("PG_ALL",
471  SqlKind.OTHER_FUNCTION,
472  null,
473  null,
474  OperandTypes.ARRAY,
475  SqlFunctionCategory.SYSTEM);
476  }
477 
478  @Override
479  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
480  assert opBinding.getOperandCount() == 1;
481  RelDataType elem_type = opBinding.getOperandType(0).getComponentType();
482  assert elem_type != null;
483  return elem_type;
484  }
485  }
486 
487  /* NOW() */
488  public static class Now extends SqlFunction {
489  public Now() {
490  super("NOW",
491  SqlKind.OTHER_FUNCTION,
492  null,
493  null,
494  OperandTypes.NILADIC,
495  SqlFunctionCategory.SYSTEM);
496  }
497 
498  @Override
499  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
500  assert opBinding.getOperandCount() == 0;
501  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
502  return typeFactory.createSqlType(SqlTypeName.TIMESTAMP);
503  }
504  }
505 
506  /* DATETIME */
507  public static class Datetime extends SqlFunction {
508  public Datetime() {
509  super("DATETIME",
510  SqlKind.OTHER_FUNCTION,
511  null,
512  null,
513  OperandTypes.STRING,
514  SqlFunctionCategory.SYSTEM);
515  }
516 
517  @Override
518  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
519  assert opBinding.getOperandCount() == 1;
520  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
521  return typeFactory.createSqlType(
522  SqlTypeName.TIMESTAMP, opBinding.getOperandType(0).getPrecision());
523  }
524  }
525 
526  /* Postgres-style EXTRACT */
527  public static class PgExtract extends SqlFunction {
528  public PgExtract() {
529  super("PG_EXTRACT",
530  SqlKind.OTHER_FUNCTION,
531  null,
532  null,
533  OperandTypes.family(SqlTypeFamily.STRING, SqlTypeFamily.DATETIME),
534  SqlFunctionCategory.SYSTEM);
535  }
536 
537  @Override
538  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
539  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
540  return typeFactory.createTypeWithNullability(
541  typeFactory.createSqlType(SqlTypeName.BIGINT),
542  opBinding.getOperandType(1).isNullable());
543  }
544  }
545 
546  public static class Datepart extends SqlFunction {
547  public Datepart() {
548  super("DATEPART",
549  SqlKind.OTHER_FUNCTION,
550  null,
551  null,
552  OperandTypes.family(SqlTypeFamily.STRING, SqlTypeFamily.DATETIME),
553  SqlFunctionCategory.TIMEDATE);
554  }
555 
556  @Override
557  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
558  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
559  return typeFactory.createTypeWithNullability(
560  typeFactory.createSqlType(SqlTypeName.BIGINT),
561  opBinding.getOperandType(1).isNullable());
562  }
563  }
564 
565  public static class Dateadd extends SqlFunction {
566  public Dateadd() {
567  super("DATEADD",
568  SqlKind.OTHER_FUNCTION,
569  null,
570  null,
571  OperandTypes.family(SqlTypeFamily.STRING,
572  SqlTypeFamily.INTEGER,
573  SqlTypeFamily.DATETIME),
574  SqlFunctionCategory.TIMEDATE);
575  }
576 
577  @Override
578  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
579  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
580  return typeFactory.createTypeWithNullability(
581  typeFactory.createSqlType(
582  SqlTypeName.TIMESTAMP, opBinding.getOperandType(2).getPrecision()),
583  opBinding.getOperandType(2).isNullable());
584  }
585  }
586 
587  public static class Datediff extends SqlFunction {
588  public Datediff() {
589  super("DATEDIFF",
590  SqlKind.OTHER_FUNCTION,
591  null,
592  null,
593  OperandTypes.family(SqlTypeFamily.STRING,
594  SqlTypeFamily.DATETIME,
595  SqlTypeFamily.DATETIME),
596  SqlFunctionCategory.TIMEDATE);
597  }
598 
599  @Override
600  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
601  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
602  return typeFactory.createTypeWithNullability(
603  typeFactory.createSqlType(SqlTypeName.BIGINT),
604  opBinding.getOperandType(1).isNullable()
605  || opBinding.getOperandType(2).isNullable());
606  }
607  }
608 
609  /* Postgres-style DATE_TRUNC */
610  public static class PgDateTrunc extends SqlFunction {
611  public PgDateTrunc() {
612  super("PG_DATE_TRUNC",
613  SqlKind.OTHER_FUNCTION,
614  null,
615  null,
616  OperandTypes.family(SqlTypeFamily.STRING, SqlTypeFamily.DATETIME),
617  SqlFunctionCategory.SYSTEM);
618  }
619 
620  @Override
621  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
622  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
623  return typeFactory.createTypeWithNullability(
624  typeFactory.createSqlType(
625  SqlTypeName.TIMESTAMP, opBinding.getOperandType(1).getPrecision()),
626  opBinding.getOperandType(1).isNullable());
627  }
628  }
629 
630  public static class Length extends SqlFunction {
631  public Length() {
632  super("LENGTH",
633  SqlKind.OTHER_FUNCTION,
634  null,
635  null,
636  OperandTypes.STRING,
637  SqlFunctionCategory.SYSTEM);
638  }
639 
640  @Override
641  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
642  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
643  return typeFactory.createSqlType(SqlTypeName.INTEGER);
644  }
645  }
646 
647  public static class CharLength extends SqlFunction {
648  public CharLength() {
649  super("CHAR_LENGTH",
650  SqlKind.OTHER_FUNCTION,
651  null,
652  null,
653  OperandTypes.STRING,
654  SqlFunctionCategory.SYSTEM);
655  }
656 
657  @Override
658  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
659  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
660  return typeFactory.createSqlType(SqlTypeName.INTEGER);
661  }
662  }
663 
664  public static class KeyForString extends SqlFunction {
665  public KeyForString() {
666  super("KEY_FOR_STRING",
667  SqlKind.OTHER_FUNCTION,
668  null,
669  null,
670  OperandTypes.STRING,
671  SqlFunctionCategory.SYSTEM);
672  }
673 
674  @Override
675  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
676  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
677  return typeFactory.createTypeWithNullability(
678  typeFactory.createSqlType(SqlTypeName.INTEGER),
679  opBinding.getOperandType(0).isNullable());
680  }
681  }
682 
683  public static class SampleRatio extends SqlFunction {
684  public SampleRatio() {
685  super("SAMPLE_RATIO",
686  SqlKind.OTHER_FUNCTION,
687  null,
688  null,
689  OperandTypes.family(signature()),
690  SqlFunctionCategory.SYSTEM);
691  }
692 
693  @Override
694  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
695  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
696  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
697  }
698 
699  private static java.util.List<SqlTypeFamily> signature() {
700  java.util.ArrayList<SqlTypeFamily> families =
701  new java.util.ArrayList<SqlTypeFamily>();
702  families.add(SqlTypeFamily.NUMERIC);
703  return families;
704  }
705  }
706 
707  public static class WidthBucket extends SqlFunction {
708  public WidthBucket() {
709  super("WIDTH_BUCKET",
710  SqlKind.OTHER_FUNCTION,
711  null,
712  null,
713  OperandTypes.family(signature()),
714  SqlFunctionCategory.SYSTEM);
715  }
716 
717  @Override
718  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
719  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
720  return typeFactory.createTypeWithNullability(
721  typeFactory.createSqlType(SqlTypeName.INTEGER), /*nullable=*/true);
722  }
723 
724  private static java.util.List<SqlTypeFamily> signature() {
725  java.util.ArrayList<SqlTypeFamily> families =
726  new java.util.ArrayList<SqlTypeFamily>();
727  families.add(SqlTypeFamily.NUMERIC);
728  families.add(SqlTypeFamily.NUMERIC);
729  families.add(SqlTypeFamily.NUMERIC);
730  families.add(SqlTypeFamily.INTEGER);
731  return families;
732  }
733  }
734 
735  public static class LeadInFrame extends SqlLeadLag {
736  public LeadInFrame() {
737  super("LEAD_IN_FRAME", SqlKind.LEAD);
738  }
739  }
740 
741  public static class LagInFrame extends SqlLeadLag {
742  public LagInFrame() {
743  super("LAG_IN_FRAME", SqlKind.LAG);
744  }
745  }
746 
747  public static class NthValueInFrame extends SqlNthValueInFrame {
748  public NthValueInFrame() {
749  super("NTH_VALUE_IN_FRAME");
750  }
751  }
752 
753  public static class ArrayLength extends SqlFunction {
754  public ArrayLength() {
755  super("ARRAY_LENGTH",
756  SqlKind.OTHER_FUNCTION,
757  null,
758  null,
759  OperandTypes.ARRAY,
760  SqlFunctionCategory.SYSTEM);
761  }
762 
763  @Override
764  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
765  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
766  return typeFactory.createSqlType(SqlTypeName.INTEGER);
767  }
768  }
769 
770  public static class PgILike extends SqlFunction {
771  public PgILike() {
772  super("PG_ILIKE",
773  SqlKind.OTHER_FUNCTION,
774  null,
775  null,
776  OperandTypes.family(getSignatureFamilies(), new EscapeOptional()),
777  SqlFunctionCategory.SYSTEM);
778  }
779 
780  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
781  java.util.ArrayList<SqlTypeFamily> families =
782  new java.util.ArrayList<SqlTypeFamily>();
783  families.add(SqlTypeFamily.STRING);
784  families.add(SqlTypeFamily.STRING);
785  families.add(SqlTypeFamily.STRING);
786  return families;
787  }
788 
789  private static class EscapeOptional
790  implements java.util.function.Predicate<Integer>, Predicate<Integer> {
791  @Override
792  public boolean test(Integer t) {
793  return apply(t);
794  }
795 
796  @Override
797  public boolean apply(Integer t) {
798  return t == 2;
799  }
800  }
801 
802  @Override
803  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
804  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
805  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
806  }
807  }
808 
809  public static class RegexpLike extends SqlFunction {
810  public RegexpLike() {
811  super("REGEXP_LIKE",
812  SqlKind.OTHER_FUNCTION,
813  null,
814  null,
815  OperandTypes.family(getSignatureFamilies(), new EscapeOptional()),
816  SqlFunctionCategory.SYSTEM);
817  }
818 
819  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
820  java.util.ArrayList<SqlTypeFamily> families =
821  new java.util.ArrayList<SqlTypeFamily>();
822  families.add(SqlTypeFamily.STRING);
823  families.add(SqlTypeFamily.STRING);
824  families.add(SqlTypeFamily.STRING);
825  return families;
826  }
827 
828  private static class EscapeOptional
829  implements java.util.function.Predicate<Integer>, Predicate<Integer> {
830  @Override
831  public boolean test(Integer t) {
832  return apply(t);
833  }
834 
835  public boolean apply(Integer t) {
836  return t == 2;
837  }
838  }
839 
840  @Override
841  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
842  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
843  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
844  }
845  }
846 
847  public static class LeftRightTrim extends SqlFunction {
848  public LeftRightTrim(final String name, final SqlKind kind) {
849  super(name,
850  kind,
851  ReturnTypes.ARG0.andThen(SqlTypeTransforms.TO_NULLABLE)
852  .andThen(SqlTypeTransforms.TO_VARYING),
853  null,
854  OperandTypes.and(
855  OperandTypes.family(SqlTypeFamily.STRING, SqlTypeFamily.STRING),
856  new SameOperandTypeChecker(2) {
857  @Override
858  protected List<Integer> getOperandList(int operandCount) {
859  return ImmutableList.of(0, 1);
860  }
861  }),
862  SqlFunctionCategory.STRING);
863  }
864 
865  @Override
866  public SqlCall createCall(@Nullable SqlLiteral functionQualifier,
867  SqlParserPos pos,
868  @Nullable SqlNode... operands) {
869  assert functionQualifier == null;
870  switch (operands.length) {
871  case 1:
872  operands = new SqlNode[] {operands[0], SqlLiteral.createCharString(" ", pos)};
873  break;
874  case 2:
875  if (operands[1] == null) {
876  operands[1] = SqlLiteral.createCharString(" ", pos);
877  }
878  operands = new SqlNode[] {operands[0], operands[1]};
879  break;
880  default:
881  throw new IllegalArgumentException(
882  "Invalid operand count " + Arrays.toString(operands));
883  }
884  return super.createCall(functionQualifier, pos, operands);
885  }
886 
887  @Override
888  public boolean requiresCreate(List<SqlNode> operands) {
889  // if there is only 1 Operand, the code will be creating 'defaults'
890  return (operands.size() == 1);
891  }
892  }
893 
894  public static class LTrim extends LeftRightTrim {
895  public LTrim() {
896  super("LTRIM", SqlKind.LTRIM);
897  }
898  }
899  public static class RTrim extends LeftRightTrim {
900  public RTrim() {
901  super("RTRIM", SqlKind.RTRIM);
902  }
903  }
904  public static class LeftRightPad extends SqlFunction {
905  public LeftRightPad(final String name) {
906  super(name,
907  SqlKind.OTHER_FUNCTION,
908  ReturnTypes.ARG0.andThen(SqlTypeTransforms.TO_NULLABLE)
909  .andThen(SqlTypeTransforms.TO_VARYING),
910  null,
911  OperandTypes.and(OperandTypes.family(SqlTypeFamily.STRING,
912  SqlTypeFamily.INTEGER,
913  SqlTypeFamily.STRING),
914  new SameOperandTypeChecker(3) {
915  @Override
916  protected List<Integer> getOperandList(int operandCount) {
917  return ImmutableList.of(0, 2);
918  }
919  }),
920  SqlFunctionCategory.STRING);
921  }
922 
923  @Override
924  public SqlCall createCall(@Nullable SqlLiteral functionQualifier,
925  SqlParserPos pos,
926  @Nullable SqlNode... operands) {
927  assert functionQualifier == null;
928  switch (operands.length) {
929  case 2:
930  operands = new SqlNode[] {
931  operands[0], operands[1], SqlLiteral.createCharString(" ", pos)};
932  break;
933  case 3:
934  if (operands[2] == null) {
935  operands[2] = SqlLiteral.createCharString(" ", pos);
936  }
937  operands = new SqlNode[] {operands[0], operands[1], operands[2]};
938  break;
939  default:
940  throw new IllegalArgumentException(
941  "Invalid operand count " + Arrays.toString(operands));
942  }
943  return super.createCall(functionQualifier, pos, operands);
944  }
945 
946  @Override
947  public boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure) {
948  if (!super.checkOperandTypes(callBinding, throwOnFailure)) {
949  return false;
950  }
951  switch (kind) {
952  case TRIM:
953  return SqlTypeUtil.isCharTypeComparable(callBinding,
954  ImmutableList.of(callBinding.operand(0), callBinding.operand(2)),
955  throwOnFailure);
956  default:
957  return true;
958  }
959  }
960 
961  @Override
962  public boolean requiresCreate(List<SqlNode> operands) {
963  // if there are only 2 Operands, the code will be creating 'defaults'
964  return (operands.size() == 2);
965  }
966  }
967 
968  public static class LPad extends LeftRightPad {
969  public LPad() {
970  super("LPAD");
971  }
972  }
973  public static class RPad extends LeftRightPad {
974  public RPad() {
975  super("RPAD");
976  }
977  }
978 
979  public static class SplitPart extends SqlFunction {
980  public SplitPart() {
981  super("SPLIT_PART",
982  SqlKind.OTHER_FUNCTION,
983  null,
984  null,
985  OperandTypes.family(getSignatureFamilies()),
987  }
988 
989  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
990  java.util.ArrayList<SqlTypeFamily> families =
991  new java.util.ArrayList<SqlTypeFamily>();
992  families.add(SqlTypeFamily.STRING);
993  families.add(SqlTypeFamily.STRING);
994  families.add(SqlTypeFamily.INTEGER);
995  return families;
996  }
997 
998  @Override
999  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1000  return opBinding.getOperandType(0);
1001  }
1002  }
1003 
1004  public static class Replace extends SqlFunction {
1005  public Replace() {
1006  super("REPLACE",
1007  SqlKind.OTHER_FUNCTION,
1008  null,
1009  null,
1010  OperandTypes.family(getSignatureFamilies()),
1012  }
1013 
1014  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
1015  java.util.ArrayList<SqlTypeFamily> families =
1016  new java.util.ArrayList<SqlTypeFamily>();
1017  families.add(SqlTypeFamily.STRING);
1018  families.add(SqlTypeFamily.STRING);
1019  families.add(SqlTypeFamily.STRING);
1020  return families;
1021  }
1022 
1023  @Override
1024  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1025  return opBinding.getOperandType(0);
1026  }
1027 
1028  @Override
1029  public SqlCall createCall(@Nullable SqlLiteral functionQualifier,
1030  SqlParserPos pos,
1031  @Nullable SqlNode... operands) {
1032  assert functionQualifier == null;
1033  switch (operands.length) {
1034  case 2:
1035  operands = new SqlNode[] {
1036  operands[0], operands[1], SqlLiteral.createCharString("", pos)};
1037  break;
1038  case 3:
1039  break;
1040  default:
1041  throw new IllegalArgumentException(
1042  "Invalid operand count " + Arrays.toString(operands));
1043  }
1044  return super.createCall(functionQualifier, pos, operands);
1045  }
1046 
1047  @Override
1048  public boolean requiresCreate(List<SqlNode> operands) {
1049  // if there are only 2 Operands, the code will be creating 'defaults'
1050  return (operands.size() == 2);
1051  }
1052  }
1053  public static class Reverse extends SqlFunction {
1054  public Reverse() {
1055  super("REVERSE",
1056  SqlKind.OTHER_FUNCTION,
1057  null,
1058  null,
1059  OperandTypes.family(getSignatureFamilies()),
1061  }
1062 
1063  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
1064  java.util.ArrayList<SqlTypeFamily> families =
1065  new java.util.ArrayList<SqlTypeFamily>();
1066  families.add(SqlTypeFamily.STRING);
1067  return families;
1068  }
1069 
1070  @Override
1071  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1072  return opBinding.getOperandType(0);
1073  }
1074  }
1075  public static class Repeat extends SqlFunction {
1076  public Repeat() {
1077  super("REPEAT",
1078  SqlKind.OTHER_FUNCTION,
1079  null,
1080  null,
1081  OperandTypes.family(getSignatureFamilies()),
1083  }
1084 
1085  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
1086  java.util.ArrayList<SqlTypeFamily> families =
1087  new java.util.ArrayList<SqlTypeFamily>();
1088  families.add(SqlTypeFamily.STRING);
1089  families.add(SqlTypeFamily.INTEGER);
1090  return families;
1091  }
1092 
1093  @Override
1094  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1095  return opBinding.getOperandType(0);
1096  }
1097  }
1098 
1099  public static class RegexpReplace extends SqlFunction {
1100  public RegexpReplace() {
1101  super("REGEXP_REPLACE",
1102  SqlKind.OTHER_FUNCTION,
1103  null,
1104  null,
1105  OperandTypes.family(getSignatureFamilies()),
1107  }
1108 
1109  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
1110  java.util.ArrayList<SqlTypeFamily> families =
1111  new java.util.ArrayList<SqlTypeFamily>();
1112  families.add(SqlTypeFamily.STRING);
1113  families.add(SqlTypeFamily.STRING);
1114  families.add(SqlTypeFamily.STRING);
1115  families.add(SqlTypeFamily.INTEGER);
1116  families.add(SqlTypeFamily.INTEGER);
1117  families.add(SqlTypeFamily.STRING);
1118  return families;
1119  }
1120 
1121  @Override
1122  public SqlCall createCall(@Nullable SqlLiteral functionQualifier,
1123  SqlParserPos pos,
1124  @Nullable SqlNode... operands) {
1125  assert functionQualifier == null;
1126  final int num_operands = operands.length;
1127  if (num_operands < 2 || num_operands > 6) {
1128  throw new IllegalArgumentException(
1129  "Invalid operand count " + Arrays.toString(operands));
1130  }
1131  SqlNode[] new_operands = new SqlNode[6];
1132  // operand string
1133  new_operands[0] = operands[0];
1134  // pattern
1135  new_operands[1] = operands[1];
1136  // replacement
1137  if (num_operands < 3 || operands[2] == null) {
1138  new_operands[2] = SqlLiteral.createCharString("", pos);
1139  } else {
1140  new_operands[2] = operands[2];
1141  }
1142  // position
1143  if (num_operands < 4 || operands[3] == null) {
1144  new_operands[3] = SqlLiteral.createExactNumeric("1", pos);
1145  } else {
1146  new_operands[3] = operands[3];
1147  }
1148  // occurrence
1149  if (num_operands < 5 || operands[4] == null) {
1150  new_operands[4] = SqlLiteral.createExactNumeric("0", pos);
1151  } else {
1152  new_operands[4] = operands[4];
1153  }
1154  // parameters
1155  if (num_operands < 6 || operands[5] == null) {
1156  new_operands[5] = SqlLiteral.createCharString("c", pos);
1157  } else {
1158  new_operands[5] = operands[5];
1159  }
1160  return super.createCall(functionQualifier, pos, new_operands);
1161  }
1162 
1163  @Override
1164  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1165  return opBinding.getOperandType(0);
1166  }
1167  }
1168 
1169  public static class RegexpSubstr extends SqlFunction {
1170  public RegexpSubstr() {
1171  super("REGEXP_SUBSTR",
1172  SqlKind.OTHER_FUNCTION,
1173  null,
1174  null,
1175  OperandTypes.family(getSignatureFamilies()),
1177  }
1178 
1179  public RegexpSubstr(final String alias) {
1180  super(alias,
1181  SqlKind.OTHER_FUNCTION,
1182  null,
1183  null,
1184  OperandTypes.family(getSignatureFamilies()),
1185  SqlFunctionCategory.SYSTEM);
1186  }
1187 
1188  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
1189  java.util.ArrayList<SqlTypeFamily> families =
1190  new java.util.ArrayList<SqlTypeFamily>();
1191  families.add(SqlTypeFamily.STRING);
1192  families.add(SqlTypeFamily.STRING);
1193  families.add(SqlTypeFamily.INTEGER);
1194  families.add(SqlTypeFamily.INTEGER);
1195  families.add(SqlTypeFamily.STRING);
1196  families.add(SqlTypeFamily.INTEGER);
1197  return families;
1198  }
1199 
1200  @Override
1201  public SqlCall createCall(@Nullable SqlLiteral functionQualifier,
1202  SqlParserPos pos,
1203  @Nullable SqlNode... operands) {
1204  assert functionQualifier == null;
1205  final int num_operands = operands.length;
1206  if (num_operands < 2 || num_operands > 6) {
1207  throw new IllegalArgumentException(
1208  "Invalid operand count " + Arrays.toString(operands));
1209  }
1210  SqlNode[] new_operands = new SqlNode[6];
1211 
1212  // operand string (required)
1213  new_operands[0] = operands[0];
1214  // pattern (required)
1215  new_operands[1] = operands[1];
1216  // start position
1217  if (num_operands < 3 || operands[2] == null) {
1218  new_operands[2] = SqlLiteral.createExactNumeric("1", pos);
1219  } else {
1220  new_operands[2] = operands[2];
1221  }
1222  // match occurrence
1223  if (num_operands < 4 || operands[3] == null) {
1224  new_operands[3] = SqlLiteral.createExactNumeric("1", pos);
1225  } else {
1226  new_operands[3] = operands[3];
1227  }
1228  // regex params (default 'c' = case sensitive)
1229  if (num_operands < 5 || operands[4] == null) {
1230  new_operands[4] = SqlLiteral.createCharString("c", pos);
1231  } else {
1232  new_operands[4] = operands[4];
1233  }
1234  // Sub-match occurrence, valid with regex param 'e'
1235  if (num_operands < 6 || operands[5] == null) {
1236  new_operands[5] = SqlLiteral.createExactNumeric("1", pos);
1237  } else {
1238  new_operands[5] = operands[5];
1239  }
1240  return super.createCall(functionQualifier, pos, new_operands);
1241  }
1242 
1243  @Override
1244  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1245  return opBinding.getOperandType(0);
1246  }
1247  }
1248 
1249  public static class RegexpMatch extends RegexpSubstr {
1250  public RegexpMatch() {
1251  super("REGEXP_MATCH");
1252  }
1253  }
1254  public static class Base64Encode extends SqlFunction {
1255  public Base64Encode() {
1256  super("BASE64_ENCODE",
1257  SqlKind.OTHER_FUNCTION,
1258  null,
1259  null,
1260  OperandTypes.family(getSignatureFamilies()),
1262  }
1263 
1264  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
1265  java.util.ArrayList<SqlTypeFamily> families =
1266  new java.util.ArrayList<SqlTypeFamily>();
1267  families.add(SqlTypeFamily.STRING);
1268  return families;
1269  }
1270 
1271  @Override
1272  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1273  return opBinding.getOperandType(0);
1274  }
1275  }
1276 
1277  public static class Base64Decode extends SqlFunction {
1278  public Base64Decode() {
1279  super("BASE64_DECODE",
1280  SqlKind.OTHER_FUNCTION,
1281  null,
1282  null,
1283  OperandTypes.family(getSignatureFamilies()),
1285  }
1286 
1287  private static java.util.List<SqlTypeFamily> getSignatureFamilies() {
1288  java.util.ArrayList<SqlTypeFamily> families =
1289  new java.util.ArrayList<SqlTypeFamily>();
1290  families.add(SqlTypeFamily.STRING);
1291  return families;
1292  }
1293 
1294  @Override
1295  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1296  return opBinding.getOperandType(0);
1297  }
1298  }
1299 
1300  public static class TryCast extends SqlFunction {
1301  //~ Instance fields --------------------------------------------------------
1302 
1303  public TryCast() {
1304  super("TRY_CAST",
1305  SqlKind.OTHER_FUNCTION,
1306  null,
1307  InferTypes.FIRST_KNOWN,
1308  null,
1309  SqlFunctionCategory.SYSTEM);
1310  }
1311 
1312  //~ Methods ----------------------------------------------------------------
1313 
1314  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1315  assert opBinding.getOperandCount() == 2;
1316  RelDataType ret = opBinding.getOperandType(1);
1317  RelDataType firstType = opBinding.getOperandType(0);
1318  ret = opBinding.getTypeFactory().createTypeWithNullability(
1319  ret, firstType.isNullable());
1320  if (opBinding instanceof SqlCallBinding) {
1321  SqlCallBinding callBinding = (SqlCallBinding) opBinding;
1322  SqlNode operand0 = callBinding.operand(0);
1323 
1324  // dynamic parameters and null constants need their types assigned
1325  // to them using the type they are casted to.
1326  if (((operand0 instanceof SqlLiteral)
1327  && (((SqlLiteral) operand0).getValue() == null))
1328  || (operand0 instanceof SqlDynamicParam)) {
1329  final SqlValidatorImpl validator =
1330  (SqlValidatorImpl) callBinding.getValidator();
1331  validator.setValidatedNodeType(operand0, ret);
1332  }
1333  }
1334  return ret;
1335  }
1336 
1337  public String getSignatureTemplate(final int operandsCount) {
1338  assert operandsCount == 2;
1339  return "{0}({1} AS {2})";
1340  }
1341 
1342  public SqlOperandCountRange getOperandCountRange() {
1343  return SqlOperandCountRanges.of(2);
1344  }
1345 
1351  public boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure) {
1352  final SqlNode left = callBinding.operand(0);
1353  final SqlNode right = callBinding.operand(1);
1354  if (SqlUtil.isNullLiteral(left, false) || left instanceof SqlDynamicParam) {
1355  return true;
1356  }
1357  RelDataType validatedNodeType =
1358  callBinding.getValidator().getValidatedNodeType(left);
1359  RelDataType returnType =
1360  callBinding.getValidator().deriveType(callBinding.getScope(), right);
1361  if (!SqlTypeUtil.canCastFrom(returnType, validatedNodeType, true)) {
1362  if (throwOnFailure) {
1363  throw callBinding.newError(RESOURCE.cannotCastValue(
1364  validatedNodeType.toString(), returnType.toString()));
1365  }
1366  return false;
1367  }
1368  if (SqlTypeUtil.areCharacterSetsMismatched(validatedNodeType, returnType)) {
1369  if (throwOnFailure) {
1370  // Include full type string to indicate character
1371  // set mismatch.
1372  throw callBinding.newError(RESOURCE.cannotCastValue(
1373  validatedNodeType.getFullTypeString(), returnType.getFullTypeString()));
1374  }
1375  return false;
1376  }
1377  return true;
1378  }
1379 
1380  public SqlSyntax getSyntax() {
1381  return SqlSyntax.FUNCTION;
1382  }
1383 
1384  public void unparse(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) {
1385  assert call.operandCount() == 2;
1386  final SqlWriter.Frame frame = writer.startFunCall(getName());
1387  call.operand(0).unparse(writer, 0, 0);
1388  writer.sep("AS");
1389  if (call.operand(1) instanceof SqlIntervalQualifier) {
1390  writer.sep("INTERVAL");
1391  }
1392  call.operand(1).unparse(writer, 0, 0);
1393  writer.endFunCall(frame);
1394  }
1395  }
1396 
1397  public static class Likely extends SqlFunction {
1398  public Likely() {
1399  super("LIKELY",
1400  SqlKind.OTHER_FUNCTION,
1401  null,
1402  null,
1403  OperandTypes.BOOLEAN,
1404  SqlFunctionCategory.SYSTEM);
1405  }
1406 
1407  @Override
1408  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1409  return opBinding.getOperandType(0);
1410  }
1411  }
1412 
1413  public static class Unlikely extends SqlFunction {
1414  public Unlikely() {
1415  super("UNLIKELY",
1416  SqlKind.OTHER_FUNCTION,
1417  null,
1418  null,
1419  OperandTypes.BOOLEAN,
1420  SqlFunctionCategory.SYSTEM);
1421  }
1422 
1423  @Override
1424  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1425  return opBinding.getOperandType(0);
1426  }
1427  }
1428 
1429  public static class Sign extends SqlFunction {
1430  public Sign() {
1431  super("SIGN",
1432  SqlKind.OTHER_FUNCTION,
1433  null,
1434  null,
1435  OperandTypes.NUMERIC,
1436  SqlFunctionCategory.NUMERIC);
1437  }
1438 
1439  @Override
1440  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1441  return opBinding.getOperandType(0);
1442  }
1443  }
1444 
1445  static class Truncate extends SqlFunction {
1447  super("TRUNCATE",
1448  SqlKind.OTHER_FUNCTION,
1449  null,
1450  null,
1451  OperandTypes.family(signature()),
1452  SqlFunctionCategory.NUMERIC);
1453  }
1454 
1455  @Override
1456  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1457  assert opBinding.getOperandCount() == 2;
1458  return opBinding.getOperandType(0);
1459  }
1460 
1461  private static java.util.List<SqlTypeFamily> signature() {
1462  java.util.List<SqlTypeFamily> truncate_sig =
1463  new java.util.ArrayList<SqlTypeFamily>();
1464  truncate_sig.add(SqlTypeFamily.NUMERIC);
1465  truncate_sig.add(SqlTypeFamily.INTEGER);
1466  return truncate_sig;
1467  }
1468  }
1469 
1470  static class ST_IsEmpty extends SqlFunction {
1472  super("ST_IsEmpty",
1473  SqlKind.OTHER_FUNCTION,
1474  null,
1475  null,
1476  OperandTypes.family(signature()),
1477  SqlFunctionCategory.SYSTEM);
1478  }
1479 
1480  @Override
1481  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1482  assert opBinding.getOperandCount() == 1;
1483  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1484  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
1485  }
1486 
1487  private static java.util.List<SqlTypeFamily> signature() {
1488  java.util.List<SqlTypeFamily> st_isempty_sig =
1489  new java.util.ArrayList<SqlTypeFamily>();
1490  st_isempty_sig.add(SqlTypeFamily.ANY);
1491  return st_isempty_sig;
1492  }
1493  }
1494 
1495  static class ST_IsValid extends SqlFunction {
1497  super("ST_IsValid",
1498  SqlKind.OTHER_FUNCTION,
1499  null,
1500  null,
1501  OperandTypes.family(signature()),
1502  SqlFunctionCategory.SYSTEM);
1503  }
1504 
1505  @Override
1506  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1507  assert opBinding.getOperandCount() == 1;
1508  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1509  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
1510  }
1511 
1512  private static java.util.List<SqlTypeFamily> signature() {
1513  java.util.List<SqlTypeFamily> st_isvalid_sig =
1514  new java.util.ArrayList<SqlTypeFamily>();
1515  st_isvalid_sig.add(SqlTypeFamily.ANY);
1516  return st_isvalid_sig;
1517  }
1518  }
1519 
1520  static class ST_Contains extends SqlFunction {
1522  super("ST_Contains",
1523  SqlKind.OTHER_FUNCTION,
1524  null,
1525  null,
1526  OperandTypes.family(signature()),
1527  SqlFunctionCategory.SYSTEM);
1528  }
1529 
1530  @Override
1531  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1532  assert opBinding.getOperandCount() == 2;
1533  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1534  return typeFactory.createTypeWithNullability(
1535  typeFactory.createSqlType(SqlTypeName.BOOLEAN),
1536  opBinding.getOperandType(0).isNullable()
1537  || opBinding.getOperandType(1).isNullable());
1538  }
1539 
1540  private static java.util.List<SqlTypeFamily> signature() {
1541  java.util.List<SqlTypeFamily> st_contains_sig =
1542  new java.util.ArrayList<SqlTypeFamily>();
1543  st_contains_sig.add(SqlTypeFamily.ANY);
1544  st_contains_sig.add(SqlTypeFamily.ANY);
1545  return st_contains_sig;
1546  }
1547  }
1548 
1549  static class ST_Equals extends SqlFunction {
1551  super("ST_Equals",
1552  SqlKind.OTHER_FUNCTION,
1553  null,
1554  null,
1555  OperandTypes.family(signature()),
1556  SqlFunctionCategory.SYSTEM);
1557  }
1558 
1559  @Override
1560  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1561  assert opBinding.getOperandCount() == 2;
1562  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1563  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
1564  }
1565 
1566  private static java.util.List<SqlTypeFamily> signature() {
1567  java.util.List<SqlTypeFamily> st_equals_sig =
1568  new java.util.ArrayList<SqlTypeFamily>();
1569  st_equals_sig.add(SqlTypeFamily.ANY);
1570  st_equals_sig.add(SqlTypeFamily.ANY);
1571  return st_equals_sig;
1572  }
1573  }
1574 
1575  static class ST_Intersects extends SqlFunction {
1577  super("ST_Intersects",
1578  SqlKind.OTHER_FUNCTION,
1579  null,
1580  null,
1581  OperandTypes.family(signature()),
1582  SqlFunctionCategory.SYSTEM);
1583  }
1584 
1585  @Override
1586  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1587  assert opBinding.getOperandCount() == 2;
1588  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1589  return typeFactory.createTypeWithNullability(
1590  typeFactory.createSqlType(SqlTypeName.BOOLEAN),
1591  opBinding.getOperandType(0).isNullable()
1592  || opBinding.getOperandType(1).isNullable());
1593  }
1594 
1595  private static java.util.List<SqlTypeFamily> signature() {
1596  java.util.List<SqlTypeFamily> st_intersects_sig =
1597  new java.util.ArrayList<SqlTypeFamily>();
1598  st_intersects_sig.add(SqlTypeFamily.ANY);
1599  st_intersects_sig.add(SqlTypeFamily.ANY);
1600  return st_intersects_sig;
1601  }
1602  }
1603 
1604  static class ST_Overlaps extends SqlFunction {
1606  super("ST_Overlaps",
1607  SqlKind.OTHER_FUNCTION,
1608  null,
1609  null,
1610  OperandTypes.family(signature()),
1611  SqlFunctionCategory.SYSTEM);
1612  }
1613 
1614  @Override
1615  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1616  assert opBinding.getOperandCount() == 2;
1617  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1618  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
1619  }
1620 
1621  private static java.util.List<SqlTypeFamily> signature() {
1622  java.util.List<SqlTypeFamily> st_overlaps_sig =
1623  new java.util.ArrayList<SqlTypeFamily>();
1624  st_overlaps_sig.add(SqlTypeFamily.ANY);
1625  st_overlaps_sig.add(SqlTypeFamily.ANY);
1626  return st_overlaps_sig;
1627  }
1628  }
1629 
1630  static class ST_Approx_Overlaps extends SqlFunction {
1632  super("ST_Approx_Overlaps",
1633  SqlKind.OTHER_FUNCTION,
1634  null,
1635  null,
1636  OperandTypes.family(signature()),
1637  SqlFunctionCategory.SYSTEM);
1638  }
1639 
1640  @Override
1641  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1642  assert opBinding.getOperandCount() == 2;
1643  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1644  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
1645  }
1646 
1647  private static java.util.List<SqlTypeFamily> signature() {
1648  java.util.List<SqlTypeFamily> st_overlaps_sig =
1649  new java.util.ArrayList<SqlTypeFamily>();
1650  st_overlaps_sig.add(SqlTypeFamily.ANY);
1651  st_overlaps_sig.add(SqlTypeFamily.ANY);
1652  return st_overlaps_sig;
1653  }
1654  }
1655 
1656  static class ST_Disjoint extends SqlFunction {
1658  super("ST_Disjoint",
1659  SqlKind.OTHER_FUNCTION,
1660  null,
1661  null,
1662  OperandTypes.family(signature()),
1663  SqlFunctionCategory.SYSTEM);
1664  }
1665 
1666  @Override
1667  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1668  assert opBinding.getOperandCount() == 2;
1669  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1670  return typeFactory.createTypeWithNullability(
1671  typeFactory.createSqlType(SqlTypeName.BOOLEAN),
1672  opBinding.getOperandType(0).isNullable()
1673  || opBinding.getOperandType(1).isNullable());
1674  }
1675 
1676  private static java.util.List<SqlTypeFamily> signature() {
1677  java.util.List<SqlTypeFamily> st_disjoint_sig =
1678  new java.util.ArrayList<SqlTypeFamily>();
1679  st_disjoint_sig.add(SqlTypeFamily.ANY);
1680  st_disjoint_sig.add(SqlTypeFamily.ANY);
1681  return st_disjoint_sig;
1682  }
1683  }
1684 
1685  static class ST_Within extends SqlFunction {
1687  super("ST_Within",
1688  SqlKind.OTHER_FUNCTION,
1689  null,
1690  null,
1691  OperandTypes.family(signature()),
1692  SqlFunctionCategory.SYSTEM);
1693  }
1694 
1695  @Override
1696  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1697  assert opBinding.getOperandCount() == 2;
1698  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1699  return typeFactory.createTypeWithNullability(
1700  typeFactory.createSqlType(SqlTypeName.BOOLEAN),
1701  opBinding.getOperandType(0).isNullable()
1702  || opBinding.getOperandType(1).isNullable());
1703  }
1704 
1705  private static java.util.List<SqlTypeFamily> signature() {
1706  java.util.List<SqlTypeFamily> st_within_sig =
1707  new java.util.ArrayList<SqlTypeFamily>();
1708  st_within_sig.add(SqlTypeFamily.ANY);
1709  st_within_sig.add(SqlTypeFamily.ANY);
1710  return st_within_sig;
1711  }
1712  }
1713 
1714  static class ST_DWithin extends SqlFunction {
1716  super("ST_DWithin",
1717  SqlKind.OTHER_FUNCTION,
1718  null,
1719  null,
1720  OperandTypes.family(signature()),
1721  SqlFunctionCategory.SYSTEM);
1722  }
1723 
1724  @Override
1725  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1726  assert opBinding.getOperandCount() == 3;
1727  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1728  return typeFactory.createTypeWithNullability(
1729  typeFactory.createSqlType(SqlTypeName.BOOLEAN),
1730  opBinding.getOperandType(0).isNullable()
1731  || opBinding.getOperandType(1).isNullable()
1732  || opBinding.getOperandType(2).isNullable());
1733  }
1734 
1735  private static java.util.List<SqlTypeFamily> signature() {
1736  java.util.List<SqlTypeFamily> st_dwithin_sig =
1737  new java.util.ArrayList<SqlTypeFamily>();
1738  st_dwithin_sig.add(SqlTypeFamily.ANY);
1739  st_dwithin_sig.add(SqlTypeFamily.ANY);
1740  st_dwithin_sig.add(SqlTypeFamily.NUMERIC);
1741  return st_dwithin_sig;
1742  }
1743  }
1744 
1745  static class ST_DFullyWithin extends SqlFunction {
1747  super("ST_DFullyWithin",
1748  SqlKind.OTHER_FUNCTION,
1749  null,
1750  null,
1751  OperandTypes.family(signature()),
1752  SqlFunctionCategory.SYSTEM);
1753  }
1754 
1755  @Override
1756  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1757  assert opBinding.getOperandCount() == 3;
1758  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1759  return typeFactory.createTypeWithNullability(
1760  typeFactory.createSqlType(SqlTypeName.BOOLEAN),
1761  opBinding.getOperandType(0).isNullable()
1762  || opBinding.getOperandType(1).isNullable()
1763  || opBinding.getOperandType(2).isNullable());
1764  }
1765 
1766  private static java.util.List<SqlTypeFamily> signature() {
1767  java.util.List<SqlTypeFamily> st_dwithin_sig =
1768  new java.util.ArrayList<SqlTypeFamily>();
1769  st_dwithin_sig.add(SqlTypeFamily.ANY);
1770  st_dwithin_sig.add(SqlTypeFamily.ANY);
1771  st_dwithin_sig.add(SqlTypeFamily.NUMERIC);
1772  return st_dwithin_sig;
1773  }
1774  }
1775 
1776  static class ST_Distance extends SqlFunction {
1778  super("ST_Distance",
1779  SqlKind.OTHER_FUNCTION,
1780  null,
1781  null,
1782  OperandTypes.family(signature()),
1783  SqlFunctionCategory.SYSTEM);
1784  }
1785 
1786  @Override
1787  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1788  assert opBinding.getOperandCount() == 2;
1789  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1790  return typeFactory.createTypeWithNullability(
1791  typeFactory.createSqlType(SqlTypeName.DOUBLE),
1792  opBinding.getOperandType(0).isNullable()
1793  || opBinding.getOperandType(1).isNullable());
1794  }
1795 
1796  private static java.util.List<SqlTypeFamily> signature() {
1797  java.util.List<SqlTypeFamily> st_distance_sig =
1798  new java.util.ArrayList<SqlTypeFamily>();
1799  st_distance_sig.add(SqlTypeFamily.ANY);
1800  st_distance_sig.add(SqlTypeFamily.ANY);
1801  return st_distance_sig;
1802  }
1803  }
1804 
1805  static class ST_MaxDistance extends SqlFunction {
1807  super("ST_MaxDistance",
1808  SqlKind.OTHER_FUNCTION,
1809  null,
1810  null,
1811  OperandTypes.family(signature()),
1812  SqlFunctionCategory.SYSTEM);
1813  }
1814 
1815  @Override
1816  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1817  assert opBinding.getOperandCount() == 2;
1818  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1819  return typeFactory.createTypeWithNullability(
1820  typeFactory.createSqlType(SqlTypeName.DOUBLE),
1821  opBinding.getOperandType(0).isNullable()
1822  || opBinding.getOperandType(1).isNullable());
1823  }
1824 
1825  private static java.util.List<SqlTypeFamily> signature() {
1826  java.util.List<SqlTypeFamily> st_maxdistance_sig =
1827  new java.util.ArrayList<SqlTypeFamily>();
1828  st_maxdistance_sig.add(SqlTypeFamily.ANY);
1829  st_maxdistance_sig.add(SqlTypeFamily.ANY);
1830  return st_maxdistance_sig;
1831  }
1832  }
1833 
1834  static class ST_GeogFromText extends SqlFunction {
1836  super("ST_GeogFromText",
1837  SqlKind.OTHER_FUNCTION,
1838  null,
1839  null,
1840  OperandTypes.or(OperandTypes.family(SqlTypeFamily.ANY),
1841  OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.INTEGER)),
1842  SqlFunctionCategory.SYSTEM);
1843  }
1844 
1845  @Override
1846  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1847  assert opBinding.getOperandCount() == 1;
1848  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1849  return typeFactory.createSqlType(SqlTypeName.INTEGER);
1850  }
1851  }
1852 
1853  static class ST_GeomFromText extends SqlFunction {
1855  super("ST_GeomFromText",
1856  SqlKind.OTHER_FUNCTION,
1857  null,
1858  null,
1859  OperandTypes.or(OperandTypes.family(SqlTypeFamily.ANY),
1860  OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.INTEGER)),
1861  SqlFunctionCategory.SYSTEM);
1862  }
1863 
1864  @Override
1865  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1866  assert opBinding.getOperandCount() == 1;
1867  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1868  return typeFactory.createSqlType(SqlTypeName.INTEGER);
1869  }
1870  }
1871 
1872  static class ST_Transform extends SqlFunction {
1874  super("ST_Transform",
1875  SqlKind.OTHER_FUNCTION,
1876  null,
1877  null,
1878  OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.INTEGER),
1879  SqlFunctionCategory.SYSTEM);
1880  }
1881 
1882  @Override
1883  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1884  assert opBinding.getOperandCount() == 1;
1885  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1886  return typeFactory.createTypeWithNullability(
1887  typeFactory.createSqlType(SqlTypeName.INTEGER),
1888  opBinding.getOperandType(0).isNullable());
1889  }
1890  }
1891 
1892  static class ST_X extends SqlFunction {
1893  ST_X() {
1894  super("ST_X",
1895  SqlKind.OTHER_FUNCTION,
1896  null,
1897  null,
1898  OperandTypes.family(SqlTypeFamily.ANY),
1899  SqlFunctionCategory.SYSTEM);
1900  }
1901 
1902  @Override
1903  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1904  assert opBinding.getOperandCount() == 1;
1905  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1906  return typeFactory.createTypeWithNullability(
1907  typeFactory.createSqlType(SqlTypeName.DOUBLE),
1908  opBinding.getOperandType(0).isNullable());
1909  }
1910  }
1911 
1912  static class ST_Y extends SqlFunction {
1913  ST_Y() {
1914  super("ST_Y",
1915  SqlKind.OTHER_FUNCTION,
1916  null,
1917  null,
1918  OperandTypes.family(SqlTypeFamily.ANY),
1919  SqlFunctionCategory.SYSTEM);
1920  }
1921 
1922  @Override
1923  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1924  assert opBinding.getOperandCount() == 1;
1925  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1926  return typeFactory.createTypeWithNullability(
1927  typeFactory.createSqlType(SqlTypeName.DOUBLE),
1928  opBinding.getOperandType(0).isNullable());
1929  }
1930  }
1931 
1932  static class ST_XMin extends SqlFunction {
1934  super("ST_XMin",
1935  SqlKind.OTHER_FUNCTION,
1936  null,
1937  null,
1938  OperandTypes.family(SqlTypeFamily.ANY),
1939  SqlFunctionCategory.SYSTEM);
1940  }
1941 
1942  @Override
1943  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1944  assert opBinding.getOperandCount() == 1;
1945  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1946  return typeFactory.createTypeWithNullability(
1947  typeFactory.createSqlType(SqlTypeName.DOUBLE),
1948  opBinding.getOperandType(0).isNullable());
1949  }
1950  }
1951 
1952  static class ST_XMax extends SqlFunction {
1954  super("ST_XMax",
1955  SqlKind.OTHER_FUNCTION,
1956  null,
1957  null,
1958  OperandTypes.family(SqlTypeFamily.ANY),
1959  SqlFunctionCategory.SYSTEM);
1960  }
1961 
1962  @Override
1963  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1964  assert opBinding.getOperandCount() == 1;
1965  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1966  return typeFactory.createTypeWithNullability(
1967  typeFactory.createSqlType(SqlTypeName.DOUBLE),
1968  opBinding.getOperandType(0).isNullable());
1969  }
1970  }
1971 
1972  static class ST_YMin extends SqlFunction {
1974  super("ST_YMin",
1975  SqlKind.OTHER_FUNCTION,
1976  null,
1977  null,
1978  OperandTypes.family(SqlTypeFamily.ANY),
1979  SqlFunctionCategory.SYSTEM);
1980  }
1981 
1982  @Override
1983  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
1984  assert opBinding.getOperandCount() == 1;
1985  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
1986  return typeFactory.createTypeWithNullability(
1987  typeFactory.createSqlType(SqlTypeName.DOUBLE),
1988  opBinding.getOperandType(0).isNullable());
1989  }
1990  }
1991 
1992  static class ST_YMax extends SqlFunction {
1994  super("ST_YMax",
1995  SqlKind.OTHER_FUNCTION,
1996  null,
1997  null,
1998  OperandTypes.family(SqlTypeFamily.ANY),
1999  SqlFunctionCategory.SYSTEM);
2000  }
2001 
2002  @Override
2003  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2004  assert opBinding.getOperandCount() == 1;
2005  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2006  return typeFactory.createTypeWithNullability(
2007  typeFactory.createSqlType(SqlTypeName.DOUBLE),
2008  opBinding.getOperandType(0).isNullable());
2009  }
2010  }
2011 
2012  static class ST_PointN extends SqlFunction {
2014  super("ST_PointN",
2015  SqlKind.OTHER_FUNCTION,
2016  null,
2017  null,
2018  OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.INTEGER),
2019  SqlFunctionCategory.SYSTEM);
2020  }
2021 
2022  @Override
2023  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2024  assert opBinding.getOperandCount() == 1;
2025  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2026  return typeFactory.createTypeWithNullability(
2027  typeFactory.createSqlType(SqlTypeName.INTEGER),
2028  opBinding.getOperandType(0).isNullable());
2029  }
2030  }
2031 
2032  static class ST_EndPoint extends SqlFunction {
2034  super("ST_EndPoint",
2035  SqlKind.OTHER_FUNCTION,
2036  null,
2037  null,
2038  OperandTypes.family(SqlTypeFamily.ANY),
2039  SqlFunctionCategory.SYSTEM);
2040  }
2041 
2042  @Override
2043  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2044  assert opBinding.getOperandCount() == 1;
2045  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2046  return typeFactory.createTypeWithNullability(
2047  typeFactory.createSqlType(SqlTypeName.INTEGER),
2048  opBinding.getOperandType(0).isNullable());
2049  }
2050  }
2051 
2052  static class ST_StartPoint extends SqlFunction {
2054  super("ST_StartPoint",
2055  SqlKind.OTHER_FUNCTION,
2056  null,
2057  null,
2058  OperandTypes.family(SqlTypeFamily.ANY),
2059  SqlFunctionCategory.SYSTEM);
2060  }
2061 
2062  @Override
2063  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2064  assert opBinding.getOperandCount() == 1;
2065  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2066  return typeFactory.createTypeWithNullability(
2067  typeFactory.createSqlType(SqlTypeName.INTEGER),
2068  opBinding.getOperandType(0).isNullable());
2069  }
2070  }
2071 
2072  static class ST_Length extends SqlFunction {
2074  super("ST_Length",
2075  SqlKind.OTHER_FUNCTION,
2076  null,
2077  null,
2078  OperandTypes.family(SqlTypeFamily.ANY),
2079  SqlFunctionCategory.SYSTEM);
2080  }
2081 
2082  @Override
2083  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2084  assert opBinding.getOperandCount() == 1;
2085  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2086  return typeFactory.createTypeWithNullability(
2087  typeFactory.createSqlType(SqlTypeName.DOUBLE),
2088  opBinding.getOperandType(0).isNullable());
2089  }
2090  }
2091 
2092  static class ST_Perimeter extends SqlFunction {
2094  super("ST_Perimeter",
2095  SqlKind.OTHER_FUNCTION,
2096  null,
2097  null,
2098  OperandTypes.family(SqlTypeFamily.ANY),
2099  SqlFunctionCategory.SYSTEM);
2100  }
2101 
2102  @Override
2103  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2104  assert opBinding.getOperandCount() == 1;
2105  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2106  return typeFactory.createTypeWithNullability(
2107  typeFactory.createSqlType(SqlTypeName.DOUBLE),
2108  opBinding.getOperandType(0).isNullable());
2109  }
2110  }
2111 
2112  static class ST_Area extends SqlFunction {
2114  super("ST_Area",
2115  SqlKind.OTHER_FUNCTION,
2116  null,
2117  null,
2118  OperandTypes.family(SqlTypeFamily.ANY),
2119  SqlFunctionCategory.SYSTEM);
2120  }
2121 
2122  @Override
2123  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2124  assert opBinding.getOperandCount() == 1;
2125  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2126  return typeFactory.createTypeWithNullability(
2127  typeFactory.createSqlType(SqlTypeName.DOUBLE),
2128  opBinding.getOperandType(0).isNullable());
2129  }
2130  }
2131 
2132  static class ST_NPoints extends SqlFunction {
2134  super("ST_NPoints",
2135  SqlKind.OTHER_FUNCTION,
2136  null,
2137  null,
2138  OperandTypes.family(SqlTypeFamily.ANY),
2139  SqlFunctionCategory.SYSTEM);
2140  }
2141 
2142  @Override
2143  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2144  assert opBinding.getOperandCount() == 1;
2145  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2146  return typeFactory.createTypeWithNullability(
2147  typeFactory.createSqlType(SqlTypeName.INTEGER),
2148  opBinding.getOperandType(0).isNullable());
2149  }
2150  }
2151 
2152  static class ST_NRings extends SqlFunction {
2154  super("ST_NRings",
2155  SqlKind.OTHER_FUNCTION,
2156  null,
2157  null,
2158  OperandTypes.family(SqlTypeFamily.ANY),
2159  SqlFunctionCategory.SYSTEM);
2160  }
2161 
2162  @Override
2163  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2164  assert opBinding.getOperandCount() == 1;
2165  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2166  return typeFactory.createTypeWithNullability(
2167  typeFactory.createSqlType(SqlTypeName.INTEGER),
2168  opBinding.getOperandType(0).isNullable());
2169  }
2170  }
2171 
2172  static class ST_NumGeometries extends SqlFunction {
2174  super("ST_NumGeometries",
2175  SqlKind.OTHER_FUNCTION,
2176  null,
2177  null,
2178  OperandTypes.family(SqlTypeFamily.ANY),
2179  SqlFunctionCategory.SYSTEM);
2180  }
2181 
2182  @Override
2183  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2184  assert opBinding.getOperandCount() == 1;
2185  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2186  return typeFactory.createTypeWithNullability(
2187  typeFactory.createSqlType(SqlTypeName.INTEGER),
2188  opBinding.getOperandType(0).isNullable());
2189  }
2190  }
2191 
2192  static class ST_SRID extends SqlFunction {
2194  super("ST_SRID",
2195  SqlKind.OTHER_FUNCTION,
2196  null,
2197  null,
2198  OperandTypes.family(SqlTypeFamily.ANY),
2199  SqlFunctionCategory.SYSTEM);
2200  }
2201 
2202  @Override
2203  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2204  assert opBinding.getOperandCount() == 1;
2205  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2206  return typeFactory.createTypeWithNullability(
2207  typeFactory.createSqlType(SqlTypeName.INTEGER),
2208  opBinding.getOperandType(0).isNullable());
2209  }
2210  }
2211 
2212  static class ST_SetSRID extends SqlFunction {
2214  super("ST_SetSRID",
2215  SqlKind.OTHER_FUNCTION,
2216  null,
2217  null,
2218  OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.INTEGER),
2219  SqlFunctionCategory.SYSTEM);
2220  }
2221 
2222  @Override
2223  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2224  assert opBinding.getOperandCount() == 1;
2225  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2226  return typeFactory.createTypeWithNullability(
2227  typeFactory.createSqlType(SqlTypeName.INTEGER),
2228  opBinding.getOperandType(0).isNullable());
2229  }
2230  }
2231 
2232  static class ST_Point extends SqlFunction {
2234  super("ST_Point",
2235  SqlKind.OTHER_FUNCTION,
2236  null,
2237  null,
2238  OperandTypes.family(SqlTypeFamily.NUMERIC, SqlTypeFamily.NUMERIC),
2239  SqlFunctionCategory.SYSTEM);
2240  }
2241 
2242  @Override
2243  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2244  assert opBinding.getOperandCount() == 2;
2245  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2246  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2247  }
2248  }
2249 
2250  static class ST_Centroid extends SqlFunction {
2252  super("ST_Centroid",
2253  SqlKind.OTHER_FUNCTION,
2254  null,
2255  null,
2256  OperandTypes.family(signature()),
2257  SqlFunctionCategory.SYSTEM);
2258  }
2259 
2260  @Override
2261  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2262  assert opBinding.getOperandCount() == 1;
2263  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2264  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2265  }
2266 
2267  private static java.util.List<SqlTypeFamily> signature() {
2268  java.util.List<SqlTypeFamily> st_centroid_sig =
2269  new java.util.ArrayList<SqlTypeFamily>();
2270  st_centroid_sig.add(SqlTypeFamily.ANY);
2271  return st_centroid_sig;
2272  }
2273  }
2274 
2275  static class ST_Buffer extends SqlFunction {
2277  super("ST_Buffer",
2278  SqlKind.OTHER_FUNCTION,
2279  null,
2280  null,
2281  OperandTypes.family(signature()),
2282  SqlFunctionCategory.SYSTEM);
2283  }
2284 
2285  @Override
2286  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2287  assert opBinding.getOperandCount() == 2;
2288  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2289  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2290  }
2291 
2292  private static java.util.List<SqlTypeFamily> signature() {
2293  java.util.List<SqlTypeFamily> st_buffer_sig =
2294  new java.util.ArrayList<SqlTypeFamily>();
2295  st_buffer_sig.add(SqlTypeFamily.ANY);
2296  st_buffer_sig.add(SqlTypeFamily.NUMERIC);
2297  return st_buffer_sig;
2298  }
2299  }
2300 
2301  static class ST_ConcaveHull extends SqlFunction {
2303  super("ST_ConcaveHull",
2304  SqlKind.OTHER_FUNCTION,
2305  null,
2306  null,
2307  OperandTypes.family(signature()),
2308  SqlFunctionCategory.SYSTEM);
2309  }
2310 
2311  @Override
2312  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2313  assert opBinding.getOperandCount() == 2;
2314  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2315  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2316  }
2317 
2318  private static java.util.List<SqlTypeFamily> signature() {
2319  java.util.List<SqlTypeFamily> st_concavehull_sig =
2320  new java.util.ArrayList<SqlTypeFamily>();
2321  st_concavehull_sig.add(SqlTypeFamily.ANY);
2322  st_concavehull_sig.add(SqlTypeFamily.NUMERIC);
2323  return st_concavehull_sig;
2324  }
2325  }
2326 
2327  static class ST_ConvexHull extends SqlFunction {
2329  super("ST_ConvexHull",
2330  SqlKind.OTHER_FUNCTION,
2331  null,
2332  null,
2333  OperandTypes.family(signature()),
2334  SqlFunctionCategory.SYSTEM);
2335  }
2336 
2337  @Override
2338  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2339  assert opBinding.getOperandCount() == 1;
2340  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2341  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2342  }
2343 
2344  private static java.util.List<SqlTypeFamily> signature() {
2345  java.util.List<SqlTypeFamily> st_convexhull_sig =
2346  new java.util.ArrayList<SqlTypeFamily>();
2347  st_convexhull_sig.add(SqlTypeFamily.ANY);
2348  return st_convexhull_sig;
2349  }
2350  }
2351 
2352  static class ST_Intersection extends SqlFunction {
2354  super("ST_Intersection",
2355  SqlKind.OTHER_FUNCTION,
2356  null,
2357  null,
2358  OperandTypes.family(signature()),
2359  SqlFunctionCategory.SYSTEM);
2360  }
2361 
2362  @Override
2363  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2364  assert opBinding.getOperandCount() == 2;
2365  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2366  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2367  }
2368 
2369  private static java.util.List<SqlTypeFamily> signature() {
2370  java.util.List<SqlTypeFamily> st_intersection_sig =
2371  new java.util.ArrayList<SqlTypeFamily>();
2372  st_intersection_sig.add(SqlTypeFamily.ANY);
2373  st_intersection_sig.add(SqlTypeFamily.ANY);
2374  return st_intersection_sig;
2375  }
2376  }
2377 
2378  static class ST_Union extends SqlFunction {
2380  super("ST_Union",
2381  SqlKind.OTHER_FUNCTION,
2382  null,
2383  null,
2384  OperandTypes.family(signature()),
2385  SqlFunctionCategory.SYSTEM);
2386  }
2387 
2388  @Override
2389  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2390  assert opBinding.getOperandCount() == 2;
2391  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2392  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2393  }
2394 
2395  private static java.util.List<SqlTypeFamily> signature() {
2396  java.util.List<SqlTypeFamily> st_union_sig =
2397  new java.util.ArrayList<SqlTypeFamily>();
2398  st_union_sig.add(SqlTypeFamily.ANY);
2399  st_union_sig.add(SqlTypeFamily.ANY);
2400  return st_union_sig;
2401  }
2402  }
2403 
2404  static class ST_Difference extends SqlFunction {
2406  super("ST_Difference",
2407  SqlKind.OTHER_FUNCTION,
2408  null,
2409  null,
2410  OperandTypes.family(signature()),
2411  SqlFunctionCategory.SYSTEM);
2412  }
2413 
2414  @Override
2415  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2416  assert opBinding.getOperandCount() == 2;
2417  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2418  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2419  }
2420 
2421  private static java.util.List<SqlTypeFamily> signature() {
2422  java.util.List<SqlTypeFamily> st_difference_sig =
2423  new java.util.ArrayList<SqlTypeFamily>();
2424  st_difference_sig.add(SqlTypeFamily.ANY);
2425  st_difference_sig.add(SqlTypeFamily.ANY);
2426  return st_difference_sig;
2427  }
2428  }
2429 
2430  static class CastToGeography extends SqlFunction {
2432  super("CastToGeography",
2433  SqlKind.OTHER_FUNCTION,
2434  null,
2435  null,
2436  OperandTypes.family(SqlTypeFamily.ANY),
2437  SqlFunctionCategory.SYSTEM);
2438  }
2439 
2440  @Override
2441  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2442  assert opBinding.getOperandCount() == 1;
2443  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2444  return typeFactory.createSqlType(SqlTypeName.INTEGER);
2445  }
2446  }
2447 
2448  static class EncodeText extends SqlFunction {
2450  super("ENCODE_TEXT",
2451  SqlKind.OTHER_FUNCTION,
2452  null,
2453  null,
2454  OperandTypes.family(SqlTypeFamily.STRING),
2455  SqlFunctionCategory.SYSTEM);
2456  }
2457 
2458  @Override
2459  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2460  assert opBinding.getOperandCount() == 1;
2461  return opBinding.getOperandType(0);
2462  }
2463  }
2464 
2465  /* OFFSET_IN_FRAGMENT() */
2466  public static class OffsetInFragment extends SqlFunction {
2467  public OffsetInFragment() {
2468  super("OFFSET_IN_FRAGMENT",
2469  SqlKind.OTHER_FUNCTION,
2470  null,
2471  null,
2472  OperandTypes.NILADIC,
2473  SqlFunctionCategory.SYSTEM);
2474  }
2475 
2476  @Override
2477  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2478  assert opBinding.getOperandCount() == 0;
2479  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2480  return typeFactory.createSqlType(SqlTypeName.BIGINT);
2481  }
2482  }
2483 
2484  static class ApproxCountDistinct extends SqlAggFunction {
2486  super("APPROX_COUNT_DISTINCT",
2487  null,
2488  SqlKind.OTHER_FUNCTION,
2489  null,
2490  null,
2491  OperandTypes.or(OperandTypes.family(SqlTypeFamily.ANY),
2492  OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.INTEGER)),
2493  SqlFunctionCategory.SYSTEM,
2494  false,
2495  false,
2496  Optionality.FORBIDDEN);
2497  }
2498 
2499  @Override
2500  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2501  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2502  return typeFactory.createSqlType(SqlTypeName.BIGINT);
2503  }
2504  }
2505 
2506  static class ApproxMedian extends SqlAggFunction {
2508  super("APPROX_MEDIAN",
2509  SqlKind.OTHER_FUNCTION,
2510  null,
2511  null,
2512  OperandTypes.family(SqlTypeFamily.NUMERIC),
2513  SqlFunctionCategory.SYSTEM);
2514  }
2515 
2516  @Override
2517  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2518  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2519  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
2520  }
2521  }
2522 
2523  static class ApproxPercentile extends SqlAggFunction {
2525  super("APPROX_PERCENTILE",
2526  SqlKind.OTHER_FUNCTION,
2527  null,
2528  null,
2529  OperandTypes.family(SqlTypeFamily.NUMERIC, SqlTypeFamily.NUMERIC),
2530  SqlFunctionCategory.SYSTEM);
2531  }
2532 
2533  @Override
2534  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2535  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2536  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
2537  }
2538  }
2539 
2540  static class ApproxQuantile extends SqlAggFunction {
2542  super("APPROX_QUANTILE",
2543  SqlKind.OTHER_FUNCTION,
2544  null,
2545  null,
2546  OperandTypes.family(SqlTypeFamily.NUMERIC, SqlTypeFamily.NUMERIC),
2547  SqlFunctionCategory.SYSTEM);
2548  }
2549 
2550  @Override
2551  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2552  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2553  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
2554  }
2555  }
2556 
2557  static class MapDAvg extends SqlAggFunction {
2559  super("AVG",
2560  null,
2561  SqlKind.OTHER_FUNCTION,
2562  null,
2563  null,
2564  OperandTypes.family(SqlTypeFamily.NUMERIC),
2565  SqlFunctionCategory.SYSTEM);
2566  }
2567 
2568  @Override
2569  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2570  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2571  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
2572  }
2573  }
2574 
2575  static class Mode extends SqlAggFunction {
2576  Mode() {
2577  super("MODE",
2578  SqlKind.OTHER_FUNCTION,
2579  null,
2580  null,
2581  OperandTypes.ANY,
2582  SqlFunctionCategory.SYSTEM);
2583  }
2584 
2585  @Override
2586  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2587  return opBinding.getOperandType(0);
2588  }
2589  }
2590 
2591  public static class Sample extends SqlAggFunction {
2592  public Sample() {
2593  super("SAMPLE",
2594  null,
2595  SqlKind.OTHER_FUNCTION,
2596  null,
2597  null,
2598  OperandTypes.ANY,
2599  SqlFunctionCategory.SYSTEM,
2600  false,
2601  false,
2602  Optionality.FORBIDDEN);
2603  }
2604 
2605  @Override
2606  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2607  return opBinding.getOperandType(0);
2608  }
2609  }
2610 
2611  // for backwards compatibility
2612  public static class LastSample extends SqlAggFunction {
2613  public LastSample() {
2614  super("LAST_SAMPLE",
2615  null,
2616  SqlKind.OTHER_FUNCTION,
2617  null,
2618  null,
2619  OperandTypes.ANY,
2620  SqlFunctionCategory.SYSTEM,
2621  false,
2622  false,
2623  Optionality.FORBIDDEN);
2624  }
2625 
2626  @Override
2627  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2628  return opBinding.getOperandType(0);
2629  }
2630  }
2631 
2632  static class CountIf extends SqlAggFunction {
2634  super("COUNT_IF",
2635  null,
2636  SqlKind.OTHER_FUNCTION,
2637  null,
2638  null,
2639  OperandTypes.ANY,
2640  SqlFunctionCategory.SYSTEM,
2641  false,
2642  false,
2643  Optionality.FORBIDDEN);
2644  }
2645 
2646  @Override
2647  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2648  return opBinding.getOperandType(0);
2649  }
2650  }
2651 
2652  static class SumIf extends SqlAggFunction {
2653  SumIf() {
2654  super("SUM_IF",
2655  SqlKind.OTHER_FUNCTION,
2656  null,
2657  null,
2658  OperandTypes.family(SqlTypeFamily.NUMERIC, SqlTypeFamily.BOOLEAN),
2659  SqlFunctionCategory.SYSTEM);
2660  }
2661 
2662  @Override
2663  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2664  return opBinding.getOperandType(0);
2665  }
2666  }
2667 
2668  static class ExtFunction extends SqlFunction {
2669  ExtFunction(final String name, final ExtensionFunction sig) {
2670  super(name,
2671  SqlKind.OTHER_FUNCTION,
2672  null,
2673  null,
2674  OperandTypes.family(sig.toSqlSignature()),
2675  SqlFunctionCategory.SYSTEM);
2676  this.sig = sig;
2677  arg_names = sig.getArgNames();
2678  }
2679 
2680  @Override
2681  public List<String> getParamNames() {
2682  return arg_names;
2683  }
2684 
2685  @Override
2686  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
2687  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
2688  if (ExtensionFunction.isArrayType(sig.getRet())) {
2689  SqlTypeName valueType =
2690  toSqlTypeName(ExtensionFunction.getValueType(sig.getRet()));
2691  RelDataType subType = typeFactory.createSqlType(valueType, -1);
2692  RelDataType arr = typeFactory.createArrayType(subType, -1);
2693  // should the return type nullable property be true?
2694  return arr;
2695  } else {
2696  SqlTypeName ret = sig.getSqlRet();
2697  return typeFactory.createTypeWithNullability(
2698  typeFactory.createSqlType(ret), true);
2699  }
2700  }
2701 
2702  private final ExtensionFunction sig;
2703  private final List<String> arg_names;
2704  }
2705 
2706  public class ExtTableFunction extends SqlFunction implements SqlTableFunction {
2707  ExtTableFunction(final String name, final ExtensionFunction sig) {
2708  super(name,
2709  SqlKind.OTHER_FUNCTION,
2710  ReturnTypes.CURSOR,
2711  null,
2713  SqlFunctionCategory.USER_DEFINED_TABLE_FUNCTION);
2714  arg_types = sig.getArgs();
2715  outs = sig.getOuts();
2716  out_names = sig.getOutNames();
2717  arg_names = sig.getArgNames();
2718  // pretty_arg_names will be same as arg_names, except with
2719  // arg names for cursors stripped of array elements, i.e
2720  // my_cursor_input[x, y, z] => my_cursor_input
2721  pretty_arg_names = sig.getPrettyArgNames();
2722  options = sig.getOptions();
2723  cursor_field_types = sig.getCursorFieldTypes();
2724  }
2725 
2726  // The following method allows for parameter annotation
2727  // i.e. my_param => 3.
2728  // Note this method is deprecated, and it appears that
2729  // getParameters() is the correct method to use, but
2730  // need to troubleshoot why it's not being called
2731  @Override
2732  public List<String> getParamNames() {
2733  return pretty_arg_names;
2734  }
2735 
2736  // Per the above, this appears to be the non-deprecated way
2737  // to allow for parameter annotation, and it also allows
2738  // for specifying optionality.
2739  // However it currently is not being picked up/called,
2740  // so need to troubleshot. Leaving in for now as scaffolding
2741  // for the correct approach forward.
2742 
2743  // Note that OperandTypeInference seems another route
2744  // to implementing optionality.
2745 
2746  public List<FunctionParameter> getParameters() {
2747  final Boolean has_names = this.pretty_arg_names != null
2748  && this.pretty_arg_names.size() == this.arg_types.size();
2749  final List<FunctionParameter> parameters = new java.util.ArrayList<>();
2750  for (int i = 0; i < this.arg_types.size(); i++) {
2751  final int arg_idx = i;
2752  parameters.add(new FunctionParameter() {
2753  public int getOrdinal() {
2754  return arg_idx;
2755  }
2756 
2757  public String getName() {
2758  if (has_names) {
2759  return pretty_arg_names.get(arg_idx);
2760  }
2761  return "arg" + arg_idx;
2762  }
2763 
2764  public RelDataType getType(RelDataTypeFactory typeFactory) {
2765  SqlTypeFamily type = toSqlTypeName(arg_types.get(arg_idx)).getFamily();
2766  return type.getDefaultConcreteType(typeFactory);
2767  }
2768 
2769  public boolean isOptional() {
2770  return false;
2771  }
2772  });
2773  }
2774  return parameters;
2775  }
2776 
2777  @Override
2778  public SqlReturnTypeInference getRowTypeInference() {
2779  return opBinding -> {
2780  RelDataTypeFactory fact = opBinding.getTypeFactory();
2781  FieldInfoBuilder ret = fact.builder();
2782  for (int out_idx = 0; out_idx < outs.size(); ++out_idx) {
2783  RelDataType type;
2784  if (toSqlTypeName(outs.get(out_idx)) == SqlTypeName.ARRAY) {
2785  ExtArgumentType extSubType = getValueType(outs.get(out_idx));
2786  if (ExtensionFunction.isColumnArrayType(outs.get(out_idx))) {
2787  extSubType = getValueType(extSubType);
2788  }
2789  RelDataType subtype = fact.createSqlType(toSqlTypeName(extSubType));
2790  type = fact.createArrayType(subtype, -1);
2791  } else {
2792  type = fact.createSqlType(toSqlTypeName(outs.get(out_idx)));
2793  }
2794  ret = ret.add(out_names.get(out_idx), type);
2795  ret = ret.nullable(true);
2796  }
2797  return ret.build();
2798  };
2799  }
2800 
2801  private void debugPrint(String msg, Boolean debugMode) {
2802  if (debugMode) {
2803  System.out.println(msg);
2804  }
2805  }
2806 
2807  public Set<RelColumnMapping> getColumnMappings() {
2808  final Boolean debugMode = false;
2809  Set<RelColumnMapping> s = new HashSet<RelColumnMapping>();
2810  debugPrint("getNameAsId() -> " + getNameAsId() + ", arg_names=" + arg_names
2811  + ", out_names=" + out_names,
2812  debugMode);
2813  if (Integer.valueOf(options.getOrDefault("filter_table_function_transpose", "0"))
2814  == 1) {
2815  debugPrint("getNameAsId() -> " + getNameAsId(), debugMode);
2816  int rel_idx = -1;
2817  for (int arg_idx = 0; arg_idx < arg_names.size(); ++arg_idx) {
2818  String arg_name = arg_names.get(arg_idx);
2819  String[] fields;
2820  int start = arg_name.indexOf("[");
2821  if (start != -1) {
2822  rel_idx += 1;
2823  int end = arg_name.lastIndexOf("]");
2824  fields = arg_name.substring(start + 1, end)
2825  .replaceAll("\\s+", "")
2826  .split(",", 0);
2827  } else {
2828  fields = new String[] {arg_name};
2829  }
2830  debugPrint("fields=" + Arrays.toString(fields), debugMode);
2831  for (int field_idx = 0; field_idx < fields.length; ++field_idx) {
2832  int out_idx = out_names.indexOf(fields[field_idx]);
2833  if (out_idx >= 0) {
2834  s.add(new RelColumnMapping(out_idx, rel_idx, field_idx, false));
2835  debugPrint("out_idx, arg_idx/rel_idx, field_idx=" + out_idx + ", " + arg_idx
2836  + "/" + rel_idx + ", " + field_idx,
2837  debugMode);
2838  }
2839  }
2840  }
2841  }
2842  return s;
2843  }
2844 
2845  // Returns the table function's signature, with extended operand
2846  // type information, including CURSOR field types and operand
2847  // names.
2848 
2849  // E.g. for the following UDTF:
2850  // my_udtf(Column<int64_t> input_col) -> Column<int64_t>
2851  // it'll build the signature:
2852  // 'my_udtf(input_col => <CURSOR>[BIGINT])'
2853 
2854  public String getExtendedSignature() {
2855  StringBuilder ret = new StringBuilder();
2856  ret.append("'");
2857  ret.append(this.getName());
2858  ret.append("(");
2859 
2860  for (int i = 0; i < this.arg_types.size(); i++) {
2861  if (i > 0) {
2862  ret.append(", ");
2863  }
2864 
2865  ExtArgumentType type = arg_types.get(i);
2866  String paramName = arg_names.get(i);
2867  ret.append(paramName).append(" => ");
2868 
2869  final String t = type.toString().toUpperCase(Locale.ROOT);
2870  ret.append("<").append(t);
2871  if (type == ExtArgumentType.Cursor) {
2872  List<ExtensionFunction.ExtArgumentType> field_types =
2873  cursor_field_types.get(paramName);
2874  ret.append("[");
2875  for (int j = 0; j < field_types.size(); j++) {
2876  if (j > 0) {
2877  ret.append(",");
2878  }
2879  ExtArgumentType field_type = field_types.get(j);
2880  ret.append(toSqlTypeName(field_type));
2881  if (isColumnListType(field_type)) {
2882  ExtArgumentType subtype = getValueType(field_type);
2883  ret.append("[");
2884  ret.append(toSqlTypeName(subtype));
2885  ret.append("]");
2886  } else if (isColumnArrayType(field_type) || isArrayType(field_type)) {
2887  ExtArgumentType subtype = getValueType(getValueType(field_type));
2888  ret.append("[");
2889  ret.append(toSqlTypeName(subtype));
2890  ret.append("]");
2891  }
2892  }
2893  ret.append("]");
2894  }
2895  ret.append(">");
2896  }
2897  ret.append(")'");
2898 
2899  return ret.toString();
2900  }
2901 
2902  // This returns the original arg names, with CURSOR field names included.
2903  // Is used to map arguments to their input annotations.
2904  public List<String> getExtendedParamNames() {
2905  return this.arg_names;
2906  }
2907 
2908  // Required to store ExtTableFunctions in Collections
2909  @Override
2910  public int hashCode() {
2911  return this.getExtendedSignature().hashCode();
2912  }
2913 
2914  // Required to store ExtTableFunctions in Collections
2915  // We disambiguate ExtTableFunctions by their names and input arg
2916  // types, including CURSOR field types.
2917  @Override
2918  public boolean equals(final Object obj) {
2919  if (obj == null) {
2920  return false;
2921  }
2922 
2923  if (getClass() != obj.getClass()) {
2924  return false;
2925  }
2926 
2927  if (this == obj) {
2928  return true;
2929  }
2930 
2931  final ExtTableFunction other = (ExtTableFunction) obj;
2932  if (!this.getName().equals(other.getName())) {
2933  return false;
2934  }
2935  if (arg_types.size() != other.arg_types.size()) {
2936  return false;
2937  }
2938 
2939  for (int i = 0; i < arg_types.size(); i++) {
2940  if (arg_types.get(i) != other.arg_types.get(i)) {
2941  return false;
2942  }
2943  if (arg_types.get(i) == ExtArgumentType.Cursor) {
2944  String paramName = this.arg_names.get(i);
2945  String otherParamName = other.getExtendedParamNames().get(i);
2946  if (!paramName.equals(otherParamName)) {
2947  return false;
2948  }
2949 
2950  List<ExtArgumentType> field_types = this.getCursorFieldTypes().get(paramName);
2951  List<ExtArgumentType> other_field_types =
2952  other.getCursorFieldTypes().get(paramName);
2953  if (field_types.size() != other_field_types.size()) {
2954  return false;
2955  }
2956  for (int j = 0; j < field_types.size(); j++) {
2957  if (field_types.get(j) != other_field_types.get(j)) {
2958  return false;
2959  }
2960  }
2961  }
2962  }
2963  return true;
2964  }
2965 
2966  @Override
2967  public String toString() {
2968  return new String(getName() + "("
2969  + String.join(",",
2970  this.arg_types.stream()
2971  .map(s -> s.toString())
2972  .collect(Collectors.toList()))
2973  + ")");
2974  }
2975 
2976  Map<String, List<ExtArgumentType>> getCursorFieldTypes() {
2977  return cursor_field_types;
2978  }
2979 
2980  List<ExtArgumentType> getArgTypes() {
2981  return arg_types;
2982  }
2983 
2984  private final List<ExtArgumentType> arg_types;
2985  private final List<ExtArgumentType> outs;
2986  private final List<String> arg_names;
2987  private final List<String> pretty_arg_names;
2988  private final List<String> out_names;
2989  private final Map<String, String> options;
2990  private final Map<String, List<ExtArgumentType>> cursor_field_types;
2991  }
2992 
2993  //
2994  // Internal accessors for in-situ poly render queries
2995  //
2996 
2997  static class HeavyDB_Geo_PolyBoundsPtr extends SqlFunction {
2999  super("HeavyDB_Geo_PolyBoundsPtr",
3000  SqlKind.OTHER_FUNCTION,
3001  null,
3002  null,
3003  OperandTypes.family(SqlTypeFamily.ANY),
3004  SqlFunctionCategory.SYSTEM);
3005  }
3006 
3007  @Override
3008  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3009  assert opBinding.getOperandCount() == 1;
3010  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3011  return typeFactory.createSqlType(SqlTypeName.BIGINT);
3012  }
3013  }
3014 
3015  static class HeavyDB_Geo_PolyRenderGroup extends SqlFunction {
3017  super("HeavyDB_Geo_PolyRenderGroup",
3018  SqlKind.OTHER_FUNCTION,
3019  null,
3020  null,
3021  OperandTypes.family(SqlTypeFamily.ANY),
3022  SqlFunctionCategory.SYSTEM);
3023  }
3024 
3025  @Override
3026  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3027  assert opBinding.getOperandCount() == 1;
3028  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3029  return typeFactory.createSqlType(SqlTypeName.INTEGER);
3030  }
3031  }
3032 
3033  static class HeavyDB_Geo_PolyCoordsArray extends SqlFunction {
3035  super("HeavyDB_Geo_PolyCoordsArray",
3036  SqlKind.OTHER_FUNCTION,
3037  null,
3038  null,
3039  OperandTypes.family(SqlTypeFamily.ANY),
3040  SqlFunctionCategory.SYSTEM);
3041  }
3042 
3043  @Override
3044  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3045  assert opBinding.getOperandCount() == 1;
3046  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3047  return typeFactory.createArrayType(
3048  typeFactory.createSqlType(SqlTypeName.DOUBLE), -1);
3049  }
3050  }
3051 
3052  static class HeavyDB_Geo_PolyRingSizesArray extends SqlFunction {
3054  super("HeavyDB_Geo_PolyRingSizesArray",
3055  SqlKind.OTHER_FUNCTION,
3056  null,
3057  null,
3058  OperandTypes.family(SqlTypeFamily.ANY),
3059  SqlFunctionCategory.SYSTEM);
3060  }
3061 
3062  @Override
3063  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3064  assert opBinding.getOperandCount() == 1;
3065  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3066  return typeFactory.createArrayType(
3067  typeFactory.createSqlType(SqlTypeName.INTEGER), -1);
3068  }
3069  }
3070 
3071  static class HeavyDB_Geo_PolyPolyRingsArray extends SqlFunction {
3073  super("HeavyDB_Geo_PolyPolyRingsArray",
3074  SqlKind.OTHER_FUNCTION,
3075  null,
3076  null,
3077  OperandTypes.family(SqlTypeFamily.ANY),
3078  SqlFunctionCategory.SYSTEM);
3079  }
3080 
3081  @Override
3082  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3083  assert opBinding.getOperandCount() == 1;
3084  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3085  return typeFactory.createArrayType(
3086  typeFactory.createSqlType(SqlTypeName.INTEGER), -1);
3087  }
3088  }
3089 
3090  static class convert_meters_to_pixel_width extends SqlFunction {
3092  super("convert_meters_to_pixel_width",
3093  SqlKind.OTHER_FUNCTION,
3094  null,
3095  null,
3096  OperandTypes.family(SqlTypeFamily.NUMERIC,
3097  SqlTypeFamily.ANY,
3098  SqlTypeFamily.NUMERIC,
3099  SqlTypeFamily.NUMERIC,
3100  SqlTypeFamily.NUMERIC,
3101  SqlTypeFamily.NUMERIC),
3102  SqlFunctionCategory.SYSTEM);
3103  }
3104 
3105  @Override
3106  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3107  assert opBinding.getOperandCount() == 6;
3108  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3109  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
3110  }
3111  }
3112 
3113  static class convert_meters_to_pixel_height extends SqlFunction {
3115  super("convert_meters_to_pixel_height",
3116  SqlKind.OTHER_FUNCTION,
3117  null,
3118  null,
3119  OperandTypes.family(SqlTypeFamily.NUMERIC,
3120  SqlTypeFamily.ANY,
3121  SqlTypeFamily.NUMERIC,
3122  SqlTypeFamily.NUMERIC,
3123  SqlTypeFamily.NUMERIC,
3124  SqlTypeFamily.NUMERIC),
3125  SqlFunctionCategory.SYSTEM);
3126  }
3127 
3128  @Override
3129  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3130  assert opBinding.getOperandCount() == 6;
3131  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3132  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
3133  }
3134  }
3135 
3136  static class is_point_in_view extends SqlFunction {
3138  super("is_point_in_view",
3139  SqlKind.OTHER_FUNCTION,
3140  null,
3141  null,
3142  OperandTypes.family(SqlTypeFamily.ANY,
3143  SqlTypeFamily.NUMERIC,
3144  SqlTypeFamily.NUMERIC,
3145  SqlTypeFamily.NUMERIC,
3146  SqlTypeFamily.NUMERIC),
3147  SqlFunctionCategory.SYSTEM);
3148  }
3149 
3150  @Override
3151  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3152  assert opBinding.getOperandCount() == 5;
3153  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3154  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
3155  }
3156  }
3157 
3158  static class is_point_size_in_view extends SqlFunction {
3160  super("is_point_size_in_view",
3161  SqlKind.OTHER_FUNCTION,
3162  null,
3163  null,
3164  OperandTypes.family(SqlTypeFamily.ANY,
3165  SqlTypeFamily.NUMERIC,
3166  SqlTypeFamily.NUMERIC,
3167  SqlTypeFamily.NUMERIC,
3168  SqlTypeFamily.NUMERIC,
3169  SqlTypeFamily.NUMERIC),
3170  SqlFunctionCategory.SYSTEM);
3171  }
3172 
3173  @Override
3174  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3175  assert opBinding.getOperandCount() == 6;
3176  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3177  return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
3178  }
3179  }
3180 
3181  public static class usTimestamp extends SqlFunction {
3182  public usTimestamp() {
3183  super("usTIMESTAMP",
3184  SqlKind.OTHER_FUNCTION,
3185  null,
3186  null,
3187  OperandTypes.STRING,
3188  SqlFunctionCategory.SYSTEM);
3189  }
3190 
3191  @Override
3192  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3193  assert opBinding.getOperandCount() == 1;
3194  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3195  return typeFactory.createSqlType(SqlTypeName.TIMESTAMP, 6);
3196  }
3197  }
3198 
3199  public static class nsTimestamp extends SqlFunction {
3200  public nsTimestamp() {
3201  super("nsTIMESTAMP",
3202  SqlKind.OTHER_FUNCTION,
3203  null,
3204  null,
3205  OperandTypes.STRING,
3206  SqlFunctionCategory.SYSTEM);
3207  }
3208 
3209  @Override
3210  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
3211  assert opBinding.getOperandCount() == 1;
3212  final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
3213  return typeFactory.createSqlType(SqlTypeName.TIMESTAMP, 9);
3214  }
3215  }
3216 }
3217 
3218 // End HeavyDBSqlOperatorTable.java
EXTENSION_NOINLINE double convert_meters_to_pixel_width(const double meters, int8_t *p, const int64_t psize, const int32_t ic, const int32_t isr, const int32_t osr, const double min_lon, const double max_lon, const int32_t img_width, const double min_width)
EXTENSION_INLINE int64_t HeavyDB_Geo_PolyBoundsPtr(double *bounds, int64_t size)
final java.util.List< SqlTypeFamily > toSqlSignature()
size_t append(FILE *f, const size_t size, const int8_t *buf)
Appends the specified number of bytes to the end of the file f from buf.
Definition: File.cpp:178
RelDataType inferReturnType(SqlOperatorBinding opBinding)
ExtTableFunction(final String name, final ExtensionFunction sig)
EXTENSION_NOINLINE double ST_XMax(int8_t *coords, int64_t size, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_NOINLINE bool is_point_size_in_view(int8_t *p, const int64_t psize, const int32_t ic, const double meters, const double min_lon, const double max_lon, const double min_lat, const double max_lat)
EXTENSION_NOINLINE double ST_YMax(int8_t *coords, int64_t size, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_INLINE Array< int32_t > HeavyDB_Geo_PolyRingSizesArray(int32_t *mpoly_ring_sizes, int64_t mpoly_num_rings)
SqlCall createCall(@Nullable SqlLiteral functionQualifier, SqlParserPos pos,@Nullable SqlNode...operands)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
EXTENSION_NOINLINE double ST_XMin(int8_t *coords, int64_t size, int32_t ic, int32_t isr, int32_t osr)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
EXTENSION_NOINLINE double convert_meters_to_pixel_height(const double meters, int8_t *p, const int64_t psize, const int32_t ic, const int32_t isr, const int32_t osr, const double min_lat, const double max_lat, const int32_t img_height, const double min_height)
tuple STRING
Definition: dtypes.py:31
constexpr double f
Definition: Utm.h:31
boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
static java.util.List< SqlTypeFamily > getSignatureFamilies()
RelDataType inferReturnType(SqlOperatorBinding opBinding)
RelDataType getComponentType(RelDataTypeFactory typeFactory, List< RelDataType > argTypes)
EXTENSION_NOINLINE double ST_YMin(int8_t *coords, int64_t size, int32_t ic, int32_t isr, int32_t osr)
EXTENSION_INLINE Array< double > HeavyDB_Geo_PolyCoordsArray(int8_t *mpoly_coords, int64_t mpoly_coords_size, const int32_t ic)
SqlCall createCall(@Nullable SqlLiteral functionQualifier, SqlParserPos pos,@Nullable SqlNode...operands)
static java.util.List< SqlTypeFamily > getSignatureFamilies()
RelDataType inferReturnType(SqlOperatorBinding opBinding)
static boolean isColumnArrayType(final ExtArgumentType type)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
EXTENSION_INLINE int32_t HeavyDB_Geo_PolyRenderGroup(int32_t render_group)
void addUDF(final Map< String, ExtensionFunction > extSigs)
EXTENSION_NOINLINE bool is_point_in_view(int8_t *p, const int64_t psize, const int32_t ic, const double min_lon, const double max_lon, const double min_lat, const double max_lat)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
ExtFunction(final String name, final ExtensionFunction sig)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
static java.util.List< SqlTypeFamily > getSignatureFamilies()
RelDataType inferReturnType(SqlOperatorBinding opBinding)
static java.util.List< SqlTypeFamily > getSignatureFamilies()
void unparse(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec)
static boolean isArrayType(final ExtArgumentType type)
SqlCall createCall(@Nullable SqlLiteral functionQualifier, SqlParserPos pos,@Nullable SqlNode...operands)
SqlCall createCall(@Nullable SqlLiteral functionQualifier, SqlParserPos pos,@Nullable SqlNode...operands)
EXTENSION_NOINLINE double Truncate(const double x, const int32_t y)
EXTENSION_INLINE Array< int32_t > HeavyDB_Geo_PolyPolyRingsArray(int32_t *mpoly_poly_sizes, int64_t mpoly_num_polys)
SqlCall createCall(@Nullable SqlLiteral functionQualifier, SqlParserPos pos,@Nullable SqlNode...operands)
string name
Definition: setup.in.py:72
boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
static final SqlArrayValueConstructorAllowingEmpty ARRAY_VALUE_CONSTRUCTOR
RelDataType inferReturnType(SqlOperatorBinding opBinding)
static ExtArgumentType getValueType(final ExtArgumentType type)
RelDataType inferReturnType(SqlOperatorBinding opBinding)
void lookupOperatorOverloads(SqlIdentifier opName, SqlFunctionCategory category, SqlSyntax syntax, List< SqlOperator > operatorList, SqlNameMatcher nameMatcher)
RelDataType inferReturnType(SqlOperatorBinding opBinding)