mirror of
https://github.com/postgres/postgres.git
synced 2025-07-15 19:21:59 +03:00
Initial restructuring to add jdbc3 support. There was a significant amount
of duplicated code between the jdbc1 and jdbc2. This checkin restructures the code so that the duplication is removed so that the jdbc3 support can be added without adding yet another copy of everything. Also many classes were renamed to avoid confusion with multiple different objects having the same name. The timestamp tests were also updated to add support for testing timestamp without time zone in addition to timestamp with time zone Modified Files: jdbc/Makefile jdbc/build.xml jdbc/example/ImageViewer.java jdbc/example/basic.java jdbc/example/blobtest.java jdbc/example/threadsafe.java jdbc/org/postgresql/Driver.java.in jdbc/org/postgresql/Field.java jdbc/org/postgresql/core/QueryExecutor.java jdbc/org/postgresql/fastpath/Fastpath.java jdbc/org/postgresql/jdbc1/CallableStatement.java jdbc/org/postgresql/jdbc1/DatabaseMetaData.java jdbc/org/postgresql/jdbc1/PreparedStatement.java jdbc/org/postgresql/jdbc2/Array.java jdbc/org/postgresql/jdbc2/CallableStatement.java jdbc/org/postgresql/jdbc2/DatabaseMetaData.java jdbc/org/postgresql/jdbc2/PreparedStatement.java jdbc/org/postgresql/jdbc2/UpdateableResultSet.java jdbc/org/postgresql/largeobject/LargeObjectManager.java jdbc/org/postgresql/largeobject/PGblob.java jdbc/org/postgresql/largeobject/PGclob.java jdbc/org/postgresql/test/jdbc2/BlobTest.java jdbc/org/postgresql/test/jdbc2/ConnectionTest.java jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java jdbc/org/postgresql/test/jdbc2/TimestampTest.java jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java jdbc/org/postgresql/util/Serialize.java Added Files: jdbc/org/postgresql/PGConnection.java jdbc/org/postgresql/PGStatement.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java jdbc/org/postgresql/jdbc1/Jdbc1Connection.java jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java jdbc/org/postgresql/jdbc1/Jdbc1Statement.java jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java jdbc/org/postgresql/jdbc2/Jdbc2Connection.java jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java jdbc/org/postgresql/jdbc2/Jdbc2Statement.java Removed Files: jdbc/org/postgresql/Connection.java jdbc/org/postgresql/ResultSet.java jdbc/org/postgresql/Statement.java jdbc/org/postgresql/jdbc1/Connection.java jdbc/org/postgresql/jdbc1/ResultSet.java jdbc/org/postgresql/jdbc1/Statement.java jdbc/org/postgresql/jdbc2/Connection.java jdbc/org/postgresql/jdbc2/ResultSet.java jdbc/org/postgresql/jdbc2/Statement.java
This commit is contained in:
@ -0,0 +1,471 @@
|
||||
package org.postgresql.jdbc1;
|
||||
|
||||
import java.sql.*;
|
||||
import org.postgresql.util.PSQLException;
|
||||
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.1 2002/07/23 03:59:55 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
|
||||
*/
|
||||
public abstract class AbstractJdbc1Statement implements org.postgresql.PGStatement
|
||||
{
|
||||
|
||||
// The connection who created us
|
||||
protected AbstractJdbc1Connection connection;
|
||||
|
||||
/** The warnings chain. */
|
||||
protected SQLWarning warnings = null;
|
||||
|
||||
/** Maximum number of rows to return, 0 = unlimited */
|
||||
protected int maxrows = 0;
|
||||
|
||||
/** Timeout (in seconds) for a query (not used) */
|
||||
protected int timeout = 0;
|
||||
|
||||
protected boolean escapeProcessing = true;
|
||||
|
||||
/** The current results */
|
||||
protected java.sql.ResultSet result = null;
|
||||
|
||||
// Static variables for parsing SQL when escapeProcessing is true.
|
||||
private static final short IN_SQLCODE = 0;
|
||||
private static final short IN_STRING = 1;
|
||||
private static final short BACKSLASH = 2;
|
||||
private static final short ESC_TIMEDATE = 3;
|
||||
|
||||
/*
|
||||
* 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 && !((AbstractJdbc1ResultSet)result).reallyResultSet())
|
||||
result = ((AbstractJdbc1ResultSet)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);
|
||||
if (((AbstractJdbc1ResultSet)result).reallyResultSet())
|
||||
throw new PSQLException("postgresql.stat.result");
|
||||
return this.getUpdateCount();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = ((AbstractJdbc1Connection)connection).ExecSQL(sql, (java.sql.Statement)this);
|
||||
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* <p><B>Note:</B> 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.
|
||||
*
|
||||
* <p>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
|
||||
{
|
||||
((AbstractJdbc1Connection)connection).setCursorName(name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 (((AbstractJdbc1ResultSet)result).reallyResultSet())
|
||||
return -1;
|
||||
return ((AbstractJdbc1ResultSet)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 = ((AbstractJdbc1ResultSet)result).getNext();
|
||||
return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Returns the status message from the current Result.<p>
|
||||
* This is used internally by the driver.
|
||||
*
|
||||
* @return status message from backend
|
||||
*/
|
||||
public String getResultStatusString()
|
||||
{
|
||||
if (result == null)
|
||||
return null;
|
||||
return ((AbstractJdbc1ResultSet)result).getStatusString();
|
||||
}
|
||||
|
||||
/*
|
||||
* The maxRows limit is set to limit the number of rows that
|
||||
* any ResultSet can contain. If the limit is exceeded, the
|
||||
* excess rows are silently dropped.
|
||||
*
|
||||
* @return the current maximum row limit; zero means unlimited
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getMaxRows() throws SQLException
|
||||
{
|
||||
return maxrows;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the maximum number of rows
|
||||
*
|
||||
* @param max the new max rows limit; zero means unlimited
|
||||
* @exception SQLException if a database access error occurs
|
||||
* @see getMaxRows
|
||||
*/
|
||||
public void setMaxRows(int max) throws SQLException
|
||||
{
|
||||
maxrows = max;
|
||||
}
|
||||
|
||||
/*
|
||||
* If escape scanning is on (the default), the driver will do escape
|
||||
* substitution before sending the SQL to the database.
|
||||
*
|
||||
* @param enable true to enable; false to disable
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public void setEscapeProcessing(boolean enable) throws SQLException
|
||||
{
|
||||
escapeProcessing = enable;
|
||||
}
|
||||
|
||||
/*
|
||||
* The queryTimeout limit is the number of seconds the driver
|
||||
* will wait for a Statement to execute. If the limit is
|
||||
* exceeded, a SQLException is thrown.
|
||||
*
|
||||
* @return the current query timeout limit in seconds; 0 = unlimited
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getQueryTimeout() throws SQLException
|
||||
{
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the queryTimeout limit
|
||||
*
|
||||
* @param seconds - the new query timeout limit in seconds
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public void setQueryTimeout(int seconds) throws SQLException
|
||||
{
|
||||
timeout = seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* This adds a warning to the warning chain.
|
||||
* @param msg message to add
|
||||
*/
|
||||
public void addWarning(String msg)
|
||||
{
|
||||
if (warnings != null)
|
||||
warnings.setNextWarning(new SQLWarning(msg));
|
||||
else
|
||||
warnings = new SQLWarning(msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* The first warning reported by calls on this Statement is
|
||||
* returned. A Statement's execute methods clear its SQLWarning
|
||||
* chain. Subsequent Statement warnings will be chained to this
|
||||
* SQLWarning.
|
||||
*
|
||||
* <p>The Warning chain is automatically cleared each time a statement
|
||||
* is (re)executed.
|
||||
*
|
||||
* <p><B>Note:</B> If you are processing a ResultSet then any warnings
|
||||
* associated with ResultSet reads will be chained on the ResultSet
|
||||
* object.
|
||||
*
|
||||
* @return the first SQLWarning on null
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public SQLWarning getWarnings() throws SQLException
|
||||
{
|
||||
return warnings;
|
||||
}
|
||||
|
||||
/*
|
||||
* The maxFieldSize limit (in bytes) is the maximum amount of
|
||||
* data returned for any column value; it only applies to
|
||||
* BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
|
||||
* columns. If the limit is exceeded, the excess data is silently
|
||||
* discarded.
|
||||
*
|
||||
* @return the current max column size limit; zero means unlimited
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getMaxFieldSize() throws SQLException
|
||||
{
|
||||
return 8192; // We cannot change this
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the maxFieldSize - NOT! - We throw an SQLException just
|
||||
* to inform them to stop doing this.
|
||||
*
|
||||
* @param max the new max column size limit; zero means unlimited
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public void setMaxFieldSize(int max) throws SQLException
|
||||
{
|
||||
throw new PSQLException("postgresql.stat.maxfieldsize");
|
||||
}
|
||||
|
||||
/*
|
||||
* After this call, getWarnings returns null until a new warning
|
||||
* is reported for this Statement.
|
||||
*
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public void clearWarnings() throws SQLException
|
||||
{
|
||||
warnings = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cancel can be used by one thread to cancel a statement that
|
||||
* is being executed by another thread.
|
||||
* <p>
|
||||
* Not implemented, this method is a no-op.
|
||||
*
|
||||
* @exception SQLException only because thats the spec.
|
||||
*/
|
||||
public void cancel() throws SQLException
|
||||
{
|
||||
throw new PSQLException("postgresql.unimplemented");
|
||||
}
|
||||
|
||||
/*
|
||||
* getResultSet returns the current result as a ResultSet. It
|
||||
* should only be called once per result.
|
||||
*
|
||||
* @return the current result set; null if there are no more
|
||||
* @exception SQLException if a database access error occurs (why?)
|
||||
*/
|
||||
public java.sql.ResultSet getResultSet() throws SQLException
|
||||
{
|
||||
if (result != null && ((AbstractJdbc1ResultSet) result).reallyResultSet())
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* In many cases, it is desirable to immediately release a
|
||||
* Statement's database and JDBC resources instead of waiting
|
||||
* for this to happen when it is automatically closed. The
|
||||
* close method provides this immediate release.
|
||||
*
|
||||
* <p><B>Note:</B> A Statement is automatically closed when it is
|
||||
* garbage collected. When a Statement is closed, its current
|
||||
* ResultSet, if one exists, is also closed.
|
||||
*
|
||||
* @exception SQLException if a database access error occurs (why?)
|
||||
*/
|
||||
public void close() throws SQLException
|
||||
{
|
||||
// Force the ResultSet to close
|
||||
java.sql.ResultSet rs = getResultSet();
|
||||
if (rs != null)
|
||||
rs.close();
|
||||
|
||||
// Disasociate it from us (For Garbage Collection)
|
||||
result = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Filter the SQL string of Java SQL Escape clauses.
|
||||
*
|
||||
* Currently implemented Escape clauses are those mentioned in 11.3
|
||||
* in the specification. Basically we look through the sql string for
|
||||
* {d xxx}, {t xxx} or {ts xxx} in non-string sql code. When we find
|
||||
* them, we just strip the escape part leaving only the xxx part.
|
||||
* So, something like "select * from x where d={d '2001-10-09'}" would
|
||||
* return "select * from x where d= '2001-10-09'".
|
||||
*/
|
||||
protected static String escapeSQL(String sql)
|
||||
{
|
||||
// Since escape codes can only appear in SQL CODE, we keep track
|
||||
// of if we enter a string or not.
|
||||
StringBuffer newsql = new StringBuffer();
|
||||
short state = IN_SQLCODE;
|
||||
|
||||
int i = -1;
|
||||
int len = sql.length();
|
||||
while (++i < len)
|
||||
{
|
||||
char c = sql.charAt(i);
|
||||
switch (state)
|
||||
{
|
||||
case IN_SQLCODE:
|
||||
if (c == '\'') // start of a string?
|
||||
state = IN_STRING;
|
||||
else if (c == '{') // start of an escape code?
|
||||
if (i + 1 < len)
|
||||
{
|
||||
char next = sql.charAt(i + 1);
|
||||
if (next == 'd')
|
||||
{
|
||||
state = ESC_TIMEDATE;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
else if (next == 't')
|
||||
{
|
||||
state = ESC_TIMEDATE;
|
||||
i += (i + 2 < len && sql.charAt(i + 2) == 's') ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
newsql.append(c);
|
||||
break;
|
||||
|
||||
case IN_STRING:
|
||||
if (c == '\'') // end of string?
|
||||
state = IN_SQLCODE;
|
||||
else if (c == '\\') // a backslash?
|
||||
state = BACKSLASH;
|
||||
|
||||
newsql.append(c);
|
||||
break;
|
||||
|
||||
case BACKSLASH:
|
||||
state = IN_STRING;
|
||||
|
||||
newsql.append(c);
|
||||
break;
|
||||
|
||||
case ESC_TIMEDATE:
|
||||
if (c == '}')
|
||||
state = IN_SQLCODE; // end of escape code.
|
||||
else
|
||||
newsql.append(c);
|
||||
break;
|
||||
} // end switch
|
||||
}
|
||||
|
||||
return newsql.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* The following methods are postgres extensions and are defined
|
||||
* in the interface org.postgresql.Statement
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Returns the Last inserted/updated oid. Deprecated in 7.2 because
|
||||
* range of OID values is greater than a java signed int.
|
||||
* @deprecated Replaced by getLastOID in 7.2
|
||||
*/
|
||||
public int getInsertedOID() throws SQLException
|
||||
{
|
||||
if (result == null)
|
||||
return 0;
|
||||
return (int)((AbstractJdbc1ResultSet)result).getLastOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the Last inserted/updated oid.
|
||||
* @return OID of last insert
|
||||
* @since 7.2
|
||||
*/
|
||||
public long getLastOID() throws SQLException
|
||||
{
|
||||
if (result == null)
|
||||
return 0;
|
||||
return ((AbstractJdbc1ResultSet)result).getLastOID();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user