Skip to content

Commit a077238

Browse files
committed
Support FETCH FIRST on SQL class
1 parent 49f7153 commit a077238

File tree

2 files changed

+130
-13
lines changed

2 files changed

+130
-13
lines changed

src/main/java/org/apache/ibatis/jdbc/AbstractSQL.java

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,12 @@ public T ORDER_BY(String... columns) {
267267
*
268268
* @param variable a limit variable string
269269
* @return a self instance
270+
* @see #OFFSET(String)
270271
* @since 3.5.2
271272
*/
272273
public T LIMIT(String variable) {
273274
sql().limit = variable;
275+
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.OFFSET_LIMIT;
274276
return getSelf();
275277
}
276278

@@ -279,10 +281,12 @@ public T LIMIT(String variable) {
279281
*
280282
* @param value an offset value
281283
* @return a self instance
284+
* @see #OFFSET(long)
282285
* @since 3.5.2
283286
*/
284287
public T LIMIT(int value) {
285288
sql().limit = String.valueOf(value);
289+
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.OFFSET_LIMIT;
286290
return getSelf();
287291
}
288292

@@ -291,10 +295,12 @@ public T LIMIT(int value) {
291295
*
292296
* @param variable a offset variable string
293297
* @return a self instance
298+
* @see #LIMIT(String)
294299
* @since 3.5.2
295300
*/
296301
public T OFFSET(String variable) {
297302
sql().offset = variable;
303+
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.OFFSET_LIMIT;
298304
return getSelf();
299305
}
300306

@@ -303,10 +309,68 @@ public T OFFSET(String variable) {
303309
*
304310
* @param value an offset value
305311
* @return a self instance
312+
* @see #LIMIT(int)
306313
* @since 3.5.2
307314
*/
308315
public T OFFSET(long value) {
309316
sql().offset = String.valueOf(value);
317+
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.OFFSET_LIMIT;
318+
return getSelf();
319+
}
320+
321+
/**
322+
* Set the fetch first rows variable string(e.g. {@code "#{fetchFirstRows}"}).
323+
*
324+
* @param variable a fetch first rows variable string
325+
* @return a self instance
326+
* @see #OFFSET_ROWS(String)
327+
* @since 3.5.2
328+
*/
329+
public T FETCH_FIRST_ROWS_ONLY(String variable) {
330+
sql().limit = variable;
331+
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.ISO;
332+
return getSelf();
333+
}
334+
335+
/**
336+
* Set the fetch first rows value.
337+
*
338+
* @param value a fetch first rows value
339+
* @return a self instance
340+
* @see #OFFSET_ROWS(long)
341+
* @since 3.5.2
342+
*/
343+
public T FETCH_FIRST_ROWS_ONLY(int value) {
344+
sql().limit = String.valueOf(value);
345+
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.ISO;
346+
return getSelf();
347+
}
348+
349+
/**
350+
* Set the offset rows variable string(e.g. {@code "#{offset}"}).
351+
*
352+
* @param variable a offset rows variable string
353+
* @return a self instance
354+
* @see #FETCH_FIRST_ROWS_ONLY(String)
355+
* @since 3.5.2
356+
*/
357+
public T OFFSET_ROWS(String variable) {
358+
sql().offset = variable;
359+
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.ISO;
360+
return getSelf();
361+
}
362+
363+
/**
364+
* Set the offset rows value.
365+
*
366+
* @param value an offset rows value
367+
* @return a self instance
368+
* @see #FETCH_FIRST_ROWS_ONLY(int)
369+
* @since 3.5.2
370+
*/
371+
public T OFFSET_ROWS(long value) {
372+
sql().offset = String.valueOf(value);
373+
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.ISO;
310374
return getSelf();
311375
}
312376

@@ -359,6 +423,40 @@ public enum StatementType {
359423
DELETE, INSERT, SELECT, UPDATE
360424
}
361425

426+
private enum LimitingRowsStrategy {
427+
NOP {
428+
@Override
429+
protected void appendClause(SafeAppendable builder, String offset, String limit) {
430+
// NOP
431+
}
432+
},
433+
ISO {
434+
@Override
435+
protected void appendClause(SafeAppendable builder, String offset, String limit) {
436+
if (offset != null) {
437+
builder.append(" OFFSET ").append(offset).append(" ROWS");
438+
}
439+
if (limit != null) {
440+
builder.append(" FETCH FIRST ").append(limit).append(" ROWS ONLY");
441+
}
442+
}
443+
},
444+
OFFSET_LIMIT {
445+
@Override
446+
protected void appendClause(SafeAppendable builder, String offset, String limit) {
447+
if (limit != null) {
448+
builder.append(" LIMIT ").append(limit);
449+
}
450+
if (offset != null) {
451+
builder.append(" OFFSET ").append(offset);
452+
}
453+
}
454+
};
455+
456+
protected abstract void appendClause(SafeAppendable builder, String offset, String limit);
457+
458+
}
459+
362460
StatementType statementType;
363461
List<String> sets = new ArrayList<>();
364462
List<String> select = new ArrayList<>();
@@ -378,6 +476,7 @@ public enum StatementType {
378476
boolean distinct;
379477
String offset;
380478
String limit;
479+
LimitingRowsStrategy limitingRowsStrategy = LimitingRowsStrategy.NOP;
381480

382481
public SQLStatement() {
383482
// Prevent Synthetic Access
@@ -418,12 +517,7 @@ private String selectSQL(SafeAppendable builder) {
418517
sqlClause(builder, "GROUP BY", groupBy, "", "", ", ");
419518
sqlClause(builder, "HAVING", having, "(", ")", " AND ");
420519
sqlClause(builder, "ORDER BY", orderBy, "", "", ", ");
421-
if (limit != null) {
422-
builder.append(" LIMIT ").append(limit);
423-
}
424-
if (offset != null) {
425-
builder.append(" OFFSET ").append(offset);
426-
}
520+
limitingRowsStrategy.appendClause(builder, offset, limit);
427521
return builder.toString();
428522
}
429523

@@ -445,9 +539,7 @@ private String insertSQL(SafeAppendable builder) {
445539
private String deleteSQL(SafeAppendable builder) {
446540
sqlClause(builder, "DELETE FROM", tables, "", "", "");
447541
sqlClause(builder, "WHERE", where, "(", ")", " AND ");
448-
if (limit != null) {
449-
builder.append(" LIMIT ").append(limit);
450-
}
542+
limitingRowsStrategy.appendClause(builder, null, limit);
451543
return builder.toString();
452544
}
453545

@@ -456,9 +548,7 @@ private String updateSQL(SafeAppendable builder) {
456548
joins(builder);
457549
sqlClause(builder, "SET", sets, "", "", ", ");
458550
sqlClause(builder, "WHERE", where, "(", ")", " AND ");
459-
if (limit != null) {
460-
builder.append(" LIMIT ").append(limit);
461-
}
551+
limitingRowsStrategy.appendClause(builder, null, limit);
462552
return builder.toString();
463553
}
464554

@@ -494,4 +584,4 @@ public String sql(Appendable a) {
494584
return answer;
495585
}
496586
}
497-
}
587+
}

src/test/java/org/apache/ibatis/jdbc/SQLTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,4 +347,31 @@ void deleteUsingLimit() {
347347
assertEquals("DELETE FROM test\nWHERE (status = #{status}) LIMIT 20", sql);
348348
}
349349

350+
@Test
351+
void selectUsingFetchFirstRowsOnlyVariableName() {
352+
final String sql = new SQL() {{
353+
SELECT("*").FROM("test").ORDER_BY("id").FETCH_FIRST_ROWS_ONLY("#{fetchFirstRows}");
354+
}}.toString();
355+
356+
assertEquals("SELECT *\nFROM test\nORDER BY id FETCH FIRST #{fetchFirstRows} ROWS ONLY", sql);
357+
}
358+
359+
@Test
360+
void selectUsingOffsetRowsVariableName() {
361+
final String sql = new SQL() {{
362+
SELECT("*").FROM("test").ORDER_BY("id").OFFSET_ROWS("#{offsetRows}");
363+
}}.toString();
364+
365+
assertEquals("SELECT *\nFROM test\nORDER BY id OFFSET #{offsetRows} ROWS", sql);
366+
}
367+
368+
@Test
369+
void selectUsingOffsetRowsAndFetchFirstRowsOnly() {
370+
final String sql = new SQL() {{
371+
SELECT("*").FROM("test").ORDER_BY("id").OFFSET_ROWS(100).FETCH_FIRST_ROWS_ONLY(20);
372+
}}.toString();
373+
374+
assertEquals("SELECT *\nFROM test\nORDER BY id OFFSET 100 ROWS FETCH FIRST 20 ROWS ONLY", sql);
375+
}
376+
350377
}

0 commit comments

Comments
 (0)