https://bz.apache.org/bugzilla/show_bug.cgi?id=70269

            Bug ID: 70269
           Summary: Regression: StatementCache no longer caches statements
                    when the driver's isPoolable() returns false
           Product: Tomcat Modules
           Version: unspecified
          Hardware: All
                OS: All
            Status: NEW
          Keywords: Regression
          Severity: regression
          Priority: P2
         Component: jdbc-pool
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

Affects 11.0.26 onwards, 10.1.60 onwards, 9.0.122 onwards and main.

The fix for resetting statement properties between uses (bb64a055e2 on main,
56fe3e705d on 11.0.x, 006633d937 on 10.1.x, b5de155df8 on 9.0.x) made
CachedStatement.closeInvoked() cache a statement only if
getDelegate().isPoolable() returns true:

 
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java:368
  if (getDelegate().isPoolable() && !getDelegate().isCloseOnCompletion()) {

Some drivers always return false from isPoolable() and ignore setPoolable().
H2 and MariaDB Connector/J do. With those, every statement is closed on
close() and the StatementCache interceptor does nothing.

The Javadoc of java.sql.Statement#setPoolable says:

  "By default, a Statement is not poolable when created, and a
  PreparedStatement and CallableStatement are poolable when created."
 
https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/Statement.html#setPoolable(boolean)

So setPoolable(false) is the application's way to opt out, and what the
driver reports from isPoolable() isn't a reliable signal of that.

To reproduce: configure a pool against H2 with
StatementCache(prepared=true,max=50), prepare a statement, close it, and
check the cache size. It stays 0. In the module itself,
org.apache.tomcat.jdbc.test.TestStatementCache fails on main with 3 failures
(testMaxCacheSize, testPreparedStatementCache, testStatementClose1); they
pass on the parent of bb64a055e2. The test added by that commit
(org.apache.tomcat.jdbc.pool.interceptor.TestStatementCache) uses a mock
statement that returns true from isPoolable(). It is also outside
org/apache/tomcat/jdbc/test/, so the Ant test target doesn't run it.

Proposed fix: track the poolable hint in CachedStatement itself. Default it
to true, update it when the application calls setPoolable() on the proxy
(still passing the call on to the driver), and cache only if it is true and
isCloseOnCompletion() is false. Pull request with tests to follow.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to