diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java index 96a78fc..48b7ee1 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java @@ -420,7 +420,6 @@ registerGenericUDF(true, LEAD_FUNC_NAME, GenericUDFLead.class); registerGenericUDF(true, LAG_FUNC_NAME, GenericUDFLag.class); - registerHiveUDAFsAsWindowFunctions(); registerWindowFunction("row_number", new GenericUDAFRowNumber()); registerWindowFunction("rank", new GenericUDAFRank()); registerWindowFunction("dense_rank", new GenericUDAFDenseRank()); @@ -1003,6 +1002,10 @@ public static void registerGenericUDAF(boolean isNative, String functionName, GenericUDAFResolver genericUDAFResolver) { FunctionInfo fi = new FunctionInfo(isNative, functionName.toLowerCase(), genericUDAFResolver); mFunctions.put(functionName.toLowerCase(), fi); + + // All aggregate functions should also be usable as window functions + addFunctionInfoToWindowFunctions(functionName, fi); + registerNativeStatus(fi); } @@ -1021,6 +1024,10 @@ public static void registerUDAF(boolean isNative, String functionName, functionName.toLowerCase(), new GenericUDAFBridge( (UDAF) ReflectionUtils.newInstance(udafClass, null))); mFunctions.put(functionName.toLowerCase(), fi); + + // All aggregate functions should also be usable as window functions + addFunctionInfoToWindowFunctions(functionName, fi); + registerNativeStatus(fi); } @@ -1676,16 +1683,14 @@ public static void registerWindowFunction(String name, GenericUDAFResolver wFn, { FunctionInfo fInfo = null; if (registerAsUDAF) { + // Just register the function normally, will also get added to window functions. registerGenericUDAF(true, name, wFn); - fInfo = getFunctionInfo(name); } else { - fInfo = new FunctionInfo(true, - name.toLowerCase(), wFn); + name = name.toLowerCase(); + fInfo = new FunctionInfo(true, name, wFn); + addFunctionInfoToWindowFunctions(name, fInfo); } - - WindowFunctionInfo wInfo = new WindowFunctionInfo(fInfo); - windowFunctions.put(name.toLowerCase(), wInfo); } public static WindowFunctionInfo getWindowFunctionInfo(String name) @@ -1719,18 +1724,11 @@ public static boolean impliesOrder(String functionName) { return false; } - static void registerHiveUDAFsAsWindowFunctions() - { - Set fNames = getFunctionNames(); - for(String fName : fNames) - { - FunctionInfo fInfo = getFunctionInfo(fName); - if ( fInfo.isGenericUDAF()) - { - WindowFunctionInfo wInfo = new WindowFunctionInfo(fInfo); - windowFunctions.put(fName, wInfo); - } - } + static private void addFunctionInfoToWindowFunctions(String functionName, + FunctionInfo functionInfo) { + // Assumes that the caller has already verified that functionInfo is for an aggregate function + WindowFunctionInfo wInfo = new WindowFunctionInfo(functionInfo); + windowFunctions.put(functionName.toLowerCase(), wInfo); } public static boolean isTableFunction(String name) diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/PTFTranslator.java ql/src/java/org/apache/hadoop/hive/ql/parse/PTFTranslator.java index f011258..f339651 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/PTFTranslator.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/PTFTranslator.java @@ -345,6 +345,9 @@ private PartitionedTableFunctionDef translate(PartitionedTableFunctionSpec spec, private WindowFunctionDef translate(WindowTableFunctionDef wdwTFnDef, WindowFunctionSpec spec) throws SemanticException { WindowFunctionInfo wFnInfo = FunctionRegistry.getWindowFunctionInfo(spec.getName()); + if (wFnInfo == null) { + throw new SemanticException(ErrorMsg.INVALID_FUNCTION.getMsg(spec.getName())); + } WindowFunctionDef def = new WindowFunctionDef(); def.setName(spec.getName()); def.setAlias(spec.getAlias()); diff --git ql/src/test/queries/clientnegative/windowing_invalid_udaf.q ql/src/test/queries/clientnegative/windowing_invalid_udaf.q new file mode 100644 index 0000000..c5b593e --- /dev/null +++ ql/src/test/queries/clientnegative/windowing_invalid_udaf.q @@ -0,0 +1 @@ +select nonexistfunc(key) over () from src limit 1; diff --git ql/src/test/queries/clientpositive/windowing_udaf2.q ql/src/test/queries/clientpositive/windowing_udaf2.q new file mode 100644 index 0000000..b813657 --- /dev/null +++ ql/src/test/queries/clientpositive/windowing_udaf2.q @@ -0,0 +1,4 @@ +-- user-added aggregates should be usable as windowing functions +create temporary function mysum as 'org.apache.hadoop.hive.ql.udf.generic.GenericUDAFSum'; + +select sum(key) over (), mysum(key) over () from src limit 1; diff --git ql/src/test/results/clientnegative/windowing_invalid_udaf.q.out ql/src/test/results/clientnegative/windowing_invalid_udaf.q.out new file mode 100644 index 0000000..de9fc2c --- /dev/null +++ ql/src/test/results/clientnegative/windowing_invalid_udaf.q.out @@ -0,0 +1,2 @@ +FAILED: SemanticException Failed to breakup Windowing invocations into Groups. At least 1 group must only depend on input columns. Also check for circular dependencies. +Underlying error: Invalid function nonexistfunc diff --git ql/src/test/results/clientpositive/windowing_udaf2.q.out ql/src/test/results/clientpositive/windowing_udaf2.q.out new file mode 100644 index 0000000..5043a45 --- /dev/null +++ ql/src/test/results/clientpositive/windowing_udaf2.q.out @@ -0,0 +1,15 @@ +PREHOOK: query: -- user-added aggregates should be usable as windowing functions +create temporary function mysum as 'org.apache.hadoop.hive.ql.udf.generic.GenericUDAFSum' +PREHOOK: type: CREATEFUNCTION +POSTHOOK: query: -- user-added aggregates should be usable as windowing functions +create temporary function mysum as 'org.apache.hadoop.hive.ql.udf.generic.GenericUDAFSum' +POSTHOOK: type: CREATEFUNCTION +PREHOOK: query: select sum(key) over (), mysum(key) over () from src limit 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: query: select sum(key) over (), mysum(key) over () from src limit 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +130091.0 130091.0