Skip to content

Commit 00d948b

Browse files
authored
PHOENIX-7627 Atomic Delete return row fails for case-sensitive schema and table names (#2171)
1 parent af11be2 commit 00d948b

File tree

4 files changed

+114
-7
lines changed

4 files changed

+114
-7
lines changed

phoenix-core-client/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -884,9 +884,7 @@ public long getUpdateCount() {
884884
* @throws SQLException If something goes wrong with server side operation.
885885
*/
886886
private MutationState deleteRowAndGetMutationState(PTable table) throws SQLException {
887-
Table hTable =
888-
connection.getQueryServices()
889-
.getTable(table.getTableName().getBytes());
887+
Table hTable = connection.getQueryServices().getTable(table.getName().getBytes());
890888
try (ResultScanner scanner = hTable.getScanner(
891889
new Scan(context.getScan()))) {
892890
Result res = scanner.next();

phoenix-core-client/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,10 +687,14 @@ public Pair<Integer, ResultSet> call() throws SQLException {
687687
queryLogger.syncAudit();
688688
}
689689
success = true;
690+
TableName tableNameVal = isUpsert ?
691+
((ExecutableUpsertStatement) stmt).getTable().getName() :
692+
(isDelete ? ((ExecutableDeleteStatement) stmt)
693+
.getTable().getName() : null);
690694
return new Pair<>(lastUpdateCount,
691695
result == null || result.isEmpty() ?
692696
null : TupleUtil.getResultSet(new ResultTuple(result),
693-
tableName, connection));
697+
tableNameVal, connection));
694698
}
695699
//Force update cache and retry if meta not found error occurs
696700
catch (MetaDataEntityNotFoundException e) {

phoenix-core-client/src/main/java/org/apache/phoenix/util/TupleUtil.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
4545
import org.apache.phoenix.jdbc.PhoenixResultSet;
4646
import org.apache.phoenix.jdbc.PhoenixPrefetchedResultSet;
47+
import org.apache.phoenix.parse.TableName;
4748
import org.apache.phoenix.query.QueryConstants;
4849
import org.apache.phoenix.schema.PTable;
4950
import org.apache.phoenix.schema.SortOrder;
@@ -230,10 +231,13 @@ public static int write(Tuple result, DataOutput out) throws IOException {
230231
* @return ResultSet for the give single row.
231232
* @throws SQLException If any SQL operation fails.
232233
*/
233-
public static ResultSet getResultSet(Tuple toProject, String tableName, Connection conn)
234+
public static ResultSet getResultSet(Tuple toProject, TableName tableName, Connection conn)
234235
throws SQLException {
236+
if (tableName == null) {
237+
return null;
238+
}
235239
try (PhoenixResultSet resultSet = (PhoenixResultSet) conn.createStatement()
236-
.executeQuery("SELECT * FROM \"" + tableName + "\"")) {
240+
.executeQuery("SELECT * FROM " + tableName)) {
237241
PTable pTable =
238242
resultSet.getStatement().getQueryPlan().getContext().getResolver().getTables()
239243
.get(0).getTable();

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

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,108 @@ public void testReturnRowResult2() throws Exception {
231231
}
232232
}
233233

234+
@Test
235+
public void testReturnRowResult4() throws Exception {
236+
Assume.assumeTrue("Set correct result to RegionActionResult on hbase versions " +
237+
"2.4.18+, 2.5.9+, and 2.6.0+", isSetCorrectResultEnabledOnHBase());
238+
// NOTE - Tuple result projection does not work well with local index because
239+
// this assertion can be false: CellUtil.matchingRows(kvs[0], kvs[kvs.length-1])
240+
// as the Tuple contains different rowkeys.
241+
Assume.assumeTrue("ResultSet return does not work with local index",
242+
!indexDDL.startsWith("create local index"));
243+
244+
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
245+
String sample1 = getJsonString("json/sample_01.json");
246+
String sample2 = getJsonString("json/sample_02.json");
247+
BsonDocument bsonDocument1 = RawBsonDocument.parse(sample1);
248+
BsonDocument bsonDocument2 = RawBsonDocument.parse(sample2);
249+
try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
250+
conn.setAutoCommit(true);
251+
String tableName = "XYZ.\"abc123" + generateUniqueName() + "\"";
252+
String ddl = "CREATE TABLE " + tableName
253+
+ "(PK1 VARCHAR, PK2 DOUBLE NOT NULL, PK3 VARCHAR, COUNTER1 DOUBLE,"
254+
+ " COUNTER2 VARCHAR,"
255+
+ " COL3 BSON, COL4 INTEGER, CONSTRAINT pk PRIMARY KEY(PK1, PK2, PK3))";
256+
conn.createStatement().execute(ddl);
257+
if (!indexDDL.isEmpty()) {
258+
String indexDdl =
259+
String.format(indexDDL, "abc123" + generateUniqueName(), tableName);
260+
conn.createStatement().execute(indexDdl);
261+
}
262+
263+
validateAtomicUpsertReturnRow(tableName, conn, bsonDocument1, bsonDocument2);
264+
265+
PhoenixPreparedStatement ps =
266+
conn.prepareStatement(
267+
"DELETE FROM " + tableName + " WHERE PK1 = ? AND PK2 " +
268+
"= ? AND PK3 = ? AND COL4 = ?")
269+
.unwrap(PhoenixPreparedStatement.class);
270+
ps.setString(1, "pk000");
271+
ps.setDouble(2, -123.98);
272+
ps.setString(3, "pk003");
273+
ps.setInt(4, 235);
274+
validateReturnedRowAfterDelete(ps, "col2_001", true, false, bsonDocument2, 234);
275+
276+
ps = conn.prepareStatement("DELETE FROM " + tableName
277+
+ " WHERE PK1 = ? AND PK2 = ? AND PK3 = ? AND COL4 = ?")
278+
.unwrap(PhoenixPreparedStatement.class);
279+
ps.setString(1, "pk000");
280+
ps.setDouble(2, -123.98);
281+
ps.setString(3, "pk003");
282+
ps.setInt(4, 234);
283+
validateReturnedRowAfterDelete(ps, "col2_001", true, true, bsonDocument2, 234);
284+
285+
validateReturnedRowAfterDelete(ps, "col2_001", true, false, bsonDocument2, 234);
286+
287+
validateMultiRowDelete(tableName, conn, bsonDocument2);
288+
}
289+
}
290+
291+
@Test
292+
public void testReturnRowResult3() throws Exception {
293+
Assume.assumeTrue("Set correct result to RegionActionResult on hbase versions " +
294+
"2.4.18+, 2.5.9+, and 2.6.0+", isSetCorrectResultEnabledOnHBase());
295+
// NOTE - Tuple result projection does not work well with local index because
296+
// this assertion can be false: CellUtil.matchingRows(kvs[0], kvs[kvs.length-1])
297+
// as the Tuple contains different rowkeys.
298+
Assume.assumeTrue("ResultSet return does not work with local index",
299+
!indexDDL.startsWith("create local index"));
300+
301+
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
302+
String sample1 = getJsonString("json/sample_01.json");
303+
String sample2 = getJsonString("json/sample_02.json");
304+
BsonDocument bsonDocument1 = RawBsonDocument.parse(sample1);
305+
BsonDocument bsonDocument2 = RawBsonDocument.parse(sample2);
306+
try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
307+
conn.setAutoCommit(true);
308+
String tableName = "XYZ.\"abc123" + generateUniqueName() + "\"";
309+
String ddl = "CREATE TABLE " + tableName
310+
+ "(PK1 VARCHAR, PK2 DOUBLE NOT NULL, PK3 VARCHAR, COUNTER1 DOUBLE,"
311+
+ " COUNTER2 VARCHAR,"
312+
+ " COL3 BSON, COL4 INTEGER, CONSTRAINT pk PRIMARY KEY(PK1, PK2, PK3))";
313+
conn.createStatement().execute(ddl);
314+
if (!indexDDL.isEmpty()) {
315+
String indexDdl =
316+
String.format(indexDDL, "abc123" + generateUniqueName(), tableName);
317+
conn.createStatement().execute(indexDdl);
318+
}
319+
320+
validateAtomicUpsertReturnRow(tableName, conn, bsonDocument1, bsonDocument2);
321+
322+
PhoenixPreparedStatement ps =
323+
conn.prepareStatement(
324+
"DELETE FROM " + tableName + " WHERE PK1 = ? AND PK2 " +
325+
"= ? AND PK3 = ?").unwrap(PhoenixPreparedStatement.class);
326+
ps.setString(1, "pk000");
327+
ps.setDouble(2, -123.98);
328+
ps.setString(3, "pk003");
329+
validateReturnedRowAfterDelete(ps, "col2_001", true, true, bsonDocument2, 234);
330+
validateReturnedRowAfterDelete(ps, "col2_001", true, false, bsonDocument2, 234);
331+
332+
validateMultiRowDelete(tableName, conn, bsonDocument2);
333+
}
334+
}
335+
234336
private void verifyIndexRow(Connection conn, String tableName, boolean deleted) throws SQLException {
235337
PreparedStatement preparedStatement =
236338
conn.prepareStatement("SELECT COUNTER2 FROM " + tableName + " WHERE COUNTER1 " +
@@ -408,7 +510,6 @@ private static void validateReturnedRowAfterUpsert(Connection conn,
408510
}
409511
assertEquals(success ? 1 : 0, resultPair.getFirst().intValue());
410512
ResultSet resultSet = resultPair.getSecond();
411-
PTable table = conn.unwrap(PhoenixConnection.class).getTable(tableName);
412513

413514
assertEquals("pk000", resultSet.getString(1));
414515
assertEquals(-123.98, resultSet.getDouble(2), 0.0);

0 commit comments

Comments
 (0)