summaryrefslogtreecommitdiff
path: root/src/interfaces/jdbc/org/postgresql/Connection.java
diff options
context:
space:
mode:
authorPeter Mount <peter@retep.org.uk>2001-01-18 14:50:15 +0000
committerPeter Mount <peter@retep.org.uk>2001-01-18 14:50:15 +0000
commit45b5d792afa60ae24d57cdceaaec0e03cf6abb2a (patch)
treeb16cf82d422f6226b4dd6086e836564ce4e1438b /src/interfaces/jdbc/org/postgresql/Connection.java
parent89ac643964bff695309b66410205593dec4f1a03 (diff)
downloadpostgresql-45b5d792afa60ae24d57cdceaaec0e03cf6abb2a.tar.gz
Thu Jan 18 12:24:00 GMT 2001 peter@retep.org.uk
- These methods in org.postgresql.jdbc2.ResultSet are now implemented: getBigDecimal(int) ie: without a scale (why did this get missed?) getBlob(int) getCharacterStream(int) getConcurrency() getDate(int,Calendar) getFetchDirection() getFetchSize() getTime(int,Calendar) getTimestamp(int,Calendar) getType() NB: Where int represents the column name, the associated version taking a String were already implemented by calling the int version. - These methods no longer throw the not implemented but the new noupdate error. This is in preparation for the Updateable ResultSet support which will overide these methods by extending the existing class to implement that functionality, but needed to show something other than notimplemented: cancelRowUpdates() deleteRow() - Added new error message into errors.properties "postgresql.noupdate" This is used by jdbc2.ResultSet when an update method is called and the ResultSet is not updateable. A new method notUpdateable() has been added to that class to throw this exception, keeping the binary size down. - Added new error message into errors.properties "postgresql.psqlnotimp" This is used instead of unimplemented when it's a feature in the backend that is preventing this method from being implemented. - Removed getKeysetSize() as its not part of the ResultSet API Thu Jan 18 09:46:00 GMT 2001 peter@retep.org.uk - Applied modified patch from Richard Bullington-McGuire <rbulling@microstate.com>. I had to modify it as some of the code patched now exists in different classes, and some of it actually patched obsolete code. Wed Jan 17 10:19:00 GMT 2001 peter@retep.org.uk - Updated Implementation to include both ANT & JBuilder - Updated README to reflect the changes since 7.0 - Created jdbc.jpr file which allows JBuilder to be used to edit the source. JBuilder _CAN_NOT_ be used to compile. You must use ANT for that. It's only to allow JBuilders syntax checking to improve the drivers source. Refer to Implementation for more details
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/Connection.java')
-rw-r--r--src/interfaces/jdbc/org/postgresql/Connection.java185
1 files changed, 104 insertions, 81 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java
index b828a90b6d..3ca464d3ad 100644
--- a/src/interfaces/jdbc/org/postgresql/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/Connection.java
@@ -10,7 +10,7 @@ import org.postgresql.largeobject.*;
import org.postgresql.util.*;
/**
- * $Id: Connection.java,v 1.11 2000/12/22 03:08:52 momjian Exp $
+ * $Id: Connection.java,v 1.12 2001/01/18 14:50:14 peter Exp $
*
* This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
* JDBC2 versions of the Connection class.
@@ -20,10 +20,10 @@ public abstract class Connection
{
// This is the network stream associated with this connection
public PG_Stream pg_stream;
-
+
// This is set by org.postgresql.Statement.setMaxRows()
public int maxrows = 0; // maximum no. of rows; 0 = unlimited
-
+
private String PG_HOST;
private int PG_PORT;
private String PG_USER;
@@ -38,17 +38,17 @@ public abstract class Connection
* used.
*/
private String encoding;
-
+
public boolean CONNECTION_OK = true;
public boolean CONNECTION_BAD = false;
-
+
public boolean autoCommit = true;
public boolean readOnly = false;
-
+
public Driver this_driver;
private String this_url;
private String cursor = null; // The positioned update cursor name
-
+
// These are new for v6.3, they determine the current protocol versions
// supported by this version of the driver. They are defined in
// src/include/libpq/pqcomm.h
@@ -59,41 +59,41 @@ public abstract class Connection
private static final int SM_OPTIONS = 64;
private static final int SM_UNUSED = 64;
private static final int SM_TTY = 64;
-
+
private static final int AUTH_REQ_OK = 0;
private static final int AUTH_REQ_KRB4 = 1;
private static final int AUTH_REQ_KRB5 = 2;
private static final int AUTH_REQ_PASSWORD = 3;
private static final int AUTH_REQ_CRYPT = 4;
-
+
// New for 6.3, salt value for crypt authorisation
private String salt;
-
+
// This is used by Field to cache oid -> names.
// It's here, because it's shared across this connection only.
// Hence it cannot be static within the Field class, because it would then
// be across all connections, which could be to different backends.
public Hashtable fieldCache = new Hashtable();
-
+
// Now handle notices as warnings, so things like "show" now work
public SQLWarning firstWarning = null;
-
+
// The PID an cancellation key we get from the backend process
public int pid;
public int ckey;
// This receive_sbuf should be used by the different methods
- // that call pg_stream.ReceiveString() in this Connection, so
- // so we avoid uneccesary new allocations.
+ // that call pg_stream.ReceiveString() in this Connection, so
+ // so we avoid uneccesary new allocations.
byte receive_sbuf[] = new byte[8192];
-
+
/**
* This is called by Class.forName() from within org.postgresql.Driver
*/
public Connection()
{
}
-
+
/**
* This method actually opens the connection. It is called by Driver.
*
@@ -115,7 +115,7 @@ public abstract class Connection
throw new PSQLException("postgresql.con.user");
if(info.getProperty("password")==null)
throw new PSQLException("postgresql.con.pass");
-
+
this_driver = d;
this_url = url;
PG_DATABASE = database;
@@ -137,7 +137,7 @@ public abstract class Connection
} catch (IOException e) {
throw new PSQLException ("postgresql.con.failed",e);
}
-
+
// Now we need to construct and send a startup packet
try
{
@@ -146,13 +146,13 @@ public abstract class Connection
pg_stream.SendInteger(PG_PROTOCOL_LATEST_MAJOR,2);
pg_stream.SendInteger(PG_PROTOCOL_LATEST_MINOR,2);
pg_stream.Send(database.getBytes(),SM_DATABASE);
-
+
// This last send includes the unused fields
pg_stream.Send(PG_USER.getBytes(),SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY);
-
+
// now flush the startup packets to the backend
pg_stream.flush();
-
+
// Now get the response from the backend, either an error message
// or an authentication request
int areq = -1; // must have a value here
@@ -169,11 +169,11 @@ public abstract class Connection
//
throw new SQLException(pg_stream.ReceiveString
(receive_sbuf, 4096, getEncoding()));
-
+
case 'R':
// Get the type of request
areq = pg_stream.ReceiveIntegerR(4);
-
+
// Get the password salt if there is one
if(areq == AUTH_REQ_CRYPT) {
byte[] rst = new byte[2];
@@ -182,21 +182,21 @@ public abstract class Connection
salt = new String(rst,0,2);
DriverManager.println("Salt="+salt);
}
-
+
// now send the auth packet
switch(areq)
{
case AUTH_REQ_OK:
break;
-
+
case AUTH_REQ_KRB4:
DriverManager.println("postgresql: KRB4");
throw new PSQLException("postgresql.con.kerb4");
-
+
case AUTH_REQ_KRB5:
DriverManager.println("postgresql: KRB5");
throw new PSQLException("postgresql.con.kerb5");
-
+
case AUTH_REQ_PASSWORD:
DriverManager.println("postgresql: PASSWORD");
pg_stream.SendInteger(5+PG_PASSWORD.length(),4);
@@ -204,7 +204,7 @@ public abstract class Connection
pg_stream.SendInteger(0,1);
pg_stream.flush();
break;
-
+
case AUTH_REQ_CRYPT:
DriverManager.println("postgresql: CRYPT");
String crypted = UnixCrypt.crypt(salt,PG_PASSWORD);
@@ -213,21 +213,21 @@ public abstract class Connection
pg_stream.SendInteger(0,1);
pg_stream.flush();
break;
-
+
default:
throw new PSQLException("postgresql.con.auth",new Integer(areq));
}
break;
-
+
default:
throw new PSQLException("postgresql.con.authfail");
}
} while(areq != AUTH_REQ_OK);
-
+
} catch (IOException e) {
throw new PSQLException("postgresql.con.failed",e);
}
-
+
// As of protocol version 2.0, we should now receive the cancellation key and the pid
int beresp = pg_stream.ReceiveChar();
@@ -266,7 +266,7 @@ public abstract class Connection
// We also ask the DB for certain properties (i.e. DatabaseEncoding at this time)
//
firstWarning = null;
-
+
java.sql.ResultSet initrset = ExecSQL("set datestyle to 'ISO'; select getdatabaseencoding()");
String dbEncoding = null;
@@ -341,19 +341,19 @@ public abstract class Connection
encoding = null;
}
}
-
+
// Initialise object handling
initObjectTypes();
-
+
// Mark the connection as ok, and cleanup
firstWarning = null;
PG_STATUS = CONNECTION_OK;
}
-
+
// 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.
-
+
/**
* This adds a warning to the warning chain.
* @param msg message to add
@@ -361,15 +361,15 @@ public abstract class Connection
public void addWarning(String msg)
{
DriverManager.println(msg);
-
+
// Add the warning to the chain
if(firstWarning!=null)
firstWarning.setNextWarning(new SQLWarning(msg));
else
firstWarning = new SQLWarning(msg);
-
+
// Now check for some specific messages
-
+
// This is obsolete in 6.5, but I've left it in here so if we need to use this
// technique again, we'll know where to place it.
//
@@ -377,13 +377,13 @@ public abstract class Connection
//if(msg.startsWith("NOTICE:") && msg.indexOf("DateStyle")>0) {
//// 13 is the length off "DateStyle is "
//msg = msg.substring(msg.indexOf("DateStyle is ")+13);
- //
+ //
//for(int i=0;i<dateStyles.length;i+=2)
//if(msg.startsWith(dateStyles[i]))
//currentDateStyle=i+1; // this is the index of the format
//}
}
-
+
/**
* Send a query to the backend. Returns one of the ResultSet
* objects.
@@ -404,8 +404,10 @@ public abstract class Connection
// This will let the driver reuse byte arrays that has already
// been allocated instead of allocating new ones in order
// to gain performance improvements.
- pg_stream.deallocate();
-
+ // PM 17/01/01: Commented out due to race bug. See comments in
+ // PG_Stream
+ //pg_stream.deallocate();
+
Field[] fields = null;
Vector tuples = new Vector();
byte[] buf = null;
@@ -415,7 +417,7 @@ public abstract class Connection
int update_count = 1;
int insert_oid = 0;
SQLException final_error = null;
-
+
// Commented out as the backend can now handle queries
// larger than 8K. Peter June 6 2000
//if (sql.length() > 8192)
@@ -441,13 +443,13 @@ public abstract class Connection
} catch (IOException e) {
throw new PSQLException("postgresql.con.ioerror",e);
}
-
+
while (!hfr || fqp > 0)
{
Object tup=null; // holds rows as they are recieved
-
+
int c = pg_stream.ReceiveChar();
-
+
switch (c)
{
case 'A': // Asynchronous Notify
@@ -464,7 +466,7 @@ public abstract class Connection
break;
case 'C': // Command Status
recv_status = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
-
+
// Now handle the update count correctly.
if(recv_status.startsWith("INSERT") || recv_status.startsWith("UPDATE") || recv_status.startsWith("DELETE")) {
try {
@@ -511,7 +513,7 @@ public abstract class Connection
break;
case 'I': // Empty Query
int t = pg_stream.ReceiveChar();
-
+
if (t != 0)
throw new PSQLException("postgresql.con.garbled");
if (fqp > 0)
@@ -538,7 +540,7 @@ public abstract class Connection
}
if (final_error != null)
throw final_error;
-
+
return getResultSet(this, fields, tuples, recv_status, update_count, insert_oid);
}
}
@@ -553,7 +555,7 @@ public abstract class Connection
{
int nf = pg_stream.ReceiveIntegerR(2), i;
Field[] fields = new Field[nf];
-
+
for (i = 0 ; i < nf ; ++i)
{
String typname = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
@@ -564,7 +566,7 @@ public abstract class Connection
}
return fields;
}
-
+
/**
* In SQL, a result table can be retrieved through a cursor that
* is named. The current row of a result can be updated or deleted
@@ -582,7 +584,7 @@ public abstract class Connection
{
this.cursor = cursor;
}
-
+
/**
* getCursorName gets the cursor name.
*
@@ -593,7 +595,7 @@ public abstract class Connection
{
return cursor;
}
-
+
/**
* We are required to bring back certain information by
* the DatabaseMetaData class. These functions do that.
@@ -607,7 +609,7 @@ public abstract class Connection
{
return this_url;
}
-
+
/**
* Method getUserName() brings back the User Name (again, we
* saved it)
@@ -622,13 +624,13 @@ public abstract class Connection
/**
* Get the character encoding to use for this connection.
- * @return the encoding to use, or <b>null</b> for the
+ * @return the encoding to use, or <b>null</b> for the
* default encoding.
*/
public String getEncoding() throws SQLException {
return encoding;
}
-
+
/**
* This returns the Fastpath API for the current connection.
*
@@ -657,10 +659,10 @@ public abstract class Connection
fastpath = new Fastpath(this,pg_stream);
return fastpath;
}
-
+
// This holds a reference to the Fastpath API if already open
private Fastpath fastpath = null;
-
+
/**
* This returns the LargeObject API for the current connection.
*
@@ -686,10 +688,10 @@ public abstract class Connection
largeobject = new LargeObjectManager(this);
return largeobject;
}
-
+
// This holds a reference to the LargeObject API if already open
private LargeObjectManager largeobject = null;
-
+
/**
* This method is used internally to return an object based around
* org.postgresql's more unique data types.
@@ -713,7 +715,7 @@ public abstract class Connection
{
try {
Object o = objectTypes.get(type);
-
+
// If o is null, then the type is unknown, so check to see if type
// is an actual table name. If it does, see if a Class is known that
// can handle it
@@ -722,7 +724,7 @@ public abstract class Connection
objectTypes.put(type,ser);
return ser.fetch(Integer.parseInt(value));
}
-
+
// If o is not null, and it is a String, then its a class name that
// extends PGobject.
//
@@ -748,11 +750,11 @@ public abstract class Connection
} catch(Exception ex) {
throw new PSQLException("postgresql.con.creobj",type,ex);
}
-
+
// should never be reached
return null;
}
-
+
/**
* This stores an object into the database.
* @param o Object to store
@@ -765,7 +767,7 @@ public abstract class Connection
try {
String type = o.getClass().getName();
Object x = objectTypes.get(type);
-
+
// If x is null, then the type is unknown, so check to see if type
// is an actual table name. If it does, see if a Class is known that
// can handle it
@@ -774,15 +776,15 @@ public abstract class Connection
objectTypes.put(type,ser);
return ser.store(o);
}
-
+
// If it's an object, it should be an instance of our Serialize class
// If so, then call it's fetch method.
if(x instanceof Serialize)
return ((Serialize)x).store(o);
-
+
// Thow an exception because the type is unknown
throw new PSQLException("postgresql.con.strobj");
-
+
} catch(SQLException sx) {
// rethrow the exception. Done because we capture any others next
sx.fillInStackTrace();
@@ -791,7 +793,7 @@ public abstract class Connection
throw new PSQLException("postgresql.con.strobjex",ex);
}
}
-
+
/**
* This allows client code to add a handler for one of org.postgresql's
* more unique data types.
@@ -816,10 +818,10 @@ public abstract class Connection
{
objectTypes.put(type,name);
}
-
+
// This holds the available types
private Hashtable objectTypes = new Hashtable();
-
+
// This array contains the types that are supported as standard.
//
// The first entry is the types name on the database, the second
@@ -835,25 +837,25 @@ public abstract class Connection
{"polygon", "org.postgresql.geometric.PGpolygon"},
{"money", "org.postgresql.util.PGmoney"}
};
-
+
// This initialises the objectTypes hashtable
private void initObjectTypes()
{
for(int i=0;i<defaultObjectTypes.length;i++)
objectTypes.put(defaultObjectTypes[i][0],defaultObjectTypes[i][1]);
}
-
+
// These are required by other common classes
public abstract java.sql.Statement createStatement() throws SQLException;
-
+
/**
* This returns a resultset. It must be overridden, so that the correct
* version (from jdbc1 or jdbc2) are returned.
*/
protected abstract java.sql.ResultSet getResultSet(org.postgresql.Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) throws SQLException;
-
+
public abstract void close() throws SQLException;
-
+
/**
* Overides finalize(). If called, it closes the connection.
*
@@ -866,12 +868,33 @@ public abstract class Connection
{
close();
}
-
+
/**
* This is an attempt to implement SQL Escape clauses
*/
public String EscapeSQL(String sql) {
- return sql;
+ //if (DEBUG) { System.out.println ("parseSQLEscapes called"); }
+
+ // If we find a "{d", assume we have a date escape.
+ //
+ // Since the date escape syntax is very close to the
+ // native Postgres date format, we just remove the escape
+ // delimiters.
+ //
+ // This implementation could use some optimization, but it has
+ // worked in practice for two years of solid use.
+ int index = sql.indexOf("{d");
+ while (index != -1) {
+ //System.out.println ("escape found at index: " + index);
+ StringBuffer buf = new StringBuffer(sql);
+ buf.setCharAt(index, ' ');
+ buf.setCharAt(index + 1, ' ');
+ buf.setCharAt(sql.indexOf('}', index), ' ');
+ sql = new String(buf);
+ index = sql.indexOf("{d");
+ }
+ //System.out.println ("modified SQL: " + sql);
+ return sql;
}
-
+
}