diff --git a/src/main/java/org/apache/ibatis/jdbc/AbstractSQL.java b/src/main/java/org/apache/ibatis/jdbc/AbstractSQL.java index 6e031c46267..356c44cc576 100644 --- a/src/main/java/org/apache/ibatis/jdbc/AbstractSQL.java +++ b/src/main/java/org/apache/ibatis/jdbc/AbstractSQL.java @@ -20,6 +20,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; /** * @author Clinton Begin @@ -526,6 +528,71 @@ public A usingAppender(A a) { return a; } + /** + * Apply sql phrases that provide by SQL consumer if condition is matches. + * + * @param applyCondition + * if {@code true} apply sql phrases + * @param sqlConsumer + * a consumer that append sql phrase to SQL instance + * + * @return a self instance + * + * @see #applyIf(BooleanSupplier, Consumer) + * + * @since 3.5.14 + */ + public T applyIf(boolean applyCondition, Consumer sqlConsumer) { + T self = getSelf(); + if (applyCondition) { + sqlConsumer.accept(self); + } + return self; + } + + /** + * Apply sql phrases that provide by SQL consumer if condition is matches. + * + * @param applyConditionSupplier + * if supplier return {@code true} apply sql phrases + * @param sqlConsumer + * a consumer that append sql phrase to SQL instance + * + * @return a self instance + * + * @see #applyIf(boolean, Consumer) + * + * @since 3.5.14 + */ + public T applyIf(BooleanSupplier applyConditionSupplier, Consumer sqlConsumer) { + return applyIf(applyConditionSupplier.getAsBoolean(), sqlConsumer); + } + + /** + * Apply sql phrases that provide by SQL consumer for iterable. + * + * @param iterable + * an iterable + * @param forEachSqlConsumer + * a consumer that append sql phrase to SQL instance + * + * @return a self instance + * + * @param + * element type of iterable + * + * @since 3.5.14 + */ + public T applyForEach(Iterable iterable, ForEachConsumer forEachSqlConsumer) { + T self = getSelf(); + int elementIndex = 0; + for (E element : iterable) { + forEachSqlConsumer.accept(self, element, elementIndex); + elementIndex++; + } + return self; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -737,4 +804,31 @@ public String sql(Appendable a) { return answer; } } + + /** + * Consumer for 'forEach' operation. + * + * @param + * SQL type + * @param + * Element type of iterable + * + * @since 3.5.14 + */ + public interface ForEachConsumer { + + /** + * Accept an iterable element with index. + * + * @param sql + * SQL instance + * @param element + * an iterable element + * @param elementIndex + * an element index + */ + void accept(T sql, E element, int elementIndex); + + } + } diff --git a/src/test/java/org/apache/ibatis/jdbc/SQLTest.java b/src/test/java/org/apache/ibatis/jdbc/SQLTest.java index 7d0efd3ea36..456728c40ce 100644 --- a/src/test/java/org/apache/ibatis/jdbc/SQLTest.java +++ b/src/test/java/org/apache/ibatis/jdbc/SQLTest.java @@ -18,6 +18,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.ArrayList; +import java.util.List; + import org.junit.jupiter.api.Test; class SQLTest { @@ -499,4 +502,52 @@ void testValues() { assertThat(sql).isEqualToIgnoringWhitespace( "INSERT INTO PERSON (ID, FIRST_NAME, LAST_NAME) VALUES (#{id}, #{firstName}, #{lastName})"); } + + @Test + void testApplyIf() { + Bean bean = new Bean(); + // @formatter:off + String sqlString = new SQL() + .UPDATE("test") + .applyIf(bean.a != null, sql -> sql.SET("a=#{a}")) + .applyIf(bean.b != null, sql -> sql.SET("b=#{b}")) + .applyIf(bean::hasC, sql -> sql.SET("c=#{c}")) + .WHERE("id=#{id}").toString(); + // @formatter:on + + assertThat(sqlString).isEqualToIgnoringWhitespace("UPDATE test SET a=#{a} WHERE (id=#{id})"); + } + + @Test + void testApplyForEach() { + List beans = new ArrayList<>(); + beans.add(new Bean()); + beans.add(new Bean()); + + // @formatter:off + String sqlString = new SQL() + .INSERT_INTO("test") + .INTO_COLUMNS("a", "b", "c") + .applyForEach(beans, (sql, element, index) -> + sql.INTO_VALUES( + String.format("#{list[%s].a}", index), + String.format("#{list[%s].b}", index), + String.format("#{list[%s].c}", index) + ).ADD_ROW()) + .toString(); + // @formatter:on + + assertThat(sqlString).isEqualToIgnoringWhitespace( + "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})"); + } + + static class Bean { + private String a = "foo"; + private String b; + private String c; + + boolean hasC() { + return c != null; + } + } }