Skip to content

Commit 0962794

Browse files
akhakuabsurdfarce
authored andcommitted
Don't return empty routing key when partition key is unbound
DefaultBoundStatement#getRoutingKey has logic to infer the routing key when no one has explicitly called setRoutingKey or otherwise set the routing key on the statement. It however doesn't check for cases where nothing has been bound yet on the statement. This causes more problems if the user decides to get a BoundStatementBuilder from the PreparedStatement, set some fields on it, and then copy it by constructing new BoundStatementBuilder objects with the BoundStatement as a parameter, since the empty ByteBuffer gets copied to all bound statements, resulting in all requests being targeted to the same Cassandra node in a token-aware load balancing policy. patch by Ammar Khaku; reviewed by Andy Tolbert, and Bret McGuire reference: #1620
1 parent a17f7be commit 0962794

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

core/src/main/java/com/datastax/oss/driver/internal/core/cql/DefaultBoundStatement.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ public ByteBuffer getRoutingKey() {
360360
if (indices.isEmpty()) {
361361
return null;
362362
} else if (indices.size() == 1) {
363-
return getBytesUnsafe(indices.get(0));
363+
int index = indices.get(0);
364+
return isSet(index) ? getBytesUnsafe(index) : null;
364365
} else {
365366
ByteBuffer[] components = new ByteBuffer[indices.size()];
366367
for (int i = 0; i < components.length; i++) {

integration-tests/src/test/java/com/datastax/oss/driver/core/cql/PreparedStatementIT.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,25 @@ private void should_infer_routing_information_when_partition_key_is_bound(String
527527
assertThat(tokenFactory.hash(boundStatement.getRoutingKey())).isEqualTo(expectedToken);
528528
}
529529

530+
@Test
531+
public void should_return_null_routing_information_when_single_partition_key_is_unbound() {
532+
should_return_null_routing_information_when_single_partition_key_is_unbound(
533+
"SELECT a FROM prepared_statement_test WHERE a = ?");
534+
should_return_null_routing_information_when_single_partition_key_is_unbound(
535+
"INSERT INTO prepared_statement_test (a) VALUES (?)");
536+
should_return_null_routing_information_when_single_partition_key_is_unbound(
537+
"UPDATE prepared_statement_test SET b = 1 WHERE a = ?");
538+
should_return_null_routing_information_when_single_partition_key_is_unbound(
539+
"DELETE FROM prepared_statement_test WHERE a = ?");
540+
}
541+
542+
private void should_return_null_routing_information_when_single_partition_key_is_unbound(
543+
String queryString) {
544+
CqlSession session = sessionRule.session();
545+
BoundStatement boundStatement = session.prepare(queryString).bind();
546+
assertThat(boundStatement.getRoutingKey()).isNull();
547+
}
548+
530549
private static Iterable<Row> firstPageOf(CompletionStage<AsyncResultSet> stage) {
531550
return CompletableFutures.getUninterruptibly(stage).currentPage();
532551
}

0 commit comments

Comments
 (0)