diff --git ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeGenericFuncDesc.java ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeGenericFuncDesc.java index 002aef6ad2..b6a519998b 100644 --- ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeGenericFuncDesc.java +++ ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeGenericFuncDesc.java @@ -26,6 +26,11 @@ import org.apache.commons.collections.Bag; import org.apache.commons.collections.bag.TreeBag; import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.hadoop.hive.ql.udf.generic.*; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableBooleanObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableConstantBooleanObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableVoidObjectInspector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,10 +45,6 @@ import org.apache.hadoop.hive.ql.session.SessionState; import org.apache.hadoop.hive.ql.session.SessionState.LogHelper; import org.apache.hadoop.hive.ql.udf.UDFType; -import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; -import org.apache.hadoop.hive.ql.udf.generic.GenericUDFBaseCompare; -import org.apache.hadoop.hive.ql.udf.generic.GenericUDFBridge; -import org.apache.hadoop.hive.ql.udf.generic.GenericUDFMacro; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo; @@ -233,6 +234,17 @@ public static ExprNodeGenericFuncDesc newInstance(GenericUDF genericUDF, childrenOIs[i] = children.get(i).getWritableObjectInspector(); } + // Check if nulls are being passed to logical operators + if (genericUDF instanceof GenericUDFOPOr || genericUDF instanceof GenericUDFOPAnd) { + for (int i = 0; i < childrenOIs.length; i++) { + if (childrenOIs[i] instanceof WritableVoidObjectInspector) { + childrenOIs[i] = PrimitiveObjectInspectorFactory + .getPrimitiveWritableConstantObjectInspector(TypeInfoFactory.booleanTypeInfo, null); + } + + } + } + // Check if a bigint is implicitely cast to a double as part of a comparison // Perform the check here instead of in GenericUDFBaseCompare to guarantee it is only run once per operator if (genericUDF instanceof GenericUDFBaseCompare && children.size() == 2) { diff --git ql/src/test/queries/clientpositive/cast3.q ql/src/test/queries/clientpositive/cast3.q new file mode 100644 index 0000000000..daec3741c2 --- /dev/null +++ ql/src/test/queries/clientpositive/cast3.q @@ -0,0 +1,5 @@ +create table cx1(bool0 boolean); + +select cast(NULL as boolean) or bool0 from cx1; + +select NULL or bool0 from cx1; diff --git ql/src/test/results/clientpositive/cast3.q.out ql/src/test/results/clientpositive/cast3.q.out new file mode 100644 index 0000000000..380d4abd9f --- /dev/null +++ ql/src/test/results/clientpositive/cast3.q.out @@ -0,0 +1,24 @@ +PREHOOK: query: create table cx1(bool0 boolean) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@cx1 +POSTHOOK: query: create table cx1(bool0 boolean) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@cx1 +PREHOOK: query: select cast(NULL as boolean) or bool0 from cx1 +PREHOOK: type: QUERY +PREHOOK: Input: default@cx1 +#### A masked pattern was here #### +POSTHOOK: query: select cast(NULL as boolean) or bool0 from cx1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@cx1 +#### A masked pattern was here #### +PREHOOK: query: select NULL or bool0 from cx1 +PREHOOK: type: QUERY +PREHOOK: Input: default@cx1 +#### A masked pattern was here #### +POSTHOOK: query: select NULL or bool0 from cx1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@cx1 +#### A masked pattern was here ####