From 557246a65cee6010d54f6588280d32058f504bbe Mon Sep 17 00:00:00 2001 From: Kang Dooho Date: Wed, 10 Nov 2021 17:45:11 +0900 Subject: [PATCH 1/4] [APIS-877] add PreparedStatement caching function --- .../cubrid/jdbc/driver/CUBRIDConnection.java | 17 ++++++++ .../jdbc/driver/CUBRIDPreparedStatement.java | 7 ++++ .../jdbc/driver/ConnectionProperties.java | 21 ++++++++++ src/jdbc/cubrid/jdbc/jci/UConnection.java | 21 ++++++++++ .../jdbc/jci/UPreparedStatementCache.java | 40 +++++++++++++++++++ 5 files changed, 106 insertions(+) create mode 100644 src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java diff --git a/src/jdbc/cubrid/jdbc/driver/CUBRIDConnection.java b/src/jdbc/cubrid/jdbc/driver/CUBRIDConnection.java index bb5bfed..c8f76be 100644 --- a/src/jdbc/cubrid/jdbc/driver/CUBRIDConnection.java +++ b/src/jdbc/cubrid/jdbc/driver/CUBRIDConnection.java @@ -35,6 +35,7 @@ import cubrid.jdbc.jci.UConnection; import cubrid.jdbc.jci.UError; import cubrid.jdbc.jci.UErrorCode; +import cubrid.jdbc.jci.UPreparedStatementCache; import cubrid.jdbc.jci.UStatement; import java.sql.Array; import java.sql.Blob; @@ -88,6 +89,7 @@ public class CUBRIDConnection implements Connection { protected CUBRIDShardMetaData shard_mdata; protected ArrayList outRs; private boolean isAutoGeneratedKeys = false; + protected UPreparedStatementCache prepStmtCache; /* * 3.0 ArrayList savepoints; int sv_count, sv_id; String sv_name; private @@ -109,6 +111,9 @@ public CUBRIDConnection(UConnection u, String r, String s) { statements = new ArrayList(); outRs = new ArrayList(); shard_mdata = null; + prepStmtCache = + new UPreparedStatementCache( + u_con.getPrepStmtCacheSize()); /* * 3.0 savepoints = new ArrayList(); sv_count = 0; sv_name = ""; @@ -811,6 +816,8 @@ protected PreparedStatement prepare( int resultHoldability, int autoGeneratedKeys) throws SQLException { + PreparedStatement pstmtCache = null; + checkIsOpen(); byte prepareFlag = (byte) 0; @@ -824,6 +831,13 @@ protected PreparedStatement prepare( prepareFlag = UConnection.PREPARE_HOLDABLE; } + if (u_con.isPrepStmtCache(sql)) { + pstmtCache = prepStmtCache.get(sql); + if (pstmtCache != null) { + return pstmtCache; + } + } + UStatement us = prepare(sql, prepareFlag); PreparedStatement pstmt = new CUBRIDPreparedStatement( @@ -835,6 +849,9 @@ protected PreparedStatement prepare( autoGeneratedKeys); addStatement(pstmt); + if (u_con.isPrepStmtCache(sql)) { + prepStmtCache.put(sql, pstmt); + } return pstmt; } diff --git a/src/jdbc/cubrid/jdbc/driver/CUBRIDPreparedStatement.java b/src/jdbc/cubrid/jdbc/driver/CUBRIDPreparedStatement.java index f988475..edeb63e 100644 --- a/src/jdbc/cubrid/jdbc/driver/CUBRIDPreparedStatement.java +++ b/src/jdbc/cubrid/jdbc/driver/CUBRIDPreparedStatement.java @@ -721,6 +721,8 @@ public void close() throws SQLException { try { synchronized (con) { synchronized (this) { + String sql = ""; + setShardId(UShardInfo.SHARD_ID_INVALID); if (is_closed) return; @@ -728,10 +730,15 @@ public void close() throws SQLException { is_closed = true; if (u_stmt != null) { + sql = u_stmt.getQuery(); u_stmt.close(); u_stmt = null; } + if (u_con.isPrepStmtCache(sql)) { + con.prepStmtCache.remove(sql); + } + con.removeStatement(this); con = null; u_con = null; diff --git a/src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java b/src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java index eb6441e..b1c45dd 100644 --- a/src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java +++ b/src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java @@ -395,6 +395,15 @@ private int getDefaultConnectTimeout() { BooleanConnectionProperty holdCursor = new BooleanConnectionProperty("hold_cursor", true); + BooleanConnectionProperty preparedStmtCache = + new BooleanConnectionProperty("preparedStmtCache", false); + + IntegerConnectionProperty preparedStmtCacheSize = + new IntegerConnectionProperty("preparedStmtCacheSize", 25, 1, Integer.MAX_VALUE); + + IntegerConnectionProperty preparedStmtCacheSqlLimit = + new IntegerConnectionProperty("preparedStmtCacheSqlLimit", 256, 1, Integer.MAX_VALUE); + public boolean getLogOnException() { return logOnException.getValueAsBoolean(); } @@ -470,4 +479,16 @@ public int getHoldCursor() { } return holdability; } + + public boolean getPrepStmtCache() { + return preparedStmtCache.getValueAsBoolean(); + } + + public int getPrepStmtCacheSize() { + return preparedStmtCacheSize.getValueAsInteger(); + } + + public int getPrepStmtCacheSqlLimit() { + return preparedStmtCacheSqlLimit.getValueAsInteger(); + } } diff --git a/src/jdbc/cubrid/jdbc/jci/UConnection.java b/src/jdbc/cubrid/jdbc/jci/UConnection.java index 058b280..55c9ffe 100644 --- a/src/jdbc/cubrid/jdbc/jci/UConnection.java +++ b/src/jdbc/cubrid/jdbc/jci/UConnection.java @@ -1490,6 +1490,27 @@ public int getClientCacheSize() { return connectionProperties.getClientCacheSize() * 1024 * 1024; } + public boolean getPrepStmtCache() { + return connectionProperties.getPrepStmtCache(); + } + + public int getPrepStmtCacheSize() { + return connectionProperties.getPrepStmtCacheSize(); + } + + public int getPrepStmtCacheSqlLimit() { + return connectionProperties.getPrepStmtCacheSqlLimit(); + } + + public boolean isPrepStmtCache(String sql) { + boolean isCacheable = false; + if (connectionProperties.getPrepStmtCache() + && sql.length() <= connectionProperties.getPrepStmtCacheSqlLimit()) { + isCacheable = true; + } + return isCacheable; + } + public void setCasIp(String casIp) { this.casIp = casIp; } diff --git a/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java b/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java new file mode 100644 index 0000000..a76f62e --- /dev/null +++ b/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java @@ -0,0 +1,40 @@ +package cubrid.jdbc.jci; + +import java.util.LinkedHashMap; +import java.util.Map.Entry; + +public class UPreparedStatementCache extends LinkedHashMap { + private static final long serialVersionUID = 1L; + protected int maxElements; + + public UPreparedStatementCache(int maxSize) { + super(maxSize, 0.75F, true); + this.maxElements = maxSize; + } + + @Override + public V get(Object key) { + synchronized (this) { + return super.get(key); + } + } + + @Override + public V put(K key, V value) { + synchronized (this) { + return super.put(key, value); + } + } + + @Override + public V remove(Object key) { + synchronized (this) { + return super.remove(key); + } + } + + @Override + protected boolean removeEldestEntry(Entry eldest) { + return (size() > this.maxElements); + } +} From bed66b2a802294a542c307d3c669f85fde78df1f Mon Sep 17 00:00:00 2001 From: Kang Dooho Date: Wed, 10 Nov 2021 18:27:00 +0900 Subject: [PATCH 2/4] change preparedStatement cache property name --- src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java b/src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java index b1c45dd..33eed86 100644 --- a/src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java +++ b/src/jdbc/cubrid/jdbc/driver/ConnectionProperties.java @@ -395,8 +395,8 @@ private int getDefaultConnectTimeout() { BooleanConnectionProperty holdCursor = new BooleanConnectionProperty("hold_cursor", true); - BooleanConnectionProperty preparedStmtCache = - new BooleanConnectionProperty("preparedStmtCache", false); + BooleanConnectionProperty usePreparedStmtCache = + new BooleanConnectionProperty("usePreparedStmtCache", false); IntegerConnectionProperty preparedStmtCacheSize = new IntegerConnectionProperty("preparedStmtCacheSize", 25, 1, Integer.MAX_VALUE); @@ -481,7 +481,7 @@ public int getHoldCursor() { } public boolean getPrepStmtCache() { - return preparedStmtCache.getValueAsBoolean(); + return usePreparedStmtCache.getValueAsBoolean(); } public int getPrepStmtCacheSize() { From 3824ac3602ebaaf4b35164a2eabd79cbe61c249d Mon Sep 17 00:00:00 2001 From: Kang Dooho Date: Thu, 11 Nov 2021 09:30:31 +0900 Subject: [PATCH 3/4] Add license to new UPreparedStatementCache.java --- .../jdbc/jci/UPreparedStatementCache.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java b/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java index a76f62e..9479cea 100644 --- a/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java +++ b/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java @@ -1,3 +1,33 @@ +/* + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + package cubrid.jdbc.jci; import java.util.LinkedHashMap; From e5ae3f6bd6ee193de12b576cc9d89558043e90b3 Mon Sep 17 00:00:00 2001 From: Kang Dooho Date: Thu, 11 Nov 2021 09:49:01 +0900 Subject: [PATCH 4/4] change cache size name maxElements to maxCacheSize --- .../cubrid/jdbc/jci/UPreparedStatementCache.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java b/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java index 9479cea..014bc0f 100644 --- a/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java +++ b/src/jdbc/cubrid/jdbc/jci/UPreparedStatementCache.java @@ -27,7 +27,7 @@ * OF SUCH DAMAGE. * */ - + package cubrid.jdbc.jci; import java.util.LinkedHashMap; @@ -35,11 +35,11 @@ public class UPreparedStatementCache extends LinkedHashMap { private static final long serialVersionUID = 1L; - protected int maxElements; + protected int maxCacheSize; - public UPreparedStatementCache(int maxSize) { - super(maxSize, 0.75F, true); - this.maxElements = maxSize; + public UPreparedStatementCache(int maxCacheSize) { + super(maxCacheSize, 0.75F, true); + this.maxCacheSize = maxCacheSize; } @Override @@ -65,6 +65,6 @@ public V remove(Object key) { @Override protected boolean removeEldestEntry(Entry eldest) { - return (size() > this.maxElements); + return (size() > this.maxCacheSize); } }