Skip to content

Commit 8b77aa9

Browse files
committed
#89 - Accept SQL directly in DatabaseClient.execute(…) stage.
We compressed client.execute().sql(…) to client.execute(…) to not require the intermediate execute() step but rather accept the SQL to execute directly. Original pull request: #112.
1 parent 36c4c1d commit 8b77aa9

File tree

10 files changed

+82
-41
lines changed

10 files changed

+82
-41
lines changed

src/main/asciidoc/reference/r2dbc-core.adoc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ public class R2dbcApp {
139139
140140
DatabaseClient client = DatabaseClient.create(connectionFactory);
141141
142-
client.execute()
143-
.sql("CREATE TABLE person" +
142+
client.sql("CREATE TABLE person" +
144143
"(id VARCHAR(255) PRIMARY KEY," +
145144
"name VARCHAR(255)," +
146145
"age INT)")

src/main/asciidoc/reference/r2dbc-sql.adoc

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,15 @@ The following example shows what you need to include for minimal but fully funct
66

77
[source,java]
88
----
9-
Mono<Void> completion = client.execute()
10-
.sql("CREATE TABLE person (id VARCHAR(255) PRIMARY KEY, name VARCHAR(255), age INTEGER);")
9+
Mono<Void> completion = client.sql("CREATE TABLE person (id VARCHAR(255) PRIMARY KEY, name VARCHAR(255), age INTEGER);")
1110
.then();
1211
----
1312

1413
`DatabaseClient` is designed for a convenient fluent usage.
1514
It exposes intermediate, continuation, and terminal methods at each stage of the execution specification.
1615
The example above uses `then()` to return a completion `Publisher` that completes as soon as the query (or queries, if the SQL query contains multiple statements) completes.
1716

18-
NOTE: `execute().sql(…)` accepts either the SQL query string or a query `Supplier<String>` to defer the actual query creation until execution.
17+
NOTE: `sql(…)` accepts either the SQL query string or a query `Supplier<String>` to defer the actual query creation until execution.
1918

2019
[[r2dbc.datbaseclient.queries]]
2120
== Running Queries
@@ -27,8 +26,7 @@ The following example shows an `UPDATE` statement that returns the number of upd
2726

2827
[source,java]
2928
----
30-
Mono<Integer> affectedRows = client.execute()
31-
.sql("UPDATE person SET name = 'Joe'")
29+
Mono<Integer> affectedRows = client.sql("UPDATE person SET name = 'Joe'")
3230
.fetch().rowsUpdated();
3331
----
3432

@@ -38,8 +36,7 @@ You might have noticed the use of `fetch()` in the previous example.
3836

3937
[source,java]
4038
----
41-
Mono<Map<String, Object>> first = client.execute()
42-
.sql("SELECT id, name FROM person")
39+
Mono<Map<String, Object>> first = client.sql("SELECT id, name FROM person")
4340
.fetch().first();
4441
----
4542

@@ -55,8 +52,7 @@ You can consume data with the following operators:
5552

5653
[source,java]
5754
----
58-
Flux<Person> all = client.execute()
59-
.sql("SELECT id, name FROM mytable")
55+
Flux<Person> all = client.sql("SELECT id, name FROM mytable")
6056
.as(Person.class)
6157
.fetch().all();
6258
----
@@ -73,8 +69,7 @@ The following example extracts the `id` column and emits its value:
7369

7470
[source,java]
7571
----
76-
Flux<String> names= client.execute()
77-
.sql("SELECT name FROM person")
72+
Flux<String> names = client.sql("SELECT name FROM person")
7873
.map((row, rowMetadata) -> row.get("id", String.class))
7974
.all();
8075
----
@@ -107,8 +102,7 @@ The following example shows parameter binding for a query:
107102

108103
[source,java]
109104
----
110-
db.execute()
111-
.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
105+
db.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
112106
.bind("id", "joe")
113107
.bind("name", "Joe")
114108
.bind("age", 34);
@@ -146,8 +140,7 @@ List<Object[]> tuples = new ArrayList<>();
146140
tuples.add(new Object[] {"John", 35});
147141
tuples.add(new Object[] {"Ann", 50});
148142
149-
db.execute()
150-
.sql("SELECT id, name, state FROM table WHERE (name, age) IN (:tuples)")
143+
db.sql("SELECT id, name, state FROM table WHERE (name, age) IN (:tuples)")
151144
.bind("tuples", tuples);
152145
----
153146

@@ -157,7 +150,6 @@ A simpler variant using `IN` predicates:
157150

158151
[source,java]
159152
----
160-
db.execute()
161-
.sql("SELECT id, name, state FROM table WHERE age IN (:ages)")
153+
db.sql("SELECT id, name, state FROM table WHERE age IN (:ages)")
162154
.bind("ages", Arrays.asList(35, 50));
163155
----

src/main/asciidoc/reference/r2dbc-transactions.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ TransactionalOperator operator = TransactionalOperator.create(tm); <1>
1818
1919
DatabaseClient client = DatabaseClient.create(connectionFactory);
2020
21-
Mono<Void> atomicOperation = client.execute().sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
21+
Mono<Void> atomicOperation = client.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
2222
.bind("id", "joe")
2323
.bind("name", "Joe")
2424
.bind("age", 34)
2525
.fetch().rowsUpdated()
26-
.then(client.execute().sql("INSERT INTO contacts (id, name) VALUES(:id, :name)")
26+
.then(client.sql("INSERT INTO contacts (id, name) VALUES(:id, :name)")
2727
.bind("id", "joe")
2828
.bind("name", "Joe")
2929
.fetch().rowsUpdated())
@@ -69,12 +69,12 @@ class MyService {
6969
@Transactional
7070
public Mono<Void> insertPerson() {
7171
72-
return client.execute().sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
72+
return client.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
7373
.bind("id", "joe")
7474
.bind("name", "Joe")
7575
.bind("age", 34)
7676
.fetch().rowsUpdated()
77-
.then(client.execute().sql("INSERT INTO contacts (id, name) VALUES(:id, :name)")
77+
.then(client.sql("INSERT INTO contacts (id, name) VALUES(:id, :name)")
7878
.bind("id", "joe")
7979
.bind("name", "Joe")
8080
.fetch().rowsUpdated())

src/main/java/org/springframework/data/r2dbc/core/DatabaseClient.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,42 @@
4545
*/
4646
public interface DatabaseClient {
4747

48+
/**
49+
* Specify a static {@code sql} string to execute. Contract for specifying a SQL call along with options leading to
50+
* the exchange. The SQL string can contain either native parameter bind markers or named parameters (e.g.
51+
* {@literal :foo, :bar}) when {@link NamedParameterExpander} is enabled.
52+
*
53+
* @see NamedParameterExpander
54+
* @see DatabaseClient.Builder#namedParameters(NamedParameterExpander)
55+
* @param sql must not be {@literal null} or empty.
56+
* @return a new {@link GenericExecuteSpec}.
57+
* @see NamedParameterExpander
58+
* @see DatabaseClient.Builder#namedParameters(NamedParameterExpander)
59+
*/
60+
GenericExecuteSpec execute(String sql);
61+
62+
/**
63+
* Specify a {@link Supplier SQL supplier} that provides SQL to execute. Contract for specifying a SQL call along with
64+
* options leading to the exchange. The SQL string can contain either native parameter bind markers or named
65+
* parameters (e.g. {@literal :foo, :bar}) when {@link NamedParameterExpander} is enabled.
66+
* <p>
67+
* Accepts {@link PreparedOperation} as SQL and binding {@link Supplier}.
68+
* </p>
69+
*
70+
* @param sqlSupplier must not be {@literal null}.
71+
* @return a new {@link GenericExecuteSpec}.
72+
* @see NamedParameterExpander
73+
* @see DatabaseClient.Builder#namedParameters(NamedParameterExpander)
74+
* @see PreparedOperation
75+
*/
76+
GenericExecuteSpec execute(Supplier<String> sqlSupplier);
77+
4878
/**
4979
* Prepare an SQL call returning a result.
80+
*
81+
* @deprecated will be removed with 1.0 M3. Use {@link #execute(String)} directly.
5082
*/
83+
@Deprecated
5184
SqlSpec execute();
5285

5386
/**
@@ -157,7 +190,9 @@ interface Builder {
157190
*
158191
* @see NamedParameterExpander
159192
* @see DatabaseClient.Builder#namedParameters(NamedParameterExpander)
193+
* @deprecated use {@code DatabaseClient.execute(…)} directly.
160194
*/
195+
@Deprecated
161196
interface SqlSpec {
162197

163198
/**
@@ -166,6 +201,7 @@ interface SqlSpec {
166201
* @param sql must not be {@literal null} or empty.
167202
* @return a new {@link GenericExecuteSpec}.
168203
*/
204+
@Deprecated
169205
GenericExecuteSpec sql(String sql);
170206

171207
/**
@@ -175,6 +211,7 @@ interface SqlSpec {
175211
* @return a new {@link GenericExecuteSpec}.
176212
* @see PreparedOperation
177213
*/
214+
@Deprecated
178215
GenericExecuteSpec sql(Supplier<String> sqlSupplier);
179216
}
180217

src/main/java/org/springframework/data/r2dbc/core/DefaultDatabaseClient.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ public DeleteFromSpec delete() {
124124
return new DefaultDeleteFromSpec();
125125
}
126126

127+
@Override
128+
public GenericExecuteSpec execute(String sql) {
129+
130+
Assert.hasText(sql, "SQL must not be null or empty!");
131+
132+
return execute(() -> sql);
133+
}
134+
135+
@Override
136+
public GenericExecuteSpec execute(Supplier<String> sqlSupplier) {
137+
138+
Assert.notNull(sqlSupplier, "SQL Supplier must not be null!");
139+
140+
return createGenericExecuteSpec(sqlSupplier);
141+
}
142+
127143
/**
128144
* Execute a callback {@link Function} within a {@link Connection} scope. The function is responsible for creating a
129145
* {@link Mono}. The connection is released after the {@link Mono} terminates (or the subscription is cancelled).

src/main/java/org/springframework/data/r2dbc/core/TransactionalDatabaseClient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
* <pre class="code">
4242
* Flux<Integer> transactionalFlux = databaseClient.inTransaction(db -> {
4343
*
44-
* return db.execute().sql("INSERT INTO person (id, firstname, lastname) VALUES(:id, :firstname, :lastname)") //
44+
* return db.execute("INSERT INTO person (id, firstname, lastname) VALUES(:id, :firstname, :lastname)") //
4545
* .bind("id", 1) //
4646
* .bind("firstname", "Walter") //
4747
* .bind("lastname", "White") //
@@ -56,7 +56,7 @@
5656
* <pre class="code">
5757
* Mono<Void> mono = databaseClient.beginTransaction()
5858
* .then(databaseClient.execute()
59-
* .sql("INSERT INTO person (id, firstname, lastname) VALUES(:id, :firstname, :lastname)") //
59+
* .execute("INSERT INTO person (id, firstname, lastname) VALUES(:id, :firstname, :lastname)") //
6060
* .bind("id", 1) //
6161
* .bind("firstname", "Walter") //
6262
* .bind("lastname", "White") //

src/main/java/org/springframework/data/r2dbc/repository/query/AbstractR2dbcQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private Object execute(RelationalParameterAccessor parameterAccessor) {
103103
BindableQuery query = createQuery(parameterAccessor);
104104

105105
ResultProcessor processor = method.getResultProcessor().withDynamicProjection(parameterAccessor);
106-
GenericExecuteSpec boundQuery = query.bind(databaseClient.execute().sql(query));
106+
GenericExecuteSpec boundQuery = query.bind(databaseClient.execute(query));
107107
FetchSpec<?> fetchSpec = boundQuery.as(resolveResultType(processor)).fetch();
108108

109109
String tableName = method.getEntityInformation().getTableName();

src/main/java/org/springframework/data/r2dbc/repository/support/SimpleR2dbcRepository.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public Mono<T> findById(ID id) {
117117

118118
PreparedOperation<?> operation = mapper.getMappedObject(selectSpec);
119119

120-
return this.databaseClient.execute().sql(operation) //
120+
return this.databaseClient.execute(operation) //
121121
.as(this.entity.getJavaType()) //
122122
.fetch() //
123123
.one();
@@ -148,7 +148,7 @@ public Mono<Boolean> existsById(ID id) {
148148

149149
PreparedOperation<?> operation = mapper.getMappedObject(selectSpec);
150150

151-
return this.databaseClient.execute().sql(operation) //
151+
return this.databaseClient.execute(operation) //
152152
.map((r, md) -> r) //
153153
.first() //
154154
.hasElement();
@@ -205,7 +205,7 @@ public Flux<T> findAllById(Publisher<ID> idPublisher) {
205205

206206
PreparedOperation<?> operation = mapper.getMappedObject(selectSpec);
207207

208-
return this.databaseClient.execute().sql(operation).as(this.entity.getJavaType()).fetch().all();
208+
return this.databaseClient.execute(operation).as(this.entity.getJavaType()).fetch().all();
209209
});
210210
}
211211

@@ -221,7 +221,7 @@ public Mono<Long> count() {
221221
.from(table) //
222222
.build();
223223

224-
return this.databaseClient.execute().sql(SqlRenderer.toString(select)) //
224+
return this.databaseClient.execute(SqlRenderer.toString(select)) //
225225
.map((r, md) -> r.get(0, Long.class)) //
226226
.first() //
227227
.defaultIfEmpty(0L);

src/test/java/org/springframework/data/r2dbc/core/AbstractDatabaseClientIntegrationTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void executeInsert() {
101101

102102
DatabaseClient databaseClient = DatabaseClient.create(connectionFactory);
103103

104-
databaseClient.execute().sql(getInsertIntoLegosetStatement()) //
104+
databaseClient.execute(getInsertIntoLegosetStatement()) //
105105
.bind("id", 42055) //
106106
.bind("name", "SCHAUFELRADBAGGER") //
107107
.bindNull("manual", Integer.class) //
@@ -120,7 +120,7 @@ public void shouldTranslateDuplicateKeyException() {
120120

121121
executeInsert();
122122

123-
databaseClient.execute().sql(getInsertIntoLegosetStatement()) //
123+
databaseClient.execute(getInsertIntoLegosetStatement()) //
124124
.bind(0, 42055) //
125125
.bind(1, "SCHAUFELRADBAGGER") //
126126
.bindNull(2, Integer.class) //
@@ -139,7 +139,7 @@ public void executeSelect() {
139139

140140
DatabaseClient databaseClient = DatabaseClient.create(connectionFactory);
141141

142-
databaseClient.execute().sql("SELECT id, name, manual FROM legoset") //
142+
databaseClient.execute("SELECT id, name, manual FROM legoset") //
143143
.as(LegoSet.class) //
144144
.fetch().all() //
145145
.as(StepVerifier::create) //

src/test/java/org/springframework/data/r2dbc/core/AbstractTransactionalDatabaseClientIntegrationTests.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,7 @@ public void executeInsertInManagedTransaction() {
145145
TransactionalDatabaseClient databaseClient = TransactionalDatabaseClient.create(connectionFactory);
146146

147147
Flux<Integer> integerFlux = databaseClient.inTransaction(db -> db //
148-
.execute() //
149-
.sql(getInsertIntoLegosetStatement()) //
148+
.execute(getInsertIntoLegosetStatement()) //
150149
.bind(0, 42055) //
151150
.bind(1, "SCHAUFELRADBAGGER") //
152151
.bindNull(2, Integer.class) //
@@ -165,7 +164,7 @@ public void executeInsertInAutoCommitTransaction() {
165164

166165
TransactionalDatabaseClient databaseClient = TransactionalDatabaseClient.create(connectionFactory);
167166

168-
Mono<Integer> integerFlux = databaseClient.execute().sql(getInsertIntoLegosetStatement()) //
167+
Mono<Integer> integerFlux = databaseClient.execute(getInsertIntoLegosetStatement()) //
169168
.bind(0, 42055) //
170169
.bind(1, "SCHAUFELRADBAGGER") //
171170
.bindNull(2, Integer.class) //
@@ -185,8 +184,7 @@ public void shouldManageUserTransaction() {
185184
TransactionalDatabaseClient databaseClient = TransactionalDatabaseClient.create(connectionFactory);
186185

187186
Flux<Long> txId = databaseClient //
188-
.execute() //
189-
.sql(getCurrentTransactionIdStatement()) //
187+
.execute(getCurrentTransactionIdStatement()) //
190188
.map((r, md) -> r.get(0, Long.class)) //
191189
.all();
192190

@@ -224,7 +222,7 @@ public void shouldRollbackTransaction() {
224222

225223
Flux<Integer> integerFlux = databaseClient.inTransaction(db -> {
226224

227-
return db.execute().sql(getInsertIntoLegosetStatement()) //
225+
return db.execute(getInsertIntoLegosetStatement()) //
228226
.bind(0, 42055) //
229227
.bind(1, "SCHAUFELRADBAGGER") //
230228
.bindNull(2, Integer.class) //
@@ -248,8 +246,7 @@ public void emitTransactionIds() {
248246
TransactionalOperator transactionalOperator = TransactionalOperator
249247
.create(new R2dbcTransactionManager(connectionFactory), new DefaultTransactionDefinition());
250248

251-
Flux<Object> txId = databaseClient.execute() //
252-
.sql(getCurrentTransactionIdStatement()) //
249+
Flux<Object> txId = databaseClient.execute(getCurrentTransactionIdStatement()) //
253250
.map((row, md) -> row.get(0)) //
254251
.all();
255252

0 commit comments

Comments
 (0)