Exemple #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;
        }
Exemple #2
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));
  }
Exemple #3
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;
 }