Example #1
0
        public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
          RelDataType type1 = opBinding.getOperandType(0);
          RelDataType type2 = opBinding.getOperandType(1);
          if (SqlTypeUtil.isExactNumeric(type1) && SqlTypeUtil.isExactNumeric(type2)) {
            if (SqlTypeUtil.isDecimal(type1) || SqlTypeUtil.isDecimal(type2)) {
              int p1 = type1.getPrecision();
              int p2 = type2.getPrecision();
              int s1 = type1.getScale();
              int s2 = type2.getScale();

              int scale = Math.max(s1, s2);
              assert scale <= SqlTypeName.MAX_NUMERIC_SCALE;
              int precision = Math.max(p1 - s1, p2 - s2) + scale + 1;
              precision = Math.min(precision, SqlTypeName.MAX_NUMERIC_PRECISION);
              assert precision > 0;

              RelDataType ret;
              ret = opBinding.getTypeFactory().createSqlType(SqlTypeName.DECIMAL, precision, scale);

              return ret;
            }
          }

          return null;
        }
 private RelDataType[] collectOperandTypes(
     SqlValidator validator, SqlValidatorScope scope, SqlCall call) {
   RelDataType[] argTypes = SqlTypeUtil.deriveAndCollectTypes(validator, scope, call.operands);
   RelDataType[] newArgTypes = {
     argTypes[VALUE_OPERAND], argTypes[LOWER_OPERAND], argTypes[UPPER_OPERAND]
   };
   return newArgTypes;
 }
Example #3
0
  /**
   * Determines whether a {@link RexCall} requires decimal expansion. It usually requires expansion
   * if it has decimal operands.
   *
   * <p>Exceptions to this rule are:
   *
   * <ul>
   *   <li>isNull doesn't require expansion
   *   <li>It's okay to cast decimals to and from char types
   *   <li>It's okay to cast nulls as decimals
   *   <li>Casts require expansion if their return type is decimal
   *   <li>Reinterpret casts can handle a decimal operand
   * </ul>
   *
   * @param expr expression possibly in need of expansion
   * @param recurse whether to check nested calls
   * @return whether the expression requires expansion
   */
  public static boolean requiresDecimalExpansion(RexNode expr, boolean recurse) {
    if (!(expr instanceof RexCall)) {
      return false;
    }
    RexCall call = (RexCall) expr;

    boolean localCheck = true;
    switch (call.getKind()) {
      case Reinterpret:
      case IsNull:
        localCheck = false;
        break;
      case Cast:
        RelDataType lhsType = call.getType();
        RelDataType rhsType = call.operands[0].getType();
        if (rhsType.getSqlTypeName() == SqlTypeName.NULL) {
          return false;
        }
        if (SqlTypeUtil.inCharFamily(lhsType) || SqlTypeUtil.inCharFamily(rhsType)) {
          localCheck = false;
        } else if (SqlTypeUtil.isDecimal(lhsType) && (lhsType != rhsType)) {
          return true;
        }
        break;
      default:
        localCheck = call.getOperator().requiresDecimalExpansion();
    }

    if (localCheck) {
      if (SqlTypeUtil.isDecimal(call.getType())) {
        // NOTE jvs 27-Mar-2007: Depending on the type factory, the
        // result of a division may be decimal, even though both inputs
        // are integer.
        return true;
      }
      for (int i = 0; i < call.operands.length; i++) {
        if (SqlTypeUtil.isDecimal(call.operands[i].getType())) {
          return true;
        }
      }
    }
    return (recurse && requiresDecimalExpansion(call.operands, recurse));
  }
Example #4
0
  /** @return true if all tuples match rowType; otherwise, assert on mismatch */
  private boolean assertRowType() {
    for (List<RexLiteral> tuple : tuples) {
      assert tuple.size() == rowType.getFieldCount();
      for (Pair<RexLiteral, RelDataTypeField> pair : Pair.zip(tuple, rowType.getFieldList())) {
        RexLiteral literal = pair.left;
        RelDataType fieldType = pair.right.getType();

        // TODO jvs 19-Feb-2006: strengthen this a bit.  For example,
        // overflow, rounding, and padding/truncation must already have
        // been dealt with.
        if (!RexLiteral.isNullLiteral(literal)) {
          assert (SqlTypeUtil.canAssignFrom(fieldType, literal.getType()));
        }
      }
    }
    return true;
  }
Example #5
0
 public RelDataType inferReturnType(SqlOperatorBinding 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;
 }
Example #6
0
        /** @pre SqlTypeUtil.sameNamedType(argTypes[0], (argTypes[1])) */
        public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
          final RelDataType argType0 = opBinding.getOperandType(0);
          final RelDataType argType1 = opBinding.getOperandType(1);
          if (!(SqlTypeUtil.inCharOrBinaryFamilies(argType0)
              && SqlTypeUtil.inCharOrBinaryFamilies(argType1))) {
            Util.pre(
                SqlTypeUtil.sameNamedType(argType0, argType1),
                "SqlTypeUtil.sameNamedType(argTypes[0], argTypes[1])");
          }
          SqlCollation pickedCollation = null;
          if (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;
          ret =
              opBinding
                  .getTypeFactory()
                  .createSqlType(typeName, argType0.getPrecision() + argType1.getPrecision());
          if (null != pickedCollation) {
            RelDataType pickedType;
            if (argType0.getCollation().equals(pickedCollation)) {
              pickedType = argType0;
            } else if (argType1.getCollation().equals(pickedCollation)) {
              pickedType = argType1;
            } else {
              throw Util.newInternal("should never come here");
            }
            ret =
                opBinding
                    .getTypeFactory()
                    .createTypeWithCharsetAndCollation(
                        ret, pickedType.getCharset(), pickedType.getCollation());
          }
          return ret;
        }
Example #7
0
 public static void checkCharsetAndCollateConsistentIfCharType(RelDataType type) {
   // (every charset must have a default collation)
   if (SqlTypeUtil.inCharFamily(type)) {
     Charset strCharset = type.getCharset();
     Charset colCharset = type.getCollation().getCharset();
     assert null != strCharset;
     assert null != colCharset;
     if (!strCharset.equals(colCharset)) {
       if (false) {
         // todo: enable this checking when we have a charset to
         //   collation mapping
         throw new Error(
             type.toString()
                 + " was found to have charset '"
                 + strCharset.name()
                 + "' and a mismatched collation charset '"
                 + colCharset.name()
                 + "'");
       }
     }
   }
 }