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_; }