Index: ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (working copy) @@ -184,10 +184,6 @@ static Map windowFunctions = Collections.synchronizedMap(new LinkedHashMap()); - /* - * UDAFS that only work when the input rows have an order. - */ - public static final HashSet UDAFS_IMPLY_ORDER = new HashSet(); static { registerUDF("concat", UDFConcat.class, false); @@ -442,15 +438,6 @@ registerWindowFunction(LEAD_FUNC_NAME, new GenericUDAFLead(), false); registerWindowFunction(LAG_FUNC_NAME, new GenericUDAFLag(), false); - UDAFS_IMPLY_ORDER.add("rank"); - UDAFS_IMPLY_ORDER.add("dense_rank"); - UDAFS_IMPLY_ORDER.add("percent_rank"); - UDAFS_IMPLY_ORDER.add("cume_dist"); - UDAFS_IMPLY_ORDER.add(LEAD_FUNC_NAME); - UDAFS_IMPLY_ORDER.add(LAG_FUNC_NAME); - UDAFS_IMPLY_ORDER.add("first_value"); - UDAFS_IMPLY_ORDER.add("last_value"); - registerTableFunction(NOOP_TABLE_FUNCTION, NoopResolver.class); registerTableFunction(NOOP_MAP_TABLE_FUNCTION, NoopWithMapResolver.class); registerTableFunction(WINDOWING_TABLE_FUNCTION, WindowingTableFunctionResolver.class); @@ -1431,8 +1418,30 @@ return windowFunctions.get(name.toLowerCase()); } + /** + * Both UDF and UDAF functions can imply order for analytical functions + * + * @param name + * name of function + * @return true if a GenericUDF or GenericUDAF exists for this name and implyOrder is true, false + * otherwise. + */ public static boolean impliesOrder(String functionName) { - return functionName == null ? false : UDAFS_IMPLY_ORDER.contains(functionName.toLowerCase()); + + FunctionInfo info = mFunctions.get(functionName.toLowerCase()); + if (info != null) { + if (info.isGenericUDF()) { + UDFType type = info.getGenericUDF().getClass().getAnnotation(UDFType.class); + if (type != null) { + return type.impliesOrder(); + } + } + } + WindowFunctionInfo windowInfo = windowFunctions.get(functionName.toLowerCase()); + if (windowInfo != null) { + return windowInfo.isImpliesOrder(); + } + return false; } static void registerHiveUDAFsAsWindowFunctions() Index: ql/src/java/org/apache/hadoop/hive/ql/exec/WindowFunctionDescription.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/WindowFunctionDescription.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/WindowFunctionDescription.java (working copy) @@ -56,5 +56,11 @@ * @return true if ranking function */ boolean rankingFunction() default false; + + /** + * Using in analytical functions to specify that UDF implies an ordering + * @return true if the function implies order + */ + boolean impliesOrder() default false; } Index: ql/src/java/org/apache/hadoop/hive/ql/exec/WindowFunctionInfo.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/WindowFunctionInfo.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/WindowFunctionInfo.java (working copy) @@ -18,8 +18,6 @@ package org.apache.hadoop.hive.ql.exec; -import org.apache.hadoop.hive.ql.exec.FunctionInfo; -import org.apache.hadoop.hive.ql.exec.WindowFunctionDescription; import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFResolver; @SuppressWarnings("deprecation") @@ -27,6 +25,7 @@ { boolean supportsWindow = true; boolean pivotResult = false; + boolean impliesOrder = false; FunctionInfo fInfo; WindowFunctionInfo(FunctionInfo fInfo) @@ -39,6 +38,7 @@ { supportsWindow = def.supportsWindow(); pivotResult = def.pivotResult(); + impliesOrder = def.impliesOrder(); } } @@ -52,6 +52,9 @@ return pivotResult; } + public boolean isImpliesOrder(){ + return impliesOrder; + } public FunctionInfo getfInfo() { return fInfo; Index: ql/src/java/org/apache/hadoop/hive/ql/udf/UDFType.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/UDFType.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/UDFType.java (working copy) @@ -34,4 +34,11 @@ boolean deterministic() default true; boolean stateful() default false; boolean distinctLike() default false; + + /** + * Using in analytical functions to specify that UDF implies an ordering + * + * @return true if the function implies order + */ + boolean impliesOrder() default false; } Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFCumeDist.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFCumeDist.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFCumeDist.java (working copy) @@ -44,7 +44,8 @@ ), supportsWindow = false, pivotResult = true, - rankingFunction = true + rankingFunction = true, + impliesOrder = true ) public class GenericUDAFCumeDist extends GenericUDAFRank { Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFDenseRank.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFDenseRank.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFDenseRank.java (working copy) @@ -35,7 +35,8 @@ ), supportsWindow = false, pivotResult = true, - rankingFunction = true + rankingFunction = true, + impliesOrder = true ) public class GenericUDAFDenseRank extends GenericUDAFRank { Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFFirstValue.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFFirstValue.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFFirstValue.java (working copy) @@ -41,7 +41,8 @@ value = "_FUNC_(x)" ), supportsWindow = true, - pivotResult = false + pivotResult = false, + impliesOrder = true ) public class GenericUDAFFirstValue extends AbstractGenericUDAFResolver { Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLag.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLag.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLag.java (working copy) @@ -33,7 +33,8 @@ value = "_FUNC_(expr, amt, default)" ), supportsWindow = false, - pivotResult = true + pivotResult = true, + impliesOrder = true ) public class GenericUDAFLag extends GenericUDAFLeadLag { Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLastValue.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLastValue.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLastValue.java (working copy) @@ -34,7 +34,7 @@ import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo; import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory; -@WindowFunctionDescription(description = @Description(name = "last_value", value = "_FUNC_(x)"), supportsWindow = true, pivotResult = false) +@WindowFunctionDescription(description = @Description(name = "last_value", value = "_FUNC_(x)"), supportsWindow = true, pivotResult = false, impliesOrder = true) public class GenericUDAFLastValue extends AbstractGenericUDAFResolver { static final Log LOG = LogFactory.getLog(GenericUDAFLastValue.class Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLead.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLead.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFLead.java (working copy) @@ -33,7 +33,8 @@ value = "_FUNC_(expr, amt, default)" ), supportsWindow = false, - pivotResult = true + pivotResult = true, + impliesOrder = true ) public class GenericUDAFLead extends GenericUDAFLeadLag { Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFPercentRank.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFPercentRank.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFPercentRank.java (working copy) @@ -41,7 +41,8 @@ ), supportsWindow = false, pivotResult = true, - rankingFunction = true + rankingFunction = true, + impliesOrder = true ) public class GenericUDAFPercentRank extends GenericUDAFRank { Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFRank.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFRank.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFRank.java (working copy) @@ -45,7 +45,8 @@ ), supportsWindow = false, pivotResult = true, - rankingFunction = true + rankingFunction = true, + impliesOrder = true ) public class GenericUDAFRank extends AbstractGenericUDAFResolver { Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFLeadLag.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFLeadLag.java (revision 1509066) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFLeadLag.java (working copy) @@ -24,6 +24,7 @@ import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException; import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.UDFType; import org.apache.hadoop.hive.serde2.objectinspector.ConstantObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; @@ -197,6 +198,7 @@ protected abstract int getIndex(int amt); + @UDFType(impliesOrder = true) public static class GenericUDFLead extends GenericUDFLeadLag { @@ -219,6 +221,7 @@ } + @UDFType(impliesOrder = true) public static class GenericUDFLag extends GenericUDFLeadLag { @Override Index: ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java =================================================================== --- ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java (revision 1509066) +++ ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java (working copy) @@ -155,4 +155,16 @@ Assert.assertTrue(FunctionRegistry.isRankingFunction("cume_dist")); Assert.assertFalse(FunctionRegistry.isRankingFunction("min")); } + + public void testImpliesOrder() { + Assert.assertTrue(FunctionRegistry.impliesOrder("rank")); + Assert.assertTrue(FunctionRegistry.impliesOrder("dense_rank")); + Assert.assertTrue(FunctionRegistry.impliesOrder("percent_rank")); + Assert.assertTrue(FunctionRegistry.impliesOrder("cume_dist")); + Assert.assertTrue(FunctionRegistry.impliesOrder("first_value")); + Assert.assertTrue(FunctionRegistry.impliesOrder("last_value")); + Assert.assertTrue(FunctionRegistry.impliesOrder("lead")); + Assert.assertTrue(FunctionRegistry.impliesOrder("lag")); + Assert.assertFalse(FunctionRegistry.impliesOrder("min")); + } }