@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());
  }
  // 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;
 }