diff --git a/ql/src/java/org/apache/hadoop/hive/ql/io/sarg/SearchArgumentImpl.java b/ql/src/java/org/apache/hadoop/hive/ql/io/sarg/SearchArgumentImpl.java index efe03ab..63b3ee9 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/io/sarg/SearchArgumentImpl.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/io/sarg/SearchArgumentImpl.java @@ -117,6 +117,12 @@ public String getColumnName() { @Override public Object getLiteral() { + // To get around a kryo 2.22 bug while deserialize a Timestamp into Date + // (https://github.com/EsotericSoftware/kryo/issues/88) + // When we see a Date, convert back into Timestamp + if (literal instanceof java.util.Date) { + return new Timestamp(((java.util.Date)literal).getTime()); + } return literal; } diff --git a/ql/src/test/org/apache/hadoop/hive/ql/io/sarg/TestSearchArgumentImpl.java b/ql/src/test/org/apache/hadoop/hive/ql/io/sarg/TestSearchArgumentImpl.java index 5e61aba..51f7f47 100644 --- a/ql/src/test/org/apache/hadoop/hive/ql/io/sarg/TestSearchArgumentImpl.java +++ b/ql/src/test/org/apache/hadoop/hive/ql/io/sarg/TestSearchArgumentImpl.java @@ -30,6 +30,7 @@ import org.apache.hadoop.hive.ql.io.sarg.SearchArgument.TruthValue; import org.apache.hadoop.hive.ql.io.sarg.SearchArgumentImpl.ExpressionBuilder; import org.apache.hadoop.hive.ql.io.sarg.SearchArgumentImpl.ExpressionTree; +import org.apache.hadoop.hive.ql.io.sarg.SearchArgumentImpl.PredicateLeafImpl; import org.apache.hadoop.hive.ql.plan.ExprNodeGenericFuncDesc; import org.apache.hadoop.hive.serde2.io.DateWritable; import org.junit.Test; @@ -37,7 +38,9 @@ import java.beans.XMLDecoder; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; import java.math.BigDecimal; +import java.sql.Timestamp; import java.util.List; import java.util.Set; @@ -3038,4 +3041,28 @@ public void testBuilderFloat() throws Exception { "0.22)), eq(z1, 0.22))"; assertEquals(expected, p.toString()); } + + @Test + public void testTimestampSerialization() throws Exception { + // There is a kryo which after serialize/deserialize, + // Timestamp becomes Date. We get around this issue in + // SearchArgumentImpl.getLiteral. Once kryo fixed the issue + // We can simplify SearchArgumentImpl.getLiteral + Timestamp now = new Timestamp(new java.util.Date().getTime()); + SearchArgument sarg = + SearchArgumentFactory.newBuilder() + .startAnd() + .lessThan("x", now) + .end() + .build(); + + String serializedSarg = sarg.toKryo(); + SearchArgument sarg2 = SearchArgumentImpl.fromKryo(serializedSarg); + + Field literalField = PredicateLeafImpl.class.getDeclaredField("literal"); + literalField.setAccessible(true); + assertTrue(literalField.get(sarg2.getLeaves().get(0)) instanceof java.util.Date); + Timestamp ts = (Timestamp)sarg2.getLeaves().get(0).getLiteral(); + assertEquals(ts, now); + } }