From 16a30346c86590fbdcd83cacd2a0a9dbd2cd00dc Mon Sep 17 00:00:00 2001 From: Barry Lind Date: Tue, 4 Feb 2003 09:20:12 +0000 Subject: [PATCH] Patch from Nic Ferrier to add support for result sets being cursor based so that rows can be fetched incrementally. This is enabled by using setFetchSize() --- .../org/postgresql/core/QueryExecutor.java | 98 +++++++--- .../jdbc1/AbstractJdbc1Connection.java | 160 ++++++---------- .../jdbc1/AbstractJdbc1DatabaseMetaData.java | 22 ++- .../jdbc1/AbstractJdbc1ResultSet.java | 64 ++++++- .../jdbc1/AbstractJdbc1Statement.java | 176 ++++++++++++++++-- .../jdbc1/Jdbc1CallableStatement.java | 5 + .../org/postgresql/jdbc1/Jdbc1Connection.java | 12 +- .../jdbc1/Jdbc1PreparedStatement.java | 4 + .../org/postgresql/jdbc1/Jdbc1ResultSet.java | 6 +- .../org/postgresql/jdbc1/Jdbc1Statement.java | 6 +- .../jdbc2/AbstractJdbc2Connection.java | 4 +- .../jdbc2/AbstractJdbc2ResultSet.java | 15 +- .../jdbc2/AbstractJdbc2Statement.java | 10 +- .../jdbc/org/postgresql/jdbc2/Array.java | 3 +- .../jdbc2/Jdbc2CallableStatement.java | 4 + .../org/postgresql/jdbc2/Jdbc2Connection.java | 13 +- .../jdbc2/Jdbc2PreparedStatement.java | 4 + .../org/postgresql/jdbc2/Jdbc2ResultSet.java | 6 +- .../org/postgresql/jdbc2/Jdbc2Statement.java | 6 +- .../jdbc3/AbstractJdbc3ResultSet.java | 6 +- .../jdbc3/Jdbc3CallableStatement.java | 5 + .../org/postgresql/jdbc3/Jdbc3Connection.java | 14 +- .../jdbc3/Jdbc3PreparedStatement.java | 5 + .../org/postgresql/jdbc3/Jdbc3ResultSet.java | 6 +- .../org/postgresql/jdbc3/Jdbc3Statement.java | 7 +- .../jdbc/org/postgresql/util/Serialize.java | 2 +- 26 files changed, 430 insertions(+), 233 deletions(-) diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java index a97638a890..7193a8a615 100644 --- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java +++ b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java @@ -6,6 +6,9 @@ import java.io.IOException; import java.sql.*; import org.postgresql.*; import org.postgresql.util.PSQLException; +import org.postgresql.jdbc1.AbstractJdbc1Connection; +import org.postgresql.jdbc1.AbstractJdbc1ResultSet; +import org.postgresql.jdbc1.AbstractJdbc1Statement; /* * Executes a query on the backend. @@ -13,36 +16,70 @@ 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.17 2002/11/14 05:35:45 barry Exp $ + * $Id: QueryExecutor.java,v 1.18 2003/02/04 09:20:08 barry Exp $ */ public class QueryExecutor { - - 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[] p_sqlFrags, Object[] p_binds, - java.sql.Statement statement, - PG_Stream pg_stream, - java.sql.Connection connection) + //This version of execute does not take an existing result set, but + //creates a new one for the results of the query + public static ResultSet execute (String[] p_sqlFrags, + Object[] p_binds, + java.sql.Statement statement) throws SQLException { - 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; - + QueryExecutor qe = new QueryExecutor(); + qe.m_sqlFrags = p_sqlFrags; + qe.m_binds = p_binds; + qe.statement = statement; if (statement != null) - maxRows = statement.getMaxRows(); + qe.maxRows = statement.getMaxRows(); else - maxRows = 0; + qe.maxRows = 0; + + qe.connection = (AbstractJdbc1Connection)((AbstractJdbc1Statement)statement).getPGConnection(); + qe.pg_stream = qe.connection.getPGStream(); + + return qe.execute(); } + //This version of execute reuses an existing result set for the query + //results, this is used when a result set is backed by a cursor and + //more results are fetched + public static void execute (String[] p_sqlFrags, + Object[] p_binds, + java.sql.ResultSet rs) + throws SQLException + { + QueryExecutor qe = new QueryExecutor(); + qe.m_sqlFrags = p_sqlFrags; + qe.m_binds = p_binds; + qe.rs = rs; + qe.statement = (java.sql.Statement)((AbstractJdbc1ResultSet)qe.rs).getPGStatement(); + if (qe.statement != null) + qe.maxRows = qe.statement.getMaxRows(); + else + qe.maxRows = 0; + + qe.connection = (AbstractJdbc1Connection)((AbstractJdbc1Statement)qe.statement).getPGConnection(); + qe.pg_stream = qe.connection.getPGStream(); + + qe.execute(); + } + + + private QueryExecutor () + { + } + + private String[] m_sqlFrags; + private Object[] m_binds; + private java.sql.Statement statement; + private java.sql.ResultSet rs; + + private AbstractJdbc1Connection connection; + private PG_Stream pg_stream; + private Field[] fields = null; private Vector tuples = new Vector(); private boolean binaryCursor = false; @@ -51,10 +88,12 @@ public class QueryExecutor private long insert_oid = 0; private int maxRows; + /* * Execute a query on the backend. + * */ - public java.sql.ResultSet execute() throws SQLException + private java.sql.ResultSet execute() throws SQLException { StringBuffer errorMessage = null; @@ -130,7 +169,18 @@ public class QueryExecutor if ( errorMessage != null ) throw new SQLException( errorMessage.toString() ); - return connection.getResultSet(statement, fields, tuples, status, update_count, insert_oid, binaryCursor); + + //if an existing result set was passed in reuse it, else + //create a new one + if (rs != null) + { + ((org.postgresql.jdbc1.AbstractJdbc1ResultSet)rs).reInit(fields, tuples, status, update_count, insert_oid, binaryCursor); + } + else + { + rs = ((AbstractJdbc1Statement)statement).createResultSet(fields, tuples, status, update_count, insert_oid, binaryCursor); + } + return rs; } } @@ -145,10 +195,12 @@ public class QueryExecutor for (int i = 0 ; i < m_binds.length ; ++i) { if (m_binds[i] == null) - throw new PSQLException("postgresql.prep.param", new Integer(i + 1)); + throw new PSQLException("postgresql.prep.param (" + i + ")", 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 e22cf53144..d7ba1b273d 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java @@ -14,7 +14,7 @@ import org.postgresql.largeobject.LargeObjectManager; import org.postgresql.util.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.13 2002/11/14 05:35:45 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.14 2003/02/04 09:20:08 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 @@ -22,8 +22,12 @@ import org.postgresql.util.*; public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnection { // This is the network stream associated with this connection - public PG_Stream pg_stream; + private PG_Stream pg_stream; + public PG_Stream getPGStream() { + return pg_stream; + } + protected String PG_HOST; protected int PG_PORT; protected String PG_USER; @@ -84,7 +88,6 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec public abstract java.sql.Statement createStatement() throws SQLException; - /* * This method actually opens the connection. It is called by Driver. * @@ -350,9 +353,10 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec // Set datestyle and fetch db encoding in a single call, to avoid making // more than one round trip to the backend during connection startup. - java.sql.ResultSet resultSet = - ExecSQL("set datestyle to 'ISO'; select version(), " + encodingQuery + ";"); + java.sql.ResultSet resultSet + = execSQL("set datestyle to 'ISO'; select version(), " + encodingQuery + ";"); + if (! resultSet.next()) { throw new PSQLException("postgresql.con.failed", "failed getting backend encoding"); @@ -373,7 +377,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec if (haveMinimumServerVersion("7.3")) { java.sql.ResultSet acRset = - ExecSQL("set client_encoding = 'UNICODE'; show autocommit"); + execSQL("set client_encoding = 'UNICODE'; show autocommit"); //set encoding to be unicode encoding = Encoding.getEncoding("UNICODE", null); @@ -388,7 +392,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec //to make the setting permanent if (acRset.getString(1).equals("off")) { - ExecSQL("set autocommit = on; commit;"); + execSQL("set autocommit = on; commit;"); } } @@ -409,13 +413,6 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec return this_driver; } - // These methods used to be in the main Connection implementation. As they - // are common to all implementations (JDBC1 or 2), they are placed here. - // This should make it easy to maintain the two specifications. - - public abstract java.sql.ResultSet getResultSet(Statement statement, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException; - - public abstract java.sql.ResultSet getResultSet(Statement statement, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount) throws SQLException; /* * This adds a warning to the warning chain. @@ -445,64 +442,15 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec //} } - /* - * 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 sql the SQL statement to be executed - * @return a ResultSet holding the results - * @exception SQLException if a database error occurs + /** Simple query execution. */ - public java.sql.ResultSet ExecSQL(String sql) throws SQLException + public java.sql.ResultSet execSQL (String s) throws SQLException { - return ExecSQL(sql, null); - } - - /* - * 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 sql the SQL statement to be executed - * @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 sql, java.sql.Statement stat) throws SQLException - { - if (isClosed()) - { - throw new PSQLException("postgresql.con.closed"); - } - 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 - { - if (isClosed()) - { - throw new PSQLException("postgresql.con.closed"); - } - return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute(); + final Object[] nullarr = new Object[0]; + java.sql.Statement stat = createStatement(); + return QueryExecutor.execute(new String[] { s }, + nullarr, + stat); } /* @@ -939,27 +887,27 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec //We do the select to ensure a transaction is in process //before we do the commit to avoid warning messages //from issuing a commit without a transaction in process - ExecSQL("select 1; commit; set autocommit = on;"); + execSQL("select 1; commit; set autocommit = on;"); } else { - ExecSQL("end"); + execSQL("end"); } } else { if (haveMinimumServerVersion("7.3")) { - ExecSQL("set autocommit = off; " + getIsolationLevelSQL()); + execSQL("set autocommit = off; " + getIsolationLevelSQL()); } else if (haveMinimumServerVersion("7.1")) { - ExecSQL("begin;" + getIsolationLevelSQL()); + execSQL("begin;" + getIsolationLevelSQL()); } else { - ExecSQL("begin"); - ExecSQL(getIsolationLevelSQL()); + execSQL("begin"); + execSQL(getIsolationLevelSQL()); } } this.autoCommit = autoCommit; @@ -993,17 +941,17 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec return ; if (haveMinimumServerVersion("7.3")) { - ExecSQL("commit; " + getIsolationLevelSQL()); + execSQL("commit; " + getIsolationLevelSQL()); } else if (haveMinimumServerVersion("7.1")) { - ExecSQL("commit;begin;" + getIsolationLevelSQL()); + execSQL("commit;begin;" + getIsolationLevelSQL()); } else { - ExecSQL("commit"); - ExecSQL("begin"); - ExecSQL(getIsolationLevelSQL()); + execSQL("commit"); + execSQL("begin"); + execSQL(getIsolationLevelSQL()); } } @@ -1024,17 +972,17 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec //we don't automatically start a transaction //but let the server functionality automatically start //one when the first statement is executed - ExecSQL("rollback; " + getIsolationLevelSQL()); + execSQL("rollback; " + getIsolationLevelSQL()); } else if (haveMinimumServerVersion("7.1")) { - ExecSQL("rollback; begin;" + getIsolationLevelSQL()); + execSQL("rollback; begin;" + getIsolationLevelSQL()); } else { - ExecSQL("rollback"); - ExecSQL("begin"); - ExecSQL(getIsolationLevelSQL()); + execSQL("rollback"); + execSQL("begin"); + execSQL(getIsolationLevelSQL()); } } @@ -1049,14 +997,14 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec String sql = "show transaction isolation level"; String level = null; if (haveMinimumServerVersion("7.3")) { - ResultSet rs = ExecSQL(sql); + ResultSet rs = execSQL(sql); if (rs.next()) { level = rs.getString(1); } rs.close(); } else { clearWarnings(); - ExecSQL(sql); + execSQL(sql); SQLWarning warning = getWarnings(); if (warning != null) { @@ -1121,7 +1069,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec new Integer(isolationLevel)); } } - ExecSQL(isolationLevelSQL); + execSQL(isolationLevelSQL); } /* @@ -1264,7 +1212,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec } else { sql = "SELECT typname FROM pg_type WHERE oid = " +oid; } - ResultSet result = ExecSQL(sql); + ResultSet result = execSQL(sql); if (((AbstractJdbc1ResultSet)result).getColumnCount() != 1 || ((AbstractJdbc1ResultSet)result).getTupleCount() != 1) { throw new PSQLException("postgresql.unexpected"); } @@ -1305,7 +1253,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec } else { sql = "SELECT oid FROM pg_type WHERE typname='" + typeName + "'"; } - ResultSet result = ExecSQL(sql); + ResultSet result = execSQL(sql); if (((AbstractJdbc1ResultSet)result).getColumnCount() != 1 || ((AbstractJdbc1ResultSet)result).getTupleCount() != 1) throw new PSQLException("postgresql.unexpected"); result.next(); @@ -1413,21 +1361,21 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec * Tip: keep these grouped together by the Types. value */ private static final int jdbc1Typei[] = { - Types.SMALLINT, - Types.INTEGER, Types.INTEGER, - Types.BIGINT, - Types.DOUBLE, Types.DOUBLE, - Types.NUMERIC, - Types.REAL, - Types.DOUBLE, - Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, - Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, - Types.BINARY, - Types.BIT, - Types.DATE, - Types.TIME, - Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP - }; + Types.SMALLINT, + Types.INTEGER, Types.INTEGER, + Types.BIGINT, + Types.DOUBLE, Types.DOUBLE, + Types.NUMERIC, + Types.REAL, + Types.DOUBLE, + Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, + Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, + Types.BINARY, + Types.BIT, + Types.DATE, + Types.TIME, + Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP + }; //Methods to support postgres notifications public void addNotification(org.postgresql.PGNotification p_notification) diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java index a1a61a58cc..9e217f7f24 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java @@ -1915,7 +1915,7 @@ public abstract class AbstractJdbc1DatabaseMetaData } rs.close(); - return connection.getResultSet(null, f, v, "OK", 1); + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, v, "OK", 1, 0, false); } /* @@ -2206,7 +2206,8 @@ public abstract class AbstractJdbc1DatabaseMetaData tuple[0] = types[i].getBytes(); v.addElement(tuple); } - return connection.getResultSet(null, f, v, "OK", 1); + + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, v, "OK", 1, 0, false); } /* @@ -2380,7 +2381,7 @@ public abstract class AbstractJdbc1DatabaseMetaData } rs.close(); - return connection.getResultSet(null, f, v, "OK", 1); + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, v, "OK", 1, 0, false); } /* @@ -2492,7 +2493,8 @@ public abstract class AbstractJdbc1DatabaseMetaData } } rs.close(); - return connection.getResultSet(null, f, v, "OK", 1); + + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, v, "OK", 1, 0, false); } /* @@ -2594,7 +2596,7 @@ public abstract class AbstractJdbc1DatabaseMetaData } rs.close(); - return connection.getResultSet(null, f, v, "OK", 1); + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, v, "OK", 1, 0, false); } private static void sortStringArray(String s[]) { @@ -2787,7 +2789,8 @@ public abstract class AbstractJdbc1DatabaseMetaData tuple[7] = Integer.toString(java.sql.DatabaseMetaData.bestRowNotPseudo).getBytes(); v.addElement(tuple); } - return connection.getResultSet(null, f, v, "OK", 1); + + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, v, "OK", 1, 0, false); } /* @@ -2857,7 +2860,7 @@ public abstract class AbstractJdbc1DatabaseMetaData /* Perhaps we should check that the given * catalog.schema.table actually exists. -KJ */ - return connection.getResultSet(null, f, v, "OK", 1); + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, v, "OK", 1, 0, false); } /* @@ -3180,7 +3183,7 @@ public abstract class AbstractJdbc1DatabaseMetaData tuples.addElement(tuple); } - return connection.getResultSet(null, f, tuples, "OK", 1); + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, tuples, "OK", 1, 0, false); } /* @@ -3465,7 +3468,8 @@ public abstract class AbstractJdbc1DatabaseMetaData v.addElement(tuple); } rs.close(); - return connection.getResultSet(null, f, v, "OK", 1); + + return ((AbstractJdbc1Statement)connection.createStatement()).createResultSet(f, v, "OK", 1, 0, false); } /* diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java index 48e8b8f70b..7c029353d5 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java @@ -13,16 +13,21 @@ import org.postgresql.largeobject.*; import org.postgresql.util.PGbytea; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.8 2003/01/14 09:13:51 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.9 2003/02/04 09:20:08 barry Exp $ * This class defines methods of the jdbc1 specification. This class is * extended by org.postgresql.jdbc2.AbstractJdbc2ResultSet which adds the jdbc2 * methods. The real ResultSet class (for jdbc1) is org.postgresql.jdbc1.Jdbc1ResultSet */ -public abstract class AbstractJdbc1ResultSet +public abstract class AbstractJdbc1ResultSet { protected Vector rows; // The results protected Statement statement; + + public org.postgresql.PGStatement getPGStatement() { + return (org.postgresql.PGStatement) statement; + } + protected Field fields[]; // The field descriptions protected String status; // Status of the result protected boolean binaryCursor = false; // is the data binary or Strings @@ -42,20 +47,44 @@ public abstract class AbstractJdbc1ResultSet public byte[][] rowBuffer = null; - public AbstractJdbc1ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) + public AbstractJdbc1ResultSet(Statement statement, + Field[] fields, + Vector tuples, + String status, + int updateCount, + long insertOID, + boolean binaryCursor) { - this.connection = conn; + this.connection = ((org.postgresql.jdbc1.AbstractJdbc1Statement)statement).getPGConnection(); this.statement = statement; this.fields = fields; this.rows = tuples; this.status = status; this.updateCount = updateCount; + + this.insertOID = insertOID; + this.this_row = null; + this.current_row = -1; + this.binaryCursor = binaryCursor; + } + + + //method to reinitialize a result set with more data + public void reInit (Field[] fields, Vector tuples, String status, + int updateCount, long insertOID, boolean binaryCursor) + { + this.fields = fields; + // on a reinit the size of this indicates how many we pulled + // back. If it's 0 then the res set has ended. + this.rows = tuples; + this.status = status; + this.updateCount = updateCount; this.insertOID = insertOID; this.this_row = null; this.current_row = -1; this.binaryCursor = binaryCursor; } - + public boolean next() throws SQLException { @@ -63,7 +92,30 @@ public abstract class AbstractJdbc1ResultSet throw new PSQLException("postgresql.con.closed"); if (++current_row >= rows.size()) - return false; + { + int fetchSize = ((AbstractJdbc1Statement)statement).fetchSize; + // Must be false if we weren't batching. + if (fetchSize == 0) + return false; + // Use the ref to the statement to get + // the details we need to do another cursor + // query - it will use reinit() to repopulate this + // with the right data. + String[] sql = new String[1]; + String[] binds = new String[0]; + // Is this the correct query??? + String cursorName = ((AbstractJdbc1Statement)statement).m_statementName; + sql[0] = "FETCH FORWARD " + fetchSize + " FROM " + cursorName; + org.postgresql.core.QueryExecutor.execute(sql, + binds, + (java.sql.ResultSet)this); + + // Test the new rows array. + if (rows.size() == 0) + return false; + // Otherwise reset the counter and let it go on... + current_row = 0; + } this_row = (byte [][])rows.elementAt(current_row); diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java index 2aeb5323db..bf91cf14c9 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.14 2002/11/20 07:34:32 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.15 2003/02/04 09:20:08 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 @@ -19,12 +19,19 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme // The connection who created us protected AbstractJdbc1Connection connection; + public org.postgresql.PGConnection getPGConnection() { + return connection; + } + /** The warnings chain. */ protected SQLWarning warnings = null; /** Maximum number of rows to return, 0 = unlimited */ protected int maxrows = 0; + /** Number of rows to get in a batch. */ + protected int fetchSize = 0; + /** Timeout (in seconds) for a query (not used) */ protected int timeout = 0; @@ -47,8 +54,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme private String[] m_origSqlFragments; private String[] m_executeSqlFragments; protected Object[] m_binds = new Object[0]; + protected String[] m_bindTypes = new String[0]; - private String m_statementName = null; + protected String m_statementName = null; + private boolean m_useServerPrepare = false; private static int m_preparedCount = 1; @@ -67,6 +76,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme protected Object callResult; + public abstract java.sql.ResultSet createResultSet(org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException; public AbstractJdbc1Statement (AbstractJdbc1Connection connection) { @@ -117,7 +127,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } - + /* * Execute a SQL statement that retruns a single ResultSet * @@ -132,11 +142,21 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme m_binds = new Object[0]; //If we have already created a server prepared statement, we need //to deallocate the existing one - if (m_statementName != null) { - ((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName); - m_statementName = null; - m_origSqlFragments = null; - m_executeSqlFragments = null; + if (m_statementName != null) + { + try + { + ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName); + } + catch (Exception e) + { + } + finally + { + m_statementName = null; + m_origSqlFragments = null; + m_executeSqlFragments = null; + } } return executeQuery(); } @@ -150,7 +170,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public java.sql.ResultSet executeQuery() throws SQLException { - this.execute(); + if (fetchSize > 0) + this.executeWithCursor(); + else + this.execute(); + while (result != null && !((AbstractJdbc1ResultSet)result).reallyResultSet()) result = ((AbstractJdbc1ResultSet)result).getNext(); if (result == null) @@ -175,7 +199,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme //If we have already created a server prepared statement, we need //to deallocate the existing one if (m_statementName != null) { - ((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName); + ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName); m_statementName = null; m_origSqlFragments = null; m_executeSqlFragments = null; @@ -219,7 +243,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme //If we have already created a server prepared statement, we need //to deallocate the existing one if (m_statementName != null) { - ((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName); + ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName); m_statementName = null; m_origSqlFragments = null; m_executeSqlFragments = null; @@ -317,7 +341,9 @@ 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(m_sqlFragments, m_binds, (java.sql.Statement)this); + result = org.postgresql.core.QueryExecutor.execute(m_sqlFragments, + m_binds, + (java.sql.Statement)this); //If we are executing a callable statement function set the return data if (isFunction) @@ -341,6 +367,102 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } } + /** version of execute which converts the query to a cursor. + */ + public boolean executeWithCursor() throws SQLException + { + 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 + m_bindTypes[0] = PG_TEXT; + // 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. + // Internal stuff will call ExecSQL directly, bypassing this. + if (result != null) + { + java.sql.ResultSet rs = getResultSet(); + if (rs != null) + rs.close(); + } + + // I've pretty much ignored server prepared statements... can declare and prepare be + // used together? + // It's trivial to change this: you just have to resolve this issue + // of how to work out whether there's a function call. If there isn't then the first + // element of the array must be the bit that you extend to become the cursor + // decleration. + // The last thing that can go wrong is when the user supplies a cursor statement + // directly: the translation takes no account of that. I think we should just look + // for declare and stop the translation if we find it. + + // The first thing to do is transform the statement text into the cursor form. + String[] origSqlFragments = m_sqlFragments; + m_sqlFragments = new String[origSqlFragments.length]; + System.arraycopy(origSqlFragments, 0, m_sqlFragments, 0, origSqlFragments.length); + // Pinch the prepared count for our own nefarious purposes. + m_statementName = "JDBC_CURS_" + m_preparedCount++; + // The static bit to prepend to all querys. + String cursDecl = "BEGIN; DECLARE " + m_statementName + " CURSOR FOR "; + String endCurs = " FETCH FORWARD " + fetchSize + " FROM " + m_statementName + ";"; + + // Add the real query to the curs decleration. + // This is the bit that really makes the presumption about + // m_sqlFragments not being a function call. + if (m_sqlFragments.length < 1) + m_sqlFragments[0] = cursDecl + "SELECT NULL;"; + + else if (m_sqlFragments.length < 2) + { + if (m_sqlFragments[0].endsWith(";")) + m_sqlFragments[0] = cursDecl + m_sqlFragments[0] + endCurs; + else + m_sqlFragments[0] = cursDecl + m_sqlFragments[0] + ";" + endCurs; + } + else + { + m_sqlFragments[0] = cursDecl + m_sqlFragments[0]; + if (m_sqlFragments[m_sqlFragments.length - 1].endsWith(";")) + m_sqlFragments[m_sqlFragments.length - 1] += endCurs; + else + m_sqlFragments[m_sqlFragments.length - 1] += (";" + endCurs); + } + + result = org.postgresql.core.QueryExecutor.execute(m_sqlFragments, + m_binds, + (java.sql.Statement)this); + + //If we are executing a callable statement function set the return data + if (isFunction) + { + if (!((AbstractJdbc1ResultSet)result).reallyResultSet()) + throw new PSQLException("postgresql.call.noreturnval"); + if (!result.next ()) + throw new PSQLException ("postgresql.call.noreturnval"); + callResult = result.getObject(1); + int columnType = result.getMetaData().getColumnType(1); + if (columnType != functionReturnType) + { + Object[] arr = + { "java.sql.Types=" + columnType, + "java.sql.Types=" + functionReturnType + }; + throw new PSQLException ("postgresql.call.wrongrtntype",arr); + } + result.close (); + return true; + } + else + { + return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet()); + } + } + + /* * setCursorName defines the SQL cursor name that will be used by * subsequent execute methods. This name can then be used in SQL @@ -593,7 +715,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme // If using server prepared statements deallocate them if (m_useServerPrepare && m_statementName != null) { - ((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName); + ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName); } // Disasociate it from us (For Garbage Collection) @@ -1690,7 +1812,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public byte[] getBytes(int parameterIndex) throws SQLException { - checkIndex (parameterIndex, Types.VARBINARY, "Bytes"); + checkIndex (parameterIndex, Types.VARBINARY, Types.BINARY, "Bytes"); return ((byte [])callResult); } @@ -1847,7 +1969,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme String l_sql = p_sql; int index = l_sql.indexOf ("="); // is implied func or proc? boolean isValid = true; - if (index != -1) + if (index > -1) { isFunction = true; isValid = l_sql.indexOf ("?") < index; // ? before = @@ -1875,11 +1997,24 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme // sure that the parameter numbers are the same as in the original // sql we add a dummy parameter in this case l_sql = (isFunction ? "?" : "") + l_sql.substring (index + 4); - l_sql = "select " + l_sql + " as " + RESULT_COLUMN + ";"; return l_sql; } + /** helperfunction for the getXXX calls to check isFunction and index == 1 + * Compare BOTH type fields against the return type. + */ + protected void checkIndex (int parameterIndex, int type1, int type2, String getName) + throws SQLException + { + checkIndex (parameterIndex); + if (type1 != this.testReturn && type2 != this.testReturn) + throw new PSQLException("postgresql.call.wrongget", + new Object[]{"java.sql.Types=" + testReturn, + getName, + "java.sql.Types=" + type1}); + } + /** helperfunction for the getXXX calls to check isFunction and index == 1 */ protected void checkIndex (int parameterIndex, int type, String getName) @@ -1888,10 +2023,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme checkIndex (parameterIndex); if (type != this.testReturn) throw new PSQLException("postgresql.call.wrongget", - new Object[]{"java.sql.Types=" + testReturn, - getName, - "java.sql.Types=" + type}); + new Object[]{"java.sql.Types=" + testReturn, + getName, + "java.sql.Types=" + type}); } + /** helperfunction for the getXXX calls to check isFunction and index == 1 * @param parameterIndex index of getXXX (index) * check to make sure is a function and index == 1 @@ -1912,7 +2048,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme //If turning server prepared statements off deallocate statement //and reset statement name if (m_useServerPrepare != flag && !flag) - ((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName); + ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName); m_statementName = null; m_useServerPrepare = flag; } else { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java index 7cd69103bd..c79cea0d49 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java @@ -10,5 +10,10 @@ public class Jdbc1CallableStatement extends AbstractJdbc1Statement implements ja { super(connection, sql); } + + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc1ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java index 3ddb071008..9ee64f7db4 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java @@ -6,7 +6,7 @@ import java.sql.*; import org.postgresql.Field; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.5 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.6 2003/02/04 09:20:10 barry Exp $ * This class implements the java.sql.Connection interface for JDBC1. * However most of the implementation is really done in * org.postgresql.jdbc1.AbstractJdbc1Connection @@ -36,16 +36,6 @@ public class Jdbc1Connection extends org.postgresql.jdbc1.AbstractJdbc1Connectio return metadata; } - public java.sql.ResultSet getResultSet(java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException - { - return new Jdbc1ResultSet(this, stat, fields, tuples, status, updateCount, insertOID, binaryCursor); - } - - public java.sql.ResultSet getResultSet(java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException - { - return new Jdbc1ResultSet(this, stat, fields, tuples, status, updateCount, 0, false); - } - } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java index b065b57224..073185a5da 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java @@ -11,4 +11,8 @@ public class Jdbc1PreparedStatement extends AbstractJdbc1Statement implements Pr super(connection, sql); } + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc1ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java index 980bf87261..edc17ff13c 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java @@ -5,7 +5,7 @@ import java.sql.*; import java.util.Vector; import org.postgresql.Field; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1ResultSet.java,v 1.4 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1ResultSet.java,v 1.5 2003/02/04 09:20:10 barry Exp $ * This class implements the java.sql.ResultSet interface for JDBC1. * However most of the implementation is really done in * org.postgresql.jdbc1.AbstractJdbc1ResultSet @@ -13,9 +13,9 @@ import org.postgresql.Field; public class Jdbc1ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet implements java.sql.ResultSet { - public Jdbc1ResultSet(Jdbc1Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) + public Jdbc1ResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) { - super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); + super(statement, fields, tuples, status, updateCount, insertOID, binaryCursor); } public java.sql.ResultSetMetaData getMetaData() throws SQLException diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java index 2b3f521cc9..ab5ba110c1 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java @@ -3,7 +3,7 @@ package org.postgresql.jdbc1; import java.sql.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.3 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.4 2003/02/04 09:20:10 barry Exp $ * This class implements the java.sql.Statement interface for JDBC1. * However most of the implementation is really done in * org.postgresql.jdbc1.AbstractJdbc1Statement @@ -16,4 +16,8 @@ public class Jdbc1Statement extends org.postgresql.jdbc1.AbstractJdbc1Statement super(c); } + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc1ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java index d5476161ed..45d18c5cb1 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java @@ -6,7 +6,7 @@ import java.net.ConnectException; import java.sql.*; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Connection.java,v 1.2 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Connection.java,v 1.3 2003/02/04 09:20:10 barry Exp $ * This class defines methods of the jdbc2 specification. This class extends * org.postgresql.jdbc1.AbstractJdbc1Connection which provides the jdbc1 * methods. The real Connection class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Connection @@ -17,7 +17,7 @@ public abstract class AbstractJdbc2Connection extends org.postgresql.jdbc1.Abstr * The current type mappings */ protected java.util.Map typemap; - + public java.sql.Statement createStatement() throws SQLException { // The spec says default of TYPE_FORWARD_ONLY but everyone is used to diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java index 3d53fe3fd0..aef0baf6c9 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java @@ -15,7 +15,7 @@ import org.postgresql.util.PGbytea; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.12 2003/01/23 18:49:22 davec Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.13 2003/02/04 09:20:10 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 @@ -38,11 +38,10 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra protected PreparedStatement deleteStatement = null; private PreparedStatement selectStatement = null; - - - public AbstractJdbc2ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) + + public AbstractJdbc2ResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) { - super (conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); + super (statement, fields, tuples, status, updateCount, insertOID, binaryCursor); } public java.net.URL getURL(int columnIndex) throws SQLException @@ -366,9 +365,7 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra public int getFetchSize() throws SQLException { - // In this implementation we return the entire result set, so - // here return the number of rows we have. Sub-classes can return a proper - // value + // Returning the current batch size seems the right thing to do. return rows.size(); } @@ -754,7 +751,6 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra } updateValue(columnIndex, theData); - } @@ -787,7 +783,6 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra throw new PSQLException("postgresql.updateable.ioerror" + ie); } updateValue(columnIndex, theData); - } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java index f439f95a4d..615d323c1d 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.10 2002/11/20 20:37:53 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.11 2003/02/04 09:20:10 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 @@ -133,7 +133,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra public int getFetchSize() throws SQLException { - return 0; + return super.fetchSize; } public int getResultSetConcurrency() throws SQLException @@ -148,12 +148,14 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra public void setFetchDirection(int direction) throws SQLException { - throw org.postgresql.Driver.notImplemented(); + // I don't think this should happen, since it's a hint it should just + // fail quietly. + // throw org.postgresql.Driver.notImplemented(); } public void setFetchSize(int rows) throws SQLException { - throw org.postgresql.Driver.notImplemented(); + super.fetchSize = rows; } public void setResultSetConcurrency(int value) throws SQLException diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java index cfaecc972b..54f5953260 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java @@ -343,7 +343,8 @@ public class Array implements java.sql.Array default: throw org.postgresql.Driver.notImplemented(); } - return ((AbstractJdbc2Connection)conn).getResultSet(null, fields, rows, "OK", 1 ); + java.sql.Statement stat = ((AbstractJdbc2Connection)conn).createStatement(); + return ((AbstractJdbc2Statement)stat).createResultSet(fields, rows, "OK", 1, 0, false); } public String toString() diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java index 46ff83a1e0..72dc7ed66e 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java @@ -11,5 +11,9 @@ public class Jdbc2CallableStatement extends org.postgresql.jdbc2.AbstractJdbc2St super(connection, sql); } + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc2ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java index 6ebd0850fb..0a7b7bbb75 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java @@ -6,7 +6,7 @@ import java.util.Vector; import java.util.Hashtable; import org.postgresql.Field; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.5 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.6 2003/02/04 09:20:10 barry Exp $ * This class implements the java.sql.Connection interface for JDBC2. * However most of the implementation is really done in * org.postgresql.jdbc2.AbstractJdbc2Connection or one of it's parents @@ -46,17 +46,6 @@ public class Jdbc2Connection extends org.postgresql.jdbc2.AbstractJdbc2Connectio return metadata; } - public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException - { - return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); - } - - public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException - { - return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, 0, false); - } - - } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java index 15fd8d9a75..79f83d6a6b 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java @@ -11,5 +11,9 @@ public class Jdbc2PreparedStatement extends org.postgresql.jdbc2.AbstractJdbc2St super(connection, sql); } + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc2ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java index 36e3aa048e..ed7979faef 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java @@ -5,7 +5,7 @@ import java.sql.*; import java.util.Vector; import org.postgresql.Field; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.6 2002/09/11 05:38:45 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.7 2003/02/04 09:20:10 barry Exp $ * This class implements the java.sql.ResultSet interface for JDBC2. * However most of the implementation is really done in * org.postgresql.jdbc2.AbstractJdbc2ResultSet or one of it's parents @@ -13,9 +13,9 @@ import org.postgresql.Field; public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet implements java.sql.ResultSet { - public Jdbc2ResultSet(Jdbc2Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) + public Jdbc2ResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) { - super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); + super(statement, fields, tuples, status, updateCount, insertOID, binaryCursor); } public java.sql.ResultSetMetaData getMetaData() throws SQLException diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java index ed894f6cd1..9d0548229c 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java @@ -3,7 +3,7 @@ package org.postgresql.jdbc2; import java.sql.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.3 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.4 2003/02/04 09:20:10 barry Exp $ * This class implements the java.sql.Statement interface for JDBC2. * However most of the implementation is really done in * org.postgresql.jdbc2.AbstractJdbc2Statement or one of it's parents @@ -16,4 +16,8 @@ public class Jdbc2Statement extends org.postgresql.jdbc2.AbstractJdbc2Statement super(c); } + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc2ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3ResultSet.java index 4be956e043..8b617fe436 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3ResultSet.java @@ -4,7 +4,7 @@ package org.postgresql.jdbc3; import java.sql.*; import java.util.Vector; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/AbstractJdbc3ResultSet.java,v 1.2 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/AbstractJdbc3ResultSet.java,v 1.3 2003/02/04 09:20:10 barry Exp $ * This class defines methods of the jdbc3 specification. This class extends * org.postgresql.jdbc2.AbstractJdbc2ResultSet which provides the jdbc2 * methods. The real Statement class (for jdbc3) is org.postgresql.jdbc3.Jdbc3ResultSet @@ -12,9 +12,9 @@ import java.util.Vector; public abstract class AbstractJdbc3ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet { - public AbstractJdbc3ResultSet(org.postgresql.PGConnection conn, Statement statement, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) + public AbstractJdbc3ResultSet(Statement statement, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) { - super (conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); + super (statement, fields, tuples, status, updateCount, insertOID, binaryCursor); } /** diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3CallableStatement.java index 64b2be2d41..7cd509f794 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3CallableStatement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3CallableStatement.java @@ -11,5 +11,10 @@ public class Jdbc3CallableStatement extends org.postgresql.jdbc3.AbstractJdbc3St super(connection, sql); } + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc3ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } + } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Connection.java index 2e1ba7d8cb..0685694b7c 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Connection.java @@ -6,7 +6,7 @@ import java.util.Vector; import java.util.Hashtable; import org.postgresql.Field; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3Connection.java,v 1.2 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3Connection.java,v 1.3 2003/02/04 09:20:10 barry Exp $ * This class implements the java.sql.Connection interface for JDBC3. * However most of the implementation is really done in * org.postgresql.jdbc3.AbstractJdbc3Connection or one of it's parents @@ -46,16 +46,4 @@ public class Jdbc3Connection extends org.postgresql.jdbc3.AbstractJdbc3Connectio return metadata; } - public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException - { - return new Jdbc3ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); - } - - public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException - { - return new Jdbc3ResultSet(this, statement, fields, tuples, status, updateCount, 0, false); - } - } - - diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PreparedStatement.java index 85ccbbb5e8..62d33925d8 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PreparedStatement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PreparedStatement.java @@ -11,5 +11,10 @@ public class Jdbc3PreparedStatement extends org.postgresql.jdbc3.AbstractJdbc3St super(connection, sql); } + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc3ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } + } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java index 4e53404e8a..255f34b6b7 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java @@ -5,7 +5,7 @@ import java.sql.*; import java.util.Vector; import org.postgresql.Field; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3ResultSet.java,v 1.3 2002/09/11 05:38:45 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3ResultSet.java,v 1.4 2003/02/04 09:20:11 barry Exp $ * This class implements the java.sql.ResultSet interface for JDBC3. * However most of the implementation is really done in * org.postgresql.jdbc3.AbstractJdbc3ResultSet or one of it's parents @@ -13,9 +13,9 @@ import org.postgresql.Field; public class Jdbc3ResultSet extends org.postgresql.jdbc3.AbstractJdbc3ResultSet implements java.sql.ResultSet { - public Jdbc3ResultSet(Jdbc3Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) + public Jdbc3ResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) { - super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); + super(statement, fields, tuples, status, updateCount, insertOID, binaryCursor); } public java.sql.ResultSetMetaData getMetaData() throws SQLException diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Statement.java index c711b11696..bcac4501d4 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Statement.java @@ -3,7 +3,7 @@ package org.postgresql.jdbc3; import java.sql.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3Statement.java,v 1.2 2002/09/06 21:23:06 momjian Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3Statement.java,v 1.3 2003/02/04 09:20:11 barry Exp $ * This class implements the java.sql.Statement interface for JDBC3. * However most of the implementation is really done in * org.postgresql.jdbc3.AbstractJdbc3Statement or one of it's parents @@ -16,4 +16,9 @@ public class Jdbc3Statement extends org.postgresql.jdbc3.AbstractJdbc3Statement super(c); } + public java.sql.ResultSet createResultSet (org.postgresql.Field[] fields, java.util.Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException + { + return new Jdbc3ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor); + } + } diff --git a/src/interfaces/jdbc/org/postgresql/util/Serialize.java b/src/interfaces/jdbc/org/postgresql/util/Serialize.java index 48d18ef02e..d4bf01fb64 100644 --- a/src/interfaces/jdbc/org/postgresql/util/Serialize.java +++ b/src/interfaces/jdbc/org/postgresql/util/Serialize.java @@ -405,7 +405,7 @@ public class Serialize if (Driver.logDebug) Driver.debug("Serialize.store: " + sb.toString() ); - ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL(sb.toString()); + ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).execSQL(sb.toString()); // fetch the OID for returning if (update)