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

vjasani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/master by this push:
     new 9cb48832a7 PHOENIX-7610 Using CAST() on pk columns always result in 
full table scan (#2150)
9cb48832a7 is described below

commit 9cb48832a7e9b9a972d682535179ab6a2fd0cb16
Author: Viraj Jasani <[email protected]>
AuthorDate: Sat May 17 18:50:55 2025 -0700

    PHOENIX-7610 Using CAST() on pk columns always result in full table scan 
(#2150)
---
 .../phoenix/expression/CoerceExpression.java       | 12 ++++++
 .../java/org/apache/phoenix/end2end/Bson4IT.java   |  4 +-
 .../apache/phoenix/end2end/CastAndCoerceIT.java    | 45 ++++++++++++++++++----
 3 files changed, 51 insertions(+), 10 deletions(-)

diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
index f6d5c21d4d..bd7e44b5b0 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
@@ -146,6 +146,18 @@ public class CoerceExpression extends BaseSingleExpression 
{
         WritableUtils.writeVInt(output, maxLength == null ? -1 : maxLength);
     }
 
+    @Override
+    public boolean isStateless() {
+        // It is important to associate the stateless-ness of the 
CoerceExpression
+        // child with the CoerceExpression. Without this, ComparisonExpression 
and
+        // KeyExpressionVisitor will not be evaluated on the client side, and
+        // thus WhereOptimizer will always select Full table scan
+        // even for the query that is supposed to use Range scan or Point 
lookup
+        // on the single row.
+        // Jira: PHOENIX-7610.
+        return getChild().isStateless();
+    }
+
     @Override
     public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
         // For CoerceExpression evaluation, lhs is coerced to rhs literal 
expression. However,
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Bson4IT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Bson4IT.java
index 26b2172875..4084561623 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Bson4IT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Bson4IT.java
@@ -484,9 +484,7 @@ public class Bson4IT extends ParallelStatsDisabledIT {
 
       assertFalse(rs.next());
 
-      // TODO : Fix this separately, using CAST with PK column results into 
full table scan due
-      //  to bug.
-      // validateExplainPlan(stmt, query, tableName, "POINT LOOKUP ON 1 KEY ");
+      validateExplainPlan(stmt, query, tableName, "POINT LOOKUP ON 1 KEY ");
 
       query = "SELECT * FROM " + tableName +
               " WHERE PK1 != CAST('" + sample1 + "' AS BSON)";
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 d5183c36da..66931a1b30 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
@@ -33,6 +33,9 @@ import java.sql.ResultSet;
 import java.util.Collection;
 import java.util.Properties;
 
+import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
 import org.apache.phoenix.util.PropertiesUtil;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
@@ -142,26 +145,54 @@ public class CastAndCoerceIT extends BaseQueryIT {
             conn.close();
         }
     }
-    
+
     @Test
     public void testCoerceTinyIntToSmallInt() throws Exception {
-        String query = "SELECT entity_id FROM " + tableName + " WHERE 
organization_id=? AND a_byte >= a_short";
+        String query = "SELECT entity_id FROM " + tableName
+                + " WHERE organization_id=? AND a_byte >= a_short";
         String url = getUrl();
         Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
-        Connection conn = DriverManager.getConnection(url, props);
-        try {
+        try (Connection conn = DriverManager.getConnection(url, props)) {
             PreparedStatement statement = conn.prepareStatement(query);
             statement.setString(1, tenantId);
             ResultSet rs = statement.executeQuery();
             assertTrue(rs.next());
             assertEquals(ROW9, rs.getString(1));
             assertFalse(rs.next());
-        } finally {
-            conn.close();
+
+            ExplainPlan plan = 
statement.unwrap(PhoenixPreparedStatement.class).optimizeQuery(query)
+                    .getExplainPlan();
+            ExplainPlanAttributes explainPlanAttributes = 
plan.getPlanStepsAsAttributes();
+            assertEquals(tableName, explainPlanAttributes.getTableName());
+            assertEquals("PARALLEL 1-WAY", 
explainPlanAttributes.getIteratorTypeAndScanSize());
+            assertEquals("RANGE SCAN ", 
explainPlanAttributes.getExplainScanType());
+        }
+    }
+
+    @Test
+    public void testCoerceWithRangeScan() throws Exception {
+        String query = "SELECT entity_id FROM " + tableName
+                + " WHERE organization_id = cast(? as varchar) AND "
+                + "cast(a_byte as smallint) >= a_short";
+        String url = getUrl();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        try (Connection conn = DriverManager.getConnection(url, props)) {
+            PreparedStatement statement = conn.prepareStatement(query);
+            statement.setString(1, tenantId);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ROW9, rs.getString(1));
+            assertFalse(rs.next());
+
+            ExplainPlan plan = 
statement.unwrap(PhoenixPreparedStatement.class).optimizeQuery(query)
+                    .getExplainPlan();
+            ExplainPlanAttributes explainPlanAttributes = 
plan.getPlanStepsAsAttributes();
+            assertEquals(tableName, explainPlanAttributes.getTableName());
+            assertEquals("PARALLEL 1-WAY", 
explainPlanAttributes.getIteratorTypeAndScanSize());
+            assertEquals("RANGE SCAN ", 
explainPlanAttributes.getExplainScanType());
         }
     }
 
-    
     @Test
     public void testCoerceDateToBigInt() throws Exception {
         Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);

Reply via email to