Skip to content

Commit 3c319c3

Browse files
committed
Revisit getToken/setToken (JAVA-312).
1 parent f2df1b5 commit 3c319c3

4 files changed

Lines changed: 95 additions & 38 deletions

File tree

driver-core/src/main/java/com/datastax/driver/core/ArrayBackedRow.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -256,19 +256,19 @@ public Token getToken(int i) {
256256
}
257257

258258
public Token getToken(String name) {
259-
// first, try with `token(name)`, preserving case sensitivity
260-
String tokenName = (name.length() >= 2 && name.charAt(0) == '"' && name.charAt(name.length() - 1) == '"')
261-
? "\"token(" + name.substring(1, name.length() - 1) + ")\""
262-
: "token(" + name + ")";
263-
int[] indexes = metadata.findAllIdx(tokenName);
264-
if (indexes != null) {
265-
return getToken(indexes[0]);
266-
}
267-
268-
// Otherwise, use normal name
269259
return getToken(metadata.getFirstIdx(name));
270260
}
271261

262+
public Token getPartitionKeyToken() {
263+
int i = 0;
264+
for (ColumnDefinitions.Definition column : metadata) {
265+
if (column.getName().matches("token(.*)"))
266+
return getToken(i);
267+
i++;
268+
}
269+
throw new IllegalStateException("Found no column named 'token(...)'. If the column is aliased, use getToken(String).");
270+
}
271+
272272
@SuppressWarnings("unchecked")
273273
public <T> List<T> getList(int i, Class<T> elementsClass) {
274274
DataType type = metadata.getType(i);

driver-core/src/main/java/com/datastax/driver/core/BoundStatement.java

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,8 @@ public BoundStatement setDouble(String name, double v) {
527527
*/
528528
public BoundStatement setString(int i, String v) {
529529
DataType.Name type = metadata().checkType(i, DataType.Name.VARCHAR,
530-
DataType.Name.TEXT,
531-
DataType.Name.ASCII);
530+
DataType.Name.TEXT,
531+
DataType.Name.ASCII);
532532
switch (type) {
533533
case ASCII:
534534
return setValue(i, v == null ? null : TypeCodec.StringCodec.asciiInstance.serialize(v));
@@ -742,7 +742,7 @@ public BoundStatement setDecimal(String name, BigDecimal v) {
742742
*/
743743
public BoundStatement setUUID(int i, UUID v) {
744744
DataType.Name type = metadata().checkType(i, DataType.Name.UUID,
745-
DataType.Name.TIMEUUID);
745+
DataType.Name.TIMEUUID);
746746

747747
if (v == null)
748748
return setValue(i, null);
@@ -823,6 +823,9 @@ public BoundStatement setInet(String name, InetAddress v) {
823823

824824
/**
825825
* Sets the {@code i}th value to the provided {@link Token}.
826+
* <p>
827+
* {@link #setPartitionKeyToken(Token)} should generally be preferred if you
828+
* have a single token variable.
826829
*
827830
* @param i the index of the variable to set.
828831
* @param v the value to set.
@@ -839,6 +842,18 @@ public BoundStatement setToken(int i, Token v) {
839842
/**
840843
* Sets the value for (all occurrences of) variable {@code name} to the
841844
* provided token.
845+
* <p>
846+
* {@link #setPartitionKeyToken(Token)} should generally be preferred if you
847+
* have a single token variable.
848+
* <p>
849+
* If you have multiple token variables, use positional binding ({@link #setToken(int, Token)},
850+
* or named bind markers:
851+
* <pre>
852+
* {@code
853+
* PreparedStatement pst = session.prepare("SELECT * FROM my_table WHERE token(k) > :min AND token(k) <= :max");
854+
* BoundStatement b = pst.bind().setToken("min", minToken).setToken("max", maxToken);
855+
* }
856+
* </pre>
842857
*
843858
* @param name the name of the variable to set; if multiple variables
844859
* {@code name} are prepared, all of them are set.
@@ -857,6 +872,40 @@ public BoundStatement setToken(String name, Token v) {
857872
return this;
858873
}
859874

875+
/**
876+
* Sets the value for (all occurrences of) variable "{@code partition key token}"
877+
* to the provided token (this is the name generated by Cassandra for markers
878+
* corresponding to a {@code token(...)} call).
879+
* <p>
880+
* This method is a shorthand for statements with a single token variable:
881+
* <pre>
882+
* {@code
883+
* Token token = ...
884+
* PreparedStatement pst = session.prepare("SELECT * FROM my_table WHERE token(k) = ?");
885+
* BoundStatement b = pst.bind().setPartitionKeyToken(token);
886+
* }
887+
* </pre>
888+
* If you have multiple token variables, use positional binding ({@link #setToken(int, Token)},
889+
* or named bind markers:
890+
* <pre>
891+
* {@code
892+
* PreparedStatement pst = session.prepare("SELECT * FROM my_table WHERE token(k) > :min AND token(k) <= :max");
893+
* BoundStatement b = pst.bind().setToken("min", minToken).setToken("max", maxToken);
894+
* }
895+
* </pre>
896+
*
897+
* @param v the value to set.
898+
* @return this BoundStatement.
899+
*
900+
* @throws IllegalArgumentException if {@code name} is not a prepared
901+
* variable, that is, if {@code !this.preparedStatement().variables().names().contains(name)}.
902+
* @throws InvalidTypeException if (any occurrence of) {@code name} is
903+
* not of the type of the token's value.
904+
*/
905+
public BoundStatement setPartitionKeyToken(Token v) {
906+
return setToken("partition key token", v);
907+
}
908+
860909
/**
861910
* Sets the {@code i}th value to the provided list.
862911
* <p>

driver-core/src/main/java/com/datastax/driver/core/Row.java

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,12 @@ public interface Row {
406406

407407
/**
408408
* Returns the {@code i}th value of this row as a {@link Token}.
409+
* <p>
410+
* {@link #getPartitionKeyToken()} should generally be preferred to this method (unless the
411+
* token column is aliased).
409412
*
410413
* @param i the index ({@code 0 <= i < size()}) of the column to retrieve.
411414
* @return the value of the {@code i}th column in this row as an Token.
412-
* If the value is NULL, {@code null} is returned.
413415
*
414416
* @throws IndexOutOfBoundsException if {@code i < 0 || i >= this.columns().size()}.
415417
* @throws InvalidTypeException if column {@code i} is not of the type of token values
@@ -420,26 +422,11 @@ public interface Row {
420422
/**
421423
* Returns the value of column {@code name} as a {@link Token}.
422424
* <p>
423-
* This method will first try with {@code token(name)}, because in most cases the column
424-
* is named that way since it results from the application of a CQL function:
425-
* <pre>
426-
* {@code
427-
* ResultSet rs = session.execute("SELECT token(k) FROM my_table WHERE k = 1");
428-
* Token token = rs.one().getToken("k"); // retrieves token(k)
429-
* }
430-
* </pre>
431-
* If that fails, it will try will {@code name}. This handles the case where the column
432-
* was aliased:
433-
* <pre>
434-
* {@code
435-
* ResultSet rs = session.execute("SELECT token(k) AS t FROM my_table WHERE k = 1");
436-
* Token token = rs.one().getToken("t");
437-
* }
438-
* </pre>
425+
* {@link #getPartitionKeyToken()} should generally be preferred to this method (unless the
426+
* token column is aliased).
439427
*
440428
* @param name the name of the column to retrieve.
441429
* @return the value of column {@code name} as a Token.
442-
* If the value is NULL, {@code null} is returned.
443430
*
444431
* @throws IllegalArgumentException if {@code name} is not part of the
445432
* ResultSet this row is part of, i.e. if {@code !this.columns().names().contains(name)}.
@@ -448,6 +435,29 @@ public interface Row {
448435
*/
449436
public Token getToken(String name);
450437

438+
/**
439+
* Returns the value of the first column containing a {@link Token}.
440+
* <p>
441+
* This method is a shorthand for queries returning a single token in an unaliased
442+
* column. It will look for the first name matching {@code token(...)}:
443+
* <pre>
444+
* {@code
445+
* ResultSet rs = session.execute("SELECT token(k) FROM my_table WHERE k = 1");
446+
* Token token = rs.one().getPartitionKeyToken(); // retrieves token(k)
447+
* }
448+
* </pre>
449+
* If that doesn't work for you (for example, if you're using an alias), use
450+
* {@link #getToken(int)} or {@link #getToken(String)}.
451+
*
452+
* @return the value of column {@code name} as a Token.
453+
*
454+
* @throws IllegalStateException if no column named {@code token(...)} exists in this
455+
* ResultSet.
456+
* @throws InvalidTypeException if the first column named {@code token(...)} is not of
457+
* the type of token values for this cluster (this depends on the configured partitioner).
458+
*/
459+
public Token getPartitionKeyToken();
460+
451461
/**
452462
* Returns the {@code i}th value of this row as a list.
453463
*

driver-core/src/test/java/com/datastax/driver/core/TokenIntegrationTest.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,21 +166,16 @@ public void should_get_token_from_row_and_set_token_in_query() {
166166
Token token = row.getToken(0);
167167
assertThat(token.getType()).isEqualTo(expectedTokenType);
168168

169-
// get by "base" column name (will add token() around it):
170169
assertThat(
171-
row.getToken("i")
170+
row.getPartitionKeyToken()
172171
).isEqualTo(token);
173172

174-
// get by name:
173+
// get by name when column is aliased:
175174
assertThat(
176175
session.execute("SELECT token(i) AS t FROM test.foo WHERE i = 1").one()
177176
.getToken("t")
178177
).isEqualTo(token);
179178

180-
// get by "base" column name when it's case-sensitive
181-
session.execute("SELECT token(\"caseSensitiveKey\") FROM test.foo2 WHERE \"caseSensitiveKey\" = 1").one()
182-
.getToken("\"caseSensitiveKey\"");
183-
184179

185180
PreparedStatement pst = session.prepare("SELECT * FROM test.foo WHERE token(i) = ?");
186181
row = session.execute(pst.bind(token)).one();
@@ -189,6 +184,9 @@ public void should_get_token_from_row_and_set_token_in_query() {
189184
row = session.execute(pst.bind().setToken(0, token)).one();
190185
assertThat(row.getInt(0)).isEqualTo(1);
191186

187+
row = session.execute(pst.bind().setPartitionKeyToken(token)).one();
188+
assertThat(row.getInt(0)).isEqualTo(1);
189+
192190
PreparedStatement pst2 = session.prepare("SELECT * FROM test.foo WHERE token(i) = :myToken");
193191
row = session.execute(pst2.bind().setToken("myToken", token)).one();
194192
assertThat(row.getInt(0)).isEqualTo(1);

0 commit comments

Comments
 (0)