Ejemplo n.º 1
0
 private static String getFnName(Type targetType) {
   return "castTo" + targetType.getPrimitiveType().toString();
 }
Ejemplo n.º 2
0
 public static void initBuiltins(Db db) {
   for (Type fromType : Type.getSupportedTypes()) {
     if (fromType.isNull()) continue;
     for (Type toType : Type.getSupportedTypes()) {
       if (toType.isNull()) continue;
       // Disable casting from string to boolean
       if (fromType.isStringType() && toType.isBoolean()) continue;
       // Disable casting from boolean/timestamp to decimal
       if ((fromType.isBoolean() || fromType.isDateType()) && toType.isDecimal()) {
         continue;
       }
       if (fromType.getPrimitiveType() == PrimitiveType.STRING
           && toType.getPrimitiveType() == PrimitiveType.CHAR) {
         // Allow casting from String to Char(N)
         String beSymbol = "impala::CastFunctions::CastToChar";
         db.addBuiltin(
             ScalarFunction.createBuiltin(
                 getFnName(ScalarType.CHAR),
                 Lists.newArrayList((Type) ScalarType.STRING),
                 false,
                 ScalarType.CHAR,
                 beSymbol,
                 null,
                 null,
                 true));
         continue;
       }
       if (fromType.getPrimitiveType() == PrimitiveType.CHAR
           && toType.getPrimitiveType() == PrimitiveType.CHAR) {
         // Allow casting from CHAR(N) to Char(N)
         String beSymbol = "impala::CastFunctions::CastToChar";
         db.addBuiltin(
             ScalarFunction.createBuiltin(
                 getFnName(ScalarType.CHAR),
                 Lists.newArrayList((Type) ScalarType.createCharType(-1)),
                 false,
                 ScalarType.CHAR,
                 beSymbol,
                 null,
                 null,
                 true));
         continue;
       }
       if (fromType.getPrimitiveType() == PrimitiveType.VARCHAR
           && toType.getPrimitiveType() == PrimitiveType.VARCHAR) {
         // Allow casting from VARCHAR(N) to VARCHAR(M)
         String beSymbol = "impala::CastFunctions::CastToStringVal";
         db.addBuiltin(
             ScalarFunction.createBuiltin(
                 getFnName(ScalarType.VARCHAR),
                 Lists.newArrayList((Type) ScalarType.VARCHAR),
                 false,
                 ScalarType.VARCHAR,
                 beSymbol,
                 null,
                 null,
                 true));
         continue;
       }
       if (fromType.getPrimitiveType() == PrimitiveType.VARCHAR
           && toType.getPrimitiveType() == PrimitiveType.CHAR) {
         // Allow casting from VARCHAR(N) to CHAR(M)
         String beSymbol = "impala::CastFunctions::CastToChar";
         db.addBuiltin(
             ScalarFunction.createBuiltin(
                 getFnName(ScalarType.CHAR),
                 Lists.newArrayList((Type) ScalarType.VARCHAR),
                 false,
                 ScalarType.CHAR,
                 beSymbol,
                 null,
                 null,
                 true));
         continue;
       }
       if (fromType.getPrimitiveType() == PrimitiveType.CHAR
           && toType.getPrimitiveType() == PrimitiveType.VARCHAR) {
         // Allow casting from CHAR(N) to VARCHAR(M)
         String beSymbol = "impala::CastFunctions::CastToStringVal";
         db.addBuiltin(
             ScalarFunction.createBuiltin(
                 getFnName(ScalarType.VARCHAR),
                 Lists.newArrayList((Type) ScalarType.CHAR),
                 false,
                 ScalarType.VARCHAR,
                 beSymbol,
                 null,
                 null,
                 true));
         continue;
       }
       // Disable no-op casts
       if (fromType.equals(toType) && !fromType.isDecimal()) continue;
       String beClass =
           toType.isDecimal() || fromType.isDecimal() ? "DecimalOperators" : "CastFunctions";
       String beSymbol = "impala::" + beClass + "::CastTo" + Function.getUdfType(toType);
       db.addBuiltin(
           ScalarFunction.createBuiltin(
               getFnName(toType),
               Lists.newArrayList(fromType),
               false,
               toType,
               beSymbol,
               null,
               null,
               true));
     }
   }
 }
Ejemplo n.º 3
0
  private void analyze() throws AnalysisException {
    targetType_.analyze();
    if (targetType_.isComplexType()) {
      throw new AnalysisException("Unsupported cast to complex type: " + targetType_.toSql());
    }

    boolean readyForCharCast =
        children_.get(0).getType().getPrimitiveType() == PrimitiveType.STRING
            || children_.get(0).getType().getPrimitiveType() == PrimitiveType.CHAR;
    if (targetType_.getPrimitiveType() == PrimitiveType.CHAR && !readyForCharCast) {
      // Back end functions only exist to cast string types to CHAR, there is not a cast
      // for every type since it is redundant with STRING. Casts to go through 2 casts:
      // (1) cast to string, to stringify the value
      // (2) cast to CHAR, to truncate or pad with spaces
      CastExpr tostring = new CastExpr(ScalarType.STRING, children_.get(0), true);
      tostring.analyze();
      children_.set(0, tostring);
    }

    if (children_.get(0) instanceof NumericLiteral && targetType_.isFloatingPointType()) {
      // Special case casting a decimal literal to a floating point number. The
      // decimal literal can be interpreted as either and we want to avoid casts
      // since that can result in loss of accuracy.
      ((NumericLiteral) children_.get(0)).explicitlyCastToFloat(targetType_);
    }

    if (children_.get(0).getType().isNull()) {
      // Make sure BE never sees TYPE_NULL
      uncheckedCastChild(targetType_, 0);
    }

    // Ensure child has non-null type (even if it's a null literal). This is required
    // for the UDF interface.
    if (children_.get(0) instanceof NullLiteral) {
      NullLiteral nullChild = (NullLiteral) (children_.get(0));
      nullChild.uncheckedCastTo(targetType_);
    }

    Type childType = children_.get(0).type_;
    Preconditions.checkState(!childType.isNull());
    if (childType.equals(targetType_)) {
      noOp_ = true;
      type_ = targetType_;
      return;
    }

    FunctionName fnName = new FunctionName(Catalog.BUILTINS_DB, getFnName(targetType_));
    Type[] args = {childType};
    Function searchDesc = new Function(fnName, args, Type.INVALID, false);
    if (isImplicit_) {
      fn_ = Catalog.getBuiltin(searchDesc, CompareMode.IS_SUPERTYPE_OF);
      Preconditions.checkState(fn_ != null);
    } else {
      fn_ = Catalog.getBuiltin(searchDesc, CompareMode.IS_IDENTICAL);
      if (fn_ == null) {
        // allow for promotion from CHAR to STRING; only if no exact match is found
        fn_ = Catalog.getBuiltin(searchDesc.promoteCharsToStrings(), CompareMode.IS_IDENTICAL);
      }
    }
    if (fn_ == null) {
      throw new AnalysisException(
          "Invalid type cast of "
              + getChild(0).toSql()
              + " from "
              + childType
              + " to "
              + targetType_);
    }

    Preconditions.checkState(
        targetType_.matchesType(fn_.getReturnType()), targetType_ + " != " + fn_.getReturnType());
    type_ = targetType_;
  }