Skip to content

Commit f1a169a

Browse files
committed
PHOENIX-7610 Using CAST() on pk columns always result in full table scan (#2150)
1 parent ccce113 commit f1a169a

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

phoenix-core-client/src/main/java/org/apache/phoenix/expression/CoerceExpression.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,18 @@ public void write(DataOutput output) throws IOException {
143143
WritableUtils.writeVInt(output, maxLength == null ? -1 : maxLength);
144144
}
145145

146+
@Override
147+
public boolean isStateless() {
148+
// It is important to associate the stateless-ness of the CoerceExpression
149+
// child with the CoerceExpression. Without this, ComparisonExpression and
150+
// KeyExpressionVisitor will not be evaluated on the client side, and
151+
// thus WhereOptimizer will always select Full table scan
152+
// even for the query that is supposed to use Range scan or Point lookup
153+
// on the single row.
154+
// Jira: PHOENIX-7610.
155+
return getChild().isStateless();
156+
}
157+
146158
@Override
147159
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
148160
if (getChild().evaluate(tuple, ptr)) {

phoenix-core/src/it/java/org/apache/phoenix/end2end/CastAndCoerceIT.java

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
import java.util.Collection;
3434
import java.util.Properties;
3535

36+
import org.apache.phoenix.compile.ExplainPlan;
37+
import org.apache.phoenix.compile.ExplainPlanAttributes;
38+
import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
3639
import org.apache.phoenix.util.PropertiesUtil;
3740
import org.junit.Test;
3841
import org.junit.experimental.categories.Category;
@@ -142,26 +145,54 @@ public void testCoerceLongToDecimal2() throws Exception {
142145
conn.close();
143146
}
144147
}
145-
148+
146149
@Test
147150
public void testCoerceTinyIntToSmallInt() throws Exception {
148-
String query = "SELECT entity_id FROM " + tableName + " WHERE organization_id=? AND a_byte >= a_short";
151+
String query = "SELECT entity_id FROM " + tableName
152+
+ " WHERE organization_id=? AND a_byte >= a_short";
149153
String url = getUrl();
150154
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
151-
Connection conn = DriverManager.getConnection(url, props);
152-
try {
155+
try (Connection conn = DriverManager.getConnection(url, props)) {
153156
PreparedStatement statement = conn.prepareStatement(query);
154157
statement.setString(1, tenantId);
155158
ResultSet rs = statement.executeQuery();
156159
assertTrue(rs.next());
157160
assertEquals(ROW9, rs.getString(1));
158161
assertFalse(rs.next());
159-
} finally {
160-
conn.close();
162+
163+
ExplainPlan plan = statement.unwrap(PhoenixPreparedStatement.class).optimizeQuery(query)
164+
.getExplainPlan();
165+
ExplainPlanAttributes explainPlanAttributes = plan.getPlanStepsAsAttributes();
166+
assertEquals(tableName, explainPlanAttributes.getTableName());
167+
assertEquals("PARALLEL 1-WAY", explainPlanAttributes.getIteratorTypeAndScanSize());
168+
assertEquals("RANGE SCAN ", explainPlanAttributes.getExplainScanType());
169+
}
170+
}
171+
172+
@Test
173+
public void testCoerceWithRangeScan() throws Exception {
174+
String query = "SELECT entity_id FROM " + tableName
175+
+ " WHERE organization_id = cast(? as varchar) AND "
176+
+ "cast(a_byte as smallint) >= a_short";
177+
String url = getUrl();
178+
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
179+
try (Connection conn = DriverManager.getConnection(url, props)) {
180+
PreparedStatement statement = conn.prepareStatement(query);
181+
statement.setString(1, tenantId);
182+
ResultSet rs = statement.executeQuery();
183+
assertTrue(rs.next());
184+
assertEquals(ROW9, rs.getString(1));
185+
assertFalse(rs.next());
186+
187+
ExplainPlan plan = statement.unwrap(PhoenixPreparedStatement.class).optimizeQuery(query)
188+
.getExplainPlan();
189+
ExplainPlanAttributes explainPlanAttributes = plan.getPlanStepsAsAttributes();
190+
assertEquals(tableName, explainPlanAttributes.getTableName());
191+
assertEquals("PARALLEL 1-WAY", explainPlanAttributes.getIteratorTypeAndScanSize());
192+
assertEquals("RANGE SCAN ", explainPlanAttributes.getExplainScanType());
161193
}
162194
}
163195

164-
165196
@Test
166197
public void testCoerceDateToBigInt() throws Exception {
167198
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);

0 commit comments

Comments
 (0)