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

com.hazelcast.org.apache.calcite.sql.type.ReturnTypes Maven / Gradle / Ivy

There is a newer version: 5.4.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in com.hazelcast.com.liance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.com.hazelcast.org.licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hazelcast.org.apache.calcite.sql.type;

import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeFactory;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeField;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeImpl;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeSystem;
import com.hazelcast.org.apache.calcite.rel.type.RelProtoDataType;
import com.hazelcast.org.apache.calcite.sql.ExplicitOperatorBinding;
import com.hazelcast.org.apache.calcite.sql.SqlCallBinding;
import com.hazelcast.org.apache.calcite.sql.SqlCollation;
import com.hazelcast.org.apache.calcite.sql.SqlOperatorBinding;
import com.hazelcast.org.apache.calcite.sql.SqlUtil;
import com.hazelcast.org.apache.calcite.util.Glossary;

import com.hazelcast.com.google.com.hazelcast.com.on.base.Preconditions;

import java.util.AbstractList;
import java.util.List;

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

/**
 * A collection of return-type inference strategies.
 */
public abstract class ReturnTypes {
  private ReturnTypes() {
  }

  public static SqlReturnTypeInferenceChain chain(
      SqlReturnTypeInference... rules) {
    return new SqlReturnTypeInferenceChain(rules);
  }

  /** Creates a return-type inference that applies a rule then a sequence of
   * transforms. */
  public static SqlTypeTransformCascade cascade(SqlReturnTypeInference rule,
      SqlTypeTransform... transforms) {
    return new SqlTypeTransformCascade(rule, transforms);
  }

  public static ExplicitReturnTypeInference explicit(
      RelProtoDataType protoType) {
    return new ExplicitReturnTypeInference(protoType);
  }

  /**
   * Creates an inference rule which returns a copy of a given data type.
   */
  public static ExplicitReturnTypeInference explicit(RelDataType type) {
    return explicit(RelDataTypeImpl.proto(type));
  }

  /**
   * Creates an inference rule which returns a type with no precision or scale,
   * such as {@code DATE}.
   */
  public static ExplicitReturnTypeInference explicit(SqlTypeName typeName) {
    return explicit(RelDataTypeImpl.proto(typeName, false));
  }

  /**
   * Creates an inference rule which returns a type with precision but no scale,
   * such as {@code VARCHAR(100)}.
   */
  public static ExplicitReturnTypeInference explicit(SqlTypeName typeName,
      int precision) {
    return explicit(RelDataTypeImpl.proto(typeName, precision, false));
  }

  /**
   * Type-inference strategy whereby the result type of a call is the type of
   * the operand #0 (0-based).
   */
  public static final SqlReturnTypeInference ARG0 =
      new OrdinalReturnTypeInference(0);
  /**
   * Type-inference strategy whereby the result type of a call is VARYING the
   * type of the first argument. The length returned is the same as length of
   * the first argument. If any of the other operands are nullable the
   * returned type will also be nullable. First Arg must be of string type.
   */
  public static final SqlReturnTypeInference ARG0_NULLABLE_VARYING =
      cascade(ARG0, SqlTypeTransforms.TO_NULLABLE,
          SqlTypeTransforms.TO_VARYING);

  /**
   * Type-inference strategy whereby the result type of a call is the type of
   * the operand #0 (0-based). If any of the other operands are nullable the
   * returned type will also be nullable.
   */
  public static final SqlReturnTypeInference ARG0_NULLABLE =
      cascade(ARG0, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy whereby the result type of a call is the type of
   * the operand #0 (0-based), with nulls always allowed.
   */
  public static final SqlReturnTypeInference ARG0_FORCE_NULLABLE =
      cascade(ARG0, SqlTypeTransforms.FORCE_NULLABLE);

  public static final SqlReturnTypeInference ARG0_INTERVAL =
      new MatchReturnTypeInference(0,
          SqlTypeFamily.DATETIME_INTERVAL.getTypeNames());

  public static final SqlReturnTypeInference ARG0_INTERVAL_NULLABLE =
      cascade(ARG0_INTERVAL, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy whereby the result type of a call is the type of
   * the operand #0 (0-based), and nullable if the call occurs within a
   * "GROUP BY ()" query. E.g. in "select sum(1) as s from empty", s may be
   * null.
   */
  public static final SqlReturnTypeInference ARG0_NULLABLE_IF_EMPTY =
      new OrdinalReturnTypeInference(0) {
        @Override public RelDataType
        inferReturnType(SqlOperatorBinding opBinding) {
          final RelDataType type = super.inferReturnType(opBinding);
          if (opBinding.getGroupCount() == 0 || opBinding.hasFilter()) {
            return opBinding.getTypeFactory()
                .createTypeWithNullability(type, true);
          } else {
            return type;
          }
        }
      };

  /**
   * Type-inference strategy whereby the result type of a call is the type of
   * the operand #1 (0-based).
   */
  public static final SqlReturnTypeInference ARG1 =
      new OrdinalReturnTypeInference(1);
  /**
   * Type-inference strategy whereby the result type of a call is the type of
   * the operand #1 (0-based). If any of the other operands are nullable the
   * returned type will also be nullable.
   */
  public static final SqlReturnTypeInference ARG1_NULLABLE =
      cascade(ARG1, SqlTypeTransforms.TO_NULLABLE);
  /**
   * Type-inference strategy whereby the result type of a call is the type of
   * operand #2 (0-based).
   */
  public static final SqlReturnTypeInference ARG2 =
      new OrdinalReturnTypeInference(2);
  /**
   * Type-inference strategy whereby the result type of a call is the type of
   * operand #2 (0-based). If any of the other operands are nullable the
   * returned type will also be nullable.
   */
  public static final SqlReturnTypeInference ARG2_NULLABLE =
      cascade(ARG2, SqlTypeTransforms.TO_NULLABLE);
  /**
   * Type-inference strategy whereby the result type of a call is Boolean.
   */
  public static final SqlReturnTypeInference BOOLEAN =
      explicit(SqlTypeName.BOOLEAN);
  /**
   * Type-inference strategy whereby the result type of a call is Boolean,
   * with nulls allowed if any of the operands allow nulls.
   */
  public static final SqlReturnTypeInference BOOLEAN_NULLABLE =
      cascade(BOOLEAN, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy with similar effect to {@link #BOOLEAN_NULLABLE},
   * which is more efficient, but can only be used if all arguments are
   * BOOLEAN.
   */
  public static final SqlReturnTypeInference BOOLEAN_NULLABLE_OPTIMIZED =
      opBinding -> {
        // Equivalent to
        //   cascade(ARG0, SqlTypeTransforms.TO_NULLABLE);
        // but implemented by hand because used in AND, which is a very com.hazelcast.com.on
        // operator.
        final int n = opBinding.getOperandCount();
        RelDataType type1 = null;
        for (int i = 0; i < n; i++) {
          type1 = opBinding.getOperandType(i);
          if (type1.isNullable()) {
            break;
          }
        }
        return type1;
      };

  /**
   * Type-inference strategy whereby the result type of a call is a nullable
   * Boolean.
   */
  public static final SqlReturnTypeInference BOOLEAN_FORCE_NULLABLE =
      cascade(BOOLEAN, SqlTypeTransforms.FORCE_NULLABLE);

  /**
   * Type-inference strategy whereby the result type of a call is Boolean
   * not null.
   */
  public static final SqlReturnTypeInference BOOLEAN_NOT_NULL =
      cascade(BOOLEAN, SqlTypeTransforms.TO_NOT_NULLABLE);
  /**
   * Type-inference strategy whereby the result type of a call is Date.
   */
  public static final SqlReturnTypeInference DATE =
      explicit(SqlTypeName.DATE);

  /**
   * Type-inference strategy whereby the result type of a call is nullable
   * Date.
   */
  public static final SqlReturnTypeInference DATE_NULLABLE =
      cascade(DATE, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy whereby the result type of a call is Time(0).
   */
  public static final SqlReturnTypeInference TIME =
      explicit(SqlTypeName.TIME, 0);
  /**
   * Type-inference strategy whereby the result type of a call is nullable
   * Time(0).
   */
  public static final SqlReturnTypeInference TIME_NULLABLE =
      cascade(TIME, SqlTypeTransforms.TO_NULLABLE);
  /**
   * Type-inference strategy whereby the result type of a call is Double.
   */
  public static final SqlReturnTypeInference DOUBLE =
      explicit(SqlTypeName.DOUBLE);
  /**
   * Type-inference strategy whereby the result type of a call is Double with
   * nulls allowed if any of the operands allow nulls.
   */
  public static final SqlReturnTypeInference DOUBLE_NULLABLE =
      cascade(DOUBLE, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy whereby the result type of a call is a Char.
   */
  public static final SqlReturnTypeInference CHAR =
          explicit(SqlTypeName.CHAR);

  /**
   * Type-inference strategy whereby the result type of a call is an Integer.
   */
  public static final SqlReturnTypeInference INTEGER =
      explicit(SqlTypeName.INTEGER);

  /**
   * Type-inference strategy whereby the result type of a call is an Integer
   * with nulls allowed if any of the operands allow nulls.
   */
  public static final SqlReturnTypeInference INTEGER_NULLABLE =
      cascade(INTEGER, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy whereby the result type of a call is a Bigint
   */
  public static final SqlReturnTypeInference BIGINT =
      explicit(SqlTypeName.BIGINT);
  /**
   * Type-inference strategy whereby the result type of a call is a nullable
   * Bigint
   */
  public static final SqlReturnTypeInference BIGINT_FORCE_NULLABLE =
      cascade(BIGINT, SqlTypeTransforms.FORCE_NULLABLE);
  /**
   * Type-inference strategy whereby the result type of a call is an Bigint
   * with nulls allowed if any of the operands allow nulls.
   */
  public static final SqlReturnTypeInference BIGINT_NULLABLE =
      cascade(BIGINT, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy that always returns "VARCHAR(4)".
   */
  public static final SqlReturnTypeInference VARCHAR_4 =
      explicit(SqlTypeName.VARCHAR, 4);

  /**
   * Type-inference strategy that always returns "VARCHAR(4)" with nulls
   * allowed if any of the operands allow nulls.
   */
  public static final SqlReturnTypeInference VARCHAR_4_NULLABLE =
      cascade(VARCHAR_4, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy that always returns "VARCHAR(2000)".
   */
  public static final SqlReturnTypeInference VARCHAR_2000 =
      explicit(SqlTypeName.VARCHAR, 2000);

  /**
   * Type-inference strategy that always returns "VARCHAR(2000)" with nulls
   * allowed if any of the operands allow nulls.
   */
  public static final SqlReturnTypeInference VARCHAR_2000_NULLABLE =
      cascade(VARCHAR_2000, SqlTypeTransforms.TO_NULLABLE);

  /**
   * Type-inference strategy for Histogram agg support
   */
  public static final SqlReturnTypeInference HISTOGRAM =
      explicit(SqlTypeName.VARBINARY, 8);

  /**
   * Type-inference strategy that always returns "CURSOR".
   */
  public static final SqlReturnTypeInference CURSOR =
      explicit(SqlTypeName.CURSOR);

  /**
   * Type-inference strategy that always returns "COLUMN_LIST".
   */
  public static final SqlReturnTypeInference COLUMN_LIST =
      explicit(SqlTypeName.COLUMN_LIST);
  /**
   * Type-inference strategy whereby the result type of a call is using its
   * operands biggest type, using the SQL:1999 rules described in "Data types
   * of results of aggregations". These rules are used in union, except,
   * intersect, case and other places.
   *
   * @see Glossary#SQL99 SQL:1999 Part 2 Section 9.3
   */
  public static final SqlReturnTypeInference LEAST_RESTRICTIVE =
      opBinding -> opBinding.getTypeFactory().leastRestrictive(
          opBinding.collectOperandTypes());
  /**
   * Returns the same type as the multiset carries. The multiset type returned
   * is the least restrictive of the call's multiset operands
   */
  public static final SqlReturnTypeInference MULTISET = opBinding -> {
    ExplicitOperatorBinding newBinding =
        new ExplicitOperatorBinding(
            opBinding,
            new AbstractList() {
              // CHECKSTYLE: IGNORE 12
              public RelDataType get(int index) {
                RelDataType type =
                    opBinding.getOperandType(index)
                        .getComponentType();
                assert type != null;
                return type;
              }

              public int size() {
                return opBinding.getOperandCount();
              }
            });
    RelDataType biggestElementType =
        LEAST_RESTRICTIVE.inferReturnType(newBinding);
    return opBinding.getTypeFactory().createMultisetType(
        biggestElementType,
        -1);
  };

  /**
   * Returns a multiset type.
   *
   * 

For example, given INTEGER, returns * INTEGER MULTISET. */ public static final SqlReturnTypeInference TO_MULTISET = cascade(ARG0, SqlTypeTransforms.TO_MULTISET); /** * Returns the element type of a multiset */ public static final SqlReturnTypeInference MULTISET_ELEMENT_NULLABLE = cascade(MULTISET, SqlTypeTransforms.TO_MULTISET_ELEMENT_TYPE); /** * Same as {@link #MULTISET} but returns with nullability if any of the * operands is nullable. */ public static final SqlReturnTypeInference MULTISET_NULLABLE = cascade(MULTISET, SqlTypeTransforms.TO_NULLABLE); /** * Returns the type of the only column of a multiset. * *

For example, given RECORD(x INTEGER) MULTISET, returns * INTEGER MULTISET. */ public static final SqlReturnTypeInference MULTISET_PROJECT_ONLY = cascade(MULTISET, SqlTypeTransforms.ONLY_COLUMN); /** * Type-inference strategy whereby the result type of a call is * {@link #ARG0_INTERVAL_NULLABLE} and {@link #LEAST_RESTRICTIVE}. These rules * are used for integer division. */ public static final SqlReturnTypeInference INTEGER_QUOTIENT_NULLABLE = chain(ARG0_INTERVAL_NULLABLE, LEAST_RESTRICTIVE); /** * Type-inference strategy for a call where the first argument is a decimal. * The result type of a call is a decimal with a scale of 0, and the same * precision and nullability as the first argument. */ public static final SqlReturnTypeInference DECIMAL_SCALE0 = opBinding -> { RelDataType type1 = opBinding.getOperandType(0); if (SqlTypeUtil.isDecimal(type1)) { if (type1.getScale() == 0) { return type1; } else { int p = type1.getPrecision(); RelDataType ret; ret = opBinding.getTypeFactory().createSqlType( SqlTypeName.DECIMAL, p, 0); if (type1.isNullable()) { ret = opBinding.getTypeFactory() .createTypeWithNullability(ret, true); } return ret; } } return null; }; /** * Type-inference strategy whereby the result type of a call is * {@link #DECIMAL_SCALE0} with a fallback to {@link #ARG0} This rule * is used for floor, ceiling. */ public static final SqlReturnTypeInference ARG0_OR_EXACT_NO_SCALE = chain(DECIMAL_SCALE0, ARG0); /** * Type-inference strategy whereby the result type of a call is the decimal * product of two exact numeric operands where at least one of the operands * is a decimal. */ public static final SqlReturnTypeInference DECIMAL_PRODUCT = opBinding -> { RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); RelDataType type1 = opBinding.getOperandType(0); RelDataType type2 = opBinding.getOperandType(1); return typeFactory.getTypeSystem().deriveDecimalMultiplyType(typeFactory, type1, type2); }; /** * Same as {@link #DECIMAL_PRODUCT} but returns with nullability if any of * the operands is nullable by using * {@link com.hazelcast.org.apache.calcite.sql.type.SqlTypeTransforms#TO_NULLABLE} */ public static final SqlReturnTypeInference DECIMAL_PRODUCT_NULLABLE = cascade(DECIMAL_PRODUCT, SqlTypeTransforms.TO_NULLABLE); /** * Type-inference strategy whereby the result type of a call is * {@link #DECIMAL_PRODUCT_NULLABLE} with a fallback to * {@link #ARG0_INTERVAL_NULLABLE} * and {@link #LEAST_RESTRICTIVE}. * These rules are used for multiplication. */ public static final SqlReturnTypeInference PRODUCT_NULLABLE = chain(DECIMAL_PRODUCT_NULLABLE, ARG0_INTERVAL_NULLABLE, LEAST_RESTRICTIVE); /** * Type-inference strategy whereby the result type of a call is the decimal * quotient of two exact numeric operands where at least one of the operands * is a decimal. */ public static final SqlReturnTypeInference DECIMAL_QUOTIENT = opBinding -> { RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); RelDataType type1 = opBinding.getOperandType(0); RelDataType type2 = opBinding.getOperandType(1); return typeFactory.getTypeSystem().deriveDecimalDivideType(typeFactory, type1, type2); }; /** * Same as {@link #DECIMAL_QUOTIENT} but returns with nullability if any of * the operands is nullable by using * {@link com.hazelcast.org.apache.calcite.sql.type.SqlTypeTransforms#TO_NULLABLE} */ public static final SqlReturnTypeInference DECIMAL_QUOTIENT_NULLABLE = cascade(DECIMAL_QUOTIENT, SqlTypeTransforms.TO_NULLABLE); /** * Type-inference strategy whereby the result type of a call is * {@link #DECIMAL_QUOTIENT_NULLABLE} with a fallback to * {@link #ARG0_INTERVAL_NULLABLE} and {@link #LEAST_RESTRICTIVE}. These rules * are used for division. */ public static final SqlReturnTypeInference QUOTIENT_NULLABLE = chain(DECIMAL_QUOTIENT_NULLABLE, ARG0_INTERVAL_NULLABLE, LEAST_RESTRICTIVE); /** * Type-inference strategy whereby the result type of a call is the decimal * sum of two exact numeric operands where at least one of the operands is a * decimal. */ public static final SqlReturnTypeInference DECIMAL_SUM = opBinding -> { RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); RelDataType type1 = opBinding.getOperandType(0); RelDataType type2 = opBinding.getOperandType(1); return typeFactory.getTypeSystem().deriveDecimalPlusType(typeFactory, type1, type2); }; /** * Same as {@link #DECIMAL_SUM} but returns with nullability if any * of the operands is nullable by using * {@link com.hazelcast.org.apache.calcite.sql.type.SqlTypeTransforms#TO_NULLABLE}. */ public static final SqlReturnTypeInference DECIMAL_SUM_NULLABLE = cascade(DECIMAL_SUM, SqlTypeTransforms.TO_NULLABLE); /** * Type-inference strategy whereby the result type of a call is * {@link #DECIMAL_SUM_NULLABLE} with a fallback to {@link #LEAST_RESTRICTIVE} * These rules are used for addition and subtraction. */ public static final SqlReturnTypeInference NULLABLE_SUM = new SqlReturnTypeInferenceChain(DECIMAL_SUM_NULLABLE, LEAST_RESTRICTIVE); public static final SqlReturnTypeInference DECIMAL_MOD = opBinding -> { RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); RelDataType type1 = opBinding.getOperandType(0); RelDataType type2 = opBinding.getOperandType(1); return typeFactory.getTypeSystem().deriveDecimalModType(typeFactory, type1, type2); }; /** * Type-inference strategy whereby the result type of a call is the decimal * modulus of two exact numeric operands where at least one of the operands is a * decimal. */ public static final SqlReturnTypeInference DECIMAL_MOD_NULLABLE = cascade(DECIMAL_MOD, SqlTypeTransforms.TO_NULLABLE); /** * Type-inference strategy whereby the result type of a call is * {@link #DECIMAL_MOD_NULLABLE} with a fallback to {@link #ARG1_NULLABLE} * These rules are used for modulus. */ public static final SqlReturnTypeInference NULLABLE_MOD = chain(DECIMAL_MOD_NULLABLE, ARG1_NULLABLE); /** * Type-inference strategy whereby the result type of a call is * *

    *
  • the same type as the input types but with the com.hazelcast.com.ined length of the * two first types
  • *
  • if types are of char type the type with the highest coercibility will * be used
  • *
  • result is varying if either input is; otherwise fixed *
* *

Pre-requisites: * *

    *
  • input types must be of the same string type *
  • types must be com.hazelcast.com.arable without casting *
*/ public static final SqlReturnTypeInference DYADIC_STRING_SUM_PRECISION = opBinding -> { final RelDataType argType0 = opBinding.getOperandType(0); final RelDataType argType1 = opBinding.getOperandType(1); final boolean containsAnyType = (argType0.getSqlTypeName() == SqlTypeName.ANY) || (argType1.getSqlTypeName() == SqlTypeName.ANY); final boolean containsNullType = (argType0.getSqlTypeName() == SqlTypeName.NULL) || (argType1.getSqlTypeName() == SqlTypeName.NULL); if (!containsAnyType && !containsNullType && !(SqlTypeUtil.inCharOrBinaryFamilies(argType0) && SqlTypeUtil.inCharOrBinaryFamilies(argType1))) { Preconditions.checkArgument( SqlTypeUtil.sameNamedType(argType0, argType1)); } SqlCollation pickedCollation = null; if (!containsAnyType && !containsNullType && SqlTypeUtil.inCharFamily(argType0)) { if (!SqlTypeUtil.isCharTypeComparable( opBinding.collectOperandTypes().subList(0, 2))) { throw opBinding.newError( RESOURCE.typeNotComparable( argType0.getFullTypeString(), argType1.getFullTypeString())); } pickedCollation = SqlCollation.getCoercibilityDyadicOperator( argType0.getCollation(), argType1.getCollation()); assert null != pickedCollation; } // Determine whether result is variable-length SqlTypeName typeName = argType0.getSqlTypeName(); if (SqlTypeUtil.isBoundedVariableWidth(argType1)) { typeName = argType1.getSqlTypeName(); } RelDataType ret; int typePrecision; final long x = (long) argType0.getPrecision() + (long) argType1.getPrecision(); final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); final RelDataTypeSystem typeSystem = typeFactory.getTypeSystem(); if (argType0.getPrecision() == RelDataType.PRECISION_NOT_SPECIFIED || argType1.getPrecision() == RelDataType.PRECISION_NOT_SPECIFIED || x > typeSystem.getMaxPrecision(typeName)) { typePrecision = RelDataType.PRECISION_NOT_SPECIFIED; } else { typePrecision = (int) x; } ret = typeFactory.createSqlType(typeName, typePrecision); if (null != pickedCollation) { RelDataType pickedType; if (argType0.getCollation().equals(pickedCollation)) { pickedType = argType0; } else if (argType1.getCollation().equals(pickedCollation)) { pickedType = argType1; } else { throw new AssertionError("should never com.hazelcast.com. here"); } ret = typeFactory.createTypeWithCharsetAndCollation(ret, pickedType.getCharset(), pickedType.getCollation()); } if (ret.getSqlTypeName() == SqlTypeName.NULL) { ret = typeFactory.createTypeWithNullability( typeFactory.createSqlType(SqlTypeName.VARCHAR), true); } return ret; }; /** * Type-inference strategy for String concatenation. * Result is varying if either input is; otherwise fixed. * For example, * *

concat(cast('a' as varchar(2)), cast('b' as varchar(3)),cast('c' as varchar(2))) * returns varchar(7).

* *

concat(cast('a' as varchar), cast('b' as varchar(2), cast('c' as varchar(2)))) * returns varchar.

* *

concat(cast('a' as varchar(65535)), cast('b' as varchar(2)), cast('c' as varchar(2))) * returns varchar.

*/ public static final SqlReturnTypeInference MULTIVALENT_STRING_SUM_PRECISION = opBinding -> { boolean hasPrecisionNotSpecifiedOperand = false; boolean precisionOverflow = false; int typePrecision; long amount = 0; List operandTypes = opBinding.collectOperandTypes(); final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); final RelDataTypeSystem typeSystem = typeFactory.getTypeSystem(); for (RelDataType operandType: operandTypes) { int operandPrecision = operandType.getPrecision(); amount = (long) operandPrecision + amount; if (operandPrecision == RelDataType.PRECISION_NOT_SPECIFIED) { hasPrecisionNotSpecifiedOperand = true; break; } if (amount > typeSystem.getMaxPrecision(SqlTypeName.VARCHAR)) { precisionOverflow = true; break; } } if (hasPrecisionNotSpecifiedOperand || precisionOverflow) { typePrecision = RelDataType.PRECISION_NOT_SPECIFIED; } else { typePrecision = (int) amount; } return opBinding.getTypeFactory() .createSqlType(SqlTypeName.VARCHAR, typePrecision); }; /** * Same as {@link #MULTIVALENT_STRING_SUM_PRECISION} and using * {@link com.hazelcast.org.apache.calcite.sql.type.SqlTypeTransforms#TO_NULLABLE}. */ public static final SqlReturnTypeInference MULTIVALENT_STRING_SUM_PRECISION_NULLABLE = cascade(MULTIVALENT_STRING_SUM_PRECISION, SqlTypeTransforms.TO_NULLABLE); /** * Same as {@link #DYADIC_STRING_SUM_PRECISION} and using * {@link com.hazelcast.org.apache.calcite.sql.type.SqlTypeTransforms#TO_NULLABLE}, * {@link com.hazelcast.org.apache.calcite.sql.type.SqlTypeTransforms#TO_VARYING}. */ public static final SqlReturnTypeInference DYADIC_STRING_SUM_PRECISION_NULLABLE_VARYING = cascade(DYADIC_STRING_SUM_PRECISION, SqlTypeTransforms.TO_NULLABLE, SqlTypeTransforms.TO_VARYING); /** * Same as {@link #DYADIC_STRING_SUM_PRECISION} and using * {@link com.hazelcast.org.apache.calcite.sql.type.SqlTypeTransforms#TO_NULLABLE} */ public static final SqlReturnTypeInference DYADIC_STRING_SUM_PRECISION_NULLABLE = cascade(DYADIC_STRING_SUM_PRECISION, SqlTypeTransforms.TO_NULLABLE); /** * Type-inference strategy where the expression is assumed to be registered * as a {@link com.hazelcast.org.apache.calcite.sql.validate.SqlValidatorNamespace}, and * therefore the result type of the call is the type of that namespace. */ public static final SqlReturnTypeInference SCOPE = opBinding -> { SqlCallBinding callBinding = (SqlCallBinding) opBinding; return callBinding.getValidator().getNamespace( callBinding.getCall()).getRowType(); }; /** * Returns a multiset of column #0 of a multiset. For example, given * RECORD(x INTEGER, y DATE) MULTISET, returns INTEGER * MULTISET. */ public static final SqlReturnTypeInference MULTISET_PROJECT0 = opBinding -> { assert opBinding.getOperandCount() == 1; final RelDataType recordMultisetType = opBinding.getOperandType(0); RelDataType multisetType = recordMultisetType.getComponentType(); assert multisetType != null : "expected a multiset type: " + recordMultisetType; final List fields = multisetType.getFieldList(); assert fields.size() > 0; final RelDataType firstColType = fields.get(0).getType(); return opBinding.getTypeFactory().createMultisetType( firstColType, -1); }; /** * Returns a multiset of the first column of a multiset. For example, given * INTEGER MULTISET, returns RECORD(x INTEGER) * MULTISET. */ public static final SqlReturnTypeInference MULTISET_RECORD = opBinding -> { assert opBinding.getOperandCount() == 1; final RelDataType multisetType = opBinding.getOperandType(0); RelDataType com.hazelcast.com.onentType = multisetType.getComponentType(); assert com.hazelcast.com.onentType != null : "expected a multiset type: " + multisetType; final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); final RelDataType type = typeFactory.builder() .add(SqlUtil.deriveAliasFromOrdinal(0), com.hazelcast.com.onentType).build(); return typeFactory.createMultisetType(type, -1); }; /** * Returns the field type of a structured type which has only one field. For * example, given {@code RECORD(x INTEGER)} returns {@code INTEGER}. */ public static final SqlReturnTypeInference RECORD_TO_SCALAR = opBinding -> { assert opBinding.getOperandCount() == 1; final RelDataType recordType = opBinding.getOperandType(0); boolean isStruct = recordType.isStruct(); int fieldCount = recordType.getFieldCount(); assert isStruct && (fieldCount == 1); RelDataTypeField fieldType = recordType.getFieldList().get(0); assert fieldType != null : "expected a record type with one field: " + recordType; final RelDataType firstColType = fieldType.getType(); return opBinding.getTypeFactory().createTypeWithNullability( firstColType, true); }; /** * Type-inference strategy for SUM aggregate function inferred from the * operand type, and nullable if the call occurs within a "GROUP BY ()" * query. E.g. in "select sum(x) as s from empty", s may be null. Also, * with the default implementation of RelDataTypeSystem, s has the same * type name as x. */ public static final SqlReturnTypeInference AGG_SUM = opBinding -> { final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); final RelDataType type = typeFactory.getTypeSystem() .deriveSumType(typeFactory, opBinding.getOperandType(0)); if (opBinding.getGroupCount() == 0 || opBinding.hasFilter()) { return typeFactory.createTypeWithNullability(type, true); } else { return type; } }; /** * Type-inference strategy for $SUM0 aggregate function inferred from the * operand type. By default the inferred type is identical to the operand * type. E.g. in "select $sum0(x) as s from empty", s has the same type as * x. */ public static final SqlReturnTypeInference AGG_SUM_EMPTY_IS_ZERO = opBinding -> { final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); final RelDataType sumType = typeFactory.getTypeSystem() .deriveSumType(typeFactory, opBinding.getOperandType(0)); // SUM0 should not return null. return typeFactory.createTypeWithNullability(sumType, false); }; /** * Type-inference strategy for the {@code CUME_DIST} and {@code PERCENT_RANK} * aggregate functions. */ public static final SqlReturnTypeInference FRACTIONAL_RANK = opBinding -> { final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); return typeFactory.getTypeSystem().deriveFractionalRankType(typeFactory); }; /** * Type-inference strategy for the {@code NTILE}, {@code RANK}, * {@code DENSE_RANK}, and {@code ROW_NUMBER} aggregate functions. */ public static final SqlReturnTypeInference RANK = opBinding -> { final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); return typeFactory.getTypeSystem().deriveRankType(typeFactory); }; public static final SqlReturnTypeInference AVG_AGG_FUNCTION = opBinding -> { final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); final RelDataType relDataType = typeFactory.getTypeSystem().deriveAvgAggType(typeFactory, opBinding.getOperandType(0)); if (opBinding.getGroupCount() == 0 || opBinding.hasFilter()) { return typeFactory.createTypeWithNullability(relDataType, true); } else { return relDataType; } }; public static final SqlReturnTypeInference COVAR_REGR_FUNCTION = opBinding -> { final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); final RelDataType relDataType = typeFactory.getTypeSystem().deriveCovarType(typeFactory, opBinding.getOperandType(0), opBinding.getOperandType(1)); if (opBinding.getGroupCount() == 0 || opBinding.hasFilter()) { return typeFactory.createTypeWithNullability(relDataType, true); } else { return relDataType; } }; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy