diff options
Diffstat (limited to 'src/interfaces/jdbc/postgresql/Connection.java')
-rw-r--r-- | src/interfaces/jdbc/postgresql/Connection.java | 105 |
1 files changed, 38 insertions, 67 deletions
diff --git a/src/interfaces/jdbc/postgresql/Connection.java b/src/interfaces/jdbc/postgresql/Connection.java index 7c565e145fa..31f6e11980e 100644 --- a/src/interfaces/jdbc/postgresql/Connection.java +++ b/src/interfaces/jdbc/postgresql/Connection.java @@ -34,6 +34,9 @@ public class Connection implements java.sql.Connection // This is set by postgresql.Statement.setMaxRows() protected int maxrows = 0; // maximum no. of rows; 0 = unlimited + // This is a cache of the DatabaseMetaData instance for this connection + protected DatabaseMetaData metadata; + private String PG_HOST; private int PG_PORT; private String PG_USER; @@ -44,17 +47,6 @@ public class Connection implements java.sql.Connection public boolean CONNECTION_OK = true; public boolean CONNECTION_BAD = false; - //private static final int STARTUP_LEN = 288; // Length of a startup packet - - // These are defined in src/include/libpq/pqcomm.h - //private int STARTUP_CODE = STARTUP_USER; - //private static final int STARTUP_USER = 7; // User auth - //private static final int STARTUP_KRB4 = 10; // Kerberos 4 (unused) - //private static final int STARTUP_KRB5 = 11; // Kerberos 5 (unused) - //private static final int STARTUP_HBA = 12; // Host Based - //private static final int STARTUP_NONE = 13; // Unauthenticated (unused) - //private static final int STARTUP_PASS = 14; // Password auth - private boolean autoCommit = true; private boolean readOnly = false; @@ -88,12 +80,6 @@ public class Connection implements java.sql.Connection // be across all connections, which could be to different backends. protected Hashtable fieldCache = new Hashtable(); - // 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. - protected Hashtable fieldCache = new Hashtable(); - /** * This is the current date style of the backend */ @@ -150,8 +136,6 @@ public class Connection implements java.sql.Connection */ public Connection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException { - //int len = STARTUP_LEN; // Length of a startup packet - // Throw an exception if the user or password properties are missing // This occasionally occurs when the client uses the properties version // of getConnection(), and is a common question on the email lists @@ -169,30 +153,15 @@ public class Connection implements java.sql.Connection PG_HOST = new String(host); PG_STATUS = CONNECTION_BAD; - // Pre 6.3 code - // This handles the auth property. Any value begining with p enables - // password authentication, while anything begining with i enables - // ident (RFC 1413) authentication. Any other values default to trust. - // - // Also, the postgresql.auth system property can be used to change the - // local default, if the auth property is not present. - // - //String auth = info.getProperty("auth",System.getProperty("postgresql.auth","trust")).toLowerCase(); - //if(auth.startsWith("p")) { - //// Password authentication - //STARTUP_CODE=STARTUP_PASS; - //} else if(auth.startsWith("i")) { - //// Ident (RFC 1413) authentication - //STARTUP_CODE=STARTUP_HBA; - //} else { - //// Anything else defaults to trust authentication - //STARTUP_CODE=STARTUP_USER; - //} - // Now make the initial connection try { pg_stream = new PG_Stream(host, port); + } catch (ConnectException cex) { + // Added by Peter Mount <[email protected]> + // ConnectException is thrown when the connection cannot be made. + // we trap this an return a more meaningful message for the end user + throw new SQLException ("Connection refused. Check that the hostname and port is correct, and that the postmaster is running with the -i flag, which enables TCP/IP networking."); } catch (IOException e) { throw new SQLException ("Connection failed: " + e.toString()); } @@ -200,30 +169,17 @@ public class Connection implements java.sql.Connection // Now we need to construct and send a startup packet try { - // Pre 6.3 code - //pg_stream.SendInteger(len, 4); len -= 4; - //pg_stream.SendInteger(STARTUP_CODE, 4); len -= 4; - //pg_stream.Send(database.getBytes(), 64); len -= 64; - //pg_stream.Send(PG_USER.getBytes(), len); - // - //// Send the password packet if required - //if(STARTUP_CODE == STARTUP_PASS) { - //len=STARTUP_LEN; - //pg_stream.SendInteger(len, 4); len -= 4; - //pg_stream.SendInteger(STARTUP_PASS, 4); len -= 4; - //pg_stream.Send(PG_USER.getBytes(), PG_USER.length()); - //len-=PG_USER.length(); - //pg_stream.SendInteger(0,1); len -= 1; - //pg_stream.Send(PG_PASSWORD.getBytes(), len); - //} - // Ver 6.3 code pg_stream.SendInteger(4+4+SM_DATABASE+SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY,4); 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); - // The last send includes the unused fields + + // 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 @@ -233,6 +189,12 @@ public class Connection implements java.sql.Connection switch(beresp) { case 'E': + // An error occured, so pass the error message to the + // user. + // + // The most common one to be thrown here is: + // "User authentication failed" + // throw new SQLException(pg_stream.ReceiveString(4096)); case 'R': @@ -267,7 +229,7 @@ public class Connection implements java.sql.Connection pg_stream.SendInteger(5+PG_PASSWORD.length(),4); pg_stream.Send(PG_PASSWORD.getBytes()); pg_stream.SendInteger(0,1); - //pg_stream.SendPacket(PG_PASSWORD.getBytes()); + pg_stream.flush(); break; case AUTH_REQ_CRYPT: @@ -276,11 +238,11 @@ public class Connection implements java.sql.Connection pg_stream.SendInteger(5+crypted.length(),4); pg_stream.Send(crypted.getBytes()); pg_stream.SendInteger(0,1); - //pg_stream.SendPacket(UnixCrypt.crypt(salt,PG_PASSWORD).getBytes()); + pg_stream.flush(); break; default: - throw new SQLException("Authentication type "+areq+" not supported"); + throw new SQLException("Authentication type "+areq+" not supported. Check that you have configured the pg_hba.conf file to include the client's IP address or Subnet, and is using a supported authentication scheme."); } break; @@ -511,7 +473,9 @@ public class Connection implements java.sql.Connection */ public java.sql.DatabaseMetaData getMetaData() throws SQLException { - return new DatabaseMetaData(this); + if(metadata==null) + metadata = new DatabaseMetaData(this); + return metadata; } /** @@ -631,8 +595,6 @@ public class Connection implements java.sql.Connection */ public void addWarning(String msg) { - //PrintStream log = DriverManager.getLogStream(); - //if(log!=null) DriverManager.println(msg); // Add the warning to the chain @@ -691,6 +653,7 @@ public class Connection implements java.sql.Connection buf = sql.getBytes(); pg_stream.Send(buf); pg_stream.SendChar(0); + pg_stream.flush(); } catch (IOException e) { throw new SQLException("I/O Error: " + e.toString()); } @@ -726,6 +689,7 @@ public class Connection implements java.sql.Connection pg_stream.SendChar('Q'); pg_stream.SendChar(' '); pg_stream.SendChar(0); + pg_stream.flush(); } catch (IOException e) { throw new SQLException("I/O Error: " + e.toString()); } @@ -964,6 +928,8 @@ public class Connection implements java.sql.Connection return ((Serialize)o).fetch(Integer.parseInt(value)); } } catch(SQLException sx) { + // rethrow the exception. Done because we capture any others next + sx.fillInStackTrace(); throw sx; } catch(Exception ex) { throw new SQLException("Failed to create object for "+type+": "+ex); @@ -999,14 +965,17 @@ public class Connection implements java.sql.Connection // 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 SQLException("The object could not be stored. Check that any tables required have already been created in the database."); + } catch(SQLException sx) { + // rethrow the exception. Done because we capture any others next + sx.fillInStackTrace(); throw sx; } catch(Exception ex) { throw new SQLException("Failed to store object: "+ex); } - - // should never be reached - return 0; } /** @@ -1045,10 +1014,12 @@ public class Connection implements java.sql.Connection private static final String defaultObjectTypes[][] = { {"box", "postgresql.geometric.PGbox"}, {"circle", "postgresql.geometric.PGcircle"}, + {"line", "postgresql.geometric.PGline"}, {"lseg", "postgresql.geometric.PGlseg"}, {"path", "postgresql.geometric.PGpath"}, {"point", "postgresql.geometric.PGpoint"}, - {"polygon", "postgresql.geometric.PGpolygon"} + {"polygon", "postgresql.geometric.PGpolygon"}, + {"money", "postgresql.util.PGmoney"} }; // This initialises the objectTypes hashtable |