Author: hashutosh
Date: Wed Dec 11 21:32:04 2013
New Revision: 1550270
URL: http://svn.apache.org/r1550270
Log:
HIVE-5979. Failure in cast to timestamps. (Jitendra Pandey)
Modified:
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/TimestampUtils.java
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorExpressionWriters.java
Modified:
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/TimestampUtils.java
URL:
http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/TimestampUtils.java?rev=1550270&r1=1550269&r2=1550270&view=diff
==============================================================================
---
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/TimestampUtils.java
(original)
+++
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/TimestampUtils.java
Wed Dec 11 21:32:04 2013
@@ -22,9 +22,27 @@ import java.sql.Timestamp;
public final class TimestampUtils {
+ /**
+ * Store the given timestamp in nanoseconds into the timestamp object.
+ * @param timeInNanoSec Given timestamp in nanoseconds
+ * @param t The timestamp object
+ */
public static void assignTimeInNanoSec(long timeInNanoSec, Timestamp t) {
- t.setTime((timeInNanoSec)/1000000);
- t.setNanos((int)((t.getNanos()) + (timeInNanoSec % 1000000)));
+ /*
+ * java.sql.Timestamp consists of a long variable to store milliseconds
and an integer variable for nanoseconds.
+ * The long variable is used to store only the full seconds converted to
millis. For example for 1234 milliseconds,
+ * 1000 is stored in the long variable, and 234000000 (234 converted to
nanoseconds) is stored as nanoseconds.
+ * The negative timestamps are also supported, but nanoseconds must be
positive therefore millisecond part is
+ * reduced by one second.
+ */
+ long integralSecInMillis = (timeInNanoSec / 1000000000) * 1000; // Full
seconds converted to millis.
+ long nanos = timeInNanoSec % 1000000000; // The nanoseconds.
+ if (nanos < 0) {
+ nanos = 1000000000 + nanos; // The positive nano-part that will be added
to milliseconds.
+ integralSecInMillis = ((timeInNanoSec / 1000000000) - 1) * 1000; //
Reduce by one second.
+ }
+ t.setTime(integralSecInMillis);
+ t.setNanos((int) nanos);
}
public static long getTimeNanoSec(Timestamp t) {
Modified:
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorExpressionWriters.java
URL:
http://svn.apache.org/viewvc/hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorExpressionWriters.java?rev=1550270&r1=1550269&r2=1550270&view=diff
==============================================================================
---
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorExpressionWriters.java
(original)
+++
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorExpressionWriters.java
Wed Dec 11 21:32:04 2013
@@ -418,4 +418,62 @@ public class TestVectorExpressionWriters
public void testVectorExpressionSetterBinary() throws HiveException {
testSetterText(TypeInfoFactory.binaryTypeInfo);
}
+
+ @Test
+ public void testTimeStampUtils(){
+ Timestamp ts = new Timestamp(0);
+
+ // Convert positive nanoseconds to timestamp object.
+ TimestampUtils.assignTimeInNanoSec(1234567891, ts);
+ Assert.assertEquals(234567891, ts.getNanos());
+ Assert.assertEquals(1234567891, TimestampUtils.getTimeNanoSec(ts));
+
+ // Test negative nanoseconds
+ TimestampUtils.assignTimeInNanoSec(-1234567891, ts);
+ Assert.assertEquals((1000000000-234567891), ts.getNanos());
+ Assert.assertEquals(-1234567891, TimestampUtils.getTimeNanoSec(ts));
+
+ // Test positive value smaller than a second.
+ TimestampUtils.assignTimeInNanoSec(234567891, ts);
+ Assert.assertEquals(234567891, ts.getNanos());
+ Assert.assertEquals(234567891, TimestampUtils.getTimeNanoSec(ts));
+
+ // Test negative value smaller than a second.
+ TimestampUtils.assignTimeInNanoSec(-234567891, ts);
+ Assert.assertEquals((1000000000-234567891), ts.getNanos());
+ Assert.assertEquals(-234567891, TimestampUtils.getTimeNanoSec(ts));
+
+ // Test a positive long timestamp
+ long big = 152414813551296L;
+ TimestampUtils.assignTimeInNanoSec(big, ts);
+ Assert.assertEquals(big % 1000000000, ts.getNanos());
+ Assert.assertEquals(big, TimestampUtils.getTimeNanoSec(ts));
+
+ // Test a negative long timestamp
+ big = -152414813551296L;
+ TimestampUtils.assignTimeInNanoSec(big, ts);
+ Assert.assertEquals((1000000000 + (big % 1000000000)), ts.getNanos());
+ Assert.assertEquals(big, TimestampUtils.getTimeNanoSec(ts));
+
+ // big/1000000 will yield zero nanoseconds
+ big = -1794750230000828416L;
+ ts = new Timestamp(0);
+ TimestampUtils.assignTimeInNanoSec(big, ts);
+ Assert.assertEquals((1000000000 + big % 1000000000), ts.getNanos());
+ Assert.assertEquals(big, TimestampUtils.getTimeNanoSec(ts));
+
+ // Very small nanosecond part
+ big = 1700000000000000016L;
+ ts = new Timestamp(0);
+ TimestampUtils.assignTimeInNanoSec(big, ts);
+ Assert.assertEquals(big % 1000000000, ts.getNanos());
+ Assert.assertEquals(big, TimestampUtils.getTimeNanoSec(ts));
+
+ // Very small nanosecond part
+ big = -1700000000000000016L;
+ ts = new Timestamp(0);
+ TimestampUtils.assignTimeInNanoSec(big, ts);
+ Assert.assertEquals((1000000000 + big % 1000000000), ts.getNanos());
+ Assert.assertEquals(big, TimestampUtils.getTimeNanoSec(ts));
+ }
}