Skip to content

Commit f4d1556

Browse files
authored
Merge pull request #2887 from kazuki43zoo/add-suport-method-for-generating-dynamic-sql-on-SQL
Add support method for generating dynamic sql on SQL class
2 parents ca826c5 + bc050f2 commit f4d1556

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed

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

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.util.Arrays;
2121
import java.util.Collections;
2222
import java.util.List;
23+
import java.util.function.BooleanSupplier;
24+
import java.util.function.Consumer;
2325

2426
/**
2527
* @author Clinton Begin
@@ -526,6 +528,71 @@ public <A extends Appendable> A usingAppender(A a) {
526528
return a;
527529
}
528530

531+
/**
532+
* Apply sql phrases that provide by SQL consumer if condition is matches.
533+
*
534+
* @param applyCondition
535+
* if {@code true} apply sql phrases
536+
* @param sqlConsumer
537+
* a consumer that append sql phrase to SQL instance
538+
*
539+
* @return a self instance
540+
*
541+
* @see #applyIf(BooleanSupplier, Consumer)
542+
*
543+
* @since 3.5.14
544+
*/
545+
public T applyIf(boolean applyCondition, Consumer<T> sqlConsumer) {
546+
T self = getSelf();
547+
if (applyCondition) {
548+
sqlConsumer.accept(self);
549+
}
550+
return self;
551+
}
552+
553+
/**
554+
* Apply sql phrases that provide by SQL consumer if condition is matches.
555+
*
556+
* @param applyConditionSupplier
557+
* if supplier return {@code true} apply sql phrases
558+
* @param sqlConsumer
559+
* a consumer that append sql phrase to SQL instance
560+
*
561+
* @return a self instance
562+
*
563+
* @see #applyIf(boolean, Consumer)
564+
*
565+
* @since 3.5.14
566+
*/
567+
public T applyIf(BooleanSupplier applyConditionSupplier, Consumer<T> sqlConsumer) {
568+
return applyIf(applyConditionSupplier.getAsBoolean(), sqlConsumer);
569+
}
570+
571+
/**
572+
* Apply sql phrases that provide by SQL consumer for iterable.
573+
*
574+
* @param iterable
575+
* an iterable
576+
* @param forEachSqlConsumer
577+
* a consumer that append sql phrase to SQL instance
578+
*
579+
* @return a self instance
580+
*
581+
* @param <E>
582+
* element type of iterable
583+
*
584+
* @since 3.5.14
585+
*/
586+
public <E> T applyForEach(Iterable<E> iterable, ForEachConsumer<T, E> forEachSqlConsumer) {
587+
T self = getSelf();
588+
int elementIndex = 0;
589+
for (E element : iterable) {
590+
forEachSqlConsumer.accept(self, element, elementIndex);
591+
elementIndex++;
592+
}
593+
return self;
594+
}
595+
529596
@Override
530597
public String toString() {
531598
StringBuilder sb = new StringBuilder();
@@ -737,4 +804,31 @@ public String sql(Appendable a) {
737804
return answer;
738805
}
739806
}
807+
808+
/**
809+
* Consumer for 'forEach' operation.
810+
*
811+
* @param <T>
812+
* SQL type
813+
* @param <E>
814+
* Element type of iterable
815+
*
816+
* @since 3.5.14
817+
*/
818+
public interface ForEachConsumer<T, E> {
819+
820+
/**
821+
* Accept an iterable element with index.
822+
*
823+
* @param sql
824+
* SQL instance
825+
* @param element
826+
* an iterable element
827+
* @param elementIndex
828+
* an element index
829+
*/
830+
void accept(T sql, E element, int elementIndex);
831+
832+
}
833+
740834
}

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
import static org.assertj.core.api.Assertions.assertThat;
1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020

21+
import java.util.ArrayList;
22+
import java.util.List;
23+
2124
import org.junit.jupiter.api.Test;
2225

2326
class SQLTest {
@@ -499,4 +502,52 @@ void testValues() {
499502
assertThat(sql).isEqualToIgnoringWhitespace(
500503
"INSERT INTO PERSON (ID, FIRST_NAME, LAST_NAME) VALUES (#{id}, #{firstName}, #{lastName})");
501504
}
505+
506+
@Test
507+
void testApplyIf() {
508+
Bean bean = new Bean();
509+
// @formatter:off
510+
String sqlString = new SQL()
511+
.UPDATE("test")
512+
.applyIf(bean.a != null, sql -> sql.SET("a=#{a}"))
513+
.applyIf(bean.b != null, sql -> sql.SET("b=#{b}"))
514+
.applyIf(bean::hasC, sql -> sql.SET("c=#{c}"))
515+
.WHERE("id=#{id}").toString();
516+
// @formatter:on
517+
518+
assertThat(sqlString).isEqualToIgnoringWhitespace("UPDATE test SET a=#{a} WHERE (id=#{id})");
519+
}
520+
521+
@Test
522+
void testApplyForEach() {
523+
List<Bean> beans = new ArrayList<>();
524+
beans.add(new Bean());
525+
beans.add(new Bean());
526+
527+
// @formatter:off
528+
String sqlString = new SQL()
529+
.INSERT_INTO("test")
530+
.INTO_COLUMNS("a", "b", "c")
531+
.applyForEach(beans, (sql, element, index) ->
532+
sql.INTO_VALUES(
533+
String.format("#{list[%s].a}", index),
534+
String.format("#{list[%s].b}", index),
535+
String.format("#{list[%s].c}", index)
536+
).ADD_ROW())
537+
.toString();
538+
// @formatter:on
539+
540+
assertThat(sqlString).isEqualToIgnoringWhitespace(
541+
"INSERT INTO test (a, b, c) VALUES (#{list[0].a}, #{list[0].b}, #{list[0].c}), (#{list[1].a}, #{list[1].b}, #{list[1].c})");
542+
}
543+
544+
static class Bean {
545+
private String a = "foo";
546+
private String b;
547+
private String c;
548+
549+
boolean hasC() {
550+
return c != null;
551+
}
552+
}
502553
}

0 commit comments

Comments
 (0)