You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by jw...@apache.org on 2016/03/11 03:56:35 UTC

[1/2] groovy git commit: Ensure BatchingStatementWrapper is closed when statement caching is enabled

Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_4_X 778cb5432 -> 9fca80db4


Ensure BatchingStatementWrapper is closed when statement caching is enabled


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/9fca80db
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/9fca80db
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/9fca80db

Branch: refs/heads/GROOVY_2_4_X
Commit: 9fca80db49a390880e1fde033b5e4c4263edde3d
Parents: 77ee2fe
Author: John Wagenleitner <jw...@apache.org>
Authored: Thu Mar 10 18:28:53 2016 -0800
Committer: John Wagenleitner <jw...@apache.org>
Committed: Thu Mar 10 18:40:05 2016 -0800

----------------------------------------------------------------------
 .../src/main/java/groovy/sql/Sql.java           |  6 +++-
 .../test/groovy/groovy/sql/SqlBatchTest.groovy  | 34 ++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/9fca80db/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java b/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
index a3f2528..1fb05f2 100644
--- a/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
+++ b/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
@@ -4221,8 +4221,12 @@ public class Sql {
         closeResources(connection);
     }
 
-    private void closeResources(BatchingStatementWrapper statement) {
+    private void closeResources(BatchingPreparedStatementWrapper statement) {
         if (cacheStatements) return;
+        closeResources((BatchingStatementWrapper) statement);
+    }
+
+    private void closeResources(BatchingStatementWrapper statement) {
         if (statement != null) {
             try {
                 statement.close();

http://git-wip-us.apache.org/repos/asf/groovy/blob/9fca80db/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlBatchTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlBatchTest.groovy b/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlBatchTest.groovy
index 3f9bafd..02a6d65 100644
--- a/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlBatchTest.groovy
+++ b/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlBatchTest.groovy
@@ -171,4 +171,38 @@ class SqlBatchTest extends GroovyTestCase {
         // FINE: Successfully executed batch with 1 command(s)
     }
 
+    void testWithBatchClosesStatement() {
+        // withBatch(int, Closure) should close connection even when statement caching is enabled
+        // since it is not cached because there is no sql text to use as the cache key.
+        BatchingStatementWrapper wrapper = null
+        sql.cacheStatements = true
+        sql.withBatch(1) { stmt ->
+            wrapper = (BatchingStatementWrapper)stmt
+            stmt.addBatch("insert into PERSON (id, firstname, lastname) values (999, 'Test', 'Closes')")
+        }
+        assert wrapper.@delegate.isClosed()
+    }
+
+    void testWithBatchClosureClosesOrCachesStatement() {
+        String sqlText = 'insert into PERSON (id, firstname, lastname) values (?, ?, ?)'
+        BatchingPreparedStatementWrapper wrapper = null
+
+        sql.cacheStatements = false
+        sql.withBatch(20, sqlText) { ps ->
+            wrapper = (BatchingPreparedStatementWrapper)ps
+            ps.addBatch(111, 'Test1', 'Closes1')
+            ps.addBatch(222, 'Test2', 'Closes2')
+        }
+        assert wrapper.@delegate.isClosed()
+
+        sql.cacheStatements = true
+        sql.withBatch(20, sqlText) { ps ->
+            wrapper = (BatchingPreparedStatementWrapper)ps
+            ps.addBatch(333, 'Test3', 'Closes3')
+            ps.addBatch(444, 'Test4', 'Closes4')
+        }
+        assert !wrapper.@delegate.isClosed()
+        assert sql.@statementCache.containsKey(sqlText)
+        assert sql.@statementCache[sqlText].is(wrapper.@delegate)
+    }
 }


[2/2] groovy git commit: GROOVY-7751 - CallableStatement leak in Sql.call() method (closes #263)

Posted by jw...@apache.org.
GROOVY-7751 - CallableStatement leak in Sql.call() method (closes #263)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/77ee2feb
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/77ee2feb
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/77ee2feb

Branch: refs/heads/GROOVY_2_4_X
Commit: 77ee2febc3bcd7cdfc81da4d567a8d1a81d5fe06
Parents: 778cb54
Author: John Wagenleitner <jw...@apache.org>
Authored: Thu Mar 10 18:27:49 2016 -0800
Committer: John Wagenleitner <jw...@apache.org>
Committed: Thu Mar 10 18:40:05 2016 -0800

----------------------------------------------------------------------
 .../src/main/java/groovy/sql/Sql.java           | 26 +++++++++----
 .../test/groovy/groovy/sql/SqlCallTest.groovy   | 39 ++++++++++++++++++++
 2 files changed, 57 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/77ee2feb/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java b/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
index 1b47539..a3f2528 100644
--- a/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
+++ b/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
@@ -3005,10 +3005,7 @@ public class Sql {
         Connection connection = createConnection();
         CallableStatement statement = null;
         try {
-            LOG.fine(sql + " | " + params);
-            statement = connection.prepareCall(sql);
-            setParameters(params, statement);
-            configure(statement);
+            statement = getCallableStatement(connection, sql, params);
             return statement.executeUpdate();
         } catch (SQLException e) {
             LOG.warning("Failed to execute: " + sql + " because: " + e.getMessage());
@@ -3300,10 +3297,7 @@ public class Sql {
         CallableStatement statement = null;
         List<GroovyResultSet> resultSetResources = new ArrayList<GroovyResultSet>();
         try {
-            statement = connection.prepareCall(sql);
-
-            LOG.fine(sql + " | " + params);
-            setParameters(params, statement);
+            statement = getCallableStatement(connection, sql, params);
             boolean hasResultSet = statement.execute();
             List<Object> results = new ArrayList<Object>();
             int indx = 0;
@@ -4368,6 +4362,14 @@ public class Sql {
         return statement;
     }
 
+    private CallableStatement getCallableStatement(Connection connection, String sql, List<Object> params) throws SQLException {
+        LOG.fine(sql + " | " + params);
+        CallableStatement statement = (CallableStatement) getAbstractStatement(new CreateCallableStatementCommand(), connection, sql);
+        setParameters(params, statement);
+        configure(statement);
+        return statement;
+    }
+
     public SqlWithParams checkForNamedParams(String sql, List<Object> params) {
         SqlWithParams preCheck = buildSqlWithIndexedProps(sql);
         if (preCheck == null) {
@@ -4503,6 +4505,7 @@ public class Sql {
             this.returnGeneratedKeys = returnGeneratedKeys;
         }
 
+        @Override
         protected PreparedStatement execute(Connection connection, String sql) throws SQLException {
             if (returnGeneratedKeys == USE_COLUMN_NAMES && keyColumnNames != null) {
                 return connection.prepareStatement(sql, keyColumnNames.toArray(new String[keyColumnNames.size()]));
@@ -4527,6 +4530,13 @@ public class Sql {
         }
     }
 
+    private class CreateCallableStatementCommand extends AbstractStatementCommand {
+        @Override
+        protected CallableStatement execute(Connection connection, String sql) throws SQLException {
+            return connection.prepareCall(sql);
+        }
+    }
+
     private class CreateStatementCommand extends AbstractStatementCommand {
         @Override
         protected Statement execute(Connection conn, String sql) throws SQLException {

http://git-wip-us.apache.org/repos/asf/groovy/blob/77ee2feb/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlCallTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlCallTest.groovy b/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlCallTest.groovy
index 3068861..8dc6189 100644
--- a/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlCallTest.groovy
+++ b/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlCallTest.groovy
@@ -19,6 +19,7 @@
 package groovy.sql
 
 import javax.sql.DataSource
+import java.sql.CallableStatement
 
 import static groovy.sql.SqlTestConstants.*
 
@@ -295,4 +296,42 @@ class SqlCallTest extends GroovyTestCase {
         assert lastRows[0].lastname == 'Ventura'
     }
 
+    void testCallWithStatementCaching() {
+        String sqlText = '{call FindByFirst(?, ?)}'
+        CallableStatement statement = null
+        sql.withStatement { statement = (CallableStatement)it }
+
+        sql.cacheStatements = false
+        sql.call sqlText, ['James', Sql.VARCHAR]
+        assert statement.isClosed()
+        assert sql.@statementCache.isEmpty()
+
+        sql.cacheStatements = true
+        sql.call sqlText, ['James', Sql.VARCHAR]
+        assert !statement.isClosed()
+        assert sql.@statementCache.containsKey(sqlText)
+        assert sql.@statementCache[sqlText].is(statement)
+    }
+
+    void testCallWithRowsStatementCaching() {
+        String sqlText = '{call FindByFirst(?, ?)}'
+        CallableStatement statement = null
+        sql.withStatement { statement = (CallableStatement)it }
+
+        sql.cacheStatements = false
+        sql.call sqlText, ['James', Sql.VARCHAR], { ans ->
+            // no-op
+        }
+        assert statement.isClosed()
+        assert sql.@statementCache.isEmpty()
+
+        sql.cacheStatements = true
+        sql.call sqlText, ['James', Sql.VARCHAR], { ans ->
+            // no-op
+        }
+        assert !statement.isClosed()
+        assert sql.@statementCache.containsKey(sqlText)
+        assert sql.@statementCache[sqlText].is(statement)
+    }
+
 }