diff --git ql/src/test/queries/clientpositive/timestamp_numerics.q ql/src/test/queries/clientpositive/timestamp_numerics.q new file mode 100644 index 0000000..49d85bb --- /dev/null +++ ql/src/test/queries/clientpositive/timestamp_numerics.q @@ -0,0 +1,7 @@ +create table ts1 (key timestamp, value string); +create table ts2 (key timestamp, value string) STORED AS SEQUENCEFILE; +load data local inpath '../data/files/kv1.txt' into table ts1; +load data local inpath '../data/files/kv1.seq' into table ts2; + +select * from ts1 limit 3; +select * from ts2 limit 3; diff --git ql/src/test/results/clientpositive/timestamp_numerics.q.out ql/src/test/results/clientpositive/timestamp_numerics.q.out new file mode 100644 index 0000000..54457df --- /dev/null +++ ql/src/test/results/clientpositive/timestamp_numerics.q.out @@ -0,0 +1,44 @@ +PREHOOK: query: create table ts1 (key timestamp, value string) +PREHOOK: type: CREATETABLE +POSTHOOK: query: create table ts1 (key timestamp, value string) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: default@ts1 +PREHOOK: query: create table ts2 (key timestamp, value string) STORED AS SEQUENCEFILE +PREHOOK: type: CREATETABLE +POSTHOOK: query: create table ts2 (key timestamp, value string) STORED AS SEQUENCEFILE +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: default@ts2 +PREHOOK: query: load data local inpath '../data/files/kv1.txt' into table ts1 +PREHOOK: type: LOAD +PREHOOK: Output: default@ts1 +POSTHOOK: query: load data local inpath '../data/files/kv1.txt' into table ts1 +POSTHOOK: type: LOAD +POSTHOOK: Output: default@ts1 +PREHOOK: query: load data local inpath '../data/files/kv1.seq' into table ts2 +PREHOOK: type: LOAD +PREHOOK: Output: default@ts2 +POSTHOOK: query: load data local inpath '../data/files/kv1.seq' into table ts2 +POSTHOOK: type: LOAD +POSTHOOK: Output: default@ts2 +PREHOOK: query: select * from ts1 limit 3 +PREHOOK: type: QUERY +PREHOOK: Input: default@ts1 +#### A masked pattern was here #### +POSTHOOK: query: select * from ts1 limit 3 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ts1 +#### A masked pattern was here #### +1969-12-31 16:00:00.238 val_238 +1969-12-31 16:00:00.086 val_86 +1969-12-31 16:00:00.311 val_311 +PREHOOK: query: select * from ts2 limit 3 +PREHOOK: type: QUERY +PREHOOK: Input: default@ts2 +#### A masked pattern was here #### +POSTHOOK: query: select * from ts2 limit 3 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ts2 +#### A masked pattern was here #### +1969-12-31 16:00:00.238 val_238 +1969-12-31 16:00:00.086 val_86 +1969-12-31 16:00:00.311 val_311 diff --git serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyTimestamp.java serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyTimestamp.java index 27895c5..b3cf363 100644 --- serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyTimestamp.java +++ serde/src/java/org/apache/hadoop/hive/serde2/lazy/LazyTimestamp.java @@ -48,6 +48,8 @@ public LazyTimestamp(LazyTimestamp copy) { data = new TimestampWritable(copy.data); } + private transient final Timestamp ts = new Timestamp(0); + /** * Initilizes LazyTimestamp object by interpreting the input bytes * as a JDBC timestamp string @@ -66,20 +68,36 @@ public void init(ByteArrayRef bytes, int start, int length) { s = ""; } - Timestamp t = null; if (s.compareTo("NULL") == 0) { isNull = true; logExceptionMessage(bytes, start, length, "TIMESTAMP"); + } else if (s.length() < 19 && isAllNumeric(s)) { + try { + ts.setTime(Long.parseLong(s)); + isNull = false; + } catch (NumberFormatException e) { + isNull = true; + logExceptionMessage(bytes, start, length, "TIMESTAMP"); + } + data.set(ts); } else { try { - t = Timestamp.valueOf(s); + data.set(Timestamp.valueOf(s)); isNull = false; } catch (IllegalArgumentException e) { isNull = true; logExceptionMessage(bytes, start, length, "TIMESTAMP"); } } - data.set(t); + } + + private boolean isAllNumeric(String s) { + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) < '0' || s.charAt(i) > '9') { + return false; + } + } + return true; } private static final String nullTimestamp = "NULL";