/**
   * Returns true if a type is a simple cast of another type. It is if the cast type is nullable and
   * the cast is one of the following:
   * <li>x TO x
   * <li>char(n) TO varchar(m)
   * <li>varchar(n) TO varchar(m)
   * <li>x not null TO x nullable
   *
   * @param origType original type passed into the cast operand
   * @param castType type the operand will be casted to
   * @return true if the cast is simple
   */
  private boolean isCastSimple(RelDataType origType, RelDataType castType) {
    SqlTypeName origTypeName = origType.getSqlTypeName();
    SqlTypeName castTypeName = castType.getSqlTypeName();

    if (!(castType.isNullable())) {
      return false;
    }

    Charset origCharset = origType.getCharset();
    Charset castCharset = castType.getCharset();
    if ((origCharset != null) || (castCharset != null)) {
      if ((origCharset == null) || (castCharset == null)) {
        return false;
      }
      if (!origCharset.equals(castCharset)) {
        return false;
      }
    }

    return ((origType == castType)
        || ((origTypeName == SqlTypeName.CHAR) && (castTypeName == SqlTypeName.VARCHAR))
        || ((origTypeName == SqlTypeName.VARCHAR) && (castTypeName == SqlTypeName.VARCHAR))
        || ((origTypeName == castTypeName)
            && (origType.getPrecision() == castType.getPrecision())
            && ((origTypeName != SqlTypeName.DECIMAL)
                || (origType.getScale() == castType.getScale()))
            && (!origType.isNullable() && castType.isNullable())));
  }
示例#2
0
文件: RexUtil.java 项目: kunlqt/optiq
 /**
  * Replaces the operands of a call. The new operands' types must match the old operands' types.
  */
 public static RexCall replaceOperands(RexCall call, RexNode[] operands) {
   if (call.operands == operands) {
     return call;
   }
   for (int i = 0; i < operands.length; i++) {
     RelDataType oldType = call.operands[i].getType();
     RelDataType newType = operands[i].getType();
     if (!oldType.isNullable() && newType.isNullable()) {
       throw Util.newInternal("invalid nullability");
     }
     assert (oldType.toString().equals(newType.toString()));
   }
   return new RexCall(call.getType(), call.getOperator(), operands);
 }
    private void reduceCasts(RexCall outerCast) {
      RexNode[] operands = outerCast.getOperands();
      if (operands.length != 1) {
        return;
      }
      RelDataType outerCastType = outerCast.getType();
      RelDataType operandType = operands[0].getType();
      if (operandType.equals(outerCastType)) {
        removableCasts.add(outerCast);
        return;
      }

      // See if the reduction
      // CAST((CAST x AS type) AS type NOT NULL)
      // -> CAST(x AS type NOT NULL)
      // applies.  TODO jvs 15-Dec-2008:  consider
      // similar cases for precision changes.
      if (!(operands[0] instanceof RexCall)) {
        return;
      }
      RexCall innerCast = (RexCall) operands[0];
      if (innerCast.getOperator() != SqlStdOperatorTable.castFunc) {
        return;
      }
      if (innerCast.getOperands().length != 1) {
        return;
      }
      RelDataTypeFactory typeFactory = preparingStmt.getFarragoTypeFactory();
      RelDataType outerTypeNullable = typeFactory.createTypeWithNullability(outerCastType, true);
      RelDataType innerTypeNullable = typeFactory.createTypeWithNullability(operandType, true);
      if (outerTypeNullable != innerTypeNullable) {
        return;
      }
      if (operandType.isNullable()) {
        removableCasts.add(innerCast);
      }
    }