Index: ql/src/java/org/apache/hadoop/hive/ql/exec/ExprNodeGenericFuncEvaluator.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/ExprNodeGenericFuncEvaluator.java (revision 1530130) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/ExprNodeGenericFuncEvaluator.java (working copy) @@ -47,35 +47,85 @@ transient boolean isEager; /** - * Class to allow deferred evaluation for GenericUDF. + * + * DeferredExprObject. + * Holds a default result, could be eager or lazy dependent on sub type. */ - class DeferredExprObject implements GenericUDF.DeferredObject { + abstract class DeferredExprObject implements GenericUDF.DeferredObject { - private final boolean eager; private final ExprNodeEvaluator eval; - private transient boolean evaluated; + DeferredExprObject(ExprNodeEvaluator eval) { + this.eval = eval; + } + + @Override + public abstract void prepare(int version) throws HiveException ; + + @Override + public abstract Object get() throws HiveException; + } + + /** + * + * DefferedEagerExprObject. + * prepare() calls get() + */ + class DefferedEagerExprObject extends DeferredExprObject { + + private final ExprNodeEvaluator eval; private transient int version; private transient Object obj; - DeferredExprObject(ExprNodeEvaluator eval, boolean eager) { + DefferedEagerExprObject(ExprNodeEvaluator eval) { + super(eval); this.eval = eval; - this.eager = eager; + this.obj = GenericUDF.NOT_EVALUATED; } @Override public void prepare(int version) throws HiveException { this.version = version; - this.evaluated = false; - if (eager) { - get(); + this.obj = GenericUDF.NOT_EVALUATED; + get(); + } + + @Override + public Object get() throws HiveException { + if (obj == GenericUDF.NOT_EVALUATED) { + obj = eval.evaluate(rowObject, version); } + return obj; } + } + /** + * + * DefferedLazyExprObject. + * prepare() does not call get() + */ + class DefferedLazyExprObject extends DeferredExprObject { + + private final ExprNodeEvaluator eval; + private transient int version; + private transient Object obj; + + DefferedLazyExprObject(ExprNodeEvaluator eval) { + super(eval); + this.eval = eval; + this.obj = GenericUDF.NOT_EVALUATED; + } + + @Override + public void prepare(int version) throws HiveException { + this.version = version; + this.obj = GenericUDF.NOT_EVALUATED; + } + + @Override public Object get() throws HiveException { - if (!evaluated) { + if (obj == GenericUDF.NOT_EVALUATED) { obj = eval.evaluate(rowObject, version); - evaluated = true; } return obj; } @@ -113,7 +163,9 @@ public ObjectInspector initialize(ObjectInspector rowInspector) throws HiveException { deferredChildren = new GenericUDF.DeferredObject[children.length]; for (int i = 0; i < deferredChildren.length; i++) { - deferredChildren[i] = new DeferredExprObject(children[i], isEager); + deferredChildren[i] = isEager ? + new DefferedEagerExprObject(children[i]) + : new DefferedLazyExprObject(children[i]); } // Initialize all children first ObjectInspector[] childrenOIs = new ObjectInspector[children.length]; Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDF.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDF.java (revision 1530130) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDF.java (working copy) @@ -21,8 +21,8 @@ import java.io.Closeable; import java.io.IOException; +import org.apache.hadoop.hive.ql.exec.FunctionRegistry; import org.apache.hadoop.hive.ql.exec.MapredContext; -import org.apache.hadoop.hive.ql.exec.FunctionRegistry; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.udf.UDFType; @@ -46,6 +46,10 @@ public abstract class GenericUDF implements Closeable { /** + * Used by Deferred Object to test evaluation + */ + public static final Object NOT_EVALUATED = new Object(); + /** * A Defered Object allows us to do lazy-evaluation and short-circuiting. * GenericUDF use DeferedObject to pass arguments. */ @@ -59,7 +63,7 @@ * Object reference. */ public static class DeferredJavaObject implements DeferredObject { - private Object value; + private final Object value; public DeferredJavaObject(Object value) { this.value = value;