From fe2dec75a9b428f2e4271af32c4f6a31717889f4 Mon Sep 17 00:00:00 2001 From: Barry Lind Date: Fri, 23 Aug 2002 20:45:49 +0000 Subject: [PATCH] Enhancements to how queries with bind values are stored internally and sent to the server. Previously we allocated a new String object for the entire final query we were sending to the database. If you had a big query, or especially if you had large bind values you ended up with essentially two copies in memory. This change will reuse the existing objects and therefore should take 1/2 the memory it does today for a given query. This restructuring will also allow in the future the ability to stream bytea data to the server instead of the current approach of pulling it all into memory. I also fixed a test that was failing on a 7.2 database. Also renamed some internal variables and some minor cleanup. Modified Files: jdbc/org/postgresql/core/QueryExecutor.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java --- .../org/postgresql/core/QueryExecutor.java | 22 +- .../jdbc1/AbstractJdbc1Connection.java | 23 +- .../jdbc1/AbstractJdbc1Statement.java | 213 +++++++++--------- .../jdbc2/AbstractJdbc2ResultSet.java | 13 +- .../jdbc2/AbstractJdbc2Statement.java | 23 +- .../test/jdbc2/DatabaseMetaDataTest.java | 15 +- 6 files changed, 162 insertions(+), 147 deletions(-) diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java index 40c6a31d7f..66b2c9341b 100644 --- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java +++ b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java @@ -13,24 +13,26 @@ import org.postgresql.util.PSQLException; *

The lifetime of a QueryExecutor object is from sending the query * until the response has been received from the backend. * - * $Id: QueryExecutor.java,v 1.13 2002/07/23 03:59:55 barry Exp $ + * $Id: QueryExecutor.java,v 1.14 2002/08/23 20:45:49 barry Exp $ */ public class QueryExecutor { - private final String sql; + private final String[] m_sqlFrags; + private final Object[] m_binds; private final java.sql.Statement statement; private final PG_Stream pg_stream; private final org.postgresql.jdbc1.AbstractJdbc1Connection connection; - public QueryExecutor(String sql, + public QueryExecutor(String[] p_sqlFrags, Object[] p_binds, java.sql.Statement statement, PG_Stream pg_stream, java.sql.Connection connection) throws SQLException { - this.sql = sql; + this.m_sqlFrags = p_sqlFrags; + this.m_binds = p_binds; this.statement = statement; this.pg_stream = pg_stream; this.connection = (org.postgresql.jdbc1.AbstractJdbc1Connection)connection; @@ -60,7 +62,7 @@ public class QueryExecutor synchronized (pg_stream) { - sendQuery(sql); + sendQuery(); int c; boolean l_endQuery = false; @@ -129,12 +131,18 @@ public class QueryExecutor /* * Send a query to the backend. */ - private void sendQuery(String query) throws SQLException + private void sendQuery() throws SQLException { try { pg_stream.SendChar('Q'); - pg_stream.Send(connection.getEncoding().encode(query)); + for (int i = 0 ; i < m_binds.length ; ++i) { + if (m_binds[i] == null) + throw new PSQLException("postgresql.prep.param", new Integer(i + 1)); + pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i])); + pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString())); + } + pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[m_binds.length])); pg_stream.SendChar(0); pg_stream.flush(); diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java index 7f6afd44c2..3c93e54031 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java @@ -13,7 +13,7 @@ import org.postgresql.largeobject.LargeObjectManager; import org.postgresql.util.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.4 2002/08/16 19:34:57 davec Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.5 2002/08/23 20:45:49 barry Exp $ * This class defines methods of the jdbc1 specification. This class is * extended by org.postgresql.jdbc2.AbstractJdbc2Connection which adds the jdbc2 * methods. The real Connection class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Connection @@ -426,7 +426,26 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec */ public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException { - return new QueryExecutor(sql, stat, pg_stream, (java.sql.Connection)this).execute(); + return new QueryExecutor(new String[] {sql}, EMPTY_OBJECT_ARRAY, stat, pg_stream, (java.sql.Connection)this).execute(); + } + private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; + + /* + * Send a query to the backend. Returns one of the ResultSet + * objects. + * + * Note: there does not seem to be any method currently + * in existance to return the update count. + * + * @param p_sqlFragmentss the SQL statement parts to be executed + * @param p_binds the SQL bind values + * @param stat The Statement associated with this query (may be null) + * @return a ResultSet holding the results + * @exception SQLException if a database error occurs + */ + public java.sql.ResultSet ExecSQL(String[] p_sqlFragments, Object[] p_binds, java.sql.Statement stat) throws SQLException + { + return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute(); } /* diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java index fc532fcc8b..5f410f9995 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java @@ -8,7 +8,7 @@ import java.util.Vector; import org.postgresql.largeobject.*; import org.postgresql.util.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.4 2002/08/16 17:51:38 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.5 2002/08/23 20:45:49 barry Exp $ * This class defines methods of the jdbc1 specification. This class is * extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2 * methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement @@ -28,12 +28,12 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme /** Timeout (in seconds) for a query (not used) */ protected int timeout = 0; - protected boolean escapeProcessing = true; + protected boolean replaceProcessingEnabled = true; /** The current results */ protected java.sql.ResultSet result = null; - // Static variables for parsing SQL when escapeProcessing is true. + // Static variables for parsing SQL when replaceProcessing is true. private static final short IN_SQLCODE = 0; private static final short IN_STRING = 1; private static final short BACKSLASH = 2; @@ -43,9 +43,8 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme private StringBuffer sbuf = new StringBuffer(32); //Used by the preparedstatement style methods - protected String sql; - protected String[] templateStrings; - protected String[] inStrings; + protected String[] m_sqlFragments; + protected Object[] m_binds = new Object[0]; //Used by the callablestatement style methods private static final String JDBC_SYNTAX = "{[? =] call ([? [,?]*]) }"; @@ -68,42 +67,46 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme this.connection = connection; } - public AbstractJdbc1Statement (AbstractJdbc1Connection connection, String sql) throws SQLException + public AbstractJdbc1Statement (AbstractJdbc1Connection connection, String p_sql) throws SQLException { - this.sql = sql; this.connection = connection; - parseSqlStmt(); // this allows Callable stmt to override + parseSqlStmt(p_sql); // this allows Callable stmt to override } - protected void parseSqlStmt () throws SQLException { - if (this instanceof CallableStatement) { - modifyJdbcCall(); + protected void parseSqlStmt (String p_sql) throws SQLException { + String l_sql = p_sql; + + l_sql = replaceProcessing(l_sql); + + if (this instanceof CallableStatement) { + l_sql = modifyJdbcCall(l_sql); } Vector v = new Vector(); boolean inQuotes = false; int lastParmEnd = 0, i; - for (i = 0; i < sql.length(); ++i) + for (i = 0; i < l_sql.length(); ++i) { - int c = sql.charAt(i); + int c = l_sql.charAt(i); if (c == '\'') inQuotes = !inQuotes; if (c == '?' && !inQuotes) { - v.addElement(sql.substring (lastParmEnd, i)); + v.addElement(l_sql.substring (lastParmEnd, i)); lastParmEnd = i + 1; } } - v.addElement(sql.substring (lastParmEnd, sql.length())); + v.addElement(l_sql.substring (lastParmEnd, l_sql.length())); - templateStrings = new String[v.size()]; - inStrings = new String[v.size() - 1]; + m_sqlFragments = new String[v.size()]; + m_binds = new String[v.size() - 1]; + //BJL why if binds is new??? clearParameters(); - for (i = 0 ; i < templateStrings.length; ++i) - templateStrings[i] = (String)v.elementAt(i); + for (i = 0 ; i < m_sqlFragments.length; ++i) + m_sqlFragments[i] = (String)v.elementAt(i); } @@ -114,14 +117,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme * @return a ResulSet that contains the data produced by the query * @exception SQLException if a database access error occurs */ - public java.sql.ResultSet executeQuery(String sql) throws SQLException + public java.sql.ResultSet executeQuery(String p_sql) throws SQLException { - this.execute(sql); - while (result != null && !((AbstractJdbc1ResultSet)result).reallyResultSet()) - result = ((AbstractJdbc1ResultSet)result).getNext(); - if (result == null) - throw new PSQLException("postgresql.stat.noresult"); - return result; + String l_sql = replaceProcessing(p_sql); + m_sqlFragments = new String[] {l_sql}; + return executeQuery(); } /* @@ -133,7 +133,12 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public java.sql.ResultSet executeQuery() throws SQLException { - return executeQuery(compileQuery()); + this.execute(); + while (result != null && !((AbstractJdbc1ResultSet)result).reallyResultSet()) + result = ((AbstractJdbc1ResultSet)result).getNext(); + if (result == null) + throw new PSQLException("postgresql.stat.noresult"); + return result; } /* @@ -145,12 +150,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme * @return either a row count, or 0 for SQL commands * @exception SQLException if a database access error occurs */ - public int executeUpdate(String sql) throws SQLException + public int executeUpdate(String p_sql) throws SQLException { - this.execute(sql); - if (((AbstractJdbc1ResultSet)result).reallyResultSet()) - throw new PSQLException("postgresql.stat.result"); - return this.getUpdateCount(); + String l_sql = replaceProcessing(p_sql); + m_sqlFragments = new String[] {l_sql}; + return executeUpdate(); } /* @@ -164,7 +168,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public int executeUpdate() throws SQLException { - return executeUpdate(compileQuery()); + this.execute(); + if (((AbstractJdbc1ResultSet)result).reallyResultSet()) + throw new PSQLException("postgresql.stat.result"); + return this.getUpdateCount(); } /* @@ -178,10 +185,30 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme * an update count or there are no more results * @exception SQLException if a database access error occurs */ - public boolean execute(String sql) throws SQLException + public boolean execute(String p_sql) throws SQLException + { + String l_sql = replaceProcessing(p_sql); + m_sqlFragments = new String[] {l_sql}; + return execute(); + } + + /* + * Some prepared statements return multiple results; the execute method + * handles these complex statements as well as the simpler form of + * statements handled by executeQuery and executeUpdate + * + * @return true if the next result is a ResultSet; false if it is an + * * update count or there are no more results + * @exception SQLException if a database access error occurs + */ + public boolean execute() throws SQLException { - if (escapeProcessing) - sql = escapeSQL(sql); + if (isFunction && !returnTypeSet) + throw new PSQLException("postgresql.call.noreturntype"); + if (isFunction) { // set entry 1 to dummy entry.. + m_binds[0] = ""; // dummy entry which ensured that no one overrode + // and calls to setXXX (2,..) really went to first arg in a function call.. + } // New in 7.1, if we have a previous resultset then force it to close // This brings us nearer to compliance, and helps memory management. @@ -195,7 +222,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme // New in 7.1, pass Statement so that ExecSQL can customise to it - result = ((AbstractJdbc1Connection)connection).ExecSQL(sql, (java.sql.Statement)this); + result = ((AbstractJdbc1Connection)connection).ExecSQL(m_sqlFragments, m_binds, (java.sql.Statement)this); //If we are executing a callable statement function set the return data if (isFunction) { @@ -216,20 +243,6 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } } - /* - * Some prepared statements return multiple results; the execute method - * handles these complex statements as well as the simpler form of - * statements handled by executeQuery and executeUpdate - * - * @return true if the next result is a ResultSet; false if it is an - * * update count or there are no more results - * @exception SQLException if a database access error occurs - */ - public boolean execute() throws SQLException - { - return execute(compileQuery()); - } - /* * setCursorName defines the SQL cursor name that will be used by * subsequent execute methods. This name can then be used in SQL @@ -336,7 +349,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setEscapeProcessing(boolean enable) throws SQLException { - escapeProcessing = enable; + replaceProcessingEnabled = enable; } /* @@ -494,18 +507,19 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme * So, something like "select * from x where d={d '2001-10-09'}" would * return "select * from x where d= '2001-10-09'". */ - protected static String escapeSQL(String sql) + protected String replaceProcessing(String p_sql) { + if (replaceProcessingEnabled) { // Since escape codes can only appear in SQL CODE, we keep track // of if we enter a string or not. - StringBuffer newsql = new StringBuffer(sql.length()); + StringBuffer newsql = new StringBuffer(p_sql.length()); short state = IN_SQLCODE; int i = -1; - int len = sql.length(); + int len = p_sql.length(); while (++i < len) { - char c = sql.charAt(i); + char c = p_sql.charAt(i); switch (state) { case IN_SQLCODE: @@ -514,7 +528,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme else if (c == '{') // start of an escape code? if (i + 1 < len) { - char next = sql.charAt(i + 1); + char next = p_sql.charAt(i + 1); if (next == 'd') { state = ESC_TIMEDATE; @@ -524,7 +538,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme else if (next == 't') { state = ESC_TIMEDATE; - i += (i + 2 < len && sql.charAt(i + 2) == 's') ? 2 : 1; + i += (i + 2 < len && p_sql.charAt(i + 2) == 's') ? 2 : 1; break; } } @@ -556,6 +570,9 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } return newsql.toString(); + } else { + return p_sql; + } } /* @@ -1113,8 +1130,8 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme { int i; - for (i = 0 ; i < inStrings.length ; i++) - inStrings[i] = null; + for (i = 0 ; i < m_binds.length ; i++) + m_binds[i] = null; } /* @@ -1532,8 +1549,6 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme /* * Returns the SQL statement with the current template values * substituted. - * NB: This is identical to compileQuery() except instead of throwing - * SQLException if a parameter is null, it places ? instead. */ public String toString() { @@ -1542,15 +1557,15 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme sbuf.setLength(0); int i; - for (i = 0 ; i < inStrings.length ; ++i) + for (i = 0 ; i < m_binds.length ; ++i) { - if (inStrings[i] == null) + if (m_binds[i] == null) sbuf.append( '?' ); else - sbuf.append (templateStrings[i]); - sbuf.append (inStrings[i]); + sbuf.append (m_sqlFragments[i]); + sbuf.append (m_binds[i]); } - sbuf.append(templateStrings[inStrings.length]); + sbuf.append(m_sqlFragments[m_binds.length]); return sbuf.toString(); } } @@ -1566,39 +1581,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ protected void set(int paramIndex, String s) throws SQLException { - if (paramIndex < 1 || paramIndex > inStrings.length) + if (paramIndex < 1 || paramIndex > m_binds.length) throw new PSQLException("postgresql.prep.range"); if (paramIndex == 1 && isFunction) // need to registerOut instead throw new PSQLException ("postgresql.call.funcover"); - inStrings[paramIndex - 1] = s; - } - - /* - * Helper - this compiles the SQL query from the various parameters - * This is identical to toString() except it throws an exception if a - * parameter is unused. - */ - protected synchronized String compileQuery() - throws SQLException - { - sbuf.setLength(0); - int i; - - if (isFunction && !returnTypeSet) - throw new PSQLException("postgresql.call.noreturntype"); - if (isFunction) { // set entry 1 to dummy entry.. - inStrings[0] = ""; // dummy entry which ensured that no one overrode - // and calls to setXXX (2,..) really went to first arg in a function call.. - } - - for (i = 0 ; i < inStrings.length ; ++i) - { - if (inStrings[i] == null) - throw new PSQLException("postgresql.prep.param", new Integer(i + 1)); - sbuf.append (templateStrings[i]).append (inStrings[i]); - } - sbuf.append(templateStrings[inStrings.length]); - return sbuf.toString(); + m_binds[paramIndex - 1] = s; } /* @@ -1630,26 +1617,27 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme * select (?, [?, ...]) as result * */ - private void modifyJdbcCall() throws SQLException { + private String modifyJdbcCall(String p_sql) throws SQLException { // syntax checking is not complete only a few basics :( - originalSql = sql; // save for error msgs.. - int index = sql.indexOf ("="); // is implied func or proc? + originalSql = p_sql; // save for error msgs.. + String l_sql = p_sql; + int index = l_sql.indexOf ("="); // is implied func or proc? boolean isValid = true; if (index != -1) { isFunction = true; - isValid = sql.indexOf ("?") < index; // ? before = + isValid = l_sql.indexOf ("?") < index; // ? before = } - sql = sql.trim (); - if (sql.startsWith ("{") && sql.endsWith ("}")) { - sql = sql.substring (1, sql.length() -1); + l_sql = l_sql.trim (); + if (l_sql.startsWith ("{") && l_sql.endsWith ("}")) { + l_sql = l_sql.substring (1, l_sql.length() -1); } else isValid = false; - index = sql.indexOf ("call"); + index = l_sql.indexOf ("call"); if (index == -1 || !isValid) throw new PSQLException ("postgresql.call.malformed", - new Object[]{sql, JDBC_SYNTAX}); - sql = sql.replace ('{', ' '); // replace these characters - sql = sql.replace ('}', ' '); - sql = sql.replace (';', ' '); + new Object[]{l_sql, JDBC_SYNTAX}); + l_sql = l_sql.replace ('{', ' '); // replace these characters + l_sql = l_sql.replace ('}', ' '); + l_sql = l_sql.replace (';', ' '); // this removes the 'call' string and also puts a hidden '?' // at the front of the line for functions, this will @@ -1658,9 +1646,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme // value that is not needed by the postgres syntax. But to make // sure that the parameter numbers are the same as in the original // sql we add a dummy parameter in this case - sql = (isFunction ? "?" : "") + sql.substring (index + 4); + l_sql = (isFunction ? "?" : "") + l_sql.substring (index + 4); - sql = "select " + sql + " as " + RESULT_COLUMN + ";"; + l_sql = "select " + l_sql + " as " + RESULT_COLUMN + ";"; + return l_sql; } /** helperfunction for the getXXX calls to check isFunction and index == 1 diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java index 3b493de2f4..43e71062ab 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java @@ -15,15 +15,13 @@ import org.postgresql.util.PGbytea; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.4 2002/08/14 20:35:39 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.5 2002/08/23 20:45:49 barry Exp $ * This class defines methods of the jdbc2 specification. This class extends * org.postgresql.jdbc1.AbstractJdbc1ResultSet which provides the jdbc1 * methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2ResultSet */ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet { - protected String sqlQuery = null; - //needed for updateable result set support protected boolean updateable = false; protected boolean doingUpdates = false; @@ -1254,7 +1252,9 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra public void parseQuery() { - StringTokenizer st = new StringTokenizer(sqlQuery, " \r\t"); + String[] l_sqlFragments = ((AbstractJdbc2Statement)statement).getSqlFragments(); + String l_sql = l_sqlFragments[0]; + StringTokenizer st = new StringTokenizer(l_sql, " \r\t"); boolean tableFound = false, tablesChecked = false; String name = ""; @@ -1326,11 +1326,6 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra } - public void setSQLQuery(String sqlQuery) { - this.sqlQuery = sqlQuery; - } - - private class PrimaryKey { int index; // where in the result set is this primaryKey String name; // what is the columnName of this primary Key diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java index d8d16985ad..457f36e941 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java @@ -8,7 +8,7 @@ import java.util.Vector; import org.postgresql.largeobject.*; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.3 2002/07/25 22:45:28 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.4 2002/08/23 20:45:49 barry Exp $ * This class defines methods of the jdbc2 specification. This class extends * org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1 * methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement @@ -43,32 +43,28 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra * an update count or there are no more results * @exception SQLException if a database access error occurs */ - public boolean execute(String sql) throws SQLException + public boolean execute() throws SQLException { - boolean l_return = super.execute(sql); + boolean l_return = super.execute(); //Now do the jdbc2 specific stuff //required for ResultSet.getStatement() to work and updateable resultsets ((AbstractJdbc2ResultSet)result).setStatement((Statement)this); - // Added this so that the Updateable resultset knows the query that gave this - ((AbstractJdbc2ResultSet)result).setSQLQuery(sql); - return l_return; } // ** JDBC 2 Extensions ** - public void addBatch(String sql) throws SQLException + public void addBatch(String p_sql) throws SQLException { if (batch == null) batch = new Vector(); - batch.addElement(sql); + batch.addElement(p_sql); } public void clearBatch() throws SQLException { - if (batch != null) - batch.removeAllElements(); + batch = null; } public int[] executeBatch() throws SQLException @@ -155,7 +151,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra public void addBatch() throws SQLException { - addBatch(compileQuery()); + addBatch(this.toString()); } public java.sql.ResultSetMetaData getMetaData() throws SQLException @@ -388,4 +384,9 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra } + //This is needed by AbstractJdbc2ResultSet to determine if the query is updateable or not + protected String[] getSqlFragments() { + return m_sqlFragments; + } + } diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java index 85a6afe60b..cb7d036a77 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java @@ -9,7 +9,7 @@ import java.sql.*; * * PS: Do you know how difficult it is to type on a train? ;-) * - * $Id: DatabaseMetaDataTest.java,v 1.11 2002/08/14 20:35:40 barry Exp $ + * $Id: DatabaseMetaDataTest.java,v 1.12 2002/08/23 20:45:49 barry Exp $ */ public class DatabaseMetaDataTest extends TestCase @@ -102,7 +102,10 @@ public class DatabaseMetaDataTest extends TestCase assertTrue(dbmd.supportsMinimumSQLGrammar()); assertTrue(!dbmd.supportsCoreSQLGrammar()); assertTrue(!dbmd.supportsExtendedSQLGrammar()); - assertTrue(dbmd.supportsANSI92EntryLevelSQL()); + if (((org.postgresql.jdbc1.AbstractJdbc1Connection)con).haveMinimumServerVersion("7.3")) + assertTrue(dbmd.supportsANSI92EntryLevelSQL()); + else + assertTrue(!dbmd.supportsANSI92EntryLevelSQL()); assertTrue(!dbmd.supportsANSI92IntermediateSQL()); assertTrue(!dbmd.supportsANSI92FullSQL()); @@ -426,12 +429,12 @@ public class DatabaseMetaDataTest extends TestCase assertNotNull(dbmd); assertTrue(dbmd.getDatabaseProductName().equals("PostgreSQL")); - //The test below doesn't make sense to me, it tests that + //The test below doesn't make sense to me, it tests that //the version of the driver = the version of the database it is connected to - //since the driver should be backwardly compatible this test is commented out + //since the driver should be backwardly compatible this test is commented out //assertTrue(dbmd.getDatabaseProductVersion().startsWith( - // Integer.toString(pc.getDriver().getMajorVersion()) - // + "." + // Integer.toString(pc.getDriver().getMajorVersion()) + // + "." // + Integer.toString(pc.getDriver().getMinorVersion()))); assertTrue(dbmd.getDriverName().equals("PostgreSQL Native Driver")); -- 2.40.0