public TDropFunctionParams toThrift() { TDropFunctionParams params = new TDropFunctionParams(); params.setFn_name(desc_.getFunctionName().toThrift()); params.setArg_types(PrimitiveType.toThrift(desc_.getArgs())); params.setIf_exists(getIfExists()); return params; }
protected CreateFunctionStmtBase( Function fn, HdfsURI location, boolean ifNotExists, HashMap<OptArg, String> optArgs) { fn_ = fn; fn_.setLocation(location); ifNotExists_ = ifNotExists; optArgs_ = optArgs; }
@Override public String toSql() { StringBuilder sb = new StringBuilder("DROP FUNCTION"); if (ifExists_) sb.append(" IF EXISTS "); sb.append(desc_.signatureString()); sb.append(")"); return sb.toString(); }
@Override public void analyze(Analyzer analyzer) throws AnalysisException, AuthorizationException { // For now, if authorization is enabled, the user needs ALL on the server // to create functions. // TODO: this is not the right granularity but acceptable for now. analyzer.getCatalog().checkCreateDropFunctionAccess(analyzer.getUser()); // Validate function name is legal fn_.getFunctionName().analyze(analyzer); // Validate DB is legal String dbName = analyzer.getTargetDbName(fn_.getFunctionName()); fn_.getFunctionName().setDb(dbName); if (analyzer.getCatalog().getDb(dbName, analyzer.getUser(), Privilege.CREATE) == null) { throw new AnalysisException(Analyzer.DB_DOES_NOT_EXIST_ERROR_MSG + dbName); } Function existingFn = analyzer.getCatalog().getFunction(fn_, Function.CompareMode.IS_INDISTINGUISHABLE); if (existingFn != null && !ifNotExists_) { throw new AnalysisException( Analyzer.FN_ALREADY_EXISTS_ERROR_MSG + existingFn.signatureString()); } fn_.getLocation().analyze(analyzer, Privilege.CREATE); // Check the file type from the binary type to infer the type of the UDA fn_.setBinaryType(getBinaryType()); }
@Override public void analyze(Analyzer analyzer) throws AnalysisException, AuthorizationException { // For now, if authorization is enabled, the user needs ALL on the server // to drop functions. // TODO: this is not the right granularity but acceptable for now. analyzer.getCatalog().checkCreateDropFunctionAccess(analyzer.getUser()); desc_.getFunctionName().analyze(analyzer); String dbName = analyzer.getTargetDbName(desc_.getFunctionName()); desc_.getFunctionName().setDb(dbName); if (analyzer.getCatalog().getDb(dbName, analyzer.getUser(), Privilege.DROP) == null && !ifExists_) { throw new AnalysisException(Analyzer.DB_DOES_NOT_EXIST_ERROR_MSG + dbName); } if (analyzer.getCatalog().getFunction(desc_, Function.CompareMode.IS_IDENTICAL) == null && !ifExists_) { throw new AnalysisException(Analyzer.FN_DOES_NOT_EXIST_ERROR_MSG + desc_.signatureString()); } }
// Returns the resolved symbol in the binary. The BE will do a lookup of 'symbol' // in the binary and try to resolve unmangled names. // If this function is expecting a return argument, retArgType is that type. It should // be null if this function isn't expecting a return argument. protected String lookupSymbol( String symbol, ColumnType retArgType, boolean hasVarArgs, ColumnType... argTypes) throws AnalysisException { if (symbol.length() == 0) { throw new AnalysisException( "Could not find symbol '' in: " + fn_.getLocation().getLocation()); } if (fn_.getBinaryType() == TFunctionBinaryType.HIVE) { // TODO: add this when hive udfs go in. return symbol; } Preconditions.checkState( fn_.getBinaryType() == TFunctionBinaryType.NATIVE || fn_.getBinaryType() == TFunctionBinaryType.IR); TSymbolLookupParams lookup = new TSymbolLookupParams(); lookup.location = fn_.getLocation().toString(); lookup.symbol = symbol; lookup.fn_binary_type = fn_.getBinaryType(); lookup.arg_types = ColumnType.toThrift(argTypes); lookup.has_var_args = hasVarArgs; if (retArgType != null) lookup.setRet_arg_type(retArgType.toThrift()); try { TSymbolLookupResult result = FeSupport.LookupSymbol(lookup); switch (result.result_code) { case SYMBOL_FOUND: return result.symbol; case BINARY_NOT_FOUND: throw new AnalysisException( "Could not load binary: " + fn_.getLocation().getLocation() + "\n" + result.error_msg); case SYMBOL_NOT_FOUND: throw new AnalysisException(result.error_msg); default: // Should never get here. throw new AnalysisException("Internal Error"); } } catch (InternalException e) { throw new AnalysisException("Could not find symbol.", e); } }
// Returns the function's binary type based on the path extension. private TFunctionBinaryType getBinaryType() throws AnalysisException { TFunctionBinaryType binaryType = null; String binaryPath = fn_.getLocation().getLocation(); int suffixIndex = binaryPath.lastIndexOf("."); if (suffixIndex != -1) { String suffix = binaryPath.substring(suffixIndex + 1); if (suffix.equalsIgnoreCase("jar")) { binaryType = TFunctionBinaryType.HIVE; } else if (suffix.equalsIgnoreCase("so")) { binaryType = TFunctionBinaryType.NATIVE; } else if (suffix.equalsIgnoreCase("ll")) { binaryType = TFunctionBinaryType.IR; } } if (binaryType == null) { throw new AnalysisException( "Unknown binary type: '" + binaryPath + "'. Binary must end in .jar, .so or .ll"); } return binaryType; }
protected TCreateFunctionParams toThrift() { TCreateFunctionParams params = new TCreateFunctionParams(fn_.toThrift()); params.setIf_not_exists(getIfNotExists()); return params; }
public FunctionName getFunction() { return desc_.getFunctionName(); }
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)); } } }
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_; }