You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by gr...@apache.org on 2014/12/21 09:36:59 UTC

phoenix git commit: PHOENIX-1127 Support milliseconds in timestamp parsing

Repository: phoenix
Updated Branches:
  refs/heads/3.0 9cd65bf0a -> ddeacbf78


PHOENIX-1127 Support milliseconds in timestamp parsing

Use Joda time for (implicit) date parsing, allowing date-time
values to contain an optional time component, as well as supporting
optional millisecond parsing.


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

Branch: refs/heads/3.0
Commit: ddeacbf78fbed11ddd7409e01920d9d198d40404
Parents: 9cd65bf
Author: Gabriel Reid <gr...@apache.org>
Authored: Sat Dec 20 18:03:58 2014 +0100
Committer: Gabriel Reid <gr...@apache.org>
Committed: Sun Dec 21 09:34:19 2014 +0100

----------------------------------------------------------------------
 .../src/build/components-major-client.xml       |  1 +
 phoenix-core/pom.xml                            |  4 ++
 .../phoenix/end2end/CSVCommonsLoaderIT.java     | 41 ++++++++++++++
 .../java/org/apache/phoenix/util/DateUtil.java  | 57 ++++++++------------
 .../org/apache/phoenix/util/DateUtilTest.java   | 42 +++++++++++++++
 5 files changed, 110 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/ddeacbf7/phoenix-assembly/src/build/components-major-client.xml
----------------------------------------------------------------------
diff --git a/phoenix-assembly/src/build/components-major-client.xml b/phoenix-assembly/src/build/components-major-client.xml
index c3980cd..ca6e9db 100644
--- a/phoenix-assembly/src/build/components-major-client.xml
+++ b/phoenix-assembly/src/build/components-major-client.xml
@@ -49,6 +49,7 @@
         <include>org.codehaus.jackson:jackson-mapper-asl</include>
         <include>org.codehaus.jackson:jackson-core-asl</include>
         <include>org.xerial.snappy:snappy-java</include>
+        <include>joda-time:joda-time</include>
       </includes>
     </dependencySet>
   </dependencySets>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ddeacbf7/phoenix-core/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-core/pom.xml b/phoenix-core/pom.xml
index fceb6c7..6098443 100644
--- a/phoenix-core/pom.xml
+++ b/phoenix-core/pom.xml
@@ -237,6 +237,10 @@
       <groupId>org.apache.hbase</groupId>
       <artifactId>hbase</artifactId>
     </dependency>
+    <dependency>
+      <groupId>joda-time</groupId>
+      <artifactId>joda-time</artifactId>
+    </dependency>
     <!-- Findbugs Annotation -->
     <dependency>
       <groupId>net.sourceforge.findbugs</groupId>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ddeacbf7/phoenix-core/src/it/java/org/apache/phoenix/end2end/CSVCommonsLoaderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CSVCommonsLoaderIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CSVCommonsLoaderIT.java
index e98d5f3..1cc5ff6 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CSVCommonsLoaderIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CSVCommonsLoaderIT.java
@@ -651,6 +651,47 @@ public class CSVCommonsLoaderIT extends BaseHBaseManagedTimeIT {
     }
 
     @Test
+    public void testCSVCommonsUpsert_WithTimestamp() throws Exception {
+        CSVParser parser = null;
+        PhoenixConnection conn = null;
+        try {
+
+            // Create table
+            String statements = "CREATE TABLE IF NOT EXISTS TS_TABLE "
+                    + "(ID BIGINT NOT NULL PRIMARY KEY, TS TIMESTAMP);";
+            conn = DriverManager.getConnection(getUrl()).unwrap(
+                    PhoenixConnection.class);
+            PhoenixRuntime.executeStatements(conn,
+                    new StringReader(statements), null);
+
+            // Upsert CSV file
+            CSVCommonsLoader csvUtil = new CSVCommonsLoader(conn, "TS_TABLE",
+                    null, true, ',', '"', null, "!");
+            csvUtil.upsert(
+                    new StringReader("ID,TS\n"
+                            + "1,1970-01-01 00:00:10\n"
+                            + "2,1970-01-01 00:00:10.123\n"));
+
+            // Compare Phoenix ResultSet with CSV file content
+            PreparedStatement statement = conn
+                    .prepareStatement("SELECT ID, TS FROM TS_TABLE ORDER BY ID");
+            ResultSet phoenixResultSet = statement.executeQuery();
+            assertTrue(phoenixResultSet.next());
+            assertEquals(1L, phoenixResultSet.getLong(1));
+            assertEquals(10000L, phoenixResultSet.getTimestamp(2).getTime());
+            assertTrue(phoenixResultSet.next());
+            assertEquals(2L, phoenixResultSet.getLong(1));
+            assertEquals(10123L, phoenixResultSet.getTimestamp(2).getTime());
+            assertFalse(phoenixResultSet.next());
+        } finally {
+            if (parser != null)
+                parser.close();
+            if (conn != null)
+                conn.close();
+        }
+    }
+
+    @Test
     public void testCSVCommonsUpsert_NonExistentTable() throws Exception {
         PhoenixConnection conn = null;
         try {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ddeacbf7/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 c940067..8952708 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
@@ -30,7 +30,11 @@ import org.apache.commons.lang.time.FastDateFormat;
 
 import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.IllegalDataException;
-
+import org.joda.time.DateTime;
+import org.joda.time.chrono.ISOChronology;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.DateTimeFormatterBuilder;
+import org.joda.time.format.ISODateTimeFormat;
 
 
 @SuppressWarnings("serial")
@@ -45,6 +49,14 @@ public class DateUtil {
     public static final Format DEFAULT_MS_DATE_FORMATTER = FastDateFormat.getInstance(
             DEFAULT_MS_DATE_FORMAT, TimeZone.getTimeZone(DEFAULT_TIME_ZONE_ID));
 
+    private static final DateTimeFormatter DATE_TIME_PARSER = new DateTimeFormatterBuilder()
+            .append(ISODateTimeFormat.dateParser())
+            .appendOptional(new DateTimeFormatterBuilder()
+                    .appendLiteral(' ')
+                    .append(ISODateTimeFormat.timeParser()).toParser())
+            .toFormatter()
+            .withChronology(ISOChronology.getInstanceUTC());
+
     private DateUtil() {
     }
 
@@ -102,49 +114,24 @@ public class DateUtil {
                 : FastDateFormat.getInstance(pattern, DateUtil.DEFAULT_TIME_ZONE);
     }
 
-    private static ThreadLocal<Format> dateFormat =
-            new ThreadLocal < Format > () {
-        @Override protected Format initialValue() {
-            return getDateParser(DEFAULT_DATE_FORMAT);
-        }
-    };
-
-    public static Date parseDate(String dateValue) {
+    private static DateTime parseDateTime(String dateTimeValue) {
         try {
-            return (Date)dateFormat.get().parseObject(dateValue);
-        } catch (ParseException e) {
+            return DATE_TIME_PARSER.parseDateTime(dateTimeValue);
+        } catch (IllegalArgumentException e) {
             throw new IllegalDataException(e);
         }
     }
 
-    private static ThreadLocal<Format> timeFormat =
-            new ThreadLocal < Format > () {
-        @Override protected Format initialValue() {
-            return getTimeParser(DEFAULT_DATE_FORMAT);
-        }
-    };
+    public static Date parseDate(String dateValue) {
+        return new Date(parseDateTime(dateValue).getMillis());
+    }
 
     public static Time parseTime(String timeValue) {
-        try {
-            return (Time)timeFormat.get().parseObject(timeValue);
-        } catch (ParseException e) {
-            throw new IllegalDataException(e);
-        }
+        return new Time(parseDateTime(timeValue).getMillis());
     }
 
-    private static ThreadLocal<Format> timestampFormat =
-            new ThreadLocal < Format > () {
-        @Override protected Format initialValue() {
-            return getTimestampParser(DEFAULT_DATE_FORMAT);
-        }
-    };
-
-    public static Timestamp parseTimestamp(String timeValue) {
-        try {
-            return (Timestamp)timestampFormat.get().parseObject(timeValue);
-        } catch (ParseException e) {
-            throw new IllegalDataException(e);
-        }
+    public static Timestamp parseTimestamp(String timestampValue) {
+        return new Timestamp(parseDateTime(timestampValue).getMillis());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/phoenix/blob/ddeacbf7/phoenix-core/src/test/java/org/apache/phoenix/util/DateUtilTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/DateUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/DateUtilTest.java
index 36acf70..e5d4dfa 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/DateUtilTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/DateUtilTest.java
@@ -23,11 +23,13 @@ import java.sql.Timestamp;
 import java.text.ParseException;
 import java.util.TimeZone;
 
+import org.apache.phoenix.schema.IllegalDataException;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 /**
  * Test class for {@link DateUtil}
@@ -127,4 +129,44 @@ public class DateUtilTest {
                 "HH:mm:ss", TimeZone.getDefault()).parseObject("00:00:00");
         assertEquals(Time.valueOf("00:00:00"), time);
     }
+
+    @Test
+    public void testParseDate() {
+        assertEquals(10000L, DateUtil.parseDate("1970-01-01 00:00:10").getTime());
+    }
+
+    @Test
+    public void testParseDate_PureDate() {
+        assertEquals(0L, DateUtil.parseDate("1970-01-01").getTime());
+    }
+
+    @Test(expected = IllegalDataException.class)
+    public void testParseDate_InvalidDate() {
+        DateUtil.parseDate("not-a-date");
+    }
+
+    @Test
+    public void testParseTime() {
+        assertEquals(10000L, DateUtil.parseTime("1970-01-01 00:00:10").getTime());
+    }
+
+    @Test(expected=IllegalDataException.class)
+    public void testParseTime_InvalidTime() {
+        DateUtil.parseDate("not-a-time");
+    }
+
+    @Test
+    public void testParseTimestamp() {
+        assertEquals(10000L, DateUtil.parseTimestamp("1970-01-01 00:00:10").getTime());
+    }
+
+    @Test
+    public void testParseTimestamp_WithMillis() {
+        assertEquals(10123L, DateUtil.parseTimestamp("1970-01-01 00:00:10.123").getTime());
+    }
+
+    @Test(expected=IllegalDataException.class)
+    public void testParseTimestamp_InvalidTimestamp() {
+        DateUtil.parseTimestamp("not-a-timestamp");
+    }
 }