From 37a66f1ee230eb77f29bb31c99d48bfa66e5896b Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Mon, 4 Feb 2019 14:24:47 +1300 Subject: [PATCH] Playing around with SqlUpdate and bind expansion for ?1 etc --- .../server/core/DefaultSqlUpdate.java | 34 +++++- .../TestSqlUpdateBindMultipleLists.java | 100 ++++++++++++++++++ 2 files changed, 131 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/ebeaninternal/server/core/DefaultSqlUpdate.java b/src/main/java/io/ebeaninternal/server/core/DefaultSqlUpdate.java index 7b028fa2b..04390da12 100644 --- a/src/main/java/io/ebeaninternal/server/core/DefaultSqlUpdate.java +++ b/src/main/java/io/ebeaninternal/server/core/DefaultSqlUpdate.java @@ -9,6 +9,7 @@ import io.ebeaninternal.api.SpiSqlUpdate; import io.ebeaninternal.api.SpiTransaction; import java.io.Serializable; +import java.util.Collection; /** * A SQL Update Delete or Insert statement that can be executed. For the times @@ -66,6 +67,8 @@ public final class DefaultSqlUpdate implements Serializable, SpiSqlUpdate { */ private int addPos; + private int bindExpansion; + private boolean getGeneratedKeys; private Object generatedKey; @@ -253,21 +256,46 @@ public final class DefaultSqlUpdate implements Serializable, SpiSqlUpdate { return this; } + private SqlUpdate setParamWithBindExpansion(int position, Collection values, String bindLiteral) { + + StringBuilder sqlExpand = new StringBuilder(values.size() * 2); + int offset = 0; + for (Object val : values) { + if (offset > 0) { + sqlExpand.append(","); + } + sqlExpand.append("?"); + bindParams.setParameter(position + offset++, val); + } + bindExpansion += offset; + generatedSql = generatedSql.replace(bindLiteral, sqlExpand.toString()); + return this; + } + @Override public SqlUpdate setParameter(int position, Object value) { - bindParams.setParameter(position, value); + + if (value instanceof Collection) { + String bindLiteral = "?" + position; + int pos = sql.indexOf(bindLiteral); + if (pos > -1) { + return setParamWithBindExpansion(position, (Collection) value, bindLiteral); + } + } + + bindParams.setParameter(bindExpansion + position, value); return this; } @Override public SqlUpdate setNull(int position, int jdbcType) { - bindParams.setNullParameter(position, jdbcType); + bindParams.setNullParameter(bindExpansion + position, jdbcType); return this; } @Override public SqlUpdate setNullParameter(int position, int jdbcType) { - bindParams.setNullParameter(position, jdbcType); + bindParams.setNullParameter(bindExpansion + position, jdbcType); return this; } diff --git a/src/test/java/org/tests/update/TestSqlUpdateBindMultipleLists.java b/src/test/java/org/tests/update/TestSqlUpdateBindMultipleLists.java index acef06709..0bad6f45c 100644 --- a/src/test/java/org/tests/update/TestSqlUpdateBindMultipleLists.java +++ b/src/test/java/org/tests/update/TestSqlUpdateBindMultipleLists.java @@ -1,8 +1,10 @@ package org.tests.update; import io.ebean.BaseTestCase; +import io.ebean.DB; import io.ebean.Ebean; import io.ebean.SqlUpdate; +import io.ebean.Transaction; import org.junit.Test; import static java.util.Arrays.asList; @@ -26,6 +28,104 @@ public class TestSqlUpdateBindMultipleLists extends BaseTestCase { } + @Test + public void positionParamsExpansion() { + + SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (?1)"); + + sqlUpdate.setParameter(1, asList(9991, 9992, 9993)); + sqlUpdate.execute(); + + assertEquals("delete from o_customer where id in (?,?,?)", sqlUpdate.getGeneratedSql()); + + sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (?1)"); + + sqlUpdate.setParameter(1, asList(9991, 9993)); + sqlUpdate.execute(); + + assertEquals("delete from o_customer where id in (?,?)", sqlUpdate.getGeneratedSql()); + + sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (?1)"); + + sqlUpdate.setParameter(1, asList(9993)); + sqlUpdate.execute(); + + assertEquals("delete from o_customer where id in (?)", sqlUpdate.getGeneratedSql()); + } + + @Test + public void positionParamsExpansion_withPrePost() { + + SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?"); + + sqlUpdate.setParameter(1, 90); + sqlUpdate.setParameter(2, asList(9991, 9992, 9993)); + sqlUpdate.setParameter(3, 91); + + sqlUpdate.execute(); + + assertEquals("delete from o_customer where id > ? and id in (?,?,?) and id < ?", sqlUpdate.getGeneratedSql()); + } + + @Test + public void positionParamsExpansion_withPrePost_usingParam() { + + SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?"); + + sqlUpdate.setParams(90, asList(9991, 9992, 9993), 91); + sqlUpdate.execute(); + + assertEquals("delete from o_customer where id > ? and id in (?,?,?) and id < ?", sqlUpdate.getGeneratedSql()); + } + + @Test + public void positionParamsExpansion_withPre() { + + SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where name = ? and id in (?2)"); + + sqlUpdate.setParameter(1, "Foo"); + sqlUpdate.setParameter(2, asList(9991, 9992, 9993)); + + sqlUpdate.execute(); + + assertEquals("delete from o_customer where name = ? and id in (?,?,?)", sqlUpdate.getGeneratedSql()); + } + + @Test + public void positionParamsExpansion_withPost() { + + SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (?1) and name = ?"); + + sqlUpdate.setParameter(1, asList(9991, 9992, 9993)); + sqlUpdate.setParameter(2, "Foo"); + sqlUpdate.execute(); + + assertEquals("delete from o_customer where id in (?,?,?) and name = ?", sqlUpdate.getGeneratedSql()); + } + + @Test + public void positionParamsExpansion_withPost_andBatch() { + + SqlUpdate upd = Ebean.createSqlUpdate("delete from o_customer where id in (:ids) and name = :name"); + + try (Transaction transaction = DB.beginTransaction()) { + transaction.setBatchMode(true); + + upd.setParameter("ids", asList(9991, 9992, 9993)); + upd.setParameter("name", "Foo"); + upd.execute(); + + upd.setParameter("ids", asList(9991, 9992)); + upd.setParameter("name", "Bar"); + upd.execute(); + + upd.setParameter("ids", asList(9991, 9992, 9999)); + upd.setParameter("name", "Baz"); + upd.execute(); + + transaction.commit(); + } + } @Test public void test_multipleLists() {