package org.postgresql.jdbc2; // IMPORTANT NOTE: This file implements the JDBC 2 version of the driver. // If you make any modifications to this file, you must make sure that the // changes are also made (if relevent) to the related JDBC 1 class in the // org.postgresql.jdbc1 package. import java.sql.*; import java.util.Vector; import org.postgresql.util.*; /* * A Statement object is used for executing a static SQL statement and * obtaining the results produced by it. * *
Only one ResultSet per Statement can be open at any point in time. * Therefore, if the reading of one ResultSet is interleaved with the * reading of another, each must have been generated by different * Statements. All statement execute methods implicitly close a * statement's current ResultSet if an open one exists. * * @see java.sql.Statement * @see ResultSet */ public class Statement extends org.postgresql.Statement implements java.sql.Statement { private Connection connection; // The connection who created us private Vector batch = null; private int resultsettype; // the resultset type to return private int concurrency; // is it updateable or not? /* * Constructor for a Statement. It simply sets the connection * that created us. * * @param c the Connection instantation that creates us */ public Statement (Connection c) { connection = c; resultsettype = java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE; concurrency = java.sql.ResultSet.CONCUR_READ_ONLY; } /* * Execute a SQL statement that retruns a single ResultSet * * @param sql typically a static SQL SELECT statement * @return a ResulSet that contains the data produced by the query * @exception SQLException if a database access error occurs */ public java.sql.ResultSet executeQuery(String sql) throws SQLException { this.execute(sql); while (result != null && !((org.postgresql.ResultSet)result).reallyResultSet()) result = ((org.postgresql.ResultSet)result).getNext(); if (result == null) throw new PSQLException("postgresql.stat.noresult"); return result; } /* * Execute a SQL INSERT, UPDATE or DELETE statement. In addition * SQL statements that return nothing such as SQL DDL statements * can be executed * * @param sql a SQL statement * @return either a row count, or 0 for SQL commands * @exception SQLException if a database access error occurs */ public int executeUpdate(String sql) throws SQLException { this.execute(sql); return this.getUpdateCount(); } /* * setCursorName defines the SQL cursor name that will be used by * subsequent execute methods. This name can then be used in SQL * positioned update/delete statements to identify the current row * in the ResultSet generated by this statement. If a database * doesn't support positioned update/delete, this method is a * no-op. * *
Note: By definition, positioned update/delete execution * must be done by a different Statement than the one which * generated the ResultSet being used for positioning. Also, cursor * names must be unique within a Connection. * *
We throw an additional constriction. There can only be one * cursor active at any one time. * * @param name the new cursor name * @exception SQLException if a database access error occurs */ public void setCursorName(String name) throws SQLException { connection.setCursorName(name); } /* * Execute a SQL statement that may return multiple results. We * don't have to worry about this since we do not support multiple * ResultSets. You can use getResultSet or getUpdateCount to * retrieve the result. * * @param sql any SQL statement * @return true if the next result is a ResulSet, false if it is * an update count or there are no more results * @exception SQLException if a database access error occurs */ public boolean execute(String sql) throws SQLException { if (escapeProcessing) sql = escapeSQL(sql); // 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(); } // New in 7.1, pass Statement so that ExecSQL can customise to it result = connection.ExecSQL(sql, this); // New in 7.1, required for ResultSet.getStatement() to work ((org.postgresql.jdbc2.ResultSet)result).setStatement(this); return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet()); } /* * getUpdateCount returns the current result as an update count, * if the result is a ResultSet or there are no more results, -1 * is returned. It should only be called once per result. * * @return the current result as an update count. * @exception SQLException if a database access error occurs */ public int getUpdateCount() throws SQLException { if (result == null) return -1; if (((org.postgresql.ResultSet)result).reallyResultSet()) return -1; return ((org.postgresql.ResultSet)result).getResultCount(); } /* * getMoreResults moves to a Statement's next result. If it returns * true, this result is a ResulSet. * * @return true if the next ResultSet is valid * @exception SQLException if a database access error occurs */ public boolean getMoreResults() throws SQLException { result = ((org.postgresql.ResultSet)result).getNext(); return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet()); } // ** JDBC 2 Extensions ** public void addBatch(String sql) throws SQLException { if (batch == null) batch = new Vector(); batch.addElement(sql); } public void clearBatch() throws SQLException { if (batch != null) batch.removeAllElements(); } public int[] executeBatch() throws SQLException { if (batch == null) batch = new Vector(); int size = batch.size(); int[] result = new int[size]; int i = 0; try { for (i = 0;i < size;i++) result[i] = this.executeUpdate((String)batch.elementAt(i)); } catch (SQLException e) { int[] resultSucceeded = new int[i]; System.arraycopy(result, 0, resultSucceeded, 0, i); PBatchUpdateException updex = new PBatchUpdateException("postgresql.stat.batch.error", new Integer(i), batch.elementAt(i), resultSucceeded); updex.setNextException(e); throw updex; } finally { batch.removeAllElements(); } return result; } public void cancel() throws SQLException { connection.cancelQuery(); } public java.sql.Connection getConnection() throws SQLException { return (java.sql.Connection)connection; } public int getFetchDirection() throws SQLException { throw new PSQLException("postgresql.psqlnotimp"); } public int getFetchSize() throws SQLException { // This one can only return a valid value when were a cursor? throw org.postgresql.Driver.notImplemented(); } public int getResultSetConcurrency() throws SQLException { // new in 7.1 return concurrency; } public int getResultSetType() throws SQLException { // new in 7.1 return resultsettype; } public void setFetchDirection(int direction) throws SQLException { throw org.postgresql.Driver.notImplemented(); } public void setFetchSize(int rows) throws SQLException { throw org.postgresql.Driver.notImplemented(); } /* * New in 7.1 */ public void setResultSetConcurrency(int value) throws SQLException { concurrency = value; } /* * New in 7.1 */ public void setResultSetType(int value) throws SQLException { resultsettype = value; } }