PageRenderTime 85ms CodeModel.GetById 16ms app.highlight 60ms RepoModel.GetById 2ms app.codeStats 0ms

/tags/release-0.1-rc2/hive/external/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java

#
Java | 1066 lines | 797 code | 105 blank | 164 comment | 111 complexity | 5e768398288ae0dd4a5f13db6dcc3d83 MD5 | raw file
   1/**
   2 * Licensed to the Apache Software Foundation (ASF) under one
   3 * or more contributor license agreements.  See the NOTICE file
   4 * distributed with this work for additional information
   5 * regarding copyright ownership.  The ASF licenses this file
   6 * to you under the Apache License, Version 2.0 (the
   7 * "License"); you may not use this file except in compliance
   8 * with the License.  You may obtain a copy of the License at
   9 *
  10 *     http://www.apache.org/licenses/LICENSE-2.0
  11 *
  12 * Unless required by applicable law or agreed to in writing, software
  13 * distributed under the License is distributed on an "AS IS" BASIS,
  14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15 * See the License for the specific language governing permissions and
  16 * limitations under the License.
  17 */
  18
  19package org.apache.hadoop.hive.ql.exec;
  20
  21import java.lang.reflect.Method;
  22import java.util.ArrayList;
  23import java.util.Arrays;
  24import java.util.HashMap;
  25import java.util.HashSet;
  26import java.util.LinkedHashMap;
  27import java.util.List;
  28import java.util.Map;
  29import java.util.Set;
  30import java.util.TreeSet;
  31import java.util.regex.Pattern;
  32import java.util.regex.PatternSyntaxException;
  33
  34import org.apache.commons.logging.Log;
  35import org.apache.commons.logging.LogFactory;
  36import org.apache.hadoop.hive.ql.metadata.HiveException;
  37import org.apache.hadoop.hive.ql.parse.SemanticException;
  38import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
  39import org.apache.hadoop.hive.ql.plan.ExprNodeGenericFuncDesc;
  40import org.apache.hadoop.hive.ql.udf.UDAFPercentile;
  41import org.apache.hadoop.hive.ql.udf.UDFAbs;
  42import org.apache.hadoop.hive.ql.udf.UDFAcos;
  43import org.apache.hadoop.hive.ql.udf.UDFAscii;
  44import org.apache.hadoop.hive.ql.udf.UDFAsin;
  45import org.apache.hadoop.hive.ql.udf.UDFAtan;
  46import org.apache.hadoop.hive.ql.udf.UDFBin;
  47import org.apache.hadoop.hive.ql.udf.UDFCeil;
  48import org.apache.hadoop.hive.ql.udf.UDFConcat;
  49import org.apache.hadoop.hive.ql.udf.UDFConv;
  50import org.apache.hadoop.hive.ql.udf.UDFCos;
  51import org.apache.hadoop.hive.ql.udf.UDFDate;
  52import org.apache.hadoop.hive.ql.udf.UDFDateAdd;
  53import org.apache.hadoop.hive.ql.udf.UDFDateDiff;
  54import org.apache.hadoop.hive.ql.udf.UDFDateSub;
  55import org.apache.hadoop.hive.ql.udf.UDFDayOfMonth;
  56import org.apache.hadoop.hive.ql.udf.UDFDegrees;
  57import org.apache.hadoop.hive.ql.udf.UDFE;
  58import org.apache.hadoop.hive.ql.udf.UDFExp;
  59import org.apache.hadoop.hive.ql.udf.UDFFindInSet;
  60import org.apache.hadoop.hive.ql.udf.UDFFloor;
  61import org.apache.hadoop.hive.ql.udf.UDFFromUnixTime;
  62import org.apache.hadoop.hive.ql.udf.UDFHex;
  63import org.apache.hadoop.hive.ql.udf.UDFHour;
  64import org.apache.hadoop.hive.ql.udf.UDFJson;
  65import org.apache.hadoop.hive.ql.udf.UDFLTrim;
  66import org.apache.hadoop.hive.ql.udf.UDFLength;
  67import org.apache.hadoop.hive.ql.udf.UDFLike;
  68import org.apache.hadoop.hive.ql.udf.UDFLn;
  69import org.apache.hadoop.hive.ql.udf.UDFLog;
  70import org.apache.hadoop.hive.ql.udf.UDFLog10;
  71import org.apache.hadoop.hive.ql.udf.UDFLog2;
  72import org.apache.hadoop.hive.ql.udf.UDFLower;
  73import org.apache.hadoop.hive.ql.udf.UDFLpad;
  74import org.apache.hadoop.hive.ql.udf.UDFMinute;
  75import org.apache.hadoop.hive.ql.udf.UDFMonth;
  76import org.apache.hadoop.hive.ql.udf.UDFOPBitAnd;
  77import org.apache.hadoop.hive.ql.udf.UDFOPBitNot;
  78import org.apache.hadoop.hive.ql.udf.UDFOPBitOr;
  79import org.apache.hadoop.hive.ql.udf.UDFOPBitXor;
  80import org.apache.hadoop.hive.ql.udf.UDFOPDivide;
  81import org.apache.hadoop.hive.ql.udf.UDFOPLongDivide;
  82import org.apache.hadoop.hive.ql.udf.UDFOPMinus;
  83import org.apache.hadoop.hive.ql.udf.UDFOPMod;
  84import org.apache.hadoop.hive.ql.udf.UDFOPMultiply;
  85import org.apache.hadoop.hive.ql.udf.UDFOPNegative;
  86import org.apache.hadoop.hive.ql.udf.UDFOPPlus;
  87import org.apache.hadoop.hive.ql.udf.UDFOPPositive;
  88import org.apache.hadoop.hive.ql.udf.UDFPI;
  89import org.apache.hadoop.hive.ql.udf.UDFParseUrl;
  90import org.apache.hadoop.hive.ql.udf.UDFPosMod;
  91import org.apache.hadoop.hive.ql.udf.UDFPower;
  92import org.apache.hadoop.hive.ql.udf.UDFRTrim;
  93import org.apache.hadoop.hive.ql.udf.UDFRadians;
  94import org.apache.hadoop.hive.ql.udf.UDFRand;
  95import org.apache.hadoop.hive.ql.udf.UDFRegExp;
  96import org.apache.hadoop.hive.ql.udf.UDFRegExpExtract;
  97import org.apache.hadoop.hive.ql.udf.UDFRegExpReplace;
  98import org.apache.hadoop.hive.ql.udf.UDFRepeat;
  99import org.apache.hadoop.hive.ql.udf.UDFReverse;
 100import org.apache.hadoop.hive.ql.udf.UDFRound;
 101import org.apache.hadoop.hive.ql.udf.UDFRpad;
 102import org.apache.hadoop.hive.ql.udf.UDFSecond;
 103import org.apache.hadoop.hive.ql.udf.UDFSign;
 104import org.apache.hadoop.hive.ql.udf.UDFSin;
 105import org.apache.hadoop.hive.ql.udf.UDFSpace;
 106import org.apache.hadoop.hive.ql.udf.UDFSqrt;
 107import org.apache.hadoop.hive.ql.udf.UDFSubstr;
 108import org.apache.hadoop.hive.ql.udf.UDFTan;
 109import org.apache.hadoop.hive.ql.udf.UDFToBoolean;
 110import org.apache.hadoop.hive.ql.udf.UDFToByte;
 111import org.apache.hadoop.hive.ql.udf.UDFToDouble;
 112import org.apache.hadoop.hive.ql.udf.UDFToFloat;
 113import org.apache.hadoop.hive.ql.udf.UDFToInteger;
 114import org.apache.hadoop.hive.ql.udf.UDFToLong;
 115import org.apache.hadoop.hive.ql.udf.UDFToShort;
 116import org.apache.hadoop.hive.ql.udf.UDFToString;
 117import org.apache.hadoop.hive.ql.udf.UDFTrim;
 118import org.apache.hadoop.hive.ql.udf.UDFType;
 119import org.apache.hadoop.hive.ql.udf.UDFUnhex;
 120import org.apache.hadoop.hive.ql.udf.UDFUnixTimeStamp;
 121import org.apache.hadoop.hive.ql.udf.UDFUpper;
 122import org.apache.hadoop.hive.ql.udf.UDFWeekOfYear;
 123import org.apache.hadoop.hive.ql.udf.UDFYear;
 124import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFAverage;
 125import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFBridge;
 126import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFCollectSet;
 127import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFContextNGrams;
 128import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFCorrelation;
 129import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFCount;
 130import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFCovariance;
 131import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFCovarianceSample;
 132import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
 133import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFHistogramNumeric;
 134import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFMax;
 135import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFMin;
 136import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFParameterInfo;
 137import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFPercentileApprox;
 138import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFResolver;
 139import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFResolver2;
 140import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFStd;
 141import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFStdSample;
 142import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFSum;
 143import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFVariance;
 144import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFVarianceSample;
 145import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFnGrams;
 146import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
 147import org.apache.hadoop.hive.ql.udf.generic.GenericUDFArray;
 148import org.apache.hadoop.hive.ql.udf.generic.GenericUDFArrayContains;
 149import org.apache.hadoop.hive.ql.udf.generic.GenericUDFBridge;
 150import org.apache.hadoop.hive.ql.udf.generic.GenericUDFCase;
 151import org.apache.hadoop.hive.ql.udf.generic.GenericUDFCoalesce;
 152import org.apache.hadoop.hive.ql.udf.generic.GenericUDFConcatWS;
 153import org.apache.hadoop.hive.ql.udf.generic.GenericUDFElt;
 154import org.apache.hadoop.hive.ql.udf.generic.GenericUDFField;
 155import org.apache.hadoop.hive.ql.udf.generic.GenericUDFHash;
 156import org.apache.hadoop.hive.ql.udf.generic.GenericUDFIf;
 157import org.apache.hadoop.hive.ql.udf.generic.GenericUDFIn;
 158import org.apache.hadoop.hive.ql.udf.generic.GenericUDFIndex;
 159import org.apache.hadoop.hive.ql.udf.generic.GenericUDFInstr;
 160import org.apache.hadoop.hive.ql.udf.generic.GenericUDFLocate;
 161import org.apache.hadoop.hive.ql.udf.generic.GenericUDFMap;
 162import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPAnd;
 163import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPEqual;
 164import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPEqualOrGreaterThan;
 165import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPEqualOrLessThan;
 166import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPGreaterThan;
 167import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPLessThan;
 168import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPNot;
 169import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPNotEqual;
 170import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPNotNull;
 171import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPNull;
 172import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPOr;
 173import org.apache.hadoop.hive.ql.udf.generic.GenericUDFReflect;
 174import org.apache.hadoop.hive.ql.udf.generic.GenericUDFSentences;
 175import org.apache.hadoop.hive.ql.udf.generic.GenericUDFSize;
 176import org.apache.hadoop.hive.ql.udf.generic.GenericUDFSplit;
 177import org.apache.hadoop.hive.ql.udf.generic.GenericUDFStringToMap;
 178import org.apache.hadoop.hive.ql.udf.generic.GenericUDFStruct;
 179import org.apache.hadoop.hive.ql.udf.generic.GenericUDFUnion;
 180import org.apache.hadoop.hive.ql.udf.generic.GenericUDFWhen;
 181import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
 182import org.apache.hadoop.hive.ql.udf.generic.GenericUDTFExplode;
 183import org.apache.hadoop.hive.ql.udf.generic.GenericUDTFJSONTuple;
 184import org.apache.hadoop.hive.ql.udf.generic.GenericUDTFParseUrlTuple;
 185import org.apache.hadoop.hive.ql.udf.generic.SimpleGenericUDAFParameterInfo;
 186import org.apache.hadoop.hive.ql.udf.xml.GenericUDFXPath;
 187import org.apache.hadoop.hive.ql.udf.xml.UDFXPathBoolean;
 188import org.apache.hadoop.hive.ql.udf.xml.UDFXPathDouble;
 189import org.apache.hadoop.hive.ql.udf.xml.UDFXPathFloat;
 190import org.apache.hadoop.hive.ql.udf.xml.UDFXPathInteger;
 191import org.apache.hadoop.hive.ql.udf.xml.UDFXPathLong;
 192import org.apache.hadoop.hive.ql.udf.xml.UDFXPathShort;
 193import org.apache.hadoop.hive.ql.udf.xml.UDFXPathString;
 194import org.apache.hadoop.hive.serde.Constants;
 195import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;
 196import org.apache.hadoop.hive.serde2.typeinfo.ListTypeInfo;
 197import org.apache.hadoop.hive.serde2.typeinfo.MapTypeInfo;
 198import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
 199import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
 200import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils;
 201import org.apache.hadoop.util.ReflectionUtils;
 202
 203
 204/**
 205 * FunctionRegistry.
 206 */
 207public final class FunctionRegistry {
 208
 209  private static Log LOG = LogFactory.getLog("org.apache.hadoop.hive.ql.exec.FunctionRegistry");
 210
 211  /**
 212   * The mapping from expression function names to expression classes.
 213   */
 214  static Map<String, FunctionInfo> mFunctions = new LinkedHashMap<String, FunctionInfo>();
 215  static {
 216    registerUDF("concat", UDFConcat.class, false);
 217    registerUDF("substr", UDFSubstr.class, false);
 218    registerUDF("substring", UDFSubstr.class, false);
 219    registerUDF("space", UDFSpace.class, false);
 220    registerUDF("repeat", UDFRepeat.class, false);
 221    registerUDF("ascii", UDFAscii.class, false);
 222    registerUDF("lpad", UDFLpad.class, false);
 223    registerUDF("rpad", UDFRpad.class, false);
 224
 225    registerGenericUDF("size", GenericUDFSize.class);
 226
 227    registerUDF("round", UDFRound.class, false);
 228    registerUDF("floor", UDFFloor.class, false);
 229    registerUDF("sqrt", UDFSqrt.class, false);
 230    registerUDF("ceil", UDFCeil.class, false);
 231    registerUDF("ceiling", UDFCeil.class, false);
 232    registerUDF("rand", UDFRand.class, false);
 233    registerUDF("abs", UDFAbs.class, false);
 234    registerUDF("pmod", UDFPosMod.class, false);
 235
 236    registerUDF("ln", UDFLn.class, false);
 237    registerUDF("log2", UDFLog2.class, false);
 238    registerUDF("sin", UDFSin.class, false);
 239    registerUDF("asin", UDFAsin.class, false);
 240    registerUDF("cos", UDFCos.class, false);
 241    registerUDF("acos", UDFAcos.class, false);
 242    registerUDF("log10", UDFLog10.class, false);
 243    registerUDF("log", UDFLog.class, false);
 244    registerUDF("exp", UDFExp.class, false);
 245    registerUDF("power", UDFPower.class, false);
 246    registerUDF("pow", UDFPower.class, false);
 247    registerUDF("sign", UDFSign.class, false);
 248    registerUDF("pi", UDFPI.class, false);
 249    registerUDF("degrees", UDFDegrees.class, false);
 250    registerUDF("radians", UDFRadians.class, false);
 251    registerUDF("atan", UDFAtan.class, false);
 252    registerUDF("tan", UDFTan.class, false);
 253    registerUDF("e", UDFE.class, false);
 254
 255    registerUDF("conv", UDFConv.class, false);
 256    registerUDF("bin", UDFBin.class, false);
 257    registerUDF("hex", UDFHex.class, false);
 258    registerUDF("unhex", UDFUnhex.class, false);
 259
 260    registerUDF("upper", UDFUpper.class, false);
 261    registerUDF("lower", UDFLower.class, false);
 262    registerUDF("ucase", UDFUpper.class, false);
 263    registerUDF("lcase", UDFLower.class, false);
 264    registerUDF("trim", UDFTrim.class, false);
 265    registerUDF("ltrim", UDFLTrim.class, false);
 266    registerUDF("rtrim", UDFRTrim.class, false);
 267    registerUDF("length", UDFLength.class, false);
 268    registerUDF("reverse", UDFReverse.class, false);
 269    registerGenericUDF("field", GenericUDFField.class);
 270    registerUDF("find_in_set", UDFFindInSet.class, false);
 271
 272    registerUDF("like", UDFLike.class, true);
 273    registerUDF("rlike", UDFRegExp.class, true);
 274    registerUDF("regexp", UDFRegExp.class, true);
 275    registerUDF("regexp_replace", UDFRegExpReplace.class, false);
 276    registerUDF("regexp_extract", UDFRegExpExtract.class, false);
 277    registerUDF("parse_url", UDFParseUrl.class, false);
 278    registerGenericUDF("split", GenericUDFSplit.class);
 279    registerGenericUDF("str_to_map", GenericUDFStringToMap.class);
 280
 281    registerUDF("positive", UDFOPPositive.class, true, "+");
 282    registerUDF("negative", UDFOPNegative.class, true, "-");
 283
 284    registerUDF("day", UDFDayOfMonth.class, false);
 285    registerUDF("dayofmonth", UDFDayOfMonth.class, false);
 286    registerUDF("month", UDFMonth.class, false);
 287    registerUDF("year", UDFYear.class, false);
 288    registerUDF("hour", UDFHour.class, false);
 289    registerUDF("minute", UDFMinute.class, false);
 290    registerUDF("second", UDFSecond.class, false);
 291    registerUDF("from_unixtime", UDFFromUnixTime.class, false);
 292    registerUDF("unix_timestamp", UDFUnixTimeStamp.class, false);
 293    registerUDF("to_date", UDFDate.class, false);
 294    registerUDF("weekofyear", UDFWeekOfYear.class, false);
 295
 296    registerUDF("date_add", UDFDateAdd.class, false);
 297    registerUDF("date_sub", UDFDateSub.class, false);
 298    registerUDF("datediff", UDFDateDiff.class, false);
 299
 300    registerUDF("get_json_object", UDFJson.class, false);
 301
 302    registerUDF("xpath_string", UDFXPathString.class, false);
 303    registerUDF("xpath_boolean", UDFXPathBoolean.class, false);
 304    registerUDF("xpath_number", UDFXPathDouble.class, false);
 305    registerUDF("xpath_double", UDFXPathDouble.class, false);
 306    registerUDF("xpath_float", UDFXPathFloat.class, false);
 307    registerUDF("xpath_long", UDFXPathLong.class, false);
 308    registerUDF("xpath_int", UDFXPathInteger.class, false);
 309    registerUDF("xpath_short", UDFXPathShort.class, false);
 310    registerGenericUDF("xpath", GenericUDFXPath.class);
 311
 312    registerUDF("+", UDFOPPlus.class, true);
 313    registerUDF("-", UDFOPMinus.class, true);
 314    registerUDF("*", UDFOPMultiply.class, true);
 315    registerUDF("/", UDFOPDivide.class, true);
 316    registerUDF("%", UDFOPMod.class, true);
 317    registerUDF("div", UDFOPLongDivide.class, true);
 318
 319    registerUDF("&", UDFOPBitAnd.class, true);
 320    registerUDF("|", UDFOPBitOr.class, true);
 321    registerUDF("^", UDFOPBitXor.class, true);
 322    registerUDF("~", UDFOPBitNot.class, true);
 323
 324    registerGenericUDF("isnull", GenericUDFOPNull.class);
 325    registerGenericUDF("isnotnull", GenericUDFOPNotNull.class);
 326
 327    registerGenericUDF("if", GenericUDFIf.class);
 328    registerGenericUDF("in", GenericUDFIn.class);
 329    registerGenericUDF("and", GenericUDFOPAnd.class);
 330    registerGenericUDF("or", GenericUDFOPOr.class);
 331    registerGenericUDF("=", GenericUDFOPEqual.class);
 332    registerGenericUDF("==", GenericUDFOPEqual.class);
 333    registerGenericUDF("!=", GenericUDFOPNotEqual.class);
 334    registerGenericUDF("<>", GenericUDFOPNotEqual.class);
 335    registerGenericUDF("<", GenericUDFOPLessThan.class);
 336    registerGenericUDF("<=", GenericUDFOPEqualOrLessThan.class);
 337    registerGenericUDF(">", GenericUDFOPGreaterThan.class);
 338    registerGenericUDF(">=", GenericUDFOPEqualOrGreaterThan.class);
 339    registerGenericUDF("not", GenericUDFOPNot.class);
 340    registerGenericUDF("!", GenericUDFOPNot.class);
 341
 342
 343    // Aliases for Java Class Names
 344    // These are used in getImplicitConvertUDFMethod
 345    registerUDF(Constants.BOOLEAN_TYPE_NAME, UDFToBoolean.class, false,
 346        UDFToBoolean.class.getSimpleName());
 347    registerUDF(Constants.TINYINT_TYPE_NAME, UDFToByte.class, false,
 348        UDFToByte.class.getSimpleName());
 349    registerUDF(Constants.SMALLINT_TYPE_NAME, UDFToShort.class, false,
 350        UDFToShort.class.getSimpleName());
 351    registerUDF(Constants.INT_TYPE_NAME, UDFToInteger.class, false,
 352        UDFToInteger.class.getSimpleName());
 353    registerUDF(Constants.BIGINT_TYPE_NAME, UDFToLong.class, false,
 354        UDFToLong.class.getSimpleName());
 355    registerUDF(Constants.FLOAT_TYPE_NAME, UDFToFloat.class, false,
 356        UDFToFloat.class.getSimpleName());
 357    registerUDF(Constants.DOUBLE_TYPE_NAME, UDFToDouble.class, false,
 358        UDFToDouble.class.getSimpleName());
 359    registerUDF(Constants.STRING_TYPE_NAME, UDFToString.class, false,
 360        UDFToString.class.getSimpleName());
 361
 362    // Aggregate functions
 363    registerGenericUDAF("max", new GenericUDAFMax());
 364    registerGenericUDAF("min", new GenericUDAFMin());
 365
 366    registerGenericUDAF("sum", new GenericUDAFSum());
 367    registerGenericUDAF("count", new GenericUDAFCount());
 368    registerGenericUDAF("avg", new GenericUDAFAverage());
 369
 370    registerGenericUDAF("std", new GenericUDAFStd());
 371    registerGenericUDAF("stddev", new GenericUDAFStd());
 372    registerGenericUDAF("stddev_pop", new GenericUDAFStd());
 373    registerGenericUDAF("stddev_samp", new GenericUDAFStdSample());
 374    registerGenericUDAF("variance", new GenericUDAFVariance());
 375    registerGenericUDAF("var_pop", new GenericUDAFVariance());
 376    registerGenericUDAF("var_samp", new GenericUDAFVarianceSample());
 377    registerGenericUDAF("covar_pop", new GenericUDAFCovariance());
 378    registerGenericUDAF("covar_samp", new GenericUDAFCovarianceSample());
 379    registerGenericUDAF("corr", new GenericUDAFCorrelation());
 380    registerGenericUDAF("histogram_numeric", new GenericUDAFHistogramNumeric());
 381    registerGenericUDAF("percentile_approx", new GenericUDAFPercentileApprox());
 382    registerGenericUDAF("collect_set", new GenericUDAFCollectSet());
 383
 384    registerGenericUDAF("ngrams", new GenericUDAFnGrams());
 385    registerGenericUDAF("context_ngrams", new GenericUDAFContextNGrams());
 386
 387    registerUDAF("percentile", UDAFPercentile.class);
 388
 389
 390    // Generic UDFs
 391    registerGenericUDF("reflect", GenericUDFReflect.class);
 392
 393    registerGenericUDF("array", GenericUDFArray.class);
 394    registerGenericUDF("map", GenericUDFMap.class);
 395    registerGenericUDF("struct", GenericUDFStruct.class);
 396    registerGenericUDF("create_union", GenericUDFUnion.class);
 397
 398    registerGenericUDF("case", GenericUDFCase.class);
 399    registerGenericUDF("when", GenericUDFWhen.class);
 400    registerGenericUDF("hash", GenericUDFHash.class);
 401    registerGenericUDF("coalesce", GenericUDFCoalesce.class);
 402    registerGenericUDF("index", GenericUDFIndex.class);
 403    registerGenericUDF("instr", GenericUDFInstr.class);
 404    registerGenericUDF("locate", GenericUDFLocate.class);
 405    registerGenericUDF("elt", GenericUDFElt.class);
 406    registerGenericUDF("concat_ws", GenericUDFConcatWS.class);
 407    registerGenericUDF("array_contains", GenericUDFArrayContains.class);
 408    registerGenericUDF("sentences", GenericUDFSentences.class);
 409
 410    // Generic UDTF's
 411    registerGenericUDTF("explode", GenericUDTFExplode.class);
 412    registerGenericUDTF("json_tuple", GenericUDTFJSONTuple.class);
 413    registerGenericUDTF("parse_url_tuple", GenericUDTFParseUrlTuple.class);
 414  }
 415
 416  public static void registerTemporaryUDF(String functionName,
 417      Class<? extends UDF> UDFClass, boolean isOperator) {
 418    registerUDF(false, functionName, UDFClass, isOperator);
 419  }
 420
 421  static void registerUDF(String functionName, Class<? extends UDF> UDFClass,
 422      boolean isOperator) {
 423    registerUDF(true, functionName, UDFClass, isOperator);
 424  }
 425
 426  public static void registerUDF(boolean isNative, String functionName,
 427      Class<? extends UDF> UDFClass, boolean isOperator) {
 428    registerUDF(isNative, functionName, UDFClass, isOperator, functionName
 429        .toLowerCase());
 430  }
 431
 432  public static void registerUDF(String functionName,
 433      Class<? extends UDF> UDFClass, boolean isOperator, String displayName) {
 434    registerUDF(true, functionName, UDFClass, isOperator, displayName);
 435  }
 436
 437  public static void registerUDF(boolean isNative, String functionName,
 438      Class<? extends UDF> UDFClass, boolean isOperator, String displayName) {
 439    if (UDF.class.isAssignableFrom(UDFClass)) {
 440      FunctionInfo fI = new FunctionInfo(isNative, displayName,
 441          new GenericUDFBridge(displayName, isOperator, UDFClass));
 442      mFunctions.put(functionName.toLowerCase(), fI);
 443    } else {
 444      throw new RuntimeException("Registering UDF Class " + UDFClass
 445          + " which does not extend " + UDF.class);
 446    }
 447  }
 448
 449  public static void registerTemporaryGenericUDF(String functionName,
 450      Class<? extends GenericUDF> genericUDFClass) {
 451    registerGenericUDF(false, functionName, genericUDFClass);
 452  }
 453
 454  static void registerGenericUDF(String functionName,
 455      Class<? extends GenericUDF> genericUDFClass) {
 456    registerGenericUDF(true, functionName, genericUDFClass);
 457  }
 458
 459  public static void registerGenericUDF(boolean isNative, String functionName,
 460      Class<? extends GenericUDF> genericUDFClass) {
 461    if (GenericUDF.class.isAssignableFrom(genericUDFClass)) {
 462      FunctionInfo fI = new FunctionInfo(isNative, functionName,
 463          (GenericUDF) ReflectionUtils.newInstance(genericUDFClass, null));
 464      mFunctions.put(functionName.toLowerCase(), fI);
 465    } else {
 466      throw new RuntimeException("Registering GenericUDF Class "
 467          + genericUDFClass + " which does not extend " + GenericUDF.class);
 468    }
 469  }
 470
 471  public static void registerTemporaryGenericUDTF(String functionName,
 472      Class<? extends GenericUDTF> genericUDTFClass) {
 473    registerGenericUDTF(false, functionName, genericUDTFClass);
 474  }
 475
 476  static void registerGenericUDTF(String functionName,
 477      Class<? extends GenericUDTF> genericUDTFClass) {
 478    registerGenericUDTF(true, functionName, genericUDTFClass);
 479  }
 480
 481  public static void registerGenericUDTF(boolean isNative, String functionName,
 482      Class<? extends GenericUDTF> genericUDTFClass) {
 483    if (GenericUDTF.class.isAssignableFrom(genericUDTFClass)) {
 484      FunctionInfo fI = new FunctionInfo(isNative, functionName,
 485          (GenericUDTF) ReflectionUtils.newInstance(genericUDTFClass, null));
 486      mFunctions.put(functionName.toLowerCase(), fI);
 487    } else {
 488      throw new RuntimeException("Registering GenericUDTF Class "
 489          + genericUDTFClass + " which does not extend " + GenericUDTF.class);
 490    }
 491  }
 492
 493  public static FunctionInfo getFunctionInfo(String functionName) {
 494    return mFunctions.get(functionName.toLowerCase());
 495  }
 496
 497  /**
 498   * Returns a set of registered function names. This is used for the CLI
 499   * command "SHOW FUNCTIONS;"
 500   *
 501   * @return set of strings contains function names
 502   */
 503  public static Set<String> getFunctionNames() {
 504    return mFunctions.keySet();
 505  }
 506
 507  /**
 508   * Returns a set of registered function names. This is used for the CLI
 509   * command "SHOW FUNCTIONS 'regular expression';" Returns an empty set when
 510   * the regular expression is not valid.
 511   *
 512   * @param funcPatternStr
 513   *          regular expression of the interested function names
 514   * @return set of strings contains function names
 515   */
 516  public static Set<String> getFunctionNames(String funcPatternStr) {
 517    Set<String> funcNames = new TreeSet<String>();
 518    Pattern funcPattern = null;
 519    try {
 520      funcPattern = Pattern.compile(funcPatternStr);
 521    } catch (PatternSyntaxException e) {
 522      return funcNames;
 523    }
 524    for (String funcName : mFunctions.keySet()) {
 525      if (funcPattern.matcher(funcName).matches()) {
 526        funcNames.add(funcName);
 527      }
 528    }
 529    return funcNames;
 530  }
 531
 532  /**
 533   * Returns the set of synonyms of the supplied function.
 534   *
 535   * @param funcName
 536   *          the name of the function
 537   * @return Set of synonyms for funcName
 538   */
 539  public static Set<String> getFunctionSynonyms(String funcName) {
 540    Set<String> synonyms = new HashSet<String>();
 541
 542    FunctionInfo funcInfo = getFunctionInfo(funcName);
 543    if (null == funcInfo) {
 544      return synonyms;
 545    }
 546
 547    Class<?> funcClass = funcInfo.getFunctionClass();
 548    for (String name : mFunctions.keySet()) {
 549      if (name.equals(funcName)) {
 550        continue;
 551      }
 552      if (mFunctions.get(name).getFunctionClass().equals(funcClass)) {
 553        synonyms.add(name);
 554      }
 555    }
 556
 557    return synonyms;
 558  }
 559
 560  static Map<TypeInfo, Integer> numericTypes = new HashMap<TypeInfo, Integer>();
 561  static List<TypeInfo> numericTypeList = new ArrayList<TypeInfo>();
 562
 563  static void registerNumericType(String typeName, int level) {
 564    TypeInfo t = TypeInfoFactory.getPrimitiveTypeInfo(typeName);
 565    numericTypeList.add(t);
 566    numericTypes.put(t, level);
 567  }
 568
 569  static {
 570    registerNumericType(Constants.TINYINT_TYPE_NAME, 1);
 571    registerNumericType(Constants.SMALLINT_TYPE_NAME, 2);
 572    registerNumericType(Constants.INT_TYPE_NAME, 3);
 573    registerNumericType(Constants.BIGINT_TYPE_NAME, 4);
 574    registerNumericType(Constants.FLOAT_TYPE_NAME, 5);
 575    registerNumericType(Constants.DOUBLE_TYPE_NAME, 6);
 576    registerNumericType(Constants.STRING_TYPE_NAME, 7);
 577  }
 578
 579  /**
 580   * Find a common class that objects of both TypeInfo a and TypeInfo b can
 581   * convert to. This is used for comparing objects of type a and type b.
 582   *
 583   * When we are comparing string and double, we will always convert both of
 584   * them to double and then compare.
 585   *
 586   * @return null if no common class could be found.
 587   */
 588  public static TypeInfo getCommonClassForComparison(TypeInfo a, TypeInfo b) {
 589    // If same return one of them
 590    if (a.equals(b)) {
 591      return a;
 592    }
 593
 594    for (TypeInfo t : numericTypeList) {
 595      if (FunctionRegistry.implicitConvertable(a, t)
 596          && FunctionRegistry.implicitConvertable(b, t)) {
 597        return t;
 598      }
 599    }
 600    return null;
 601  }
 602
 603  /**
 604   * Find a common class that objects of both TypeInfo a and TypeInfo b can
 605   * convert to. This is used for places other than comparison.
 606   *
 607   * The common class of string and double is string.
 608   *
 609   * @return null if no common class could be found.
 610   */
 611  public static TypeInfo getCommonClass(TypeInfo a, TypeInfo b) {
 612    Integer ai = numericTypes.get(a);
 613    Integer bi = numericTypes.get(b);
 614    if (ai == null || bi == null) {
 615      // If either is not a numeric type, return null.
 616      return null;
 617    }
 618    return (ai > bi) ? a : b;
 619  }
 620
 621  /**
 622   * Returns whether it is possible to implicitly convert an object of Class
 623   * from to Class to.
 624   */
 625  public static boolean implicitConvertable(TypeInfo from, TypeInfo to) {
 626    if (from.equals(to)) {
 627      return true;
 628    }
 629    // Allow implicit String to Double conversion
 630    if (from.equals(TypeInfoFactory.stringTypeInfo)
 631        && to.equals(TypeInfoFactory.doubleTypeInfo)) {
 632      return true;
 633    }
 634    // Void can be converted to any type
 635    if (from.equals(TypeInfoFactory.voidTypeInfo)) {
 636      return true;
 637    }
 638
 639    // Allow implicit conversion from Byte -> Integer -> Long -> Float -> Double
 640    // -> String
 641    Integer f = numericTypes.get(from);
 642    Integer t = numericTypes.get(to);
 643    if (f == null || t == null) {
 644      return false;
 645    }
 646    if (f.intValue() > t.intValue()) {
 647      return false;
 648    }
 649    return true;
 650  }
 651
 652  /**
 653   * Get the GenericUDAF evaluator for the name and argumentClasses.
 654   *
 655   * @param name
 656   *          the name of the UDAF
 657   * @param argumentTypeInfos
 658   * @return The UDAF evaluator
 659   */
 660  @SuppressWarnings("deprecation")
 661  public static GenericUDAFEvaluator getGenericUDAFEvaluator(String name,
 662      List<TypeInfo> argumentTypeInfos, boolean isDistinct,
 663      boolean isAllColumns) throws SemanticException {
 664
 665    GenericUDAFResolver udafResolver = getGenericUDAFResolver(name);
 666    if (udafResolver == null) {
 667      return null;
 668    }
 669
 670    TypeInfo[] parameters = new TypeInfo[argumentTypeInfos.size()];
 671    for (int i = 0; i < parameters.length; i++) {
 672      parameters[i] = argumentTypeInfos.get(i);
 673    }
 674
 675    GenericUDAFEvaluator udafEvaluator = null;
 676    if (udafResolver instanceof GenericUDAFResolver2) {
 677      GenericUDAFParameterInfo paramInfo =
 678          new SimpleGenericUDAFParameterInfo(
 679              parameters, isDistinct, isAllColumns);
 680      udafEvaluator =
 681          ((GenericUDAFResolver2) udafResolver).getEvaluator(paramInfo);
 682    } else {
 683      udafEvaluator = udafResolver.getEvaluator(parameters);
 684    }
 685    return udafEvaluator;
 686  }
 687
 688  /**
 689   * This method is shared between UDFRegistry and UDAFRegistry. methodName will
 690   * be "evaluate" for UDFRegistry, and "aggregate"/"evaluate"/"evaluatePartial"
 691   * for UDAFRegistry.
 692   * @throws UDFArgumentException
 693   */
 694  public static <T> Method getMethodInternal(Class<? extends T> udfClass,
 695      String methodName, boolean exact, List<TypeInfo> argumentClasses)
 696      throws UDFArgumentException {
 697
 698    List<Method> mlist = new ArrayList<Method>();
 699
 700    for (Method m : Arrays.asList(udfClass.getMethods())) {
 701      if (m.getName().equals(methodName)) {
 702        mlist.add(m);
 703      }
 704    }
 705
 706    return getMethodInternal(udfClass, mlist, exact, argumentClasses);
 707  }
 708
 709  public static void registerTemporaryGenericUDAF(String functionName,
 710      GenericUDAFResolver genericUDAFResolver) {
 711    registerGenericUDAF(false, functionName, genericUDAFResolver);
 712  }
 713
 714  static void registerGenericUDAF(String functionName,
 715      GenericUDAFResolver genericUDAFResolver) {
 716    registerGenericUDAF(true, functionName, genericUDAFResolver);
 717  }
 718
 719  public static void registerGenericUDAF(boolean isNative, String functionName,
 720      GenericUDAFResolver genericUDAFResolver) {
 721    mFunctions.put(functionName.toLowerCase(), new FunctionInfo(isNative,
 722        functionName.toLowerCase(), genericUDAFResolver));
 723  }
 724
 725  public static void registerTemporaryUDAF(String functionName,
 726      Class<? extends UDAF> udafClass) {
 727    registerUDAF(false, functionName, udafClass);
 728  }
 729
 730  static void registerUDAF(String functionName, Class<? extends UDAF> udafClass) {
 731    registerUDAF(true, functionName, udafClass);
 732  }
 733
 734  public static void registerUDAF(boolean isNative, String functionName,
 735      Class<? extends UDAF> udafClass) {
 736    mFunctions.put(functionName.toLowerCase(), new FunctionInfo(isNative,
 737        functionName.toLowerCase(), new GenericUDAFBridge(
 738        (UDAF) ReflectionUtils.newInstance(udafClass, null))));
 739  }
 740
 741  public static void unregisterTemporaryUDF(String functionName) throws HiveException {
 742    FunctionInfo fi = mFunctions.get(functionName.toLowerCase());
 743    if (fi != null) {
 744      if (!fi.isNative()) {
 745        mFunctions.remove(functionName.toLowerCase());
 746      } else {
 747        throw new HiveException("Function " + functionName
 748            + " is hive native, it can't be dropped");
 749      }
 750    }
 751  }
 752
 753  public static GenericUDAFResolver getGenericUDAFResolver(String functionName) {
 754    if (LOG.isDebugEnabled()) {
 755      LOG.debug("Looking up GenericUDAF: " + functionName);
 756    }
 757    FunctionInfo finfo = mFunctions.get(functionName.toLowerCase());
 758    if (finfo == null) {
 759      return null;
 760    }
 761    GenericUDAFResolver result = finfo.getGenericUDAFResolver();
 762    return result;
 763  }
 764
 765  public static Object invoke(Method m, Object thisObject, Object... arguments)
 766      throws HiveException {
 767    Object o;
 768    try {
 769      o = m.invoke(thisObject, arguments);
 770    } catch (Exception e) {
 771      String thisObjectString = "" + thisObject + " of class "
 772          + (thisObject == null ? "null" : thisObject.getClass().getName());
 773
 774      StringBuilder argumentString = new StringBuilder();
 775      if (arguments == null) {
 776        argumentString.append("null");
 777      } else {
 778        argumentString.append("{");
 779        for (int i = 0; i < arguments.length; i++) {
 780          if (i > 0) {
 781            argumentString.append(", ");
 782          }
 783          if (arguments[i] == null) {
 784            argumentString.append("null");
 785          } else {
 786            argumentString.append("" + arguments[i] + ":"
 787                + arguments[i].getClass().getName());
 788          }
 789        }
 790        argumentString.append("} of size " + arguments.length);
 791      }
 792
 793      throw new HiveException("Unable to execute method " + m + " "
 794          + " on object " + thisObjectString + " with arguments "
 795          + argumentString.toString(), e);
 796    }
 797    return o;
 798  }
 799
 800  /**
 801   * Returns -1 if passed does not match accepted. Otherwise return the cost
 802   * (usually 0 for no conversion and 1 for conversion).
 803   */
 804  public static int matchCost(TypeInfo argumentPassed,
 805      TypeInfo argumentAccepted, boolean exact) {
 806    if (argumentAccepted.equals(argumentPassed)) {
 807      // matches
 808      return 0;
 809    }
 810    if (argumentPassed.equals(TypeInfoFactory.voidTypeInfo)) {
 811      // passing null matches everything
 812      return 0;
 813    }
 814    if (argumentPassed.getCategory().equals(Category.LIST)
 815        && argumentAccepted.getCategory().equals(Category.LIST)) {
 816      // lists are compatible if and only-if the elements are compatible
 817      TypeInfo argumentPassedElement = ((ListTypeInfo) argumentPassed)
 818          .getListElementTypeInfo();
 819      TypeInfo argumentAcceptedElement = ((ListTypeInfo) argumentAccepted)
 820          .getListElementTypeInfo();
 821      return matchCost(argumentPassedElement, argumentAcceptedElement, exact);
 822    }
 823    if (argumentPassed.getCategory().equals(Category.MAP)
 824        && argumentAccepted.getCategory().equals(Category.MAP)) {
 825      // lists are compatible if and only-if the elements are compatible
 826      TypeInfo argumentPassedKey = ((MapTypeInfo) argumentPassed)
 827          .getMapKeyTypeInfo();
 828      TypeInfo argumentAcceptedKey = ((MapTypeInfo) argumentAccepted)
 829          .getMapKeyTypeInfo();
 830      TypeInfo argumentPassedValue = ((MapTypeInfo) argumentPassed)
 831          .getMapValueTypeInfo();
 832      TypeInfo argumentAcceptedValue = ((MapTypeInfo) argumentAccepted)
 833          .getMapValueTypeInfo();
 834      int cost1 = matchCost(argumentPassedKey, argumentAcceptedKey, exact);
 835      int cost2 = matchCost(argumentPassedValue, argumentAcceptedValue, exact);
 836      if (cost1 < 0 || cost2 < 0) {
 837        return -1;
 838      }
 839      return Math.max(cost1, cost2);
 840    }
 841
 842    if (argumentAccepted.equals(TypeInfoFactory.unknownTypeInfo)) {
 843      // accepting Object means accepting everything,
 844      // but there is a conversion cost.
 845      return 1;
 846    }
 847    if (!exact && implicitConvertable(argumentPassed, argumentAccepted)) {
 848      return 1;
 849    }
 850
 851    return -1;
 852  }
 853
 854  /**
 855   * Gets the closest matching method corresponding to the argument list from a
 856   * list of methods.
 857   *
 858   * @param mlist
 859   *          The list of methods to inspect.
 860   * @param exact
 861   *          Boolean to indicate whether this is an exact match or not.
 862   * @param argumentsPassed
 863   *          The classes for the argument.
 864   * @return The matching method.
 865   */
 866  public static Method getMethodInternal(Class<?> udfClass, List<Method> mlist, boolean exact,
 867      List<TypeInfo> argumentsPassed) throws UDFArgumentException {
 868
 869    // result
 870    List<Method> udfMethods = new ArrayList<Method>();
 871    // The cost of the result
 872    int leastConversionCost = Integer.MAX_VALUE;
 873
 874    for (Method m : mlist) {
 875      List<TypeInfo> argumentsAccepted = TypeInfoUtils.getParameterTypeInfos(m,
 876          argumentsPassed.size());
 877      if (argumentsAccepted == null) {
 878        // null means the method does not accept number of arguments passed.
 879        continue;
 880      }
 881
 882      boolean match = (argumentsAccepted.size() == argumentsPassed.size());
 883      int conversionCost = 0;
 884
 885      for (int i = 0; i < argumentsPassed.size() && match; i++) {
 886        int cost = matchCost(argumentsPassed.get(i), argumentsAccepted.get(i),
 887            exact);
 888        if (cost == -1) {
 889          match = false;
 890        } else {
 891          conversionCost += cost;
 892        }
 893      }
 894      if (LOG.isDebugEnabled()) {
 895        LOG.debug("Method " + (match ? "did" : "didn't") + " match: passed = "
 896                  + argumentsPassed + " accepted = " + argumentsAccepted +
 897                  " method = " + m);
 898      }
 899      if (match) {
 900        // Always choose the function with least implicit conversions.
 901        if (conversionCost < leastConversionCost) {
 902          udfMethods.clear();
 903          udfMethods.add(m);
 904          leastConversionCost = conversionCost;
 905          // Found an exact match
 906          if (leastConversionCost == 0) {
 907            break;
 908          }
 909        } else if (conversionCost == leastConversionCost) {
 910          // Ambiguous call: two methods with the same number of implicit
 911          // conversions
 912          udfMethods.add(m);
 913          // Don't break! We might find a better match later.
 914        } else {
 915          // do nothing if implicitConversions > leastImplicitConversions
 916        }
 917      }
 918    }
 919
 920    if (udfMethods.size() == 0) {
 921      // No matching methods found
 922      throw new NoMatchingMethodException(udfClass, argumentsPassed, mlist);
 923    }
 924    if (udfMethods.size() > 1) {
 925      // Ambiguous method found
 926      throw new AmbiguousMethodException(udfClass, argumentsPassed, mlist);
 927    }
 928    return udfMethods.get(0);
 929  }
 930
 931  /**
 932   * A shortcut to get the "index" GenericUDF. This is used for getting elements
 933   * out of array and getting values out of map.
 934   */
 935  public static GenericUDF getGenericUDFForIndex() {
 936    return FunctionRegistry.getFunctionInfo("index").getGenericUDF();
 937  }
 938
 939  /**
 940   * A shortcut to get the "and" GenericUDF.
 941   */
 942  public static GenericUDF getGenericUDFForAnd() {
 943    return FunctionRegistry.getFunctionInfo("and").getGenericUDF();
 944  }
 945
 946  /**
 947   * Create a copy of an existing GenericUDF.
 948   */
 949  public static GenericUDF cloneGenericUDF(GenericUDF genericUDF) {
 950    if (null == genericUDF) {
 951      return null;
 952    }
 953
 954    if (genericUDF instanceof GenericUDFBridge) {
 955      GenericUDFBridge bridge = (GenericUDFBridge) genericUDF;
 956      return new GenericUDFBridge(bridge.getUdfName(), bridge.isOperator(),
 957          bridge.getUdfClass());
 958    }
 959
 960    return (GenericUDF) ReflectionUtils
 961        .newInstance(genericUDF.getClass(), null);
 962  }
 963
 964  /**
 965   * Create a copy of an existing GenericUDTF.
 966   */
 967  public static GenericUDTF cloneGenericUDTF(GenericUDTF genericUDTF) {
 968    if (null == genericUDTF) {
 969      return null;
 970    }
 971    return (GenericUDTF) ReflectionUtils.newInstance(genericUDTF.getClass(),
 972        null);
 973  }
 974
 975  /**
 976   * Get the UDF class from an exprNodeDesc. Returns null if the exprNodeDesc
 977   * does not contain a UDF class.
 978   */
 979  private static Class<? extends GenericUDF> getGenericUDFClassFromExprDesc(ExprNodeDesc desc) {
 980    if (!(desc instanceof ExprNodeGenericFuncDesc)) {
 981      return null;
 982    }
 983    ExprNodeGenericFuncDesc genericFuncDesc = (ExprNodeGenericFuncDesc) desc;
 984    return genericFuncDesc.getGenericUDF().getClass();
 985  }
 986
 987  /**
 988   * Get the UDF class from an exprNodeDesc. Returns null if the exprNodeDesc
 989   * does not contain a UDF class.
 990   */
 991  private static Class<? extends UDF> getUDFClassFromExprDesc(ExprNodeDesc desc) {
 992    if (!(desc instanceof ExprNodeGenericFuncDesc)) {
 993      return null;
 994    }
 995    ExprNodeGenericFuncDesc genericFuncDesc = (ExprNodeGenericFuncDesc) desc;
 996    if (!(genericFuncDesc.getGenericUDF() instanceof GenericUDFBridge)) {
 997      return null;
 998    }
 999    GenericUDFBridge bridge = (GenericUDFBridge) (genericFuncDesc
1000        .getGenericUDF());
1001    return bridge.getUdfClass();
1002  }
1003
1004  /**
1005   * Returns whether a GenericUDF is deterministic or not.
1006   */
1007  public static boolean isDeterministic(GenericUDF genericUDF) {
1008    UDFType genericUDFType = genericUDF.getClass().getAnnotation(UDFType.class);
1009    if (genericUDFType != null && genericUDFType.deterministic() == false) {
1010      return false;
1011    }
1012
1013    if (genericUDF instanceof GenericUDFBridge) {
1014      GenericUDFBridge bridge = (GenericUDFBridge) (genericUDF);
1015      UDFType bridgeUDFType = bridge.getUdfClass().getAnnotation(UDFType.class);
1016      if (bridgeUDFType != null && bridgeUDFType.deterministic() == false) {
1017        return false;
1018      }
1019    }
1020
1021    return true;
1022  }
1023
1024  /**
1025   * Returns whether the exprNodeDesc is a node of "and", "or", "not".
1026   */
1027  public static boolean isOpAndOrNot(ExprNodeDesc desc) {
1028    Class<? extends GenericUDF> genericUdfClass = getGenericUDFClassFromExprDesc(desc);
1029    return GenericUDFOPAnd.class == genericUdfClass
1030        || GenericUDFOPOr.class == genericUdfClass
1031        || GenericUDFOPNot.class == genericUdfClass;
1032  }
1033
1034  /**
1035   * Returns whether the exprNodeDesc is a node of "and".
1036   */
1037  public static boolean isOpAnd(ExprNodeDesc desc) {
1038    return GenericUDFOPAnd.class == getGenericUDFClassFromExprDesc(desc);
1039  }
1040
1041  /**
1042   * Returns whether the exprNodeDesc is a node of "or".
1043   */
1044  public static boolean isOpOr(ExprNodeDesc desc) {
1045    return GenericUDFOPOr.class == getGenericUDFClassFromExprDesc(desc);
1046  }
1047
1048  /**
1049   * Returns whether the exprNodeDesc is a node of "not".
1050   */
1051  public static boolean isOpNot(ExprNodeDesc desc) {
1052    return GenericUDFOPNot.class == getGenericUDFClassFromExprDesc(desc);
1053  }
1054
1055  /**
1056   * Returns whether the exprNodeDesc is a node of "positive".
1057   */
1058  public static boolean isOpPositive(ExprNodeDesc desc) {
1059    Class<? extends UDF> udfClass = getUDFClassFromExprDesc(desc);
1060    return UDFOPPositive.class == udfClass;
1061  }
1062
1063  private FunctionRegistry() {
1064    // prevent instantiation
1065  }
1066}