22
22
import java .util .LinkedHashMap ;
23
23
import java .util .List ;
24
24
import java .util .Map ;
25
+ import java .util .function .BiFunction ;
25
26
import java .util .stream .Collectors ;
26
27
27
28
import org .springframework .data .domain .Pageable ;
30
31
import org .springframework .data .r2dbc .mapping .SettableValue ;
31
32
import org .springframework .data .r2dbc .query .Criteria ;
32
33
import org .springframework .data .r2dbc .query .Update ;
34
+ import org .springframework .data .relational .core .sql .Column ;
35
+ import org .springframework .data .relational .core .sql .Expression ;
36
+ import org .springframework .data .relational .core .sql .Table ;
33
37
import org .springframework .data .relational .core .sql .SqlIdentifier ;
34
38
import org .springframework .lang .Nullable ;
35
39
@@ -179,19 +183,23 @@ default DeleteSpec createDelete(SqlIdentifier table) {
179
183
*/
180
184
class SelectSpec {
181
185
182
- private final SqlIdentifier table ;
183
- private final List <SqlIdentifier > projectedFields ;
186
+ private final Table table ;
187
+ private final List <String > projectedFields ;
188
+ private final List <Expression > selectList ;
184
189
private final @ Nullable Criteria criteria ;
185
190
private final Sort sort ;
186
- private final Pageable page ;
191
+ private final long offset ;
192
+ private final int limit ;
187
193
188
- protected SelectSpec (SqlIdentifier table , List <SqlIdentifier > projectedFields , @ Nullable Criteria criteria ,
189
- Sort sort , Pageable page ) {
194
+ protected SelectSpec (Table table , List <String > projectedFields , List < Expression > selectList ,
195
+ @ Nullable Criteria criteria , Sort sort , int limit , long offset ) {
190
196
this .table = table ;
191
197
this .projectedFields = projectedFields ;
198
+ this .selectList = selectList ;
192
199
this .criteria = criteria ;
193
200
this .sort = sort ;
194
- this .page = page ;
201
+ this .offset = offset ;
202
+ this .limit = limit ;
195
203
}
196
204
197
205
/**
@@ -212,7 +220,23 @@ public static SelectSpec create(String table) {
212
220
* @since 1.1
213
221
*/
214
222
public static SelectSpec create (SqlIdentifier table ) {
215
- return new SelectSpec (table , Collections .emptyList (), null , Sort .unsorted (), Pageable .unpaged ());
223
+ return new SelectSpec (Table .create (table ), Collections .emptyList (), Collections .emptyList (), null ,
224
+ Sort .unsorted (), -1 , -1 );
225
+ }
226
+
227
+ public SelectSpec doWithTable (BiFunction <Table , SelectSpec , SelectSpec > function ) {
228
+ return function .apply (getTable (), this );
229
+ }
230
+
231
+ /**
232
+ * Associate {@code projectedFields} with the select and create a new {@link SelectSpec}.
233
+ *
234
+ * @param projectedFields
235
+ * @return the {@link SelectSpec}.
236
+ * @since 1.1
237
+ */
238
+ public SelectSpec withProjection (String ... projectedFields ) {
239
+ return withProjection (Arrays .asList (projectedFields ));
216
240
}
217
241
218
242
/**
@@ -237,7 +261,25 @@ public SelectSpec withProjection(Collection<SqlIdentifier> projectedFields) {
237
261
List <SqlIdentifier > fields = new ArrayList <>(this .projectedFields );
238
262
fields .addAll (projectedFields );
239
263
240
- return new SelectSpec (this .table , fields , this .criteria , this .sort , this .page );
264
+ List <Expression > selectList = new ArrayList <>(this .selectList );
265
+ projectedFields .stream ().map (s -> Column .create (s , table )).forEach (selectList ::add );
266
+
267
+ return new SelectSpec (this .table , fields , selectList , this .criteria , this .sort , this .limit , this .offset );
268
+ }
269
+
270
+ /**
271
+ * Associate {@code expressions} with the select list and create a new {@link SelectSpec}.
272
+ *
273
+ * @param expressions
274
+ * @return the {@link SelectSpec}.
275
+ * @since 1.1
276
+ */
277
+ public SelectSpec withProjection (Expression ... expressions ) {
278
+
279
+ List <Expression > selectList = new ArrayList <>(this .selectList );
280
+ selectList .addAll (Arrays .asList (expressions ));
281
+
282
+ return new SelectSpec (this .table , projectedFields , selectList , this .criteria , this .sort , this .limit , this .offset );
241
283
}
242
284
243
285
/**
@@ -247,7 +289,8 @@ public SelectSpec withProjection(Collection<SqlIdentifier> projectedFields) {
247
289
* @return the {@link SelectSpec}.
248
290
*/
249
291
public SelectSpec withCriteria (Criteria criteria ) {
250
- return new SelectSpec (this .table , this .projectedFields , criteria , this .sort , this .page );
292
+ return new SelectSpec (this .table , this .projectedFields , this .selectList , criteria , this .sort , this .limit ,
293
+ this .offset );
251
294
}
252
295
253
296
/**
@@ -259,10 +302,12 @@ public SelectSpec withCriteria(Criteria criteria) {
259
302
public SelectSpec withSort (Sort sort ) {
260
303
261
304
if (sort .isSorted ()) {
262
- return new SelectSpec (this .table , this .projectedFields , this .criteria , sort , this .page );
305
+ return new SelectSpec (this .table , this .projectedFields , this .selectList , this .criteria , sort , this .limit ,
306
+ this .offset );
263
307
}
264
308
265
- return new SelectSpec (this .table , this .projectedFields , this .criteria , this .sort , this .page );
309
+ return new SelectSpec (this .table , this .projectedFields , this .selectList , this .criteria , this .sort , this .limit ,
310
+ this .offset );
266
311
}
267
312
268
313
/**
@@ -277,21 +322,48 @@ public SelectSpec withPage(Pageable page) {
277
322
278
323
Sort sort = page .getSort ();
279
324
280
- return new SelectSpec (this .table , this .projectedFields , this .criteria , sort . isSorted () ? sort : this .sort ,
281
- page );
325
+ return new SelectSpec (this .table , this .projectedFields , this .selectList , this .criteria ,
326
+ sort . isSorted () ? sort : this . sort , page . getPageSize (), page . getOffset () );
282
327
}
283
328
284
- return new SelectSpec (this .table , this .projectedFields , this .criteria , this .sort , page );
329
+ return new SelectSpec (this .table , this .projectedFields , this .selectList , this .criteria , this .sort , this .limit ,
330
+ this .offset );
285
331
}
286
332
287
- public SqlIdentifier getTable () {
333
+ /**
334
+ * Associate a result offset with the select and create a new {@link SelectSpec}.
335
+ *
336
+ * @param page
337
+ * @return the {@link SelectSpec}.
338
+ */
339
+ public SelectSpec offset (long offset ) {
340
+ return new SelectSpec (this .table , this .projectedFields , this .selectList , this .criteria , this .sort , this .limit ,
341
+ offset );
342
+ }
343
+
344
+ /**
345
+ * Associate a result limit with the select and create a new {@link SelectSpec}.
346
+ *
347
+ * @param page
348
+ * @return the {@link SelectSpec}.
349
+ */
350
+ public SelectSpec limit (int limit ) {
351
+ return new SelectSpec (this .table , this .projectedFields , this .selectList , this .criteria , this .sort , limit ,
352
+ this .offset );
353
+ }
354
+
355
+ public Table getTable () {
288
356
return this .table ;
289
357
}
290
358
291
359
public List <SqlIdentifier > getProjectedFields () {
292
360
return Collections .unmodifiableList (this .projectedFields );
293
361
}
294
362
363
+ public List <Expression > getSelectList () {
364
+ return Collections .unmodifiableList (selectList );
365
+ }
366
+
295
367
@ Nullable
296
368
public Criteria getCriteria () {
297
369
return this .criteria ;
@@ -301,8 +373,12 @@ public Sort getSort() {
301
373
return this .sort ;
302
374
}
303
375
304
- public Pageable getPage () {
305
- return this .page ;
376
+ public long getOffset () {
377
+ return this .offset ;
378
+ }
379
+
380
+ public int getLimit () {
381
+ return this .limit ;
306
382
}
307
383
}
308
384
0 commit comments