mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
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()
This commit is contained in:
@ -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.
|
||||
*
|
||||
* <B>Note:</B> 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.
|
||||
*
|
||||
* <B>Note:</B> 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.
|
||||
*
|
||||
* <B>Note:</B> 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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user