phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamestay...@apache.org
Subject git commit: PHOENIX-788 Support cast from/to DATE/TIME/TIMESTAMP to/from LONG/UNSIGNED_LONG
Date Mon, 28 Jul 2014 19:40:57 GMT
Repository: phoenix
Updated Branches:
  refs/heads/master b7f46c105 -> 72d4d5a68


PHOENIX-788 Support cast from/to DATE/TIME/TIMESTAMP to/from LONG/UNSIGNED_LONG


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

Branch: refs/heads/master
Commit: 72d4d5a680468f85fac22fa9ab69465c9feaebca
Parents: b7f46c1
Author: James Taylor <jtaylor@salesforce.com>
Authored: Mon Jul 28 11:48:51 2014 -0700
Committer: James Taylor <jtaylor@salesforce.com>
Committed: Mon Jul 28 12:42:31 2014 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/end2end/BaseQueryIT.java | 138 +++++++++++++++++++
 .../apache/phoenix/end2end/CaseStatementIT.java |   2 +-
 .../apache/phoenix/end2end/CastAndCoerceIT.java |  98 ++++++++++++-
 .../end2end/ClientTimeArithmeticQueryIT.java    |   2 +-
 .../org/apache/phoenix/end2end/GroupByIT.java   |   2 +-
 .../org/apache/phoenix/end2end/NotQueryIT.java  |   2 +-
 .../org/apache/phoenix/end2end/QueryIT.java     |  96 +------------
 .../org/apache/phoenix/end2end/ScanQueryIT.java |   2 +-
 .../function/CeilDecimalExpression.java         |  17 ++-
 .../function/FloorDecimalExpression.java        |  17 ++-
 .../function/RoundDecimalExpression.java        |  24 +++-
 .../org/apache/phoenix/parse/CastParseNode.java |  18 ++-
 .../org/apache/phoenix/parse/CeilParseNode.java |   2 +-
 .../apache/phoenix/parse/FloorParseNode.java    |   2 +-
 .../apache/phoenix/parse/RoundParseNode.java    |   6 +-
 .../org/apache/phoenix/schema/PDataType.java    |  15 ++
 .../RoundFloorCeilExpressionsUnitTests.java     |   5 +-
 17 files changed, 325 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java
new file mode 100644
index 0000000..d736612
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseQueryIT.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.hbase.index.write.IndexWriterUtils;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.ReadOnlyProps;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+
+
+/**
+ * 
+ * Basic tests for Phoenix JDBC implementation
+ *
+ * 
+ * @since 0.1
+ */
+
+@Category(ClientManagedTimeTest.class)
+@RunWith(Parameterized.class)
+public abstract class BaseQueryIT extends BaseClientManagedTimeIT {
+    protected static final String tenantId = getOrganizationId();
+    protected static final String ATABLE_INDEX_NAME = "ATABLE_IDX";
+    protected static final long BATCH_SIZE = 3;
+    
+    @BeforeClass
+    @Shadower(classBeingShadowed = BaseClientManagedTimeIT.class)
+    public static void doSetup() throws Exception {
+        int targetQueryConcurrency = 2;
+        int maxQueryConcurrency = 3;
+        Map<String,String> props = Maps.newHashMapWithExpectedSize(5);
+        props.put(QueryServices.QUEUE_SIZE_ATTRIB, Integer.toString(100));
+        props.put(QueryServices.MAX_QUERY_CONCURRENCY_ATTRIB, Integer.toString(maxQueryConcurrency));
+        props.put(QueryServices.TARGET_QUERY_CONCURRENCY_ATTRIB, Integer.toString(targetQueryConcurrency));
+        props.put(IndexWriterUtils.HTABLE_THREAD_KEY, Integer.toString(100));
+        // Make a small batch size to test multiple calls to reserve sequences
+        props.put(QueryServices.SEQUENCE_CACHE_SIZE_ATTRIB, Long.toString(BATCH_SIZE));
+        
+        // Must update config before starting server
+        setUpTestDriver(getUrl(), new ReadOnlyProps(props.entrySet().iterator()));
+    }
+    
+    protected long ts;
+    protected Date date;
+    private String indexDDL;
+    
+    public BaseQueryIT(String indexDDL) {
+        this.indexDDL = indexDDL;
+    }
+    
+    @Before
+    public void initTable() throws Exception {
+         ts = nextTimestamp();
+        initATableValues(tenantId, getDefaultSplits(tenantId), date=new Date(System.currentTimeMillis()),
ts);
+        if (indexDDL != null && indexDDL.length() > 0) {
+            Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
+            Connection conn = DriverManager.getConnection(getUrl(), props);
+            conn.createStatement().execute(indexDDL);
+        }
+    }
+    
+    @Parameters(name="{0}")
+    public static Collection<Object> data() {
+        List<Object> testCases = Lists.newArrayList();
+        testCases.add(new String[] { "CREATE INDEX " + ATABLE_INDEX_NAME + " ON aTable (a_integer
DESC) INCLUDE ("
+                + "    A_STRING, " + "    B_STRING, " + "    A_DATE)" });
+        testCases.add(new String[] { "CREATE INDEX " + ATABLE_INDEX_NAME + " ON aTable (a_integer,
a_string) INCLUDE ("
+                + "    B_STRING, " + "    A_DATE)" });
+        testCases.add(new String[] { "CREATE INDEX " + ATABLE_INDEX_NAME + " ON aTable (a_integer)
INCLUDE ("
+                + "    A_STRING, " + "    B_STRING, " + "    A_DATE)" });
+        testCases.add(new String[] { "" });
+        return testCases;
+    }
+    
+    protected void assertValueEqualsResultSet(ResultSet rs, List<Object> expectedResults)
throws SQLException {
+        List<List<Object>> nestedExpectedResults = Lists.newArrayListWithExpectedSize(expectedResults.size());
+        for (Object expectedResult : expectedResults) {
+            nestedExpectedResults.add(Arrays.asList(expectedResult));
+        }
+        assertValuesEqualsResultSet(rs, nestedExpectedResults); 
+    }
+
+    protected static boolean compare(CompareOp op, ImmutableBytesWritable lhsOutPtr, ImmutableBytesWritable
rhsOutPtr) {
+        int compareResult = Bytes.compareTo(lhsOutPtr.get(), lhsOutPtr.getOffset(), lhsOutPtr.getLength(),
rhsOutPtr.get(), rhsOutPtr.getOffset(), rhsOutPtr.getLength());
+        return ByteUtil.compare(op, compareResult);
+    }
+    
+    
+    private static AtomicInteger runCount = new AtomicInteger(0);
+    protected static int nextRunCount() {
+        return runCount.getAndAdd(1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/it/java/org/apache/phoenix/end2end/CaseStatementIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CaseStatementIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CaseStatementIT.java
index 57838a0..6354de3 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CaseStatementIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CaseStatementIT.java
@@ -56,7 +56,7 @@ import com.google.common.collect.Lists;
 
 @Category(ClientManagedTimeTest.class)
 @RunWith(Parameterized.class)
-public class CaseStatementIT extends QueryIT {
+public class CaseStatementIT extends BaseQueryIT {
 
     public CaseStatementIT(String indexDDL) {
         super(indexDDL);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/it/java/org/apache/phoenix/end2end/CastAndCoerceIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CastAndCoerceIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CastAndCoerceIT.java
index 5f1fa7b..7a0c3e3 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CastAndCoerceIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CastAndCoerceIT.java
@@ -19,6 +19,7 @@
  */
 package org.apache.phoenix.end2end;
 
+import static org.apache.phoenix.util.TestUtil.ROW1;
 import static org.apache.phoenix.util.TestUtil.ROW7;
 import static org.apache.phoenix.util.TestUtil.ROW9;
 import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
@@ -44,7 +45,7 @@ import org.junit.runners.Parameterized.Parameters;
 
 @Category(ClientManagedTimeTest.class)
 @RunWith(Parameterized.class)
-public class CastAndCoerceIT extends QueryIT {
+public class CastAndCoerceIT extends BaseQueryIT {
 
     public CastAndCoerceIT(String indexDDL) {
         super(indexDDL);
@@ -165,4 +166,99 @@ public class CastAndCoerceIT extends QueryIT {
         }
     }
 
+    
+    @Test
+    public void testCoerceDateToBigInt() throws Exception {
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        PreparedStatement statement;
+        ResultSet rs;
+        String query;
+        long dateAsLong;
+        BigDecimal dateAsDecimal;
+        String url;
+        Connection conn;
+        url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 3);
+        conn = DriverManager.getConnection(url, props);
+        conn.setAutoCommit(true);
+        conn.createStatement().execute("UPSERT INTO ATABLE(organization_id,entity_id,a_time,a_timestamp)
SELECT organization_id,entity_id,a_date,a_date FROM ATABLE");
+
+        url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 5);
+        conn = DriverManager.getConnection(url, props);
+        try {
+            query = "SELECT entity_id, CAST(a_date AS BIGINT) FROM ATABLE WHERE organization_id=?
AND a_date IS NOT NULL LIMIT 1";
+            statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW1, rs.getString(1));
+            dateAsLong = rs.getLong(2);
+            assertFalse(rs.next());
+        
+            query = "SELECT entity_id FROM ATABLE WHERE organization_id=? AND a_date = CAST(?
AS DATE) LIMIT 1";
+            statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            statement.setLong(2, dateAsLong);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW1, rs.getString(1));
+            assertFalse(rs.next());
+
+            query = "SELECT entity_id, CAST(a_time AS BIGINT) FROM ATABLE WHERE organization_id=?
AND a_time IS NOT NULL LIMIT 1";
+            statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW1, rs.getString(1));
+            dateAsLong = rs.getLong(2);
+            assertFalse(rs.next());
+        
+            query = "SELECT entity_id FROM ATABLE WHERE organization_id=? AND a_time = CAST(?
AS TIME) LIMIT 1";
+            statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            statement.setLong(2, dateAsLong);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW1, rs.getString(1));
+            assertFalse(rs.next());
+
+            query = "SELECT entity_id, CAST(a_timestamp AS DECIMAL) FROM ATABLE WHERE organization_id=?
AND a_timestamp IS NOT NULL LIMIT 1";
+            statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW1, rs.getString(1));
+            dateAsDecimal = rs.getBigDecimal(2);
+            assertFalse(rs.next());
+        
+            query = "SELECT entity_id FROM ATABLE WHERE organization_id=? AND a_timestamp
= CAST(? AS TIMESTAMP) LIMIT 1";
+            statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            statement.setBigDecimal(2, dateAsDecimal);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW1, rs.getString(1));
+            assertFalse(rs.next());
+
+
+            query = "SELECT entity_id, CAST(a_timestamp AS BIGINT) FROM ATABLE WHERE organization_id=?
AND a_timestamp IS NOT NULL LIMIT 1";
+            statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW1, rs.getString(1));
+            dateAsLong = rs.getLong(2);
+            assertFalse(rs.next());
+        
+            query = "SELECT entity_id FROM ATABLE WHERE organization_id=? AND a_timestamp
= CAST(? AS TIMESTAMP) LIMIT 1";
+            statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            statement.setLong(2, dateAsLong);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW1, rs.getString(1));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/it/java/org/apache/phoenix/end2end/ClientTimeArithmeticQueryIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ClientTimeArithmeticQueryIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ClientTimeArithmeticQueryIT.java
index f5eb7d6..9be6fc1 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ClientTimeArithmeticQueryIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ClientTimeArithmeticQueryIT.java
@@ -59,7 +59,7 @@ import com.google.common.collect.Lists;
 
 @Category(ClientManagedTimeTest.class)
 @RunWith(Parameterized.class)
-public class ClientTimeArithmeticQueryIT extends QueryIT {
+public class ClientTimeArithmeticQueryIT extends BaseQueryIT {
 
     public ClientTimeArithmeticQueryIT(String indexDDL) {
         super(indexDDL);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/it/java/org/apache/phoenix/end2end/GroupByIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/GroupByIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/GroupByIT.java
index fce93ea..6002d58 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/GroupByIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/GroupByIT.java
@@ -54,7 +54,7 @@ import com.google.common.collect.Lists;
 
 @Category(ClientManagedTimeTest.class)
 @RunWith(Parameterized.class)
-public class GroupByIT extends QueryIT {
+public class GroupByIT extends BaseQueryIT {
 
     public GroupByIT(String indexDDL) {
         super(indexDDL);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/it/java/org/apache/phoenix/end2end/NotQueryIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/NotQueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/NotQueryIT.java
index 0e6562c..d6f0c13 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/NotQueryIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/NotQueryIT.java
@@ -53,7 +53,7 @@ import com.google.common.primitives.Floats;
 
 @Category(ClientManagedTimeTest.class)
 @RunWith(Parameterized.class)
-public class NotQueryIT extends QueryIT {
+public class NotQueryIT extends BaseQueryIT {
 
     public NotQueryIT(String indexDDL) {
         super(indexDDL);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java
index 9f5200e..d9c3862 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java
@@ -43,15 +43,10 @@ import java.sql.Date;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.sql.SQLException;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
 import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
@@ -59,9 +54,7 @@ import org.apache.hadoop.hbase.client.HTable;
 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.phoenix.hbase.index.write.IndexWriterUtils;
 import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.query.QueryServices;
 import org.apache.phoenix.schema.ConstraintViolationException;
 import org.apache.phoenix.schema.PDataType;
 import org.apache.phoenix.schema.SequenceNotFoundException;
@@ -69,17 +62,8 @@ import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.MetaDataUtil;
 import org.apache.phoenix.util.PhoenixRuntime;
 import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.ReadOnlyProps;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 
 
 
@@ -92,70 +76,10 @@ import com.google.common.collect.Maps;
  */
 
 @Category(ClientManagedTimeTest.class)
-@RunWith(Parameterized.class)
-public class QueryIT extends BaseClientManagedTimeIT {
-    protected static final String tenantId = getOrganizationId();
-    protected static final String ATABLE_INDEX_NAME = "ATABLE_IDX";
-    protected static final long BATCH_SIZE = 3;
-    
-    @BeforeClass
-    @Shadower(classBeingShadowed = BaseClientManagedTimeIT.class)
-    public static void doSetup() throws Exception {
-        int targetQueryConcurrency = 2;
-        int maxQueryConcurrency = 3;
-        Map<String,String> props = Maps.newHashMapWithExpectedSize(5);
-        props.put(QueryServices.QUEUE_SIZE_ATTRIB, Integer.toString(100));
-        props.put(QueryServices.MAX_QUERY_CONCURRENCY_ATTRIB, Integer.toString(maxQueryConcurrency));
-        props.put(QueryServices.TARGET_QUERY_CONCURRENCY_ATTRIB, Integer.toString(targetQueryConcurrency));
-        props.put(IndexWriterUtils.HTABLE_THREAD_KEY, Integer.toString(100));
-        // Make a small batch size to test multiple calls to reserve sequences
-        props.put(QueryServices.SEQUENCE_CACHE_SIZE_ATTRIB, Long.toString(BATCH_SIZE));
-        
-        // Must update config before starting server
-        setUpTestDriver(getUrl(), new ReadOnlyProps(props.entrySet().iterator()));
-    }
-    
-    protected long ts;
-    private Date date;
-    private String indexDDL;
+public class QueryIT extends BaseQueryIT {
     
     public QueryIT(String indexDDL) {
-        this.indexDDL = indexDDL;
-    }
-    
-    @Before
-    public void initTable() throws Exception {
-         ts = nextTimestamp();
-        initATableValues(tenantId, getDefaultSplits(tenantId), date=new Date(System.currentTimeMillis()),
ts);
-        if (indexDDL != null && indexDDL.length() > 0) {
-            Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
-            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
-            Connection conn = DriverManager.getConnection(getUrl(), props);
-            conn.createStatement().execute(indexDDL);
-        }
-    }
-    
-    @Parameters(name="{0}")
-    public static Collection<Object> data() {
-        List<Object> testCases = Lists.newArrayList();
-        testCases.add(new String[] { "CREATE INDEX " + ATABLE_INDEX_NAME + " ON aTable (a_integer
DESC) INCLUDE ("
-                + "    A_STRING, " + "    B_STRING, " + "    A_DATE)" });
-        testCases.add(new String[] { "CREATE INDEX " + ATABLE_INDEX_NAME + " ON aTable (a_integer,
a_string) INCLUDE ("
-                + "    B_STRING, " + "    A_DATE)" });
-        testCases.add(new String[] { "CREATE INDEX " + ATABLE_INDEX_NAME + " ON aTable (a_integer)
INCLUDE ("
-                + "    A_STRING, " + "    B_STRING, " + "    A_DATE)" });
-        testCases.add(new String[] { "CREATE LOCAL INDEX " + ATABLE_INDEX_NAME + " ON aTable
(a_integer, a_string) INCLUDE ("
-                + "    B_STRING, " + "    A_DATE)" });
-        testCases.add(new String[] { "" });
-        return testCases;
-    }
-    
-    protected void assertValueEqualsResultSet(ResultSet rs, List<Object> expectedResults)
throws SQLException {
-        List<List<Object>> nestedExpectedResults = Lists.newArrayListWithExpectedSize(expectedResults.size());
-        for (Object expectedResult : expectedResults) {
-            nestedExpectedResults.add(Arrays.asList(expectedResult));
-        }
-        assertValuesEqualsResultSet(rs, nestedExpectedResults); 
+        super(indexDDL);
     }
     
     @Test
@@ -274,7 +198,7 @@ public class QueryIT extends BaseClientManagedTimeIT {
         }
     }
 
-    public void testNoStringValue(String value) throws Exception {
+    private void testNoStringValue(String value) throws Exception {
         String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + (ts + 1);
         Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
         Connection upsertConn = DriverManager.getConnection(url, props);
@@ -425,15 +349,6 @@ public class QueryIT extends BaseClientManagedTimeIT {
         conn.close();
     }
     
-
-    
-
-    private static boolean compare(CompareOp op, ImmutableBytesWritable lhsOutPtr, ImmutableBytesWritable
rhsOutPtr) {
-        int compareResult = Bytes.compareTo(lhsOutPtr.get(), lhsOutPtr.getOffset(), lhsOutPtr.getLength(),
rhsOutPtr.get(), rhsOutPtr.getOffset(), rhsOutPtr.getLength());
-        return ByteUtil.compare(op, compareResult);
-    }
-    
-    
     @Test
     public void testDateInList() throws Exception {
         String query = "SELECT entity_id FROM ATABLE WHERE a_date IN (?,?) AND a_integer
< 4";
@@ -795,11 +710,6 @@ public class QueryIT extends BaseClientManagedTimeIT {
         }
     }
     
-    private static AtomicInteger runCount = new AtomicInteger(0);
-    private static int nextRunCount() {
-        return runCount.getAndAdd(1);
-    }
-    
     @Test
     public void testSplitWithCachedMeta() throws Exception {
         // Tests that you don't get an ambiguous column exception when using the same alias
as the column name

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/it/java/org/apache/phoenix/end2end/ScanQueryIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ScanQueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ScanQueryIT.java
index fcb16e5..f817c2b 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ScanQueryIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ScanQueryIT.java
@@ -62,7 +62,7 @@ import com.google.common.primitives.Floats;
 
 @Category(ClientManagedTimeTest.class)
 @RunWith(Parameterized.class)
-public class ScanQueryIT extends QueryIT {
+public class ScanQueryIT extends BaseQueryIT {
     
     @Parameters(name="{0}")
     public static Collection<Object> data() {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDecimalExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDecimalExpression.java
b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDecimalExpression.java
index e07acb3..5e3f2f6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDecimalExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDecimalExpression.java
@@ -21,11 +21,12 @@ import java.math.RoundingMode;
 import java.sql.SQLException;
 import java.util.List;
 
-import com.google.common.collect.Lists;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
 import org.apache.phoenix.schema.PDataType;
 
+import com.google.common.collect.Lists;
+
 /**
  * 
  * Class encapsulating the CEIL operation on a {@link org.apache.phoenix.schema.PDataType#DECIMAL}
@@ -37,7 +38,7 @@ public class CeilDecimalExpression extends RoundDecimalExpression {
     
     public CeilDecimalExpression() {}
     
-    public CeilDecimalExpression(List<Expression> children) {
+    private CeilDecimalExpression(List<Expression> children) {
         super(children);
     }
     
@@ -54,6 +55,18 @@ public class CeilDecimalExpression extends RoundDecimalExpression {
        return new CeilDecimalExpression(expressions);
    }
    
+   public static Expression create(List<Expression> exprs) throws SQLException {
+       Expression expr = exprs.get(0);
+       if (expr.getDataType().isCoercibleTo(PDataType.LONG)) {
+           return expr;
+       }
+       if (exprs.size() == 1) {
+           Expression scaleExpr = LiteralExpression.newConstant(0, PDataType.INTEGER, true);
+           exprs = Lists.newArrayList(expr, scaleExpr);
+       }
+       return new CeilDecimalExpression(exprs);
+   }
+   
    /**
     * Creates a {@link CeilDecimalExpression} with a default scale of 0 used for rounding.

     *

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.java
b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.java
index 4b2a708..539dbfa 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.java
@@ -21,11 +21,12 @@ import java.math.RoundingMode;
 import java.sql.SQLException;
 import java.util.List;
 
-import com.google.common.collect.Lists;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
 import org.apache.phoenix.schema.PDataType;
 
+import com.google.common.collect.Lists;
+
 /**
  * 
  * Class encapsulating the FLOOR operation on 
@@ -38,7 +39,7 @@ public class FloorDecimalExpression extends RoundDecimalExpression {
     
     public FloorDecimalExpression() {}
     
-    public FloorDecimalExpression(List<Expression> children) {
+    private FloorDecimalExpression(List<Expression> children) {
         super(children);
     }
     
@@ -55,6 +56,18 @@ public class FloorDecimalExpression extends RoundDecimalExpression {
         return new FloorDecimalExpression(expressions);
     }
     
+    public static Expression create(List<Expression> exprs) throws SQLException {
+        Expression expr = exprs.get(0);
+        if (expr.getDataType().isCoercibleTo(PDataType.LONG)) {
+            return expr;
+        }
+        if (exprs.size() == 1) {
+            Expression scaleExpr = LiteralExpression.newConstant(0, PDataType.INTEGER, true);
+            exprs = Lists.newArrayList(expr, scaleExpr);
+        }
+        return new FloorDecimalExpression(exprs);
+    }
+    
     /**
      * Creates a {@link FloorDecimalExpression} with a default scale of 0 used for rounding.

      *

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
index be03682..64f957e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDecimalExpression.java
@@ -27,14 +27,14 @@ import java.util.List;
 
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.io.WritableUtils;
-
-import com.google.common.collect.Lists;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
 import org.apache.phoenix.schema.IllegalDataException;
 import org.apache.phoenix.schema.PDataType;
 import org.apache.phoenix.schema.tuple.Tuple;
 
+import com.google.common.collect.Lists;
+
 /**
  * 
  * Class encapsulating the process for rounding off a column/literal of 
@@ -69,9 +69,21 @@ public class RoundDecimalExpression extends ScalarFunction {
         return create(expr, 0);
     }
     
+    public static Expression create(List<Expression> exprs) throws SQLException {
+        Expression expr = exprs.get(0);
+        if (expr.getDataType().isCoercibleTo(PDataType.LONG)) {
+            return expr;
+        }
+        if (exprs.size() == 1) {
+            Expression scaleExpr = LiteralExpression.newConstant(0, PDataType.INTEGER, true);
+            exprs = Lists.newArrayList(expr, scaleExpr);
+        }
+        return new RoundDecimalExpression(exprs);
+    }
+    
     public RoundDecimalExpression() {}
     
-    public RoundDecimalExpression(List<Expression> children) {
+    protected RoundDecimalExpression(List<Expression> children) {
         super(children);
         LiteralExpression scaleChild = (LiteralExpression)children.get(1);
         PDataType scaleType = scaleChild.getDataType();
@@ -92,9 +104,9 @@ public class RoundDecimalExpression extends ScalarFunction {
     public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
         Expression childExpr = children.get(0);
         if(childExpr.evaluate(tuple, ptr)) {
-            BigDecimal value = (BigDecimal)PDataType.DECIMAL.toObject(ptr, getDataType(),
childExpr.getSortOrder());
+            BigDecimal value = (BigDecimal)PDataType.DECIMAL.toObject(ptr, childExpr.getDataType(),
childExpr.getSortOrder());
             BigDecimal scaledValue = value.setScale(scale, getRoundingMode());
-            ptr.set(getDataType().toBytes(scaledValue));
+            ptr.set(PDataType.DECIMAL.toBytes(scaledValue));
             return true;
         }
         return false;
@@ -102,7 +114,7 @@ public class RoundDecimalExpression extends ScalarFunction {
 
     @Override
     public PDataType getDataType() {
-        return children.get(0).getDataType();
+        return PDataType.DECIMAL;
     }
     
     protected RoundingMode getRoundingMode() {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java
index e4c7424..a5c5c03 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java
@@ -78,17 +78,23 @@ public class CastParseNode extends UnaryParseNode {
         return scale;
     }
 
+    // TODO: don't repeat this ugly cast logic (maybe use isCastable in the last else block.
     public static Expression convertToRoundExpressionIfNeeded(PDataType fromDataType, PDataType
targetDataType, List<Expression> expressions) throws SQLException {
 	    Expression firstChildExpr = expressions.get(0);
 	    if(fromDataType == targetDataType) {
 	        return firstChildExpr;
-	    } else if(fromDataType == PDataType.DECIMAL && targetDataType.isCoercibleTo(PDataType.LONG))
{
-	        return new RoundDecimalExpression(expressions);
-	    } else if((fromDataType == PDataType.TIMESTAMP || fromDataType == PDataType.UNSIGNED_TIMESTAMP)
&& targetDataType.isCoercibleTo(PDataType.DATE)) {
+//        } else if((fromDataType == PDataType.DATE || fromDataType == PDataType.UNSIGNED_DATE)
&& targetDataType.isCoercibleTo(PDataType.LONG)) {
+//            return firstChildExpr;
+//        } else if(fromDataType.isCoercibleTo(PDataType.LONG) && (targetDataType
== PDataType.DATE || targetDataType == PDataType.UNSIGNED_DATE)) {
+//            return firstChildExpr;
+	    } else if((fromDataType == PDataType.DECIMAL || fromDataType == PDataType.TIMESTAMP
|| fromDataType == PDataType.UNSIGNED_TIMESTAMP) && targetDataType.isCoercibleTo(PDataType.LONG))
{
+	        return RoundDecimalExpression.create(expressions);
+	    } else if((fromDataType == PDataType.DECIMAL || fromDataType == PDataType.TIMESTAMP
|| fromDataType == PDataType.UNSIGNED_TIMESTAMP) && targetDataType.isCoercibleTo(PDataType.DATE))
{
 	        return RoundTimestampExpression.create(expressions);
-	    } else if(!fromDataType.isCoercibleTo(targetDataType)) {
-	        throw TypeMismatchException.newException(fromDataType, targetDataType, firstChildExpr.toString());
+	    } else if(fromDataType.isCastableTo(targetDataType)) {
+	        return firstChildExpr;
+        } else {
+            throw TypeMismatchException.newException(fromDataType, targetDataType, firstChildExpr.toString());
 	    }
-	    return firstChildExpr;
 	}
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/main/java/org/apache/phoenix/parse/CeilParseNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/CeilParseNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/CeilParseNode.java
index c10ba87..08d7feb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/CeilParseNode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/CeilParseNode.java
@@ -57,7 +57,7 @@ public class CeilParseNode extends FunctionParseNode {
         } else if (firstChildDataType == PDataType.TIMESTAMP || firstChildDataType == PDataType.UNSIGNED_TIMESTAMP)
{
             return CeilTimestampExpression.create(children);
         } else if(firstChildDataType.isCoercibleTo(PDataType.DECIMAL)) {
-            return new CeilDecimalExpression(children);
+            return CeilDecimalExpression.create(children);
         } else {
             throw TypeMismatchException.newException(firstChildDataType, "1");
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/main/java/org/apache/phoenix/parse/FloorParseNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/FloorParseNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/FloorParseNode.java
index 5030931..8da17ba 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/FloorParseNode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/FloorParseNode.java
@@ -57,7 +57,7 @@ public class FloorParseNode extends FunctionParseNode {
         if(firstChildDataType.isCoercibleTo(PDataType.TIMESTAMP)) {
             return FloorDateExpression.create(children);
         } else if(firstChildDataType.isCoercibleTo(PDataType.DECIMAL)) {
-            return new FloorDecimalExpression(children);
+            return FloorDecimalExpression.create(children);
         } else {
             throw TypeMismatchException.newException(firstChildDataType, "1");
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/main/java/org/apache/phoenix/parse/RoundParseNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/RoundParseNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/RoundParseNode.java
index ea9977a..5260f88 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/RoundParseNode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/RoundParseNode.java
@@ -55,11 +55,11 @@ public class RoundParseNode extends FunctionParseNode {
         final PDataType firstChildDataType = firstChild.getDataType();
         
         if(firstChildDataType.isCoercibleTo(PDataType.DATE)) {
-            return RoundDateExpression.create(children); // FIXME: remove cast
+            return RoundDateExpression.create(children);
         } else if (firstChildDataType.isCoercibleTo(PDataType.TIMESTAMP)) {
-            return RoundTimestampExpression.create(children); // FIXME: remove cast
+            return RoundTimestampExpression.create(children);
         } else if(firstChildDataType.isCoercibleTo(PDataType.DECIMAL)) {
-            return new RoundDecimalExpression(children);
+            return RoundDecimalExpression.create(children);
         } else {
             throw TypeMismatchException.newException(firstChildDataType, "1");
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java
index c7697bf..bf0ba08 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PDataType.java
@@ -389,6 +389,12 @@ public enum PDataType {
             case DECIMAL:
                 BigDecimal d = (BigDecimal)object;
                 return d.longValueExact();
+            case DATE:
+            case UNSIGNED_DATE:
+            case TIME:
+            case UNSIGNED_TIME:
+                java.util.Date date = (java.util.Date)object;
+                return date.getTime();
             default:
                 return throwConstraintViolationException(actualType,this);
             }
@@ -412,6 +418,10 @@ public enum PDataType {
             case UNSIGNED_FLOAT:
             case DOUBLE:
             case UNSIGNED_DOUBLE:
+            case DATE:
+            case UNSIGNED_DATE:
+            case TIME:
+            case UNSIGNED_TIME:
                 return actualType.getCodec().decodeLong(b, o, sortOrder);
             case DECIMAL:
                 BigDecimal bd = (BigDecimal)actualType.toObject(b, o, l, actualType, sortOrder);
@@ -472,6 +482,11 @@ public enum PDataType {
         }
 
         @Override
+        public boolean isCastableTo(PDataType targetType) {
+            return super.isCastableTo(targetType) || targetType.isCoercibleTo(TIMESTAMP);
+        }
+
+        @Override
         public boolean isFixedWidth() {
             return true;
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/72d4d5a6/phoenix-core/src/test/java/org/apache/phoenix/expression/RoundFloorCeilExpressionsUnitTests.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/RoundFloorCeilExpressionsUnitTests.java
b/phoenix-core/src/test/java/org/apache/phoenix/expression/RoundFloorCeilExpressionsUnitTests.java
index 068670e..c92fed4 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/RoundFloorCeilExpressionsUnitTests.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/RoundFloorCeilExpressionsUnitTests.java
@@ -27,8 +27,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.junit.Test;
-
 import org.apache.phoenix.expression.function.CeilDateExpression;
 import org.apache.phoenix.expression.function.CeilDecimalExpression;
 import org.apache.phoenix.expression.function.FloorDateExpression;
@@ -39,6 +37,7 @@ import org.apache.phoenix.expression.function.TimeUnit;
 import org.apache.phoenix.schema.IllegalDataException;
 import org.apache.phoenix.schema.PDataType;
 import org.apache.phoenix.util.DateUtil;
+import org.junit.Test;
 
 /**
  * 
@@ -115,7 +114,7 @@ public class RoundFloorCeilExpressionsUnitTests {
         exprs.add(bd);
         exprs.add(scale);
         try {
-            new RoundDecimalExpression(exprs);
+            RoundDecimalExpression.create(exprs);
             fail("Evaluation should have failed because only an INTEGER is allowed for second
param in a RoundDecimalExpression");
         } catch(IllegalDataException e) {
 


Mime
View raw message