This is an automated email from the ASF dual-hosted git repository.

pboado pushed a commit to branch 5.x-cdh6
in repository https://gitbox.apache.org/repos/asf/phoenix.git

commit 4cb9269404d6ccbee440380d6e58db783b19b552
Author: Xinyi Yan <x...@salesforce.com>
AuthorDate: Tue Mar 5 06:24:36 2019 +0000

    PHOENIX-4929 IndexOutOfBoundsException when casting timestamp to date
---
 .../org/apache/phoenix/end2end/DateTimeIT.java     | 28 ++++++++++++++++++++++
 .../apache/phoenix/compile/ExpressionCompiler.java | 13 ++++++----
 .../apache/phoenix/compile/QueryCompilerTest.java  |  7 ++++++
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java
index eecc540..df94a70 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java
@@ -51,6 +51,7 @@ import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
 import java.text.Format;
+import java.time.LocalDate;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
 import java.util.Properties;
@@ -1823,6 +1824,33 @@ public class DateTimeIT extends ParallelStatsDisabledIT {
         }
     }
 
+    @Test
+    public void testCastTimeStampToDate() throws Exception {
+        String tablename = generateUniqueName();
+        String ddl = "CREATE TABLE IF NOT EXISTS " + tablename +
+                " (PK INTEGER PRIMARY KEY, A_TIMESTAMP TIMESTAMP)";
+        Properties props = new Properties();
+        props.setProperty("phoenix.query.dateFormatTimeZone", 
TimeZone.getDefault().toString());
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        conn.createStatement().execute(ddl);
+
+        String localTime = LocalDate.now().toString();
+        conn.createStatement().execute("UPSERT INTO " + tablename +
+                " VALUES(1,TO_TIMESTAMP('"+ localTime + "'))");
+
+        conn.setAutoCommit(true);
+        try {
+            PreparedStatement statement =
+                    conn.prepareStatement("SELECT CAST(A_TIMESTAMP AS DATE) as 
A_DATE FROM " + tablename);
+
+            ResultSet rs = statement.executeQuery();
+            assertTrue (rs.next());
+            assertTrue (rs.getString(1).contains(localTime));
+            assertFalse (rs.next());
+        } finally {
+            conn.close();
+        }
+    }
 
     @Test
     public void testTimestamp() throws Exception {
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
index 077e1af..980c1b9 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
@@ -586,11 +586,16 @@ public class ExpressionCompiler extends 
UnsupportedAllParseNodeVisitor<Expressio
         Expression firstChildExpr = expressions.get(0);
         if(fromDataType == targetDataType) {
             return firstChildExpr;
-        } else if((fromDataType == PDecimal.INSTANCE || fromDataType == 
PTimestamp.INSTANCE || fromDataType == PUnsignedTimestamp.INSTANCE) && 
targetDataType.isCoercibleTo(
-          PLong.INSTANCE)) {
+        } else if ((fromDataType == PDecimal.INSTANCE || fromDataType == 
PTimestamp.INSTANCE ||
+                fromDataType == PUnsignedTimestamp.INSTANCE) && 
targetDataType.isCoercibleTo(
+                PLong.INSTANCE)) {
             return RoundDecimalExpression.create(expressions);
-        } else if((fromDataType == PDecimal.INSTANCE || fromDataType == 
PTimestamp.INSTANCE || fromDataType == PUnsignedTimestamp.INSTANCE) && 
targetDataType.isCoercibleTo(
-          PDate.INSTANCE)) {
+        } else if (expressions.size() == 1 && fromDataType == 
PTimestamp.INSTANCE  &&
+                targetDataType.isCoercibleTo(PDate.INSTANCE)) {
+            return firstChildExpr;
+        } else if((fromDataType == PDecimal.INSTANCE || fromDataType == 
PTimestamp.INSTANCE ||
+                fromDataType == PUnsignedTimestamp.INSTANCE) && 
targetDataType.isCoercibleTo(
+                        PDate.INSTANCE)) {
             return RoundTimestampExpression.create(expressions);
         } else if(fromDataType.isCastableTo(targetDataType)) {
             return firstChildExpr;
diff --git 
a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java 
b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
index 2c438a6..ab804e5 100644
--- 
a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
+++ 
b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
@@ -1111,6 +1111,13 @@ public class QueryCompilerTest extends 
BaseConnectionlessQueryTest {
         List<Object> binds = Collections.emptyList();
         compileQuery(query, binds);
     }
+
+    @Test
+    public void testCastingTimestampToDateInSelect() throws Exception {
+        String query = "SELECT CAST (a_timestamp AS DATE) FROM aTable";
+        List<Object> binds = Collections.emptyList();
+        compileQuery(query, binds);
+    }
     
     @Test
     public void testCastingStringToDecimalInSelect() throws Exception {

Reply via email to