Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
CreateFunctionStmtBase.java
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.analysis;
16 
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.List;
20 
21 import org.apache.hadoop.fs.permission.FsAction;
22 
31 import com.cloudera.impala.thrift.TCreateFunctionParams;
32 import com.cloudera.impala.thrift.TFunctionBinaryType;
33 import com.google.common.collect.Lists;
34 
38 public abstract class CreateFunctionStmtBase extends StatementBase {
39  // Enums for valid keys for optional arguments.
40  public enum OptArg {
42  SYMBOL, // Only used for Udfs
43  PREPARE_FN, // Only used for Udfs
44  CLOSE_FN, // Only used for Udfs
45  UPDATE_FN, // Only used for Udas
46  INIT_FN, // Only used for Udas
47  SERIALIZE_FN, // Only used for Udas
48  MERGE_FN, // Only used for Udas
49  FINALIZE_FN // Only used for Udas
50  };
51 
52  protected final FunctionName fnName_;
53  protected final FunctionArgs args_;
54  protected final TypeDef retTypeDef_;
55  protected final HdfsUri location_;
56  protected final HashMap<CreateFunctionStmtBase.OptArg, String> optArgs_;
57  protected final boolean ifNotExists_;
58 
59  // Result of analysis.
60  protected Function fn_;
61 
62  // Set in analyze()
63  protected String sqlString_;
64 
66  TypeDef retTypeDef, HdfsUri location, boolean ifNotExists,
67  HashMap<CreateFunctionStmtBase.OptArg, String> optArgs) {
68  fnName_ = fnName;
69  args_ = args;
70  retTypeDef_ = retTypeDef;
71  location_ = location;
72  ifNotExists_ = ifNotExists;
73  optArgs_ = optArgs;
74  }
75 
76  public String getComment() { return optArgs_.get(OptArg.COMMENT); }
77  public boolean getIfNotExists() { return ifNotExists_; }
78 
79  public TCreateFunctionParams toThrift() {
80  TCreateFunctionParams params = new TCreateFunctionParams(fn_.toThrift());
81  params.setIf_not_exists(getIfNotExists());
82  params.setFn(fn_.toThrift());
83  return params;
84  }
85 
86  // Returns optArg[key], first validating that it is set.
87  protected String checkAndGetOptArg(OptArg key)
88  throws AnalysisException {
89  if (!optArgs_.containsKey(key)) {
90  throw new AnalysisException("Argument '" + key + "' must be set.");
91  }
92  return optArgs_.get(key);
93  }
94 
95  protected void checkOptArgNotSet(OptArg key)
96  throws AnalysisException {
97  if (optArgs_.containsKey(key)) {
98  throw new AnalysisException("Optional argument '" + key + "' should not be set.");
99  }
100  }
101 
102  // Returns the function's binary type based on the path extension.
103  private TFunctionBinaryType getBinaryType() throws AnalysisException {
104  TFunctionBinaryType binaryType = null;
105  String binaryPath = fn_.getLocation().getLocation();
106  int suffixIndex = binaryPath.lastIndexOf(".");
107  if (suffixIndex != -1) {
108  String suffix = binaryPath.substring(suffixIndex + 1);
109  if (suffix.equalsIgnoreCase("jar")) {
110  binaryType = TFunctionBinaryType.HIVE;
111  } else if (suffix.equalsIgnoreCase("so")) {
112  binaryType = TFunctionBinaryType.NATIVE;
113  } else if (suffix.equalsIgnoreCase("ll")) {
114  binaryType = TFunctionBinaryType.IR;
115  }
116  }
117  if (binaryType == null) {
118  throw new AnalysisException("Unknown binary type: '" + binaryPath +
119  "'. Binary must end in .jar, .so or .ll");
120  }
121  return binaryType;
122  }
123 
124  @Override
125  public void analyze(Analyzer analyzer) throws AnalysisException {
126  // Validate function name is legal
127  fnName_.analyze(analyzer);
128 
129  // Validate function arguments and return type.
130  args_.analyze(analyzer);
131  retTypeDef_.analyze(analyzer);
132 
133  fn_ = createFunction(fnName_, args_.getArgTypes(), retTypeDef_.getType(),
134  args_.hasVarArgs());
135 
136  // For now, if authorization is enabled, the user needs ALL on the server
137  // to create functions.
138  // TODO: this is not the right granularity but acceptable for now.
139  analyzer.registerPrivReq(new PrivilegeRequest(
140  new AuthorizeableFn(fn_.signatureString()), Privilege.ALL));
141 
142  Db builtinsDb = analyzer.getCatalog().getDb(Catalog.BUILTINS_DB);
143  if (builtinsDb.containsFunction(fn_.getName())) {
144  throw new AnalysisException("Function cannot have the same name as a builtin: " +
145  fn_.getFunctionName().getFunction());
146  }
147 
148  // Forbid unsupported and complex types.
149  List<Type> refdTypes = Lists.newArrayList(fn_.getReturnType());
150  refdTypes.addAll(Lists.newArrayList(fn_.getArgs()));
151  for (Type t: refdTypes) {
152  if (!t.isSupported() || t.isComplexType()) {
153  throw new AnalysisException(
154  String.format("Type '%s' is not supported in UDFs/UDAs.", t.toSql()));
155  }
156  }
157 
158  if (analyzer.getDb(fn_.dbName(), Privilege.CREATE) == null) {
159  throw new AnalysisException(Analyzer.DB_DOES_NOT_EXIST_ERROR_MSG + fn_.dbName());
160  }
161 
162  Function existingFn = analyzer.getCatalog().getFunction(
163  fn_, Function.CompareMode.IS_INDISTINGUISHABLE);
164  if (existingFn != null && !ifNotExists_) {
166  existingFn.signatureString());
167  }
168 
169  location_.analyze(analyzer, Privilege.CREATE, FsAction.READ);
170  fn_.setLocation(location_);
171 
172  // Check the file type from the binary type to infer the type of the UDA
173  fn_.setBinaryType(getBinaryType());
174  }
175 
179  protected abstract Function createFunction(FunctionName fnName,
180  ArrayList<Type> argTypes, Type retType, boolean hasVarArgs);
181 }
final HashMap< CreateFunctionStmtBase.OptArg, String > optArgs_
static final String BUILTINS_DB
Definition: Catalog.java:61
abstract Function createFunction(FunctionName fnName, ArrayList< Type > argTypes, Type retType, boolean hasVarArgs)
static final String DB_DOES_NOT_EXIST_ERROR_MSG
Definition: Analyzer.java:107
CreateFunctionStmtBase(FunctionName fnName, FunctionArgs args, TypeDef retTypeDef, HdfsUri location, boolean ifNotExists, HashMap< CreateFunctionStmtBase.OptArg, String > optArgs)
static final String FN_ALREADY_EXISTS_ERROR_MSG
Definition: Analyzer.java:112