diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java index 08e1136..942fb35 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java @@ -1739,13 +1739,13 @@ public static boolean isOpCast(ExprNodeDesc desc) { if (!(desc instanceof ExprNodeGenericFuncDesc)) { return false; } - GenericUDF genericUDF = ((ExprNodeGenericFuncDesc)desc).getGenericUDF(); - Class udfClass; - if (genericUDF instanceof GenericUDFBridge) { - udfClass = ((GenericUDFBridge)genericUDF).getUdfClass(); - } else { - udfClass = genericUDF.getClass(); - } + return isOpCast(((ExprNodeGenericFuncDesc)desc).getGenericUDF()); + } + + public static boolean isOpCast(GenericUDF genericUDF) { + Class udfClass = (genericUDF instanceof GenericUDFBridge) ? + ((GenericUDFBridge)genericUDF).getUdfClass() : genericUDF.getClass(); + return udfClass == UDFToBoolean.class || udfClass == UDFToByte.class || udfClass == UDFToDouble.class || udfClass == UDFToFloat.class || udfClass == UDFToInteger.class || udfClass == UDFToLong.class || diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/ConstantPropagateProcFactory.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/ConstantPropagateProcFactory.java index 2ac687d..ddc6787 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/ConstantPropagateProcFactory.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/ConstantPropagateProcFactory.java @@ -166,6 +166,10 @@ private static ExprNodeConstantDesc typeCast(ExprNodeDesc desc, TypeInfo ti) { } LOG.debug("Casting " + desc + " to type " + ti); ExprNodeConstantDesc c = (ExprNodeConstantDesc) desc; + if (null != c.getFoldedFromVal() && priti.getTypeName().equals(serdeConstants.STRING_TYPE_NAME)) { + // avoid double casting to preserve original string representation of constant. + return new ExprNodeConstantDesc(c.getFoldedFromVal()); + } ObjectInspector origOI = TypeInfoUtils.getStandardJavaObjectInspectorFromTypeInfo(desc.getTypeInfo()); ObjectInspector oi = @@ -554,7 +558,12 @@ private static ExprNodeDesc evaluateFunction(GenericUDF udf, List LOG.error("Unable to evaluate " + udf + ". Return value unrecoginizable."); return null; } - return new ExprNodeConstantDesc(o); + String constStr = null; + if(arguments.length == 1 && FunctionRegistry.isOpCast(udf)) { + // remember original string representation of constant. + constStr = arguments[0].get().toString(); + } + return new ExprNodeConstantDesc(o).setFoldedFromVal(constStr); } catch (HiveException e) { LOG.error("Evaluation function " + udf.getClass() + " failed in Constant Propagatation Optimizer."); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeConstantDesc.java b/ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeConstantDesc.java index 8a41577..b15df0f 100755 --- a/ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeConstantDesc.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeConstantDesc.java @@ -40,6 +40,17 @@ // If this constant was created while doing constant folding, foldedFromCol holds the name of // original column from which it was folded. private transient String foldedFromCol; + // string representation of folding constant. + private transient String foldedFromVal; + + public ExprNodeConstantDesc setFoldedFromVal(String foldedFromVal) { + this.foldedFromVal = foldedFromVal; + return this; + } + + public String getFoldedFromVal() { + return foldedFromVal; + } public String getFoldedFromCol() { return foldedFromCol; diff --git a/ql/src/test/queries/clientpositive/constprog_type.q b/ql/src/test/queries/clientpositive/constprog_type.q index 93249ad..5683a48 100644 --- a/ql/src/test/queries/clientpositive/constprog_type.q +++ b/ql/src/test/queries/clientpositive/constprog_type.q @@ -12,3 +12,28 @@ SELECT cast('2013-11-17' as date), cast(cast('1.3041352164485E9' as double) as t FROM src tablesample (1 rows); SELECT * FROM dest1; + +SELECT key, value FROM src WHERE key = cast(86 as double); + +CREATE TABLE primitives1 ( + id INT , + bool_col BOOLEAN , + tinyint_col TINYINT , + smallint_col SMALLINT , + int_col INT , + bigint_col BIGINT , + float_col FLOAT , + double_col DOUBLE , + date_string_col STRING , + string_col STRING , + timestamp_col TIMESTAMP ) +ROW FORMAT DELIMITED + FIELDS TERMINATED BY ',' + ESCAPED BY '\\' +STORED AS TEXTFILE; + +LOAD DATA LOCAL INPATH '../../data/files/types/primitives/090101.txt' +OVERWRITE INTO TABLE primitives1 ; + + +select id,bool_col,tinyint_col,smallint_col,int_col,bigint_col,float_col,double_col from primitives1 where id = cast (0 as float) and bool_col = cast('true' as boolean) and tinyint_col = cast(0 as double) and smallint_col = cast(0 as bigint) and int_col = cast (0 as double) and bigint_col = cast(0 as tinyint) and float_col = cast(0.0 as string) and double_col = cast (0.0 as float); diff --git a/ql/src/test/results/clientpositive/constprog_type.q.out b/ql/src/test/results/clientpositive/constprog_type.q.out index 1764184..d145d37 100644 --- a/ql/src/test/results/clientpositive/constprog_type.q.out +++ b/ql/src/test/results/clientpositive/constprog_type.q.out @@ -122,3 +122,69 @@ POSTHOOK: type: QUERY POSTHOOK: Input: default@dest1 #### A masked pattern was here #### 2013-11-17 2011-04-29 20:46:56.4485 +PREHOOK: query: SELECT key, value FROM src WHERE key = cast(86 as double) +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: query: SELECT key, value FROM src WHERE key = cast(86 as double) +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +86 val_86 +PREHOOK: query: CREATE TABLE primitives1 ( + id INT , + bool_col BOOLEAN , + tinyint_col TINYINT , + smallint_col SMALLINT , + int_col INT , + bigint_col BIGINT , + float_col FLOAT , + double_col DOUBLE , + date_string_col STRING , + string_col STRING , + timestamp_col TIMESTAMP ) +ROW FORMAT DELIMITED + FIELDS TERMINATED BY ',' + ESCAPED BY '\\' +STORED AS TEXTFILE +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@primitives1 +POSTHOOK: query: CREATE TABLE primitives1 ( + id INT , + bool_col BOOLEAN , + tinyint_col TINYINT , + smallint_col SMALLINT , + int_col INT , + bigint_col BIGINT , + float_col FLOAT , + double_col DOUBLE , + date_string_col STRING , + string_col STRING , + timestamp_col TIMESTAMP ) +ROW FORMAT DELIMITED + FIELDS TERMINATED BY ',' + ESCAPED BY '\\' +STORED AS TEXTFILE +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@primitives1 +PREHOOK: query: LOAD DATA LOCAL INPATH '../../data/files/types/primitives/090101.txt' +OVERWRITE INTO TABLE primitives1 +PREHOOK: type: LOAD +#### A masked pattern was here #### +PREHOOK: Output: default@primitives1 +POSTHOOK: query: LOAD DATA LOCAL INPATH '../../data/files/types/primitives/090101.txt' +OVERWRITE INTO TABLE primitives1 +POSTHOOK: type: LOAD +#### A masked pattern was here #### +POSTHOOK: Output: default@primitives1 +PREHOOK: query: select id,bool_col,tinyint_col,smallint_col,int_col,bigint_col,float_col,double_col from primitives1 where id = cast (0 as float) and bool_col = cast('true' as boolean) and tinyint_col = cast(0 as double) and smallint_col = cast(0 as bigint) and int_col = cast (0 as double) and bigint_col = cast(0 as tinyint) and float_col = cast(0.0 as string) and double_col = cast (0.0 as float) +PREHOOK: type: QUERY +PREHOOK: Input: default@primitives1 +#### A masked pattern was here #### +POSTHOOK: query: select id,bool_col,tinyint_col,smallint_col,int_col,bigint_col,float_col,double_col from primitives1 where id = cast (0 as float) and bool_col = cast('true' as boolean) and tinyint_col = cast(0 as double) and smallint_col = cast(0 as bigint) and int_col = cast (0 as double) and bigint_col = cast(0 as tinyint) and float_col = cast(0.0 as string) and double_col = cast (0.0 as float) +POSTHOOK: type: QUERY +POSTHOOK: Input: default@primitives1 +#### A masked pattern was here #### +0 true 0 0 0 0 0.0 0.0