diff -X /tmp/exclude -Nacr jdbc/org/postgresql/PGConnection.java jdbc.preparethreshold/org/postgresql/PGConnection.java *** jdbc/org/postgresql/PGConnection.java Tue Dec 2 15:13:55 2003 --- jdbc.preparethreshold/org/postgresql/PGConnection.java Tue Dec 2 21:03:47 2003 *************** *** 63,69 **** * @see org.postgresql.util.PGobject */ public void addDataType(String type, String name); ! /** @deprecated */ public Encoding getEncoding() throws SQLException; --- 63,85 ---- * @see org.postgresql.util.PGobject */ public void addDataType(String type, String name); ! ! /** ! * Set the default statement reuse threshold before enabling server-side ! * prepare. See {@link org.postgresql.PGStatement#setPrepareThreshold(int)} for ! * details. ! * ! * @param threshold the new threshold ! */ ! public void setPrepareThreshold(int threshold); ! ! /** ! * Get the default server-side prepare reuse threstold for statements created ! * from this connection. ! * ! * @return the current threshold ! */ ! public int getPrepareThreshold(); /** @deprecated */ public Encoding getEncoding() throws SQLException; diff -X /tmp/exclude -Nacr jdbc/org/postgresql/PGStatement.java jdbc.preparethreshold/org/postgresql/PGStatement.java *** jdbc/org/postgresql/PGStatement.java Tue Dec 2 15:13:55 2003 --- jdbc.preparethreshold/org/postgresql/PGStatement.java Tue Dec 2 21:03:47 2003 *************** *** 30,43 **** /** * Turn on the use of prepared statements in the server (server side * prepared statements are unrelated to jdbc PreparedStatements) * @since 7.3 */ public void setUseServerPrepare(boolean flag) throws SQLException; /** ! * Is this statement using server side prepared statements ! * @since 7.3 */ public boolean isUseServerPrepare(); } --- 30,75 ---- /** * Turn on the use of prepared statements in the server (server side * prepared statements are unrelated to jdbc PreparedStatements) + * As of 7.5, this method is equivalent to setPrepareThreshold(1). + * + * @deprecated As of 7.5, replaced by {@link #setPrepareThreshold(int)} * @since 7.3 */ public void setUseServerPrepare(boolean flag) throws SQLException; /** ! * Checks if this statement will be executed as a server-prepared statement. ! * A return value of true indicates that the next execution of the ! * statement, with an unchanged query, via a PreparedStatement variant of ! * execute(), will be done as a server-prepared statement. ! * ! * @return true if the next reuse of this statement will use a server-prepared statement */ public boolean isUseServerPrepare(); + /** + * Sets the reuse threshold for using server-prepared statements. + *

+ * If threshold is a non-zero value N, the Nth and subsequent + * uses of a statement for the same query will use server-side + * prepare. A query is currently only considered the "same" if the statement + * is a PreparedStatement, and none of the base Statement query execution methods + * that take an explicit query string have been called. + *

+ * If threshold is zero, server-side prepare will not be used. + * + * @param threshold the new threshold for this statement + * @throws SQLException if an exception occurs while changing the threshold + * @since 7.5 + */ + public void setPrepareThreshold(int threshold) throws SQLException; + + /** + * Gets the server-side prepare reuse threshold in use for this statement. + * + * @return the current threshold + * @see #setPrepareThreshold(int) + * @since 7.5 + */ + public int getPrepareThreshold(); } diff -X /tmp/exclude -Nacr jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java jdbc.preparethreshold/org/postgresql/jdbc1/AbstractJdbc1Connection.java *** jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java Tue Dec 2 15:13:55 2003 --- jdbc.preparethreshold/org/postgresql/jdbc1/AbstractJdbc1Connection.java Tue Dec 2 21:03:47 2003 *************** *** 53,58 **** --- 53,59 ---- protected boolean PG_STATUS; protected String compatible; protected boolean useSSL; + protected int prepareThreshold; // The PID an cancellation key we get from the backend process protected int pid; *************** *** 65,71 **** */ private Encoding encoding = Encoding.defaultEncoding(); ! private String dbVersionNumber; public boolean CONNECTION_OK = true; public boolean CONNECTION_BAD = false; --- 66,72 ---- */ private Encoding encoding = Encoding.defaultEncoding(); ! private String dbVersionNumber = "0.0"; // Dummy version until we really know. public boolean CONNECTION_OK = true; public boolean CONNECTION_BAD = false; *************** *** 182,187 **** --- 183,196 ---- enableDriverManagerLogging(); } + prepareThreshold = 0; + try { + prepareThreshold = Integer.parseInt(info.getProperty("prepareThreshold", "0")); + } catch (Exception e) {} + + if (prepareThreshold < 0) + prepareThreshold = 0; + //Print out the driver version number if (Driver.logInfo) Driver.info(Driver.getVersion()); *************** *** 189,194 **** --- 198,204 ---- Driver.debug(" ssl = " + useSSL); Driver.debug(" compatible = " + compatible); Driver.debug(" loglevel = " + l_logLevel); + Driver.debug(" prepare threshold = " + prepareThreshold); } // Now make the initial connection *************** *** 1838,1843 **** --- 1848,1861 ---- m_notifications = null; return l_return; } + + public int getPrepareThreshold() { + return prepareThreshold; + } + + public void setPrepareThreshold(int newThreshold) { + this.prepareThreshold = (newThreshold <= 0 ? 0 : newThreshold); + } } diff -X /tmp/exclude -Nacr jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java jdbc.preparethreshold/org/postgresql/jdbc1/AbstractJdbc1Statement.java *** jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java Tue Dec 2 15:13:55 2003 --- jdbc.preparethreshold/org/postgresql/jdbc1/AbstractJdbc1Statement.java Tue Dec 2 21:11:42 2003 *************** *** 82,88 **** private short m_isSingleSelect = UNKNOWN; // Is the query a single SELECT? private short m_isSingleStatement = UNKNOWN; // Is the query a single statement? ! private boolean m_useServerPrepare = false; // m_preparedCount is used for naming of auto-cursors and must // be synchronized so that multiple threads using the same --- 82,89 ---- private short m_isSingleSelect = UNKNOWN; // Is the query a single SELECT? private short m_isSingleStatement = UNKNOWN; // Is the query a single statement? ! private int m_prepareThreshold; // Reuse threshold to enable use of PREPARE ! private int m_useCount = 1; // Number of times this statement has been reused (plus 1) // m_preparedCount is used for naming of auto-cursors and must // be synchronized so that multiple threads using the same *************** *** 110,123 **** public abstract BaseResultSet createResultSet(Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException; ! public AbstractJdbc1Statement (BaseConnection connection) { this.connection = connection; } public AbstractJdbc1Statement (BaseConnection connection, String p_sql) throws SQLException { ! this.connection = connection; parseSqlStmt(p_sql); // this allows Callable stmt to override } --- 111,125 ---- public abstract BaseResultSet createResultSet(Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException; ! public AbstractJdbc1Statement (BaseConnection connection) throws SQLException { this.connection = connection; + setPrepareThreshold(connection.getPrepareThreshold()); } public AbstractJdbc1Statement (BaseConnection connection, String p_sql) throws SQLException { ! this(connection); parseSqlStmt(p_sql); // this allows Callable stmt to override } *************** *** 199,204 **** --- 201,207 ---- m_cursorName = null; // automatically closed at end of txn anyway m_executeSqlFragments = null; m_isSingleStatement = m_isSingleSelect = m_isSingleDML = UNKNOWN; + m_useCount = 1; } /* *************** *** 510,515 **** --- 513,519 ---- // Get the actual query fragments to run (might be a transformed version of // the original fragments) String[] fragments = getQueryFragments(); + ++m_useCount; // We used this statement once more. // New in 7.1, pass Statement so that ExecSQL can customise to it result = QueryExecutor.execute(fragments, *************** *** 2154,2178 **** throw new PSQLException("postgresql.call.noinout", PSQLState.STATEMENT_NOT_ALLOWED_IN_FUNCTION_CALL); } ! ! public void setUseServerPrepare(boolean flag) throws SQLException { ! //Server side prepared statements were introduced in 7.3 ! if (connection.haveMinimumServerVersion("7.3")) { ! if (m_useServerPrepare != flag) ! deallocateQuery(); ! m_useServerPrepare = flag; ! } else { ! //This is a pre 7.3 server so no op this method ! //which means we will never turn on the flag to use server ! //prepared statements and thus regular processing will continue ! } } ! ! public boolean isUseServerPrepare() ! { ! return m_useServerPrepare; } private java.sql.Date dateFromString (String s) throws SQLException { --- 2158,2186 ---- throw new PSQLException("postgresql.call.noinout", PSQLState.STATEMENT_NOT_ALLOWED_IN_FUNCTION_CALL); } + public void setPrepareThreshold(int newThreshold) throws SQLException { + if (newThreshold < 0) + newThreshold = 0; + + if (!connection.haveMinimumServerVersion("7.3")) + newThreshold = 0; // PREPARE was only introduced in 7.3. ! this.m_prepareThreshold = newThreshold; ! if (m_statementName != null && !isUseServerPrepare()) // Turning off a previously prepared statement. ! deallocateQuery(); } ! ! public int getPrepareThreshold() { ! return m_prepareThreshold; } + + public void setUseServerPrepare(boolean flag) throws SQLException { + setPrepareThreshold(flag ? 1 : 0); + } + + public boolean isUseServerPrepare() { + return m_prepareThreshold > 0 && m_useCount >= m_prepareThreshold; + } private java.sql.Date dateFromString (String s) throws SQLException { diff -X /tmp/exclude -Nacr jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java jdbc.preparethreshold/org/postgresql/jdbc2/AbstractJdbc2Statement.java *** jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java Tue Dec 2 15:13:55 2003 --- jdbc.preparethreshold/org/postgresql/jdbc2/AbstractJdbc2Statement.java Tue Dec 2 21:03:47 2003 *************** *** 22,28 **** protected int resultsettype; // the resultset type to return protected int concurrency; // is it updateable or not? ! public AbstractJdbc2Statement (AbstractJdbc2Connection c) { super(c); resultsettype = ResultSet.TYPE_SCROLL_INSENSITIVE; --- 22,28 ---- protected int resultsettype; // the resultset type to return protected int concurrency; // is it updateable or not? ! public AbstractJdbc2Statement (AbstractJdbc2Connection c) throws SQLException { super(c); resultsettype = ResultSet.TYPE_SCROLL_INSENSITIVE; diff -X /tmp/exclude -Nacr jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java jdbc.preparethreshold/org/postgresql/jdbc2/optional/BaseDataSource.java *** jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java Wed Sep 25 19:01:30 2002 --- jdbc.preparethreshold/org/postgresql/jdbc2/optional/BaseDataSource.java Tue Dec 2 21:03:47 2003 *************** *** 36,41 **** --- 36,42 ---- private String user; private String password; private int portNumber; + private int prepareThreshold; /** * Gets a connection to the PostgreSQL database. The database is identified by the *************** *** 226,236 **** } /** * Generates a DriverManager URL from the other properties supplied. */ private String getUrl() { ! return "jdbc:postgresql://" + serverName + (portNumber == 0 ? "" : ":" + portNumber) + "/" + databaseName; } /** --- 227,260 ---- } /** + * Sets the default threshold for enabling server-side prepare. + * See {@link org.postgresql.PGConnection#setPrepareThreshold(int)} for details. + * + * @param count the number of times a statement object must be reused before server-side + * prepare is enabled. + */ + public void setPrepareThreshold(int count) + { + this.prepareThreshold = count; + } + + /** + * Gets the default threshold for enabling server-side prepare. + * + * @see #setServerPrepareThreshold(int) + */ + public int getPrepareThreshold() + { + return prepareThreshold; + } + + /** * Generates a DriverManager URL from the other properties supplied. */ private String getUrl() { ! return "jdbc:postgresql://" + serverName + (portNumber == 0 ? "" : ":" + portNumber) + "/" + databaseName + ! (prepareThreshold == 0 ? "" : "?prepareThreshold=" + prepareThreshold); } /** *************** *** 259,264 **** --- 283,290 ---- { ref.add(new StringRefAddr("password", password)); } + if (prepareThreshold != 0) + ref.add(new StringRefAddr("prepareThreshold", Integer.toString(prepareThreshold))); return ref; } diff -X /tmp/exclude -Nacr jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java jdbc.preparethreshold/org/postgresql/jdbc2/optional/PGObjectFactory.java *** jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java Wed Sep 25 19:01:30 2002 --- jdbc.preparethreshold/org/postgresql/jdbc2/optional/PGObjectFactory.java Tue Dec 2 21:03:47 2003 *************** *** 92,97 **** --- 92,102 ---- } ds.setServerName(getProperty(ref, "serverName")); ds.setUser(getProperty(ref, "user")); + + String prepareThreshold = getProperty(ref, "prepareThreshold"); + if (prepareThreshold != null) + ds.setPrepareThreshold(Integer.parseInt(prepareThreshold)); + return ds; } diff -X /tmp/exclude -Nacr jdbc/org/postgresql/jdbc3/AbstractJdbc3Statement.java jdbc.preparethreshold/org/postgresql/jdbc3/AbstractJdbc3Statement.java *** jdbc/org/postgresql/jdbc3/AbstractJdbc3Statement.java Tue Dec 2 15:13:57 2003 --- jdbc.preparethreshold/org/postgresql/jdbc3/AbstractJdbc3Statement.java Tue Dec 2 21:03:47 2003 *************** *** 13,19 **** public abstract class AbstractJdbc3Statement extends org.postgresql.jdbc2.AbstractJdbc2Statement { ! public AbstractJdbc3Statement (AbstractJdbc3Connection c) { super(c); } --- 13,19 ---- public abstract class AbstractJdbc3Statement extends org.postgresql.jdbc2.AbstractJdbc2Statement { ! public AbstractJdbc3Statement (AbstractJdbc3Connection c) throws SQLException { super(c); } diff -X /tmp/exclude -Nacr jdbc/org/postgresql/jdbc3/Jdbc3Statement.java jdbc.preparethreshold/org/postgresql/jdbc3/Jdbc3Statement.java *** jdbc/org/postgresql/jdbc3/Jdbc3Statement.java Tue Dec 2 15:13:57 2003 --- jdbc.preparethreshold/org/postgresql/jdbc3/Jdbc3Statement.java Tue Dec 2 21:03:47 2003 *************** *** 15,21 **** public class Jdbc3Statement extends org.postgresql.jdbc3.AbstractJdbc3Statement implements java.sql.Statement { ! public Jdbc3Statement (Jdbc3Connection c) { super(c); } --- 15,21 ---- public class Jdbc3Statement extends org.postgresql.jdbc3.AbstractJdbc3Statement implements java.sql.Statement { ! public Jdbc3Statement (Jdbc3Connection c) throws SQLException { super(c); }