Repository: cayenne Updated Branches: refs/heads/master a639980d2 -> fcdd5fd5c
CAY-2443 Make SqlTemplate and SqlExec possible to return generated keys. Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/ee33e556 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/ee33e556 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/ee33e556 Branch: refs/heads/master Commit: ee33e55604e2d4b196ace747ebcbed1ab8accbba Parents: 22c2e78 Author: Arseni Bulatski <ancars...@gmail.com> Authored: Mon Jul 9 15:47:45 2018 +0300 Committer: Arseni Bulatski <ancars...@gmail.com> Committed: Mon Jul 9 16:53:24 2018 +0300 ---------------------------------------------------------------------- RELEASE-NOTES.txt | 1 + .../cayenne/access/jdbc/SQLTemplateAction.java | 37 ++++++++++++-------- .../java/org/apache/cayenne/query/SQLExec.java | 22 ++++++++++++ .../org/apache/cayenne/query/SQLTemplate.java | 20 +++++++++++ .../org/apache/cayenne/query/SQLExecIT.java | 21 +++++++++-- .../org/apache/cayenne/query/SQLTemplateIT.java | 22 ++++++++++++ 6 files changed, 105 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/ee33e556/RELEASE-NOTES.txt ---------------------------------------------------------------------- diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index b7d8a7c..43f176e 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -36,6 +36,7 @@ CAY-2415 Transaction isolation and propagation support CAY-2416 Change TreeMap for HashMap to store data in Cayenne model classes CAY-2422 Modeler: Open driver setup window on driver load error CAY-2440 cdbimport: allow cross-schema relationships +CAY-2443 Make SqlTemplate and SqlExec possible to return generated keys Bug Fixes: http://git-wip-us.apache.org/repos/asf/cayenne/blob/ee33e556/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java index a1f4b3d..cd44f01 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java @@ -19,18 +19,6 @@ package org.apache.cayenne.access.jdbc; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - import org.apache.cayenne.CayenneException; import org.apache.cayenne.DataRow; import org.apache.cayenne.ResultIterator; @@ -51,6 +39,18 @@ import org.apache.cayenne.query.SQLAction; import org.apache.cayenne.query.SQLTemplate; import org.apache.cayenne.util.Util; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + /** * Implements a strategy for execution of SQLTemplates. * @@ -186,15 +186,23 @@ public class SQLTemplateAction implements SQLAction { long t1 = System.currentTimeMillis(); boolean iteratedResult = callback.isIteratedResult(); - PreparedStatement statement = connection.prepareStatement(compiled.getSql()); + PreparedStatement statement = connection.prepareStatement(compiled.getSql(), + query.isReturnGeneratedKeys() ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS); try { bind(statement, compiled.getBindings()); // process a mix of results boolean isResultSet = statement.execute(); + + if(query.isReturnGeneratedKeys()) { + ResultSet generatedKeysResultSet = statement.getGeneratedKeys(); + if (generatedKeysResultSet != null) { + processSelectResult(compiled, connection, statement, generatedKeysResultSet, callback, t1); + } + } + boolean firstIteration = true; while (true) { - if (firstIteration) { firstIteration = false; } else { @@ -204,7 +212,6 @@ public class SQLTemplateAction implements SQLAction { if (isResultSet) { ResultSet resultSet = statement.getResultSet(); - if (resultSet != null) { try { http://git-wip-us.apache.org/repos/asf/cayenne/blob/ee33e556/cayenne-server/src/main/java/org/apache/cayenne/query/SQLExec.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLExec.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLExec.java index 57f7cc5..4ad4a22 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLExec.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLExec.java @@ -64,6 +64,7 @@ public class SQLExec extends IndirectQuery { protected StringBuilder sqlBuffer; protected Map<String, Object> params; protected List<Object> positionalParams; + protected boolean returnGeneratedKeys; public SQLExec(String sql) { this.sqlBuffer = sql != null ? new StringBuilder(sql) : new StringBuilder(); @@ -198,6 +199,26 @@ public class SQLExec extends IndirectQuery { return results.firstBatchUpdateCount(); } + /** + * @since 4.1 + * @return returnGeneratedKeys flag + */ + public boolean isReturnGeneratedKeys() { + return returnGeneratedKeys; + } + + /** + * Sets flag to return generated keys. + * + * @since 4.1 + * @param returnGeneratedKeys + * @return SQLExec query + */ + public SQLExec setReturnGeneratedKeys(boolean returnGeneratedKeys) { + this.returnGeneratedKeys = returnGeneratedKeys; + return this; + } + @Override protected Query createReplacementQuery(EntityResolver resolver) { @@ -219,6 +240,7 @@ public class SQLExec extends IndirectQuery { template.setRoot(root); template.setDefaultTemplate(getSql()); template.setFetchingDataRows(true); // in case result set will be returned + template.setReturnGeneratedKeys(returnGeneratedKeys); if (positionalParams != null) { template.setParamsList(positionalParams); http://git-wip-us.apache.org/repos/asf/cayenne/blob/ee33e556/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java index 33764d5..e5e1250 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java @@ -81,6 +81,7 @@ public class SQLTemplate extends AbstractQuery implements ParameterizedQuery { protected CapsStrategy columnNamesCapitalization; protected SQLResult result; private String dataNodeName; + protected boolean returnGeneratedKeys; SQLTemplateMetadata metaData = new SQLTemplateMetadata(); @@ -634,4 +635,23 @@ public class SQLTemplate extends AbstractQuery implements ParameterizedQuery { public void setDataNodeName(String dataNodeName) { this.dataNodeName = dataNodeName; } + + /** + * + * @since 4.1 + * @return returnGeneratedKeys flag + */ + public boolean isReturnGeneratedKeys() { + return returnGeneratedKeys; + } + + /** + * Sets flag to return generated keys. + * + * @since 4.1 + * @param returnGeneratedKeys + */ + public void setReturnGeneratedKeys(boolean returnGeneratedKeys) { + this.returnGeneratedKeys = returnGeneratedKeys; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/ee33e556/cayenne-server/src/test/java/org/apache/cayenne/query/SQLExecIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLExecIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLExecIT.java index f1c3a20..7bdbbd9 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLExecIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLExecIT.java @@ -18,9 +18,6 @@ ****************************************************************/ package org.apache.cayenne.query; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - import org.apache.cayenne.DataRow; import org.apache.cayenne.QueryResult; import org.apache.cayenne.access.DataContext; @@ -32,6 +29,9 @@ import org.apache.cayenne.unit.di.server.ServerCase; import org.apache.cayenne.unit.di.server.UseServerRuntime; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) public class SQLExecIT extends ServerCase { @@ -58,6 +58,21 @@ public class SQLExecIT extends ServerCase { } @Test + public void testReturnGeneratedKeys() { + if(unitDbAdapter.supportsGeneratedKeys()) { + QueryResult response = SQLExec.query("testmap", "INSERT INTO GENERATED_COLUMN (NAME) VALUES ('Surikov')") + .setReturnGeneratedKeys(true) + .execute(context); + assertEquals(2, response.size()); + + QueryResult response1 = SQLExec.query("testmap", "INSERT INTO GENERATED_COLUMN (NAME) VALUES ('Sidorov')") + .setReturnGeneratedKeys(false) + .execute(context); + assertEquals(1, response1.size()); + } + } + + @Test public void test_ParamsArray_Single() throws Exception { int inserted = SQLExec.query("INSERT INTO ARTIST (ARTIST_ID, ARTIST_NAME) VALUES (1, #bind($name))") http://git-wip-us.apache.org/repos/asf/cayenne/blob/ee33e556/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java index 2fcbda0..36dfb7a 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java @@ -29,6 +29,7 @@ import org.apache.cayenne.test.jdbc.DBHelper; import org.apache.cayenne.test.jdbc.TableHelper; import org.apache.cayenne.testdo.testmap.Gallery; import org.apache.cayenne.testdo.testmap.Painting; +import org.apache.cayenne.unit.UnitDbAdapter; import org.apache.cayenne.unit.di.DataChannelInterceptor; import org.apache.cayenne.unit.di.server.CayenneProjects; import org.apache.cayenne.unit.di.server.ServerCase; @@ -56,6 +57,9 @@ public class SQLTemplateIT extends ServerCase { @Inject protected DataChannelInterceptor queryInterceptor; + @Inject + protected UnitDbAdapter unitDbAdapter; + private TableHelper tPainting; private TableHelper tArtist; @@ -90,6 +94,24 @@ public class SQLTemplateIT extends ServerCase { } @Test + public void testReturnGeneratedKeys() { + if(unitDbAdapter.supportsGeneratedKeys()) { + DataMap testDataMap = context.getEntityResolver().getDataMap("testmap"); + String sql = "INSERT INTO GENERATED_COLUMN (NAME) VALUES ('Surikov')"; + SQLTemplate q1 = new SQLTemplate(testDataMap, sql, true); + q1.setReturnGeneratedKeys(true); + List<DataRow> response = context.performQuery(q1); + assertEquals(1, response.size()); + + String sql1 = "INSERT INTO GENERATED_COLUMN (NAME) VALUES ('Test')"; + SQLTemplate q2 = new SQLTemplate(testDataMap, sql1, true); + q2.setReturnGeneratedKeys(false); + List<DataRow> response1 = context.performQuery(q2); + assertEquals(0, response1.size()); + } + } + + @Test public void testSQLTemplateForDataMapWithInsertException() { DataMap testDataMap = context.getEntityResolver().getDataMap("testmap"); String sql = "INSERT INTO ARTIST VALUES (15, 'Surikov', null)";