You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by sa...@apache.org on 2015/03/07 05:50:25 UTC

phoenix git commit: PHOENIX-1577 Fix for java.lang.IllegalArgumentException: nanos > 999999999 or < 0 while setting timestamp using java.util.Calendar

Repository: phoenix
Updated Branches:
  refs/heads/master c65d5ec49 -> 020bff821


PHOENIX-1577 Fix for java.lang.IllegalArgumentException: nanos > 999999999 or < 0 while setting timestamp using java.util.Calendar


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/020bff82
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/020bff82
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/020bff82

Branch: refs/heads/master
Commit: 020bff8217f68f80cc038173ea8dc504cfb4bf9c
Parents: c65d5ec
Author: Samarth <sa...@salesforce.com>
Authored: Fri Mar 6 20:50:07 2015 -0800
Committer: Samarth <sa...@salesforce.com>
Committed: Fri Mar 6 20:50:07 2015 -0800

----------------------------------------------------------------------
 .../end2end/TimezoneOffsetFunctionIT.java       | 24 ++++++++++++++++++++
 .../phoenix/jdbc/PhoenixPreparedStatement.java  |  3 +--
 .../apache/phoenix/query/QueryConstants.java    |  2 ++
 .../java/org/apache/phoenix/util/DateUtil.java  | 19 +++++++++++++---
 4 files changed, 43 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/020bff82/phoenix-core/src/it/java/org/apache/phoenix/end2end/TimezoneOffsetFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TimezoneOffsetFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TimezoneOffsetFunctionIT.java
index 54bbe9c..96142ed 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TimezoneOffsetFunctionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TimezoneOffsetFunctionIT.java
@@ -23,7 +23,11 @@ import static org.junit.Assert.fail;
 
 import java.sql.Connection;
 import java.sql.DriverManager;
+import java.sql.PreparedStatement;
 import java.sql.ResultSet;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.TimeZone;
 
 import org.apache.phoenix.schema.IllegalDataException;
 import org.junit.Test;
@@ -156,5 +160,25 @@ public class TimezoneOffsetFunctionIT extends BaseHBaseManagedTimeIT {
 		rs.getInt(3);
 		assertTrue(rs.wasNull());
 	}
+	
+	@Test
+	public void testInsertingRetrivingTimestamp() throws Exception {
+	    Connection conn = DriverManager.getConnection(getUrl());
+        String ddl = "CREATE TABLE T (K INTEGER NOT NULL PRIMARY KEY, V TIMESTAMP)";
+        conn.createStatement().execute(ddl);
+        String dml = "UPSERT INTO T VALUES (?, ?)";
+        PreparedStatement stmt = conn.prepareStatement(dml);
+        stmt.setInt(1, 1);
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeZone(TimeZone.getTimeZone("US/Hawaii"));
+        long time = System.currentTimeMillis();
+        stmt.setTimestamp(2, new Timestamp(time), cal);
+        stmt.executeUpdate();
+        conn.commit();
+        String query = "SELECT V FROM T";
+        ResultSet rs = conn.createStatement().executeQuery(query);
+        rs.next();
+        assertEquals(new Timestamp(time), rs.getTimestamp(1));
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/020bff82/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
index 25be8c0..6a65f1d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java
@@ -493,8 +493,7 @@ public class PhoenixPreparedStatement extends PhoenixStatement implements Prepar
 
     @Override
     public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
-        cal.setTime(x);
-        setParameter(parameterIndex,  DateUtil.getTimestamp(cal.getTimeInMillis(), x.getNanos()));
+        setParameter(parameterIndex,  x);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/020bff82/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
index fe7c424..6470b72 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
@@ -171,6 +171,8 @@ public interface QueryConstants {
     public static final double MILLIS_TO_NANOS_CONVERTOR = Math.pow(10, 6);
     public static final BigDecimal BD_MILLIS_NANOS_CONVERSION = BigDecimal.valueOf(MILLIS_TO_NANOS_CONVERTOR);
     public static final BigDecimal BD_MILLIS_IN_DAY = BigDecimal.valueOf(QueryConstants.MILLIS_IN_DAY);
+    public static final int MAX_ALLOWED_NANOS = 999999999;
+    public static final int NANOS_IN_SECOND = BigDecimal.valueOf(Math.pow(10, 9)).intValue();
     public static final String CREATE_TABLE_METADATA =
             // Do not use IF NOT EXISTS as we sometimes catch the TableAlreadyExists
             // exception and add columns to the SYSTEM.TABLE dynamically.

http://git-wip-us.apache.org/repos/asf/phoenix/blob/020bff82/phoenix-core/src/main/java/org/apache/phoenix/util/DateUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/DateUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/DateUtil.java
index 0f4b54a..45c3cef 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/DateUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/DateUtil.java
@@ -17,6 +17,9 @@
  */
 package org.apache.phoenix.util;
 
+import static org.apache.phoenix.query.QueryConstants.MAX_ALLOWED_NANOS;
+import static org.apache.phoenix.query.QueryConstants.MILLIS_TO_NANOS_CONVERTOR;
+
 import java.math.BigDecimal;
 import java.sql.Date;
 import java.sql.Time;
@@ -29,7 +32,6 @@ import java.util.List;
 import java.util.TimeZone;
 
 import org.apache.commons.lang.time.FastDateFormat;
-import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.IllegalDataException;
 import org.apache.phoenix.schema.types.PDataType;
 import org.joda.time.DateTimeZone;
@@ -181,8 +183,19 @@ public class DateUtil {
      * end up losing the sub-second part of timestamp. 
      */
     public static Timestamp getTimestamp(long millis, int nanos) {
+        if (nanos > MAX_ALLOWED_NANOS || nanos < 0) {
+            throw new IllegalArgumentException("nanos > " + MAX_ALLOWED_NANOS + " or < 0");
+        }
         Timestamp ts = new Timestamp(millis);
-        ts.setNanos(ts.getNanos() + nanos);
+        if (ts.getNanos() + nanos > MAX_ALLOWED_NANOS) {
+            int millisToNanosConvertor = BigDecimal.valueOf(MILLIS_TO_NANOS_CONVERTOR).intValue();
+            int overFlowMs = (ts.getNanos() + nanos) / millisToNanosConvertor;
+            int overFlowNanos = (ts.getNanos() + nanos) - (overFlowMs * millisToNanosConvertor);
+            ts = new Timestamp(millis + overFlowMs);
+            ts.setNanos(ts.getNanos() + overFlowNanos);
+        } else {
+            ts.setNanos(ts.getNanos() + nanos);
+        }
         return ts;
     }
 
@@ -190,7 +203,7 @@ public class DateUtil {
      * Utility function to convert a {@link BigDecimal} value to {@link Timestamp}.
      */
     public static Timestamp getTimestamp(BigDecimal bd) {
-        return DateUtil.getTimestamp(bd.longValue(), ((bd.remainder(BigDecimal.ONE).multiply(BigDecimal.valueOf(QueryConstants.MILLIS_TO_NANOS_CONVERTOR))).intValue()));
+        return DateUtil.getTimestamp(bd.longValue(), ((bd.remainder(BigDecimal.ONE).multiply(BigDecimal.valueOf(MILLIS_TO_NANOS_CONVERTOR))).intValue()));
     }
 
     public static interface DateTimeParser {