Skip to content

Commit caa2c03

Browse files
committed
CNDB-15312: Fix multi-column partition key CQL generation in DataRange
1 parent 2e27958 commit caa2c03

File tree

5 files changed

+44
-5
lines changed

5 files changed

+44
-5
lines changed

src/java/org/apache/cassandra/db/DataRange.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,7 @@ public String toCQLString(TableMetadata metadata)
288288
* key are the same. If that is the case, we want to print the query as an equality on the partition key
289289
* rather than a token range, as if it was a partition query, for better readability.
290290
*/
291-
builder.append(ColumnMetadata.toCQLString(metadata.partitionKeyColumns()));
292-
builder.append(" = ");
293-
appendKeyString(builder, metadata.partitionKeyType, ((DecoratedKey) startKey()).getKey());
291+
builder.append(((DecoratedKey) startKey()).toCQLString(metadata));
294292
needAnd = true;
295293
}
296294
else

src/java/org/apache/cassandra/db/DecoratedKey.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,16 @@
1919

2020
import java.nio.ByteBuffer;
2121
import java.util.Comparator;
22+
import java.util.List;
23+
import java.util.StringJoiner;
2224
import java.util.function.BiFunction;
2325

26+
import org.apache.cassandra.db.marshal.CompositeType;
2427
import org.apache.cassandra.dht.IPartitioner;
2528
import org.apache.cassandra.dht.Token;
2629
import org.apache.cassandra.dht.Token.KeyBound;
30+
import org.apache.cassandra.schema.ColumnMetadata;
31+
import org.apache.cassandra.schema.TableMetadata;
2732
import org.apache.cassandra.utils.ByteBufferUtil;
2833
import org.apache.cassandra.utils.bytecomparable.ByteComparable;
2934
import org.apache.cassandra.utils.bytecomparable.ByteSource;
@@ -161,6 +166,32 @@ public String toString()
161166
return "DecoratedKey(" + getToken() + ", " + keystring + ")";
162167
}
163168

169+
/**
170+
* Generate CQL representation of this partition key for the given table.
171+
* For single-column keys: "k = 0"
172+
* For multi-column keys: "k1 = 1 AND k2 = 2"
173+
*/
174+
public String toCQLString(TableMetadata metadata)
175+
{
176+
List<ColumnMetadata> columns = metadata.partitionKeyColumns();
177+
178+
if (columns.size() == 1)
179+
return toCQLString(columns.get(0), getKey());
180+
181+
ByteBuffer[] values = ((CompositeType) metadata.partitionKeyType).split(getKey());
182+
StringJoiner joiner = new StringJoiner(" AND ");
183+
184+
for (int i = 0; i < columns.size(); i++)
185+
joiner.add(toCQLString(columns.get(i), values[i]));
186+
187+
return joiner.toString();
188+
}
189+
190+
private static String toCQLString(ColumnMetadata metadata, ByteBuffer key)
191+
{
192+
return String.format("%s = %s", metadata.name.toCQLString(), metadata.type.getString(key));
193+
}
194+
164195
public Token getToken()
165196
{
166197
return token;

src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,8 +1151,7 @@ protected void appendCQLWhereClause(CqlBuilder builder)
11511151
{
11521152
builder.append(" WHERE ");
11531153

1154-
builder.append(ColumnMetadata.toCQLString(metadata().partitionKeyColumns())).append(" = ");
1155-
DataRange.appendKeyString(builder, metadata().partitionKeyType, partitionKey().getKey());
1154+
builder.append(partitionKey().toCQLString(metadata()));
11561155

11571156
// We put the row filter first because the clustering index filter can end by "ORDER BY"
11581157
if (!rowFilter().isEmpty())

test/unit/org/apache/cassandra/db/PartitionRangeReadCommandCQLTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ public void testToCQLString()
8787
assertToCQLString("SELECT * FROM %s WHERE v = 0 AND k = 0 AND c1 = 1 AND c2 < 2", "SELECT * FROM %s WHERE v = 0 AND k = 0 AND c1 = 1 AND c2 < 2 ALLOW FILTERING");
8888
assertToCQLString("SELECT * FROM %s WHERE v = 0 AND k = 0 AND c1 = 1 AND c2 >= 2", "SELECT * FROM %s WHERE v = 0 AND k = 0 AND c1 = 1 AND c2 >= 2 ALLOW FILTERING");
8989
assertToCQLString("SELECT * FROM %s WHERE v = 0 AND k = 0 AND c1 = 1 AND c2 <= 2", "SELECT * FROM %s WHERE v = 0 AND k = 0 AND c1 = 1 AND c2 <= 2 ALLOW FILTERING");
90+
91+
// test with multi-column partition key and index
92+
createTable("CREATE TABLE %s (k1 int, k2 int, c int, v int, PRIMARY KEY ((k1, k2), c))");
93+
createIndex("CREATE INDEX ON %s(v)");
94+
assertToCQLString("SELECT * FROM %s WHERE v = 1 AND k1 = 1 AND k2 = 2", "SELECT * FROM %s WHERE v = 1 AND k1 = 1 AND k2 = 2 ALLOW FILTERING");
95+
assertToCQLString("SELECT * FROM %s WHERE v = 1 AND k1 = 1 AND k2 = 2 AND c = 3", "SELECT * FROM %s WHERE v = 1 AND k1 = 1 AND k2 = 2 AND c = 3 ALLOW FILTERING");
9096
}
9197

9298
@Override

test/unit/org/apache/cassandra/db/SinglePartitionReadCommandCQLTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ public void testToCQLString()
5959
assertToCQLString("SELECT * FROM %s WHERE k = 0 AND c < 0 AND v = 1 ALLOW FILTERING", "SELECT * FROM %s WHERE k = 0 AND v = 1 AND c < 0 ALLOW FILTERING");
6060
assertToCQLString("SELECT * FROM %s WHERE k = 0 AND c >= 0 AND v = 1 ALLOW FILTERING", "SELECT * FROM %s WHERE k = 0 AND v = 1 AND c >= 0 ALLOW FILTERING");
6161
assertToCQLString("SELECT * FROM %s WHERE k = 0 AND c <= 0 AND v = 1 ALLOW FILTERING", "SELECT * FROM %s WHERE k = 0 AND v = 1 AND c <= 0 ALLOW FILTERING");
62+
63+
// test with multi-column partition key (without index to test SinglePartitionReadCommand directly)
64+
createTable("CREATE TABLE %s (k1 int, k2 int, c int, v int, PRIMARY KEY ((k1, k2), c))");
65+
assertToCQLString("SELECT * FROM %s WHERE k1 = 1 AND k2 = 2", "SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 ALLOW FILTERING");
66+
assertToCQLString("SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 AND c = 3", "SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 AND c = 3 ALLOW FILTERING");
6267
}
6368

6469
@Override

0 commit comments

Comments
 (0)