Skip to content

Commit 3e2d8a1

Browse files
Gor027avelanarius
authored andcommitted
Add support for USING TIMEOUT to QueryBuilder
Add support for adding USING TIMEOUT clause to SELECT statements. The value of the clause (the timeout) can be passed either as a literal value (Duration) or as a BindMarker filled at a time of execution.
1 parent bb2fcdc commit 3e2d8a1

File tree

4 files changed

+101
-60
lines changed

4 files changed

+101
-60
lines changed

driver-core/src/main/java/com/datastax/driver/core/querybuilder/QueryBuilder.java

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
*/
1616
package com.datastax.driver.core.querybuilder;
1717

18-
import com.datastax.driver.core.DataType;
19-
import com.datastax.driver.core.Metadata;
20-
import com.datastax.driver.core.RegularStatement;
21-
import com.datastax.driver.core.TableMetadata;
18+
import com.datastax.driver.core.*;
2219
import com.datastax.driver.core.exceptions.InvalidQueryException;
2320
import java.util.Arrays;
2421
import java.util.Collections;
@@ -621,6 +618,33 @@ public static Using ttl(BindMarker marker) {
621618
return new Using.WithMarker("TTL", marker);
622619
}
623620

621+
/**
622+
* Adds a {@code USING TIMEOUT} clause to this statement with a {@link Duration} value.
623+
*
624+
* <p>If this method or {@link #timeout(BindMarker) } is called multiple times, the value from the
625+
* last invocation is used.
626+
*
627+
* @param timeout A timeout value controlling server-side query timeout.
628+
*/
629+
public static Using timeout(Duration timeout) {
630+
if (timeout == null) throw new IllegalArgumentException("Invalid timeout, should not be null");
631+
632+
return new Using.WithObject("TIMEOUT", timeout.toString());
633+
}
634+
635+
/**
636+
* Adds a {@code USING TIMEOUT} clause to this statement with a bind marker.
637+
*
638+
* <p>If this method or {@link #timeout(Duration) } is called multiple times, the value from the
639+
* last invocation is used.
640+
*
641+
* @param marker A bind marker understood as {@link Duration} controlling server-side query
642+
* timeout.
643+
*/
644+
public static Using timeout(BindMarker marker) {
645+
return new Using.WithMarker("TIMEOUT", marker);
646+
}
647+
624648
/**
625649
* Simple "set" assignment of a value to a column.
626650
*

driver-core/src/main/java/com/datastax/driver/core/querybuilder/Select.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class Select extends BuiltStatement {
3838
private final boolean isJson;
3939
private final List<Object> columnNames;
4040
private final Where where;
41+
private final Options usings;
4142
private List<Ordering> orderings;
4243
private List<Object> groupByColumnNames;
4344
private Object limit;
@@ -76,6 +77,7 @@ public class Select extends BuiltStatement {
7677
this.isDistinct = isDistinct;
7778
this.isJson = isJson;
7879
this.where = new Where(this);
80+
this.usings = new Options(this);
7981
}
8082

8183
@Override
@@ -128,6 +130,11 @@ StringBuilder buildQueryString(List<Object> variables, CodecRegistry codecRegist
128130
builder.append(" BYPASS CACHE");
129131
}
130132

133+
if (!usings.usings.isEmpty()) {
134+
builder.append(" USING ");
135+
Utils.joinAndAppend(builder, codecRegistry, " AND ", usings.usings, variables);
136+
}
137+
131138
return builder;
132139
}
133140

@@ -152,6 +159,16 @@ public Where where() {
152159
return where;
153160
}
154161

162+
/**
163+
* Adds a new options for this SELECT statement.
164+
*
165+
* @param using the option to add.
166+
* @return the options of this SELECT statement.
167+
*/
168+
public Options using(Using using) {
169+
return usings.and(using);
170+
}
171+
155172
/**
156173
* Adds an {@code ORDER BY} clause to this statement.
157174
*
@@ -320,6 +337,16 @@ public Where and(Clause clause) {
320337
return this;
321338
}
322339

340+
/**
341+
* Adds an option to the SELECT statement this WHERE clause is part of.
342+
*
343+
* @param using the using clause to add.
344+
* @return the options of the SELECT statement this WHERE clause is part of.
345+
*/
346+
public Options using(Using using) {
347+
return statement.using(using);
348+
}
349+
323350
/**
324351
* Adds an ORDER BY clause to the {@code SELECT} statement this {@code WHERE} clause if part of.
325352
*
@@ -425,6 +452,27 @@ public Select bypassCache() {
425452
}
426453
}
427454

455+
/** The options of a SELECT statement. */
456+
public static class Options extends BuiltStatement.ForwardingStatement<Select> {
457+
private final List<Using> usings = new ArrayList<Using>();
458+
459+
Options(Select statement) {
460+
super(statement);
461+
}
462+
463+
/**
464+
* Adds the provided option.
465+
*
466+
* @param using a SELECT option.
467+
* @return this {@code Options} object.
468+
*/
469+
public Options and(Using using) {
470+
usings.add(using);
471+
checkForBindMarkers(using);
472+
return this;
473+
}
474+
}
475+
428476
/** An in-construction SELECT statement. */
429477
public static class Builder {
430478

driver-core/src/main/java/com/datastax/driver/core/querybuilder/Using.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,23 @@ boolean containsBindMarker() {
6363
return true;
6464
}
6565
}
66+
67+
static class WithObject extends Using {
68+
private final Object object;
69+
70+
WithObject(String optionName, Object object) {
71+
super(optionName);
72+
this.object = object;
73+
}
74+
75+
@Override
76+
void appendTo(StringBuilder sb, List<Object> variables, CodecRegistry codecRegistry) {
77+
sb.append(optionName).append(' ').append(object);
78+
}
79+
80+
@Override
81+
boolean containsBindMarker() {
82+
return false;
83+
}
84+
}
6685
}

driver-core/src/test/java/com/datastax/driver/core/querybuilder/QueryBuilderTest.java

Lines changed: 6 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,67 +15,13 @@
1515
*/
1616
package com.datastax.driver.core.querybuilder;
1717

18-
import static com.datastax.driver.core.querybuilder.QueryBuilder.add;
19-
import static com.datastax.driver.core.querybuilder.QueryBuilder.addAll;
20-
import static com.datastax.driver.core.querybuilder.QueryBuilder.alias;
21-
import static com.datastax.driver.core.querybuilder.QueryBuilder.append;
22-
import static com.datastax.driver.core.querybuilder.QueryBuilder.appendAll;
23-
import static com.datastax.driver.core.querybuilder.QueryBuilder.asc;
24-
import static com.datastax.driver.core.querybuilder.QueryBuilder.batch;
25-
import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
26-
import static com.datastax.driver.core.querybuilder.QueryBuilder.cast;
27-
import static com.datastax.driver.core.querybuilder.QueryBuilder.column;
28-
import static com.datastax.driver.core.querybuilder.QueryBuilder.contains;
29-
import static com.datastax.driver.core.querybuilder.QueryBuilder.containsKey;
30-
import static com.datastax.driver.core.querybuilder.QueryBuilder.decr;
31-
import static com.datastax.driver.core.querybuilder.QueryBuilder.delete;
32-
import static com.datastax.driver.core.querybuilder.QueryBuilder.desc;
33-
import static com.datastax.driver.core.querybuilder.QueryBuilder.discard;
34-
import static com.datastax.driver.core.querybuilder.QueryBuilder.discardAll;
35-
import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
36-
import static com.datastax.driver.core.querybuilder.QueryBuilder.fcall;
37-
import static com.datastax.driver.core.querybuilder.QueryBuilder.fromJson;
38-
import static com.datastax.driver.core.querybuilder.QueryBuilder.gt;
39-
import static com.datastax.driver.core.querybuilder.QueryBuilder.gte;
40-
import static com.datastax.driver.core.querybuilder.QueryBuilder.in;
41-
import static com.datastax.driver.core.querybuilder.QueryBuilder.incr;
42-
import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
43-
import static com.datastax.driver.core.querybuilder.QueryBuilder.like;
44-
import static com.datastax.driver.core.querybuilder.QueryBuilder.lt;
45-
import static com.datastax.driver.core.querybuilder.QueryBuilder.lte;
46-
import static com.datastax.driver.core.querybuilder.QueryBuilder.ne;
47-
import static com.datastax.driver.core.querybuilder.QueryBuilder.notNull;
48-
import static com.datastax.driver.core.querybuilder.QueryBuilder.path;
49-
import static com.datastax.driver.core.querybuilder.QueryBuilder.prepend;
50-
import static com.datastax.driver.core.querybuilder.QueryBuilder.prependAll;
51-
import static com.datastax.driver.core.querybuilder.QueryBuilder.put;
52-
import static com.datastax.driver.core.querybuilder.QueryBuilder.putAll;
53-
import static com.datastax.driver.core.querybuilder.QueryBuilder.quote;
54-
import static com.datastax.driver.core.querybuilder.QueryBuilder.raw;
55-
import static com.datastax.driver.core.querybuilder.QueryBuilder.remove;
56-
import static com.datastax.driver.core.querybuilder.QueryBuilder.removeAll;
57-
import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
58-
import static com.datastax.driver.core.querybuilder.QueryBuilder.set;
59-
import static com.datastax.driver.core.querybuilder.QueryBuilder.setIdx;
60-
import static com.datastax.driver.core.querybuilder.QueryBuilder.timestamp;
61-
import static com.datastax.driver.core.querybuilder.QueryBuilder.toJson;
62-
import static com.datastax.driver.core.querybuilder.QueryBuilder.token;
63-
import static com.datastax.driver.core.querybuilder.QueryBuilder.truncate;
64-
import static com.datastax.driver.core.querybuilder.QueryBuilder.ttl;
65-
import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
18+
import static com.datastax.driver.core.querybuilder.QueryBuilder.*;
6619
import static org.assertj.core.api.Assertions.assertThat;
6720
import static org.assertj.core.api.Assertions.fail;
6821
import static org.testng.Assert.assertEquals;
6922
import static org.testng.Assert.assertTrue;
7023

71-
import com.datastax.driver.core.CodecRegistry;
72-
import com.datastax.driver.core.ConsistencyLevel;
73-
import com.datastax.driver.core.DataType;
74-
import com.datastax.driver.core.Metadata;
75-
import com.datastax.driver.core.ProtocolVersion;
76-
import com.datastax.driver.core.RegularStatement;
77-
import com.datastax.driver.core.Statement;
78-
import com.datastax.driver.core.TypeCodec;
24+
import com.datastax.driver.core.*;
7925
import com.datastax.driver.core.exceptions.CodecNotFoundException;
8026
import com.datastax.driver.core.exceptions.InvalidQueryException;
8127
import com.datastax.driver.core.exceptions.InvalidTypeException;
@@ -264,6 +210,10 @@ public void selectTest() throws Exception {
264210
select = select().from("foo").where(notNull("k"));
265211
assertEquals(select.toString(), query);
266212

213+
query = "SELECT * FROM foo WHERE k IS NOT NULL USING TIMEOUT 50ms;";
214+
select = select().from("foo").where(notNull("k")).using(timeout(Duration.from("50ms")));
215+
assertEquals(select.toString(), query);
216+
267217
try {
268218
select().countAll().from("foo").orderBy(asc("a"), desc("b")).orderBy(asc("a"), desc("b"));
269219
fail("Expected an IllegalStateException");

0 commit comments

Comments
 (0)