From b465f5307f9f5506beb1edbcc0fb56eed7c29c12 Mon Sep 17 00:00:00 2001 From: Barry Lind Date: Tue, 11 Jun 2002 02:55:16 +0000 Subject: [PATCH] The patch does the following: Allows you to set the loglevel at runtime by adding ?loglevel=X to the connection URL, where 1 = INFO and 2 = DEBUG. Automatically turns on logging by calling DriverManager.setPrintWriter(new PrintWriter(System.out)) if one is not already set. Adds a Driver.info() message that prints out the version number Adds member variables logDebug and logInfo that can be checked before making logging methods calls Adds a build number to the version number string. This build number will need to be manually incremented when we see fit. ---------------------------------------------------------------------- Modified Files: org/postgresql/Connection.java org/postgresql/Driver.java.in org/postgresql/fastpath/Fastpath.java org/postgresql/jdbc1/DatabaseMetaData.java org/postgresql/jdbc2/Connection.java org/postgresql/jdbc2/DatabaseMetaData.java org/postgresql/largeobject/LargeObjectManager.java org/postgresql/util/PSQLException.java org/postgresql/util/Serialize.java ---------------------------------------------------------------------- --- src/interfaces/jdbc/org/postgresql/Connection.java | 2461 ++++++++++---------- src/interfaces/jdbc/org/postgresql/Driver.java.in | 124 +- .../jdbc/org/postgresql/fastpath/Fastpath.java | 4 +- .../org/postgresql/jdbc1/DatabaseMetaData.java | 5 +- .../jdbc/org/postgresql/jdbc2/Connection.java | 10 +- .../org/postgresql/jdbc2/DatabaseMetaData.java | 160 +- .../postgresql/largeobject/LargeObjectManager.java | 3 +- .../jdbc/org/postgresql/util/Serialize.java | 23 +- 8 files changed, 1378 insertions(+), 1412 deletions(-) diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java index 96b85c78ce..7951ddd1ec 100644 --- a/src/interfaces/jdbc/org/postgresql/Connection.java +++ b/src/interfaces/jdbc/org/postgresql/Connection.java @@ -1,1215 +1,1246 @@ -package org.postgresql; - -import java.io.*; -import java.net.*; -import java.sql.*; -import java.util.*; -import org.postgresql.Driver; -import org.postgresql.Field; -import org.postgresql.fastpath.*; -import org.postgresql.largeobject.*; -import org.postgresql.util.*; -import org.postgresql.core.*; - -/* - * $Id: Connection.java,v 1.47 2002/05/17 01:19:19 tgl Exp $ - * - * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or - * JDBC2 versions of the Connection class. - * - */ -public abstract class Connection -{ - // This is the network stream associated with this connection - public PG_Stream pg_stream; - - private String PG_HOST; - private int PG_PORT; - private String PG_USER; - private String PG_DATABASE; - private boolean PG_STATUS; - private String compatible; - - /* - The encoding to use for this connection. - */ - private Encoding encoding = Encoding.defaultEncoding(); - - private String dbVersionNumber; - - 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 - protected static final int PG_PROTOCOL_LATEST_MAJOR = 2; - protected static final int PG_PROTOCOL_LATEST_MINOR = 0; - - 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; - private static final int AUTH_REQ_MD5 = 5; - - - // These are used to cache oids, PGTypes and SQLTypes - private static Hashtable sqlTypeCache = new Hashtable(); // oid -> SQLType - private static Hashtable pgTypeCache = new Hashtable(); // oid -> PGType - private static Hashtable typeOidCache = new Hashtable(); //PGType -> oid - - // Now handle notices as warnings, so things like "show" now work - public SQLWarning firstWarning = null; - - /* - * Cache of the current isolation level - */ - private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED; - - // The PID an cancellation key we get from the backend process - public int pid; - public int ckey; - - /* - * This is called by Class.forName() from within org.postgresql.Driver - */ - public Connection() - {} - - public void cancelQuery() throws SQLException - { - PG_Stream cancelStream = null; - try { - cancelStream = new PG_Stream(PG_HOST, PG_PORT); - } catch (ConnectException cex) { - // Added by Peter Mount - // ConnectException is thrown when the connection cannot be made. - // we trap this an return a more meaningful message for the end user - throw new PSQLException ("postgresql.con.refused"); - } catch (IOException e) { - throw new PSQLException ("postgresql.con.failed",e); - } - - // Now we need to construct and send a cancel packet - try { - cancelStream.SendInteger(16, 4); - cancelStream.SendInteger(80877102, 4); - cancelStream.SendInteger(pid, 4); - cancelStream.SendInteger(ckey, 4); - cancelStream.flush(); - } - catch(IOException e) { - throw new PSQLException("postgresql.con.failed",e); - } - finally { - try { - if(cancelStream != null) - cancelStream.close(); - } - catch(IOException e) {} // Ignore - } - } - - /* - * This method actually opens the connection. It is called by Driver. - * - * @param host the hostname of the database back end - * @param port the port number of the postmaster process - * @param info a Properties[] thing of the user and password - * @param database the database to connect to - * @param u the URL of the connection - * @param d the Driver instantation of the connection - * @return a valid connection profile - * @exception SQLException if a database access error occurs - */ - protected void openConnection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException - { - firstWarning = null; - - // 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 - if (info.getProperty("user") == null) - throw new PSQLException("postgresql.con.user"); - - this_driver = d; - this_url = url; - - PG_DATABASE = database; - PG_USER = info.getProperty("user"); - - String password = info.getProperty("password", ""); - PG_PORT = port; - - PG_HOST = host; - PG_STATUS = CONNECTION_BAD; - - if (info.getProperty("compatible") == null) - { - compatible = d.getMajorVersion() + "." + d.getMinorVersion(); - } - else - { - compatible = info.getProperty("compatible"); - } - - // Now make the initial connection - try - { - pg_stream = new PG_Stream(host, port); - } - catch (ConnectException cex) - { - // Added by Peter Mount - // ConnectException is thrown when the connection cannot be made. - // we trap this an return a more meaningful message for the end user - throw new PSQLException ("postgresql.con.refused"); - } - catch (IOException e) - { - throw new PSQLException ("postgresql.con.failed", e); - } - - // Now we need to construct and send a startup packet - try - { - new StartupPacket(PG_PROTOCOL_LATEST_MAJOR, - PG_PROTOCOL_LATEST_MINOR, - PG_USER, - database).writeTo(pg_stream); - - // 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 - do - { - int beresp = pg_stream.ReceiveChar(); - String salt = null; - 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 PSQLException("postgresql.con.misc", pg_stream.ReceiveString(encoding)); - - case 'R': - // Get the type of request - areq = pg_stream.ReceiveIntegerR(4); - // Get the crypt password salt if there is one - if (areq == AUTH_REQ_CRYPT) - { - byte[] rst = new byte[2]; - rst[0] = (byte)pg_stream.ReceiveChar(); - rst[1] = (byte)pg_stream.ReceiveChar(); - salt = new String(rst, 0, 2); - Driver.debug("Crypt salt=" + salt); - } - - // Or get the md5 password salt if there is one - if (areq == AUTH_REQ_MD5) - { - byte[] rst = new byte[4]; - rst[0] = (byte)pg_stream.ReceiveChar(); - rst[1] = (byte)pg_stream.ReceiveChar(); - rst[2] = (byte)pg_stream.ReceiveChar(); - rst[3] = (byte)pg_stream.ReceiveChar(); - salt = new String(rst, 0, 4); - Driver.debug("MD5 salt=" + salt); - } - - // now send the auth packet - switch (areq) - { - case AUTH_REQ_OK: - break; - - case AUTH_REQ_KRB4: - Driver.debug("postgresql: KRB4"); - throw new PSQLException("postgresql.con.kerb4"); - - case AUTH_REQ_KRB5: - Driver.debug("postgresql: KRB5"); - throw new PSQLException("postgresql.con.kerb5"); - - case AUTH_REQ_PASSWORD: - Driver.debug("postgresql: PASSWORD"); - pg_stream.SendInteger(5 + password.length(), 4); - pg_stream.Send(password.getBytes()); - pg_stream.SendInteger(0, 1); - pg_stream.flush(); - break; - - case AUTH_REQ_CRYPT: - Driver.debug("postgresql: CRYPT"); - String crypted = UnixCrypt.crypt(salt, password); - pg_stream.SendInteger(5 + crypted.length(), 4); - pg_stream.Send(crypted.getBytes()); - pg_stream.SendInteger(0, 1); - pg_stream.flush(); - break; - - case AUTH_REQ_MD5: - Driver.debug("postgresql: MD5"); - byte[] digest = MD5Digest.encode(PG_USER, password, salt); - pg_stream.SendInteger(5 + digest.length, 4); - pg_stream.Send(digest); - 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; - do { - beresp = pg_stream.ReceiveChar(); - switch (beresp) - { - case 'K': - pid = pg_stream.ReceiveIntegerR(4); - ckey = pg_stream.ReceiveIntegerR(4); - break; - case 'E': - throw new PSQLException("postgresql.con.backend", pg_stream.ReceiveString(encoding)); - case 'N': - addWarning(pg_stream.ReceiveString(encoding)); - break; - default: - throw new PSQLException("postgresql.con.setup"); - } - } while (beresp == 'N'); - - // Expect ReadyForQuery packet - do { - beresp = pg_stream.ReceiveChar(); - switch (beresp) - { - case 'Z': - break; - case 'N': - addWarning(pg_stream.ReceiveString(encoding)); - break; - case 'E': - throw new PSQLException("postgresql.con.backend", pg_stream.ReceiveString(encoding)); - default: - throw new PSQLException("postgresql.con.setup"); - } - } while (beresp == 'N'); - // "pg_encoding_to_char(1)" will return 'EUC_JP' for a backend compiled with multibyte, - // otherwise it's hardcoded to 'SQL_ASCII'. - // If the backend doesn't know about multibyte we can't assume anything about the encoding - // used, so we denote this with 'UNKNOWN'. - //Note: begining with 7.2 we should be using pg_client_encoding() which - //is new in 7.2. However it isn't easy to conditionally call this new - //function, since we don't yet have the information as to what server - //version we are talking to. Thus we will continue to call - //getdatabaseencoding() until we drop support for 7.1 and older versions - //or until someone comes up with a conditional way to run one or - //the other function depending on server version that doesn't require - //two round trips to the server per connection - - final String encodingQuery = - "case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else getdatabaseencoding() end"; - - // 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 + ";"); - - if (! resultSet.next()) - { - throw new PSQLException("postgresql.con.failed", "failed getting backend encoding"); - } - String version = resultSet.getString(1); - dbVersionNumber = extractVersionNumber(version); - - String dbEncoding = resultSet.getString(2); - encoding = Encoding.getEncoding(dbEncoding, info.getProperty("charSet")); - - // Initialise object handling - initObjectTypes(); - - // Mark the connection as ok, and cleanup - 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 - */ - public void addWarning(String 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. - // - // This is generated by the SQL "show datestyle" - //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;iNote: 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 - */ - public java.sql.ResultSet ExecSQL(String sql) throws SQLException - { - return ExecSQL(sql, null); - } - - /* - * Send a query to the backend. Returns one of the ResultSet - * objects. - * - * Note: 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 - { - return new QueryExecutor(sql, stat, pg_stream, this).execute(); - } - - /* - * 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 - * using a positioned update/delete statement that references the - * cursor name. - * - * We support one cursor per connection. - * - * setCursorName sets the cursor name. - * - * @param cursor the cursor name - * @exception SQLException if a database access error occurs - */ - public void setCursorName(String cursor) throws SQLException - { - this.cursor = cursor; - } - - /* - * getCursorName gets the cursor name. - * - * @return the current cursor name - * @exception SQLException if a database access error occurs - */ - public String getCursorName() throws SQLException - { - return cursor; - } - - /* - * We are required to bring back certain information by - * the DatabaseMetaData class. These functions do that. - * - * Method getURL() brings back the URL (good job we saved it) - * - * @return the url - * @exception SQLException just in case... - */ - public String getURL() throws SQLException - { - return this_url; - } - - /* - * Method getUserName() brings back the User Name (again, we - * saved it) - * - * @return the user name - * @exception SQLException just in case... - */ - int lastMessage = 0; - public String getUserName() throws SQLException - { - return PG_USER; - } - - /* - * Get the character encoding to use for this connection. - */ - public Encoding getEncoding() throws SQLException - { - return encoding; - } - - /* - * This returns the Fastpath API for the current connection. - * - *

NOTE: This is not part of JDBC, but allows access to - * functions on the org.postgresql backend itself. - * - *

It is primarily used by the LargeObject API - * - *

The best way to use this is as follows: - * - *

-         * import org.postgresql.fastpath.*;
-         * ...
-         * Fastpath fp = ((org.postgresql.Connection)myconn).getFastpathAPI();
-         * 
- * - *

where myconn is an open Connection to org.postgresql. - * - * @return Fastpath object allowing access to functions on the org.postgresql - * backend. - * @exception SQLException by Fastpath when initialising for first time - */ - public Fastpath getFastpathAPI() throws SQLException - { - if (fastpath == null) - 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. - * - *

NOTE: This is not part of JDBC, but allows access to - * functions on the org.postgresql backend itself. - * - *

The best way to use this is as follows: - * - *

-         * import org.postgresql.largeobject.*;
-         * ...
-         * LargeObjectManager lo = ((org.postgresql.Connection)myconn).getLargeObjectAPI();
-         * 
- * - *

where myconn is an open Connection to org.postgresql. - * - * @return LargeObject object that implements the API - * @exception SQLException by LargeObject when initialising for first time - */ - public LargeObjectManager getLargeObjectAPI() throws SQLException - { - if (largeobject == null) - 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. - * - *

It uses an internal Hashtable to get the handling class. If the - * type is not supported, then an instance of org.postgresql.util.PGobject - * is returned. - * - * You can use the getValue() or setValue() methods to handle the returned - * object. Custom objects can have their own methods. - * - * In 6.4, this is extended to use the org.postgresql.util.Serialize class to - * allow the Serialization of Java Objects into the database without using - * Blobs. Refer to that class for details on how this new feature works. - * - * @return PGobject for this type, and set to value - * @exception SQLException if value is not correct for this type - * @see org.postgresql.util.Serialize - */ - public Object getObject(String type, String value) throws SQLException - { - 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 - if (o == null) - { - Serialize ser = new Serialize(this, type); - 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. - // - // This is used to implement the org.postgresql unique types (like lseg, - // point, etc). - if (o instanceof String) - { - // 6.3 style extending PG_Object - PGobject obj = null; - obj = (PGobject)(Class.forName((String)o).newInstance()); - obj.setType(type); - obj.setValue(value); - return (Object)obj; - } - else - { - // If it's an object, it should be an instance of our Serialize class - // If so, then call it's fetch method. - if (o instanceof Serialize) - 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 PSQLException("postgresql.con.creobj", type, ex); - } - - // should never be reached - return null; - } - - /* - * This stores an object into the database. This method was - * deprecated in 7.2 bacause an OID can be larger than the java signed - * int returned by this method. - * @deprecated Replaced by storeObject() in 7.2 - */ - public int putObject(Object o) throws SQLException - { - return (int) storeObject(o); - } - - /* - * This stores an object into the database. - * @param o Object to store - * @return OID of the new rectord - * @exception SQLException if value is not correct for this type - * @see org.postgresql.util.Serialize - * @since 7.2 - */ - public long storeObject(Object o) throws SQLException - { - 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 - if (x == null) - { - Serialize ser = new Serialize(this, type); - objectTypes.put(type, ser); - return ser.storeObject(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).storeObject(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(); - throw sx; - } - catch (Exception ex) - { - 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. - * - *

NOTE: This is not part of JDBC, but an extension. - * - *

The best way to use this is as follows: - * - *

-         * ...
-         * ((org.postgresql.Connection)myconn).addDataType("mytype","my.class.name");
-         * ...
-         * 
- * - *

where myconn is an open Connection to org.postgresql. - * - *

The handling class must extend org.postgresql.util.PGobject - * - * @see org.postgresql.util.PGobject - */ - public void addDataType(String type, String name) - { - 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 - // the full class name of the handling class. - // - private static final String defaultObjectTypes[][] = { - {"box", "org.postgresql.geometric.PGbox"}, - {"circle", "org.postgresql.geometric.PGcircle"}, - {"line", "org.postgresql.geometric.PGline"}, - {"lseg", "org.postgresql.geometric.PGlseg"}, - {"path", "org.postgresql.geometric.PGpath"}, - {"point", "org.postgresql.geometric.PGpoint"}, - {"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. - */ - public abstract java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException; - - /* - * In some cases, it is desirable to immediately release a Connection's - * database and JDBC resources instead of waiting for them to be - * automatically released (cant think why off the top of my head) - * - * Note: A Connection is automatically closed when it is - * garbage collected. Certain fatal errors also result in a closed - * connection. - * - * @exception SQLException if a database access error occurs - */ - public void close() throws SQLException - { - if (pg_stream != null) - { - try - { - pg_stream.SendChar('X'); - pg_stream.flush(); - pg_stream.close(); - } - catch (IOException e) - {} - pg_stream = null; - } - } - - /* - * A driver may convert the JDBC sql grammar into its system's - * native SQL grammar prior to sending it; nativeSQL returns the - * native form of the statement that the driver would have sent. - * - * @param sql a SQL statement that may contain one or more '?' - * parameter placeholders - * @return the native form of this statement - * @exception SQLException if a database access error occurs - */ - public String nativeSQL(String sql) throws SQLException - { - return sql; - } - - /* - * The first warning reported by calls on this Connection is - * returned. - * - * Note: Sebsequent warnings will be changed to this - * SQLWarning - * - * @return the first SQLWarning or null - * @exception SQLException if a database access error occurs - */ - public SQLWarning getWarnings() throws SQLException - { - return firstWarning; - } - - /* - * After this call, getWarnings returns null until a new warning - * is reported for this connection. - * - * @exception SQLException if a database access error occurs - */ - public void clearWarnings() throws SQLException - { - firstWarning = null; - } - - - /* - * You can put a connection in read-only mode as a hunt to enable - * database optimizations - * - * Note: setReadOnly cannot be called while in the middle - * of a transaction - * - * @param readOnly - true enables read-only mode; false disables it - * @exception SQLException if a database access error occurs - */ - public void setReadOnly(boolean readOnly) throws SQLException - { - this.readOnly = readOnly; - } - - /* - * Tests to see if the connection is in Read Only Mode. Note that - * we cannot really put the database in read only mode, but we pretend - * we can by returning the value of the readOnly flag - * - * @return true if the connection is read only - * @exception SQLException if a database access error occurs - */ - public boolean isReadOnly() throws SQLException - { - return readOnly; - } - - /* - * If a connection is in auto-commit mode, than all its SQL - * statements will be executed and committed as individual - * transactions. Otherwise, its SQL statements are grouped - * into transactions that are terminated by either commit() - * or rollback(). By default, new connections are in auto- - * commit mode. The commit occurs when the statement completes - * or the next execute occurs, whichever comes first. In the - * case of statements returning a ResultSet, the statement - * completes when the last row of the ResultSet has been retrieved - * or the ResultSet has been closed. In advanced cases, a single - * statement may return multiple results as well as output parameter - * values. Here the commit occurs when all results and output param - * values have been retrieved. - * - * @param autoCommit - true enables auto-commit; false disables it - * @exception SQLException if a database access error occurs - */ - public void setAutoCommit(boolean autoCommit) throws SQLException - { - if (this.autoCommit == autoCommit) - return; - if (autoCommit) - ExecSQL("end"); - else - { - if (haveMinimumServerVersion("7.1")) - { - ExecSQL("begin;" + getIsolationLevelSQL()); - } - else - { - ExecSQL("begin"); - ExecSQL(getIsolationLevelSQL()); - } - } - this.autoCommit = autoCommit; - } - - /* - * gets the current auto-commit state - * - * @return Current state of the auto-commit mode - * @exception SQLException (why?) - * @see setAutoCommit - */ - public boolean getAutoCommit() throws SQLException - { - return this.autoCommit; - } - - /* - * The method commit() makes all changes made since the previous - * commit/rollback permanent and releases any database locks currently - * held by the Connection. This method should only be used when - * auto-commit has been disabled. (If autoCommit == true, then we - * just return anyhow) - * - * @exception SQLException if a database access error occurs - * @see setAutoCommit - */ - public void commit() throws SQLException - { - if (autoCommit) - return; - if (haveMinimumServerVersion("7.1")) - { - ExecSQL("commit;begin;" + getIsolationLevelSQL()); - } - else - { - ExecSQL("commit"); - ExecSQL("begin"); - ExecSQL(getIsolationLevelSQL()); - } - } - - /* - * The method rollback() drops all changes made since the previous - * commit/rollback and releases any database locks currently held by - * the Connection. - * - * @exception SQLException if a database access error occurs - * @see commit - */ - public void rollback() throws SQLException - { - if (autoCommit) - return; - if (haveMinimumServerVersion("7.1")) - { - ExecSQL("rollback; begin;" + getIsolationLevelSQL()); - } - else - { - ExecSQL("rollback"); - ExecSQL("begin"); - ExecSQL(getIsolationLevelSQL()); - } - } - - /* - * Get this Connection's current transaction isolation mode. - * - * @return the current TRANSACTION_* mode value - * @exception SQLException if a database access error occurs - */ - public int getTransactionIsolation() throws SQLException - { - clearWarnings(); - ExecSQL("show transaction isolation level"); - - SQLWarning warning = getWarnings(); - if (warning != null) - { - String message = warning.getMessage(); - clearWarnings(); - if (message.indexOf("READ COMMITTED") != -1) - return java.sql.Connection.TRANSACTION_READ_COMMITTED; - else if (message.indexOf("READ UNCOMMITTED") != -1) - return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; - else if (message.indexOf("REPEATABLE READ") != -1) - return java.sql.Connection.TRANSACTION_REPEATABLE_READ; - else if (message.indexOf("SERIALIZABLE") != -1) - return java.sql.Connection.TRANSACTION_SERIALIZABLE; - } - return java.sql.Connection.TRANSACTION_READ_COMMITTED; - } - - /* - * You can call this method to try to change the transaction - * isolation level using one of the TRANSACTION_* values. - * - * Note: setTransactionIsolation cannot be called while - * in the middle of a transaction - * - * @param level one of the TRANSACTION_* isolation values with - * the exception of TRANSACTION_NONE; some databases may - * not support other values - * @exception SQLException if a database access error occurs - * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel - */ - public void setTransactionIsolation(int level) throws SQLException - { - //In 7.1 and later versions of the server it is possible using - //the "set session" command to set this once for all future txns - //however in 7.0 and prior versions it is necessary to set it in - //each transaction, thus adding complexity below. - //When we decide to drop support for servers older than 7.1 - //this can be simplified - isolationLevel = level; - String isolationLevelSQL; - - if (!haveMinimumServerVersion("7.1")) - { - isolationLevelSQL = getIsolationLevelSQL(); - } - else - { - isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL "; - switch (isolationLevel) - { - case java.sql.Connection.TRANSACTION_READ_COMMITTED: - isolationLevelSQL += "READ COMMITTED"; - break; - case java.sql.Connection.TRANSACTION_SERIALIZABLE: - isolationLevelSQL += "SERIALIZABLE"; - break; - default: - throw new PSQLException("postgresql.con.isolevel", - new Integer(isolationLevel)); - } - } - ExecSQL(isolationLevelSQL); - } - - /* - * Helper method used by setTransactionIsolation(), commit(), rollback() - * and setAutoCommit(). This returns the SQL string needed to - * set the isolation level for a transaction. In 7.1 and later it - * is possible to set a default isolation level that applies to all - * future transactions, this method is only necesary for 7.0 and older - * servers, and should be removed when support for these older - * servers are dropped - */ - protected String getIsolationLevelSQL() throws SQLException - { - //7.1 and higher servers have a default specified so - //no additional SQL is required to set the isolation level - if (haveMinimumServerVersion("7.1")) - { - return ""; - } - StringBuffer sb = new StringBuffer("SET TRANSACTION ISOLATION LEVEL"); - - switch (isolationLevel) - { - case java.sql.Connection.TRANSACTION_READ_COMMITTED: - sb.append(" READ COMMITTED"); - break; - - case java.sql.Connection.TRANSACTION_SERIALIZABLE: - sb.append(" SERIALIZABLE"); - break; - - default: - throw new PSQLException("postgresql.con.isolevel", new Integer(isolationLevel)); - } - return sb.toString(); - } - - /* - * A sub-space of this Connection's database may be selected by - * setting a catalog name. If the driver does not support catalogs, - * it will silently ignore this request - * - * @exception SQLException if a database access error occurs - */ - public void setCatalog(String catalog) throws SQLException - { - //no-op - } - - /* - * Return the connections current catalog name, or null if no - * catalog name is set, or we dont support catalogs. - * - * @return the current catalog name or null - * @exception SQLException if a database access error occurs - */ - public String getCatalog() throws SQLException - { - return PG_DATABASE; - } - - /* - * Overides finalize(). If called, it closes the connection. - * - * This was done at the request of Rachel Greenham - * who hit a problem where multiple - * clients didn't close the connection, and once a fortnight enough - * clients were open to kill the org.postgres server. - */ - public void finalize() throws Throwable - { - close(); - } - - private static String extractVersionNumber(String fullVersionString) - { - StringTokenizer versionParts = new StringTokenizer(fullVersionString); - versionParts.nextToken(); /* "PostgreSQL" */ - return versionParts.nextToken(); /* "X.Y.Z" */ - } - - /* - * Get server version number - */ - public String getDBVersionNumber() - { - return dbVersionNumber; - } - - public boolean haveMinimumServerVersion(String ver) throws SQLException - { - return (getDBVersionNumber().compareTo(ver) >= 0); - } - - /* - * This method returns true if the compatible level set in the connection - * (which can be passed into the connection or specified in the URL) - * is at least the value passed to this method. This is used to toggle - * between different functionality as it changes across different releases - * of the jdbc driver code. The values here are versions of the jdbc client - * and not server versions. For example in 7.1 get/setBytes worked on - * LargeObject values, in 7.2 these methods were changed to work on bytea - * values. This change in functionality could be disabled by setting the - * "compatible" level to be 7.1, in which case the driver will revert to - * the 7.1 functionality. - */ - public boolean haveMinimumCompatibleVersion(String ver) throws SQLException - { - return (compatible.compareTo(ver) >= 0); - } - - - /* - * This returns the java.sql.Types type for a PG type oid - * - * @param oid PostgreSQL type oid - * @return the java.sql.Types type - * @exception SQLException if a database access error occurs - */ - public int getSQLType(int oid) throws SQLException - { - Integer sqlType = (Integer)sqlTypeCache.get(new Integer(oid)); - - // it's not in the cache, so perform a query, and add the result to the cache - if (sqlType == null) - { - ResultSet result = (org.postgresql.ResultSet)ExecSQL("select typname from pg_type where oid = " + oid); - if (result.getColumnCount() != 1 || result.getTupleCount() != 1) - throw new PSQLException("postgresql.unexpected"); - result.next(); - String pgType = result.getString(1); - Integer iOid = new Integer(oid); - sqlType = new Integer(getSQLType(result.getString(1))); - sqlTypeCache.put(iOid, sqlType); - pgTypeCache.put(iOid, pgType); - result.close(); - } - - return sqlType.intValue(); - } - - /* - * This returns the java.sql.Types type for a PG type - * - * @param pgTypeName PostgreSQL type name - * @return the java.sql.Types type - */ - public abstract int getSQLType(String pgTypeName); - - /* - * This returns the oid for a given PG data type - * @param typeName PostgreSQL type name - * @return PostgreSQL oid value for a field of this type - */ - public int getOID(String typeName) throws SQLException - { - int oid = -1; - if (typeName != null) - { - Integer oidValue = (Integer) typeOidCache.get(typeName); - if (oidValue != null) - { - oid = oidValue.intValue(); - } - else - { - // it's not in the cache, so perform a query, and add the result to the cache - ResultSet result = (org.postgresql.ResultSet)ExecSQL("select oid from pg_type where typname='" - + typeName + "'"); - if (result.getColumnCount() != 1 || result.getTupleCount() != 1) - throw new PSQLException("postgresql.unexpected"); - result.next(); - oid = Integer.parseInt(result.getString(1)); - typeOidCache.put(typeName, new Integer(oid)); - result.close(); - } - } - return oid; - } - - /* - * We also need to get the PG type name as returned by the back end. - * - * @return the String representation of the type of this field - * @exception SQLException if a database access error occurs - */ - public String getPGType(int oid) throws SQLException - { - String pgType = (String) pgTypeCache.get(new Integer(oid)); - if (pgType == null) - { - getSQLType(oid); - pgType = (String) pgTypeCache.get(new Integer(oid)); - } - return pgType; - } -} - +package org.postgresql; + +import java.io.*; +import java.net.*; +import java.sql.*; +import java.util.*; +import org.postgresql.Driver; +import org.postgresql.Field; +import org.postgresql.fastpath.*; +import org.postgresql.largeobject.*; +import org.postgresql.util.*; +import org.postgresql.core.*; + +/* + * $Id: Connection.java,v 1.48 2002/06/11 02:55:15 barry Exp $ + * + * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or + * JDBC2 versions of the Connection class. + * + */ +public abstract class Connection +{ + // This is the network stream associated with this connection + public PG_Stream pg_stream; + + private String PG_HOST; + private int PG_PORT; + private String PG_USER; + private String PG_DATABASE; + private boolean PG_STATUS; + private String compatible; + + /* + The encoding to use for this connection. + */ + private Encoding encoding = Encoding.defaultEncoding(); + + private String dbVersionNumber; + + 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 + protected static final int PG_PROTOCOL_LATEST_MAJOR = 2; + protected static final int PG_PROTOCOL_LATEST_MINOR = 0; + + 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; + private static final int AUTH_REQ_MD5 = 5; + + + // These are used to cache oids, PGTypes and SQLTypes + private static Hashtable sqlTypeCache = new Hashtable(); // oid -> SQLType + private static Hashtable pgTypeCache = new Hashtable(); // oid -> PGType + private static Hashtable typeOidCache = new Hashtable(); //PGType -> oid + + // Now handle notices as warnings, so things like "show" now work + public SQLWarning firstWarning = null; + + /* + * Cache of the current isolation level + */ + private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED; + + // The PID an cancellation key we get from the backend process + public int pid; + public int ckey; + + /* + * This is called by Class.forName() from within org.postgresql.Driver + */ + public Connection() + {} + + public void cancelQuery() throws SQLException + { + PG_Stream cancelStream = null; + try { + cancelStream = new PG_Stream(PG_HOST, PG_PORT); + } catch (ConnectException cex) { + // Added by Peter Mount + // ConnectException is thrown when the connection cannot be made. + // we trap this an return a more meaningful message for the end user + throw new PSQLException ("postgresql.con.refused"); + } catch (IOException e) { + throw new PSQLException ("postgresql.con.failed",e); + } + + // Now we need to construct and send a cancel packet + try { + cancelStream.SendInteger(16, 4); + cancelStream.SendInteger(80877102, 4); + cancelStream.SendInteger(pid, 4); + cancelStream.SendInteger(ckey, 4); + cancelStream.flush(); + } + catch(IOException e) { + throw new PSQLException("postgresql.con.failed",e); + } + finally { + try { + if(cancelStream != null) + cancelStream.close(); + } + catch(IOException e) {} // Ignore + } + } + + /* + * This method actually opens the connection. It is called by Driver. + * + * @param host the hostname of the database back end + * @param port the port number of the postmaster process + * @param info a Properties[] thing of the user and password + * @param database the database to connect to + * @param u the URL of the connection + * @param d the Driver instantation of the connection + * @return a valid connection profile + * @exception SQLException if a database access error occurs + */ + protected void openConnection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException + { + firstWarning = null; + + // 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 + if (info.getProperty("user") == null) + throw new PSQLException("postgresql.con.user"); + + this_driver = d; + this_url = url; + + PG_DATABASE = database; + PG_USER = info.getProperty("user"); + + String password = info.getProperty("password", ""); + PG_PORT = port; + + PG_HOST = host; + PG_STATUS = CONNECTION_BAD; + + if (info.getProperty("compatible") == null) + { + compatible = d.getMajorVersion() + "." + d.getMinorVersion(); + } + else + { + compatible = info.getProperty("compatible"); + } + + //Read loglevel arg and set the loglevel based on this value + //in addition to setting the log level enable output to + //standard out if no other printwriter is set + String l_logLevelProp = info.getProperty("loglevel","0"); + int l_logLevel = 0; + try { + l_logLevel = Integer.parseInt(l_logLevelProp); + if (l_logLevel > Driver.DEBUG || l_logLevel < Driver.INFO) { + l_logLevel = 0; + } + } catch (Exception l_e) { + //invalid value for loglevel ignore + } + if (l_logLevel > 0) { + Driver.setLogLevel(l_logLevel); + enableDriverManagerLogging(); + } + + //Print out the driver version number + if (Driver.logInfo) Driver.info(Driver.getVersion()); + + // Now make the initial connection + try + { + pg_stream = new PG_Stream(host, port); + } + catch (ConnectException cex) + { + // Added by Peter Mount + // ConnectException is thrown when the connection cannot be made. + // we trap this an return a more meaningful message for the end user + throw new PSQLException ("postgresql.con.refused"); + } + catch (IOException e) + { + throw new PSQLException ("postgresql.con.failed", e); + } + + // Now we need to construct and send a startup packet + try + { + new StartupPacket(PG_PROTOCOL_LATEST_MAJOR, + PG_PROTOCOL_LATEST_MINOR, + PG_USER, + database).writeTo(pg_stream); + + // 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 + do + { + int beresp = pg_stream.ReceiveChar(); + String salt = null; + 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 PSQLException("postgresql.con.misc", pg_stream.ReceiveString(encoding)); + + case 'R': + // Get the type of request + areq = pg_stream.ReceiveIntegerR(4); + // Get the crypt password salt if there is one + if (areq == AUTH_REQ_CRYPT) + { + byte[] rst = new byte[2]; + rst[0] = (byte)pg_stream.ReceiveChar(); + rst[1] = (byte)pg_stream.ReceiveChar(); + salt = new String(rst, 0, 2); + if (Driver.logDebug) Driver.debug("Crypt salt=" + salt); + } + + // Or get the md5 password salt if there is one + if (areq == AUTH_REQ_MD5) + { + byte[] rst = new byte[4]; + rst[0] = (byte)pg_stream.ReceiveChar(); + rst[1] = (byte)pg_stream.ReceiveChar(); + rst[2] = (byte)pg_stream.ReceiveChar(); + rst[3] = (byte)pg_stream.ReceiveChar(); + salt = new String(rst, 0, 4); + if (Driver.logDebug) Driver.debug("MD5 salt=" + salt); + } + + // now send the auth packet + switch (areq) + { + case AUTH_REQ_OK: + break; + + case AUTH_REQ_KRB4: + if (Driver.logDebug) Driver.debug("postgresql: KRB4"); + throw new PSQLException("postgresql.con.kerb4"); + + case AUTH_REQ_KRB5: + if (Driver.logDebug) Driver.debug("postgresql: KRB5"); + throw new PSQLException("postgresql.con.kerb5"); + + case AUTH_REQ_PASSWORD: + if (Driver.logDebug) Driver.debug("postgresql: PASSWORD"); + pg_stream.SendInteger(5 + password.length(), 4); + pg_stream.Send(password.getBytes()); + pg_stream.SendInteger(0, 1); + pg_stream.flush(); + break; + + case AUTH_REQ_CRYPT: + if (Driver.logDebug) Driver.debug("postgresql: CRYPT"); + String crypted = UnixCrypt.crypt(salt, password); + pg_stream.SendInteger(5 + crypted.length(), 4); + pg_stream.Send(crypted.getBytes()); + pg_stream.SendInteger(0, 1); + pg_stream.flush(); + break; + + case AUTH_REQ_MD5: + if (Driver.logDebug) Driver.debug("postgresql: MD5"); + byte[] digest = MD5Digest.encode(PG_USER, password, salt); + pg_stream.SendInteger(5 + digest.length, 4); + pg_stream.Send(digest); + 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; + do { + beresp = pg_stream.ReceiveChar(); + switch (beresp) + { + case 'K': + pid = pg_stream.ReceiveIntegerR(4); + ckey = pg_stream.ReceiveIntegerR(4); + break; + case 'E': + throw new PSQLException("postgresql.con.backend", pg_stream.ReceiveString(encoding)); + case 'N': + addWarning(pg_stream.ReceiveString(encoding)); + break; + default: + throw new PSQLException("postgresql.con.setup"); + } + } while (beresp == 'N'); + + // Expect ReadyForQuery packet + do { + beresp = pg_stream.ReceiveChar(); + switch (beresp) + { + case 'Z': + break; + case 'N': + addWarning(pg_stream.ReceiveString(encoding)); + break; + case 'E': + throw new PSQLException("postgresql.con.backend", pg_stream.ReceiveString(encoding)); + default: + throw new PSQLException("postgresql.con.setup"); + } + } while (beresp == 'N'); + // "pg_encoding_to_char(1)" will return 'EUC_JP' for a backend compiled with multibyte, + // otherwise it's hardcoded to 'SQL_ASCII'. + // If the backend doesn't know about multibyte we can't assume anything about the encoding + // used, so we denote this with 'UNKNOWN'. + //Note: begining with 7.2 we should be using pg_client_encoding() which + //is new in 7.2. However it isn't easy to conditionally call this new + //function, since we don't yet have the information as to what server + //version we are talking to. Thus we will continue to call + //getdatabaseencoding() until we drop support for 7.1 and older versions + //or until someone comes up with a conditional way to run one or + //the other function depending on server version that doesn't require + //two round trips to the server per connection + + final String encodingQuery = + "case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else getdatabaseencoding() end"; + + // 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 + ";"); + + if (! resultSet.next()) + { + throw new PSQLException("postgresql.con.failed", "failed getting backend encoding"); + } + String version = resultSet.getString(1); + dbVersionNumber = extractVersionNumber(version); + + String dbEncoding = resultSet.getString(2); + encoding = Encoding.getEncoding(dbEncoding, info.getProperty("charSet")); + + // Initialise object handling + initObjectTypes(); + + // Mark the connection as ok, and cleanup + 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 + */ + public void addWarning(String 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. + // + // This is generated by the SQL "show datestyle" + //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;iNote: 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 + */ + public java.sql.ResultSet ExecSQL(String sql) throws SQLException + { + return ExecSQL(sql, null); + } + + /* + * Send a query to the backend. Returns one of the ResultSet + * objects. + * + * Note: 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 + { + return new QueryExecutor(sql, stat, pg_stream, this).execute(); + } + + /* + * 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 + * using a positioned update/delete statement that references the + * cursor name. + * + * We support one cursor per connection. + * + * setCursorName sets the cursor name. + * + * @param cursor the cursor name + * @exception SQLException if a database access error occurs + */ + public void setCursorName(String cursor) throws SQLException + { + this.cursor = cursor; + } + + /* + * getCursorName gets the cursor name. + * + * @return the current cursor name + * @exception SQLException if a database access error occurs + */ + public String getCursorName() throws SQLException + { + return cursor; + } + + /* + * We are required to bring back certain information by + * the DatabaseMetaData class. These functions do that. + * + * Method getURL() brings back the URL (good job we saved it) + * + * @return the url + * @exception SQLException just in case... + */ + public String getURL() throws SQLException + { + return this_url; + } + + /* + * Method getUserName() brings back the User Name (again, we + * saved it) + * + * @return the user name + * @exception SQLException just in case... + */ + int lastMessage = 0; + public String getUserName() throws SQLException + { + return PG_USER; + } + + /* + * Get the character encoding to use for this connection. + */ + public Encoding getEncoding() throws SQLException + { + return encoding; + } + + /* + * This returns the Fastpath API for the current connection. + * + *

NOTE: This is not part of JDBC, but allows access to + * functions on the org.postgresql backend itself. + * + *

It is primarily used by the LargeObject API + * + *

The best way to use this is as follows: + * + *

+         * import org.postgresql.fastpath.*;
+         * ...
+         * Fastpath fp = ((org.postgresql.Connection)myconn).getFastpathAPI();
+         * 
+ * + *

where myconn is an open Connection to org.postgresql. + * + * @return Fastpath object allowing access to functions on the org.postgresql + * backend. + * @exception SQLException by Fastpath when initialising for first time + */ + public Fastpath getFastpathAPI() throws SQLException + { + if (fastpath == null) + 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. + * + *

NOTE: This is not part of JDBC, but allows access to + * functions on the org.postgresql backend itself. + * + *

The best way to use this is as follows: + * + *

+         * import org.postgresql.largeobject.*;
+         * ...
+         * LargeObjectManager lo = ((org.postgresql.Connection)myconn).getLargeObjectAPI();
+         * 
+ * + *

where myconn is an open Connection to org.postgresql. + * + * @return LargeObject object that implements the API + * @exception SQLException by LargeObject when initialising for first time + */ + public LargeObjectManager getLargeObjectAPI() throws SQLException + { + if (largeobject == null) + 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. + * + *

It uses an internal Hashtable to get the handling class. If the + * type is not supported, then an instance of org.postgresql.util.PGobject + * is returned. + * + * You can use the getValue() or setValue() methods to handle the returned + * object. Custom objects can have their own methods. + * + * In 6.4, this is extended to use the org.postgresql.util.Serialize class to + * allow the Serialization of Java Objects into the database without using + * Blobs. Refer to that class for details on how this new feature works. + * + * @return PGobject for this type, and set to value + * @exception SQLException if value is not correct for this type + * @see org.postgresql.util.Serialize + */ + public Object getObject(String type, String value) throws SQLException + { + 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 + if (o == null) + { + Serialize ser = new Serialize(this, type); + 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. + // + // This is used to implement the org.postgresql unique types (like lseg, + // point, etc). + if (o instanceof String) + { + // 6.3 style extending PG_Object + PGobject obj = null; + obj = (PGobject)(Class.forName((String)o).newInstance()); + obj.setType(type); + obj.setValue(value); + return (Object)obj; + } + else + { + // If it's an object, it should be an instance of our Serialize class + // If so, then call it's fetch method. + if (o instanceof Serialize) + 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 PSQLException("postgresql.con.creobj", type, ex); + } + + // should never be reached + return null; + } + + /* + * This stores an object into the database. This method was + * deprecated in 7.2 bacause an OID can be larger than the java signed + * int returned by this method. + * @deprecated Replaced by storeObject() in 7.2 + */ + public int putObject(Object o) throws SQLException + { + return (int) storeObject(o); + } + + /* + * This stores an object into the database. + * @param o Object to store + * @return OID of the new rectord + * @exception SQLException if value is not correct for this type + * @see org.postgresql.util.Serialize + * @since 7.2 + */ + public long storeObject(Object o) throws SQLException + { + 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 + if (x == null) + { + Serialize ser = new Serialize(this, type); + objectTypes.put(type, ser); + return ser.storeObject(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).storeObject(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(); + throw sx; + } + catch (Exception ex) + { + 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. + * + *

NOTE: This is not part of JDBC, but an extension. + * + *

The best way to use this is as follows: + * + *

+         * ...
+         * ((org.postgresql.Connection)myconn).addDataType("mytype","my.class.name");
+         * ...
+         * 
+ * + *

where myconn is an open Connection to org.postgresql. + * + *

The handling class must extend org.postgresql.util.PGobject + * + * @see org.postgresql.util.PGobject + */ + public void addDataType(String type, String name) + { + 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 + // the full class name of the handling class. + // + private static final String defaultObjectTypes[][] = { + {"box", "org.postgresql.geometric.PGbox"}, + {"circle", "org.postgresql.geometric.PGcircle"}, + {"line", "org.postgresql.geometric.PGline"}, + {"lseg", "org.postgresql.geometric.PGlseg"}, + {"path", "org.postgresql.geometric.PGpath"}, + {"point", "org.postgresql.geometric.PGpoint"}, + {"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. + */ + public abstract java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException; + + /* + * In some cases, it is desirable to immediately release a Connection's + * database and JDBC resources instead of waiting for them to be + * automatically released (cant think why off the top of my head) + * + * Note: A Connection is automatically closed when it is + * garbage collected. Certain fatal errors also result in a closed + * connection. + * + * @exception SQLException if a database access error occurs + */ + public void close() throws SQLException + { + if (pg_stream != null) + { + try + { + pg_stream.SendChar('X'); + pg_stream.flush(); + pg_stream.close(); + } + catch (IOException e) + {} + pg_stream = null; + } + } + + /* + * A driver may convert the JDBC sql grammar into its system's + * native SQL grammar prior to sending it; nativeSQL returns the + * native form of the statement that the driver would have sent. + * + * @param sql a SQL statement that may contain one or more '?' + * parameter placeholders + * @return the native form of this statement + * @exception SQLException if a database access error occurs + */ + public String nativeSQL(String sql) throws SQLException + { + return sql; + } + + /* + * The first warning reported by calls on this Connection is + * returned. + * + * Note: Sebsequent warnings will be changed to this + * SQLWarning + * + * @return the first SQLWarning or null + * @exception SQLException if a database access error occurs + */ + public SQLWarning getWarnings() throws SQLException + { + return firstWarning; + } + + /* + * After this call, getWarnings returns null until a new warning + * is reported for this connection. + * + * @exception SQLException if a database access error occurs + */ + public void clearWarnings() throws SQLException + { + firstWarning = null; + } + + + /* + * You can put a connection in read-only mode as a hunt to enable + * database optimizations + * + * Note: setReadOnly cannot be called while in the middle + * of a transaction + * + * @param readOnly - true enables read-only mode; false disables it + * @exception SQLException if a database access error occurs + */ + public void setReadOnly(boolean readOnly) throws SQLException + { + this.readOnly = readOnly; + } + + /* + * Tests to see if the connection is in Read Only Mode. Note that + * we cannot really put the database in read only mode, but we pretend + * we can by returning the value of the readOnly flag + * + * @return true if the connection is read only + * @exception SQLException if a database access error occurs + */ + public boolean isReadOnly() throws SQLException + { + return readOnly; + } + + /* + * If a connection is in auto-commit mode, than all its SQL + * statements will be executed and committed as individual + * transactions. Otherwise, its SQL statements are grouped + * into transactions that are terminated by either commit() + * or rollback(). By default, new connections are in auto- + * commit mode. The commit occurs when the statement completes + * or the next execute occurs, whichever comes first. In the + * case of statements returning a ResultSet, the statement + * completes when the last row of the ResultSet has been retrieved + * or the ResultSet has been closed. In advanced cases, a single + * statement may return multiple results as well as output parameter + * values. Here the commit occurs when all results and output param + * values have been retrieved. + * + * @param autoCommit - true enables auto-commit; false disables it + * @exception SQLException if a database access error occurs + */ + public void setAutoCommit(boolean autoCommit) throws SQLException + { + if (this.autoCommit == autoCommit) + return; + if (autoCommit) + ExecSQL("end"); + else + { + if (haveMinimumServerVersion("7.1")) + { + ExecSQL("begin;" + getIsolationLevelSQL()); + } + else + { + ExecSQL("begin"); + ExecSQL(getIsolationLevelSQL()); + } + } + this.autoCommit = autoCommit; + } + + /* + * gets the current auto-commit state + * + * @return Current state of the auto-commit mode + * @exception SQLException (why?) + * @see setAutoCommit + */ + public boolean getAutoCommit() throws SQLException + { + return this.autoCommit; + } + + /* + * The method commit() makes all changes made since the previous + * commit/rollback permanent and releases any database locks currently + * held by the Connection. This method should only be used when + * auto-commit has been disabled. (If autoCommit == true, then we + * just return anyhow) + * + * @exception SQLException if a database access error occurs + * @see setAutoCommit + */ + public void commit() throws SQLException + { + if (autoCommit) + return; + if (haveMinimumServerVersion("7.1")) + { + ExecSQL("commit;begin;" + getIsolationLevelSQL()); + } + else + { + ExecSQL("commit"); + ExecSQL("begin"); + ExecSQL(getIsolationLevelSQL()); + } + } + + /* + * The method rollback() drops all changes made since the previous + * commit/rollback and releases any database locks currently held by + * the Connection. + * + * @exception SQLException if a database access error occurs + * @see commit + */ + public void rollback() throws SQLException + { + if (autoCommit) + return; + if (haveMinimumServerVersion("7.1")) + { + ExecSQL("rollback; begin;" + getIsolationLevelSQL()); + } + else + { + ExecSQL("rollback"); + ExecSQL("begin"); + ExecSQL(getIsolationLevelSQL()); + } + } + + /* + * Get this Connection's current transaction isolation mode. + * + * @return the current TRANSACTION_* mode value + * @exception SQLException if a database access error occurs + */ + public int getTransactionIsolation() throws SQLException + { + clearWarnings(); + ExecSQL("show transaction isolation level"); + + SQLWarning warning = getWarnings(); + if (warning != null) + { + String message = warning.getMessage(); + clearWarnings(); + if (message.indexOf("READ COMMITTED") != -1) + return java.sql.Connection.TRANSACTION_READ_COMMITTED; + else if (message.indexOf("READ UNCOMMITTED") != -1) + return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; + else if (message.indexOf("REPEATABLE READ") != -1) + return java.sql.Connection.TRANSACTION_REPEATABLE_READ; + else if (message.indexOf("SERIALIZABLE") != -1) + return java.sql.Connection.TRANSACTION_SERIALIZABLE; + } + return java.sql.Connection.TRANSACTION_READ_COMMITTED; + } + + /* + * You can call this method to try to change the transaction + * isolation level using one of the TRANSACTION_* values. + * + * Note: setTransactionIsolation cannot be called while + * in the middle of a transaction + * + * @param level one of the TRANSACTION_* isolation values with + * the exception of TRANSACTION_NONE; some databases may + * not support other values + * @exception SQLException if a database access error occurs + * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel + */ + public void setTransactionIsolation(int level) throws SQLException + { + //In 7.1 and later versions of the server it is possible using + //the "set session" command to set this once for all future txns + //however in 7.0 and prior versions it is necessary to set it in + //each transaction, thus adding complexity below. + //When we decide to drop support for servers older than 7.1 + //this can be simplified + isolationLevel = level; + String isolationLevelSQL; + + if (!haveMinimumServerVersion("7.1")) + { + isolationLevelSQL = getIsolationLevelSQL(); + } + else + { + isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL "; + switch (isolationLevel) + { + case java.sql.Connection.TRANSACTION_READ_COMMITTED: + isolationLevelSQL += "READ COMMITTED"; + break; + case java.sql.Connection.TRANSACTION_SERIALIZABLE: + isolationLevelSQL += "SERIALIZABLE"; + break; + default: + throw new PSQLException("postgresql.con.isolevel", + new Integer(isolationLevel)); + } + } + ExecSQL(isolationLevelSQL); + } + + /* + * Helper method used by setTransactionIsolation(), commit(), rollback() + * and setAutoCommit(). This returns the SQL string needed to + * set the isolation level for a transaction. In 7.1 and later it + * is possible to set a default isolation level that applies to all + * future transactions, this method is only necesary for 7.0 and older + * servers, and should be removed when support for these older + * servers are dropped + */ + protected String getIsolationLevelSQL() throws SQLException + { + //7.1 and higher servers have a default specified so + //no additional SQL is required to set the isolation level + if (haveMinimumServerVersion("7.1")) + { + return ""; + } + StringBuffer sb = new StringBuffer("SET TRANSACTION ISOLATION LEVEL"); + + switch (isolationLevel) + { + case java.sql.Connection.TRANSACTION_READ_COMMITTED: + sb.append(" READ COMMITTED"); + break; + + case java.sql.Connection.TRANSACTION_SERIALIZABLE: + sb.append(" SERIALIZABLE"); + break; + + default: + throw new PSQLException("postgresql.con.isolevel", new Integer(isolationLevel)); + } + return sb.toString(); + } + + /* + * A sub-space of this Connection's database may be selected by + * setting a catalog name. If the driver does not support catalogs, + * it will silently ignore this request + * + * @exception SQLException if a database access error occurs + */ + public void setCatalog(String catalog) throws SQLException + { + //no-op + } + + /* + * Return the connections current catalog name, or null if no + * catalog name is set, or we dont support catalogs. + * + * @return the current catalog name or null + * @exception SQLException if a database access error occurs + */ + public String getCatalog() throws SQLException + { + return PG_DATABASE; + } + + /* + * Overides finalize(). If called, it closes the connection. + * + * This was done at the request of Rachel Greenham + * who hit a problem where multiple + * clients didn't close the connection, and once a fortnight enough + * clients were open to kill the org.postgres server. + */ + public void finalize() throws Throwable + { + close(); + } + + private static String extractVersionNumber(String fullVersionString) + { + StringTokenizer versionParts = new StringTokenizer(fullVersionString); + versionParts.nextToken(); /* "PostgreSQL" */ + return versionParts.nextToken(); /* "X.Y.Z" */ + } + + /* + * Get server version number + */ + public String getDBVersionNumber() + { + return dbVersionNumber; + } + + public boolean haveMinimumServerVersion(String ver) throws SQLException + { + return (getDBVersionNumber().compareTo(ver) >= 0); + } + + /* + * This method returns true if the compatible level set in the connection + * (which can be passed into the connection or specified in the URL) + * is at least the value passed to this method. This is used to toggle + * between different functionality as it changes across different releases + * of the jdbc driver code. The values here are versions of the jdbc client + * and not server versions. For example in 7.1 get/setBytes worked on + * LargeObject values, in 7.2 these methods were changed to work on bytea + * values. This change in functionality could be disabled by setting the + * "compatible" level to be 7.1, in which case the driver will revert to + * the 7.1 functionality. + */ + public boolean haveMinimumCompatibleVersion(String ver) throws SQLException + { + return (compatible.compareTo(ver) >= 0); + } + + + /* + * This returns the java.sql.Types type for a PG type oid + * + * @param oid PostgreSQL type oid + * @return the java.sql.Types type + * @exception SQLException if a database access error occurs + */ + public int getSQLType(int oid) throws SQLException + { + Integer sqlType = (Integer)sqlTypeCache.get(new Integer(oid)); + + // it's not in the cache, so perform a query, and add the result to the cache + if (sqlType == null) + { + ResultSet result = (org.postgresql.ResultSet)ExecSQL("select typname from pg_type where oid = " + oid); + if (result.getColumnCount() != 1 || result.getTupleCount() != 1) + throw new PSQLException("postgresql.unexpected"); + result.next(); + String pgType = result.getString(1); + Integer iOid = new Integer(oid); + sqlType = new Integer(getSQLType(result.getString(1))); + sqlTypeCache.put(iOid, sqlType); + pgTypeCache.put(iOid, pgType); + result.close(); + } + + return sqlType.intValue(); + } + + /* + * This returns the java.sql.Types type for a PG type + * + * @param pgTypeName PostgreSQL type name + * @return the java.sql.Types type + */ + public abstract int getSQLType(String pgTypeName); + + /* + * This returns the oid for a given PG data type + * @param typeName PostgreSQL type name + * @return PostgreSQL oid value for a field of this type + */ + public int getOID(String typeName) throws SQLException + { + int oid = -1; + if (typeName != null) + { + Integer oidValue = (Integer) typeOidCache.get(typeName); + if (oidValue != null) + { + oid = oidValue.intValue(); + } + else + { + // it's not in the cache, so perform a query, and add the result to the cache + ResultSet result = (org.postgresql.ResultSet)ExecSQL("select oid from pg_type where typname='" + + typeName + "'"); + if (result.getColumnCount() != 1 || result.getTupleCount() != 1) + throw new PSQLException("postgresql.unexpected"); + result.next(); + oid = Integer.parseInt(result.getString(1)); + typeOidCache.put(typeName, new Integer(oid)); + result.close(); + } + } + return oid; + } + + /* + * We also need to get the PG type name as returned by the back end. + * + * @return the String representation of the type of this field + * @exception SQLException if a database access error occurs + */ + public String getPGType(int oid) throws SQLException + { + String pgType = (String) pgTypeCache.get(new Integer(oid)); + if (pgType == null) + { + getSQLType(oid); + pgType = (String) pgTypeCache.get(new Integer(oid)); + } + return pgType; + } + + //Because the get/setLogStream methods are deprecated in JDBC2 + //we use them for JDBC1 here and override this method in the jdbc2 + //version of this class + protected void enableDriverManagerLogging() { + if (DriverManager.getLogStream() == null) { + DriverManager.setLogStream(System.out); + } + } + +} + diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java.in b/src/interfaces/jdbc/org/postgresql/Driver.java.in index bc1925efe5..a199fe2bc7 100644 --- a/src/interfaces/jdbc/org/postgresql/Driver.java.in +++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in @@ -29,13 +29,10 @@ public class Driver implements java.sql.Driver // make these public so they can be used in setLogLevel below - public static final int DEBUG = 0; + public static final int DEBUG = 2; public static final int INFO = 1; - public static final int WARN = 2; - public static final int ERROR = 3; - public static final int FATAL = 4; - - private static int logLevel = FATAL; + public static boolean logDebug = false; + public static boolean logInfo = false; static { @@ -46,7 +43,6 @@ public class Driver implements java.sql.Driver // my early jdbc work did - and that was based on other examples). // Placing it here, means that the driver is registered once only. java.sql.DriverManager.registerDriver(new Driver()); - } catch (SQLException e) { @@ -106,7 +102,12 @@ public class Driver implements java.sql.Driver * to/from the database to unicode. If multibyte is enabled on the * server then the character set of the database is used as the default, * otherwise the jvm character encoding is used as the default. - * compatible - This is used to toggle + * loglevel - (optional) Enable logging of messages from the driver. + * The value is an integer from 1 to 2 where: + * INFO = 1, DEBUG = 2 + * The output is sent to DriverManager.getPrintWriter() if set, + * otherwise it is sent to System.out. + * compatible - (optional) This is used to toggle * between different functionality as it changes across different releases * of the jdbc driver code. The values here are versions of the jdbc * client and not server versions. For example in 7.1 get/setBytes @@ -140,12 +141,12 @@ public class Driver implements java.sql.Driver { if ((props = parseURL(url, info)) == null) { - Driver.debug("Error in url" + url); + if (Driver.logDebug) Driver.debug("Error in url" + url); return null; } try { - Driver.debug("connect " + url); + if (Driver.logDebug) Driver.debug("connect " + url); org.postgresql.Connection con = (org.postgresql.Connection)(Class.forName("@JDBCCONNECTCLASS@").newInstance()); con.openConnection (host(), port(), props, database(), url, this); @@ -153,7 +154,7 @@ public class Driver implements java.sql.Driver } catch (ClassNotFoundException ex) { - Driver.debug("error", ex); + if (Driver.logDebug) Driver.debug("error", ex); throw new PSQLException("postgresql.jvm.version", ex); } catch (PSQLException ex1) @@ -164,7 +165,7 @@ public class Driver implements java.sql.Driver } catch (Exception ex2) { - Driver.debug("error", ex2); + if (Driver.logDebug) Driver.debug("error", ex2); throw new PSQLException("postgresql.unusual", ex2); } } @@ -251,7 +252,7 @@ public class Driver implements java.sql.Driver */ public static String getVersion() { - return "@VERSION@"; + return "@VERSION@ jdbc driver build " + m_buildNumber; } /* @@ -293,12 +294,6 @@ public class Driver implements java.sql.Driver { String token = st.nextToken(); - // PM June 29 1997 - // Added this, to help me understand how this works. - // Unless you want each token to be processed, leave this commented out - // but don't delete it. - //DriverManager.println("wellFormedURL: state="+state+" count="+count+" token='"+token+"'"); - // PM Aug 2 1997 - Modified to allow multiple backends if (count <= 3) { @@ -379,7 +374,6 @@ public class Driver implements java.sql.Driver else if (state == -5) { value = token; - //DriverManager.println("put("+key+","+value+")"); urlProps.put(key, value); state = -2; } @@ -387,13 +381,6 @@ public class Driver implements java.sql.Driver } } - // PM June 29 1997 - // This now outputs the properties only if we are logging - // PM Sep 13 1999 Commented out, as it throws a Deprecation warning - // when compiled under JDK1.2. - //if (DriverManager.getLogStream() != null) - // urlProps.list(DriverManager.getLogStream()); - return urlProps; } @@ -446,12 +433,13 @@ public class Driver implements java.sql.Driver * used to turn logging on to a certain level, can be called * by specifying fully qualified class ie org.postgresql.Driver.setLogLevel() * @param int logLevel sets the level which logging will respond to - * FATAL being almost no messages + * INFO being almost no messages * DEBUG most verbose */ public static void setLogLevel(int logLevel) { - Driver.logLevel = logLevel; + logDebug = (logLevel >= DEBUG) ? true : false; + logInfo = (logLevel >= INFO) ? true : false; } /* * logging message at the debug level @@ -459,7 +447,7 @@ public class Driver implements java.sql.Driver */ public static void debug(String msg) { - if (logLevel <= DEBUG) + if (logDebug) { DriverManager.println(msg); } @@ -470,7 +458,7 @@ public class Driver implements java.sql.Driver */ public static void debug(String msg, Exception ex) { - if (logLevel <= DEBUG) + if (logDebug) { DriverManager.println(msg + ex != null ? ex.getMessage() : "null Exception"); } @@ -481,7 +469,7 @@ public class Driver implements java.sql.Driver */ public static void info(String msg) { - if (logLevel <= INFO) + if (logInfo) { DriverManager.println(msg); } @@ -492,75 +480,13 @@ public class Driver implements java.sql.Driver */ public static void info(String msg, Exception ex) { - if (logLevel <= INFO) - { - DriverManager.println(msg + ex != null ? ex.getMessage() : "null Exception"); - } - } - /* - * logging message at warn level - * messages will be printed if the logging level is less or equal to WARN - */ - public static void warn(String msg) - { - if (logLevel <= WARN) - { - DriverManager.println(msg); - } - } - /* - * logging message at warn level - * messages will be printed if the logging level is less or equal to WARN - */ - public static void warn(String msg, Exception ex) - { - if (logLevel <= WARN) - { - DriverManager.println(msg + ex != null ? ex.getMessage() : "null Exception"); - } - } - /* - * logging message at error level - * messages will be printed if the logging level is less or equal to ERROR - */ - public static void error(String msg) - { - if (logLevel <= ERROR) - { - DriverManager.println(msg); - } - } - /* - * logging message at error level - * messages will be printed if the logging level is less or equal to ERROR - */ - public static void error(String msg, Exception ex) - { - if (logLevel <= ERROR) - { - DriverManager.println(msg + ex != null ? ex.getMessage() : "null Exception"); - } - } - /* - * logging message at fatal level - * messages will be printed if the logging level is less or equal to FATAL - */ - public static void fatal(String msg) - { - if (logLevel <= FATAL) - { - DriverManager.println(msg); - } - } - /* - * logging message at fatal level - * messages will be printed if the logging level is less or equal to FATAL - */ - public static void fatal(String msg, Exception ex) - { - if (logLevel <= FATAL) + if (logInfo) { DriverManager.println(msg + ex != null ? ex.getMessage() : "null Exception"); } } + + //The build number should be incremented for every new build + private static int m_buildNumber = 100; + } diff --git a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java index a74645015a..20f5a6f3e2 100644 --- a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java +++ b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java @@ -1,5 +1,6 @@ package org.postgresql.fastpath; +import org.postgresql.Driver; import java.io.*; import java.lang.*; import java.net.*; @@ -44,7 +45,6 @@ public class Fastpath { this.conn = conn; this.stream = stream; - //DriverManager.println("Fastpath initialised"); } /* @@ -174,7 +174,7 @@ public class Fastpath */ public Object fastpath(String name, boolean resulttype, FastpathArg[] args) throws SQLException { - //DriverManager.println("Fastpath: calling "+name); + if (Driver.logDebug) Driver.debug("Fastpath: calling "+name); return fastpath(getID(name), resulttype, args); } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java index 29f641e02f..3c447a88b4 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java @@ -13,7 +13,7 @@ import org.postgresql.util.PSQLException; /* * This class provides information about the database as a whole. * - * $Id: DatabaseMetaData.java,v 1.45 2002/06/06 14:47:52 davec Exp $ + * $Id: DatabaseMetaData.java,v 1.46 2002/06/11 02:55:16 barry Exp $ * *

Many of the methods here return lists of information in ResultSets. You * can use the normal ResultSet methods such as getString and getInt to @@ -1731,7 +1731,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData String relKind; switch (r.getBytes(3)[0]) { - case (byte) 'r': + case (byte) 'r': if ( r.getString(1).startsWith("pg_") ) { relKind = "SYSTEM TABLE"; @@ -2108,7 +2108,6 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData { byte[][] tuple = new byte[8][0]; tuple[0] = tuple[1] = "".getBytes(); - DriverManager.println("relname=\"" + r.getString(1) + "\" relacl=\"" + r.getString(2) + "\""); // For now, don't add to the result as relacl needs to be processed. //v.addElement(tuple); diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java index 0d62c74c9a..86b1a4fc79 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java @@ -17,7 +17,7 @@ import org.postgresql.largeobject.*; import org.postgresql.util.*; /* - * $Id: Connection.java,v 1.18 2002/03/26 05:52:50 barry Exp $ + * $Id: Connection.java,v 1.19 2002/06/11 02:55:16 barry Exp $ * * A Connection represents a session with a specific database. Within the * context of a Connection, SQL statements are executed and results are @@ -318,6 +318,14 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co Types.ARRAY }; + //Because the get/setLogStream methods are deprecated in JDBC2 + //we use the get/setLogWriter methods here for JDBC2 by overriding + //the base version of this method + protected void enableDriverManagerLogging() { + if (DriverManager.getLogWriter() == null) { + DriverManager.setLogWriter(new PrintWriter(System.out)); + } + } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java index 2eb2b07087..a6130720dd 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java @@ -15,7 +15,7 @@ import org.postgresql.util.PSQLException; /* * This class provides information about the database as a whole. * - * $Id: DatabaseMetaData.java,v 1.54 2002/06/06 14:47:52 davec Exp $ + * $Id: DatabaseMetaData.java,v 1.55 2002/06/11 02:55:16 barry Exp $ * *

Many of the methods here return lists of information in ResultSets. You * can use the normal ResultSet methods such as getString and getInt to @@ -62,7 +62,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean allProceduresAreCallable() throws SQLException { - Driver.debug("allProceduresAreCallable"); + if (Driver.logDebug) Driver.debug("allProceduresAreCallable"); return true; // For now... } @@ -75,7 +75,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean allTablesAreSelectable() throws SQLException { - Driver.debug("allTablesAreSelectable"); + if (Driver.logDebug) Driver.debug("allTablesAreSelectable"); return true; // For now... } @@ -88,7 +88,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public String getURL() throws SQLException { String url = connection.getURL(); - Driver.debug("getURL " + url); + if (Driver.logDebug) Driver.debug("getURL " + url); return url; } @@ -101,7 +101,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public String getUserName() throws SQLException { String userName = connection.getUserName(); - Driver.debug("getUserName " + userName); + if (Driver.logDebug) Driver.debug("getUserName " + userName); return userName; } @@ -114,7 +114,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean isReadOnly() throws SQLException { boolean isReadOnly = connection.isReadOnly(); - Driver.debug("isReadOnly " + isReadOnly); + if (Driver.logDebug) Driver.debug("isReadOnly " + isReadOnly); return isReadOnly; } @@ -127,7 +127,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean nullsAreSortedHigh() throws SQLException { boolean nullSortedHigh = connection.haveMinimumServerVersion("7.2"); - Driver.debug("nullsAreSortedHigh " + nullSortedHigh); + if (Driver.logDebug) Driver.debug("nullsAreSortedHigh " + nullSortedHigh); return nullSortedHigh; } @@ -139,7 +139,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean nullsAreSortedLow() throws SQLException { - Driver.debug("nullsAreSortedLow false"); + if (Driver.logDebug) Driver.debug("nullsAreSortedLow false"); return false; } @@ -151,7 +151,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean nullsAreSortedAtStart() throws SQLException { - Driver.debug("nullsAreSortedAtStart false"); + if (Driver.logDebug) Driver.debug("nullsAreSortedAtStart false"); return false; } @@ -164,7 +164,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean nullsAreSortedAtEnd() throws SQLException { boolean nullsAreSortedAtEnd = ! connection.haveMinimumServerVersion("7.2"); - Driver.debug("nullsAreSortedAtEnd " + nullsAreSortedAtEnd); + if (Driver.logDebug) Driver.debug("nullsAreSortedAtEnd " + nullsAreSortedAtEnd); return nullsAreSortedAtEnd; } @@ -177,7 +177,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public String getDatabaseProductName() throws SQLException { - Driver.debug("getDatabaseProductName PostgresSQL"); + if (Driver.logDebug) Driver.debug("getDatabaseProductName PostgresSQL"); return "PostgreSQL"; } @@ -190,7 +190,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public String getDatabaseProductVersion() throws SQLException { String versionNumber = connection.getDBVersionNumber(); - Driver.debug("getDatabaseProductVersion " + versionNumber); + if (Driver.logDebug) Driver.debug("getDatabaseProductVersion " + versionNumber); return versionNumber; } @@ -204,7 +204,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public String getDriverName() throws SQLException { String driverName = "PostgreSQL Native Driver"; - Driver.debug("getDriverName" + driverName); + if (Driver.logDebug) Driver.debug("getDriverName" + driverName); return driverName; } @@ -218,7 +218,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public String getDriverVersion() throws SQLException { String driverVersion = connection.this_driver.getVersion(); - Driver.debug("getDriverVersion " + driverVersion); + if (Driver.logDebug) Driver.debug("getDriverVersion " + driverVersion); return driverVersion; } @@ -230,7 +230,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public int getDriverMajorVersion() { int majorVersion = connection.this_driver.getMajorVersion(); - Driver.debug("getMajorVersion " + majorVersion); + if (Driver.logDebug) Driver.debug("getMajorVersion " + majorVersion); return majorVersion; } @@ -242,7 +242,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public int getDriverMinorVersion() { int minorVersion = connection.this_driver.getMinorVersion(); - Driver.debug("getMinorVersion " + minorVersion); + if (Driver.logDebug) Driver.debug("getMinorVersion " + minorVersion); return minorVersion; } @@ -255,7 +255,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean usesLocalFiles() throws SQLException { - Driver.debug("usesLocalFiles " + false); + if (Driver.logDebug) Driver.debug("usesLocalFiles " + false); return false; } @@ -268,7 +268,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean usesLocalFilePerTable() throws SQLException { - Driver.debug("usesLocalFilePerTable " + false); + if (Driver.logDebug) Driver.debug("usesLocalFilePerTable " + false); return false; } @@ -286,7 +286,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsMixedCaseIdentifiers() throws SQLException { - Driver.debug("supportsMixedCaseIdentifiers " + false); + if (Driver.logDebug) Driver.debug("supportsMixedCaseIdentifiers " + false); return false; } @@ -298,7 +298,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean storesUpperCaseIdentifiers() throws SQLException { - Driver.debug("storesUpperCaseIdentifiers " + false); + if (Driver.logDebug) Driver.debug("storesUpperCaseIdentifiers " + false); return false; } @@ -310,7 +310,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean storesLowerCaseIdentifiers() throws SQLException { - Driver.debug("storesLowerCaseIdentifiers " + true); + if (Driver.logDebug) Driver.debug("storesLowerCaseIdentifiers " + true); return true; } @@ -322,7 +322,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean storesMixedCaseIdentifiers() throws SQLException { - Driver.debug("storesMixedCaseIdentifiers " + false); + if (Driver.logDebug) Driver.debug("storesMixedCaseIdentifiers " + false); return false; } @@ -336,7 +336,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { - Driver.debug("supportsMixedCaseQuotedIdentifiers " + true); + if (Driver.logDebug) Driver.debug("supportsMixedCaseQuotedIdentifiers " + true); return true; } @@ -348,7 +348,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { - Driver.debug("storesUpperCaseQuotedIdentifiers " + false); + if (Driver.logDebug) Driver.debug("storesUpperCaseQuotedIdentifiers " + false); return false; } @@ -360,7 +360,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { - Driver.debug("storesLowerCaseQuotedIdentifiers " + false); + if (Driver.logDebug) Driver.debug("storesLowerCaseQuotedIdentifiers " + false); return false; } @@ -372,7 +372,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { - Driver.debug("storesMixedCaseQuotedIdentifiers " + false); + if (Driver.logDebug) Driver.debug("storesMixedCaseQuotedIdentifiers " + false); return false; } @@ -386,7 +386,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public String getIdentifierQuoteString() throws SQLException { - Driver.debug("getIdentifierQuoteString \"" ); + if (Driver.logDebug) Driver.debug("getIdentifierQuoteString \"" ); return "\""; } @@ -408,35 +408,35 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public String getSQLKeywords() throws SQLException { - Driver.debug("getSQLKeyWords"); + if (Driver.logDebug) Driver.debug("getSQLKeyWords"); return "abort,acl,add,aggregate,append,archive,arch_store,backward,binary,change,cluster,copy,database,delimiters,do,extend,explain,forward,heavy,index,inherits,isnull,light,listen,load,merge,nothing,notify,notnull,oids,purge,rename,replace,retrieve,returns,rule,recipe,setof,stdin,stdout,store,vacuum,verbose,version"; } public String getNumericFunctions() throws SQLException { // XXX-Not Implemented - Driver.debug("getNumericFunctions"); + if (Driver.logDebug) Driver.debug("getNumericFunctions"); return ""; } public String getStringFunctions() throws SQLException { // XXX-Not Implemented - Driver.debug("getStringFunctions"); + if (Driver.logDebug) Driver.debug("getStringFunctions"); return ""; } public String getSystemFunctions() throws SQLException { // XXX-Not Implemented - Driver.debug("getSystemFunctions"); + if (Driver.logDebug) Driver.debug("getSystemFunctions"); return ""; } public String getTimeDateFunctions() throws SQLException { // XXX-Not Implemented - Driver.debug("getTimeDateFunctions"); + if (Driver.logDebug) Driver.debug("getTimeDateFunctions"); return ""; } @@ -449,7 +449,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public String getSearchStringEscape() throws SQLException { - Driver.debug("getSearchStringEscape"); + if (Driver.logDebug) Driver.debug("getSearchStringEscape"); return "\\"; } @@ -466,7 +466,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public String getExtraNameCharacters() throws SQLException { - Driver.debug("getExtraNameCharacters"); + if (Driver.logDebug) Driver.debug("getExtraNameCharacters"); return ""; } @@ -479,7 +479,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsAlterTableWithAddColumn() throws SQLException { - Driver.debug("supportsAlterTableWithAddColumn " + true); + if (Driver.logDebug) Driver.debug("supportsAlterTableWithAddColumn " + true); return true; } @@ -492,7 +492,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsAlterTableWithDropColumn() throws SQLException { - Driver.debug("supportsAlterTableWithDropColumn " + false); + if (Driver.logDebug) Driver.debug("supportsAlterTableWithDropColumn " + false); return false; } @@ -516,7 +516,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsColumnAliasing() throws SQLException { - Driver.debug("supportsColumnAliasing " + true); + if (Driver.logDebug) Driver.debug("supportsColumnAliasing " + true); return true; } @@ -529,21 +529,21 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean nullPlusNonNullIsNull() throws SQLException { - Driver.debug("nullPlusNonNullIsNull " + true); + if (Driver.logDebug) Driver.debug("nullPlusNonNullIsNull " + true); return true; } public boolean supportsConvert() throws SQLException { // XXX-Not Implemented - Driver.debug("supportsConvert " + false); + if (Driver.logDebug) Driver.debug("supportsConvert " + false); return false; } public boolean supportsConvert(int fromType, int toType) throws SQLException { // XXX-Not Implemented - Driver.debug("supportsConvert " + false); + if (Driver.logDebug) Driver.debug("supportsConvert " + false); return false; } @@ -556,7 +556,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsTableCorrelationNames() throws SQLException { - Driver.debug("supportsTableCorrelationNames " + true); + if (Driver.logDebug) Driver.debug("supportsTableCorrelationNames " + true); return true; } @@ -569,7 +569,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsDifferentTableCorrelationNames() throws SQLException { - Driver.debug("supportsDifferentTableCorrelationNames " + false); + if (Driver.logDebug) Driver.debug("supportsDifferentTableCorrelationNames " + false); return false; } @@ -583,7 +583,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsExpressionsInOrderBy() throws SQLException { - Driver.debug("supportsExpressionsInOrderBy " + true); + if (Driver.logDebug) Driver.debug("supportsExpressionsInOrderBy " + true); return true; } @@ -596,7 +596,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean supportsOrderByUnrelated() throws SQLException { boolean supportsOrderByUnrelated = connection.haveMinimumServerVersion("6.4"); - Driver.debug("supportsOrderByUnrelated " + supportsOrderByUnrelated); + if (Driver.logDebug) Driver.debug("supportsOrderByUnrelated " + supportsOrderByUnrelated); return supportsOrderByUnrelated; } @@ -609,7 +609,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsGroupBy() throws SQLException { - Driver.debug("supportsGroupBy " + true); + if (Driver.logDebug) Driver.debug("supportsGroupBy " + true); return true; } @@ -622,7 +622,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean supportsGroupByUnrelated() throws SQLException { boolean supportsGroupByUnrelated = connection.haveMinimumServerVersion("6.4"); - Driver.debug("supportsGroupByUnrelated " + supportsGroupByUnrelated); + if (Driver.logDebug) Driver.debug("supportsGroupByUnrelated " + supportsGroupByUnrelated); return supportsGroupByUnrelated; } @@ -639,7 +639,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean supportsGroupByBeyondSelect() throws SQLException { boolean supportsGroupByBeyondSelect = connection.haveMinimumServerVersion("6.4"); - Driver.debug("supportsGroupByUnrelated " + supportsGroupByBeyondSelect); + if (Driver.logDebug) Driver.debug("supportsGroupByUnrelated " + supportsGroupByBeyondSelect); return supportsGroupByBeyondSelect; } @@ -653,7 +653,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean supportsLikeEscapeClause() throws SQLException { boolean supportsLikeEscapeClause = connection.haveMinimumServerVersion("7.1"); - Driver.debug("supportsLikeEscapeClause " + supportsLikeEscapeClause); + if (Driver.logDebug) Driver.debug("supportsLikeEscapeClause " + supportsLikeEscapeClause); return supportsLikeEscapeClause; } @@ -667,7 +667,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsMultipleResultSets() throws SQLException { - Driver.debug("supportsMultipleResultSets " + false); + if (Driver.logDebug) Driver.debug("supportsMultipleResultSets " + false); return false; } @@ -681,7 +681,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsMultipleTransactions() throws SQLException { - Driver.debug("supportsMultipleTransactions " + true); + if (Driver.logDebug) Driver.debug("supportsMultipleTransactions " + true); return true; } @@ -697,7 +697,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsNonNullableColumns() throws SQLException { - Driver.debug("supportsNonNullableColumns true"); + if (Driver.logDebug) Driver.debug("supportsNonNullableColumns true"); return true; } @@ -715,7 +715,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsMinimumSQLGrammar() throws SQLException { - Driver.debug("supportsMinimumSQLGrammar TRUE"); + if (Driver.logDebug) Driver.debug("supportsMinimumSQLGrammar TRUE"); return true; } @@ -728,7 +728,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsCoreSQLGrammar() throws SQLException { - Driver.debug("supportsCoreSQLGrammar FALSE "); + if (Driver.logDebug) Driver.debug("supportsCoreSQLGrammar FALSE "); return false; } @@ -742,7 +742,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsExtendedSQLGrammar() throws SQLException { - Driver.debug("supportsExtendedSQLGrammar FALSE"); + if (Driver.logDebug) Driver.debug("supportsExtendedSQLGrammar FALSE"); return false; } @@ -761,7 +761,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean supportsANSI92EntryLevelSQL() throws SQLException { boolean schemas = connection.haveMinimumServerVersion("7.3"); - Driver.debug("supportsANSI92EntryLevelSQL " + schemas); + if (Driver.logDebug) Driver.debug("supportsANSI92EntryLevelSQL " + schemas); return schemas; } @@ -775,7 +775,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsANSI92IntermediateSQL() throws SQLException { - Driver.debug("supportsANSI92IntermediateSQL false "); + if (Driver.logDebug) Driver.debug("supportsANSI92IntermediateSQL false "); return false; } @@ -787,7 +787,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsANSI92FullSQL() throws SQLException { - Driver.debug("supportsANSI92FullSQL false "); + if (Driver.logDebug) Driver.debug("supportsANSI92FullSQL false "); return false; } @@ -800,7 +800,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsIntegrityEnhancementFacility() throws SQLException { - Driver.debug("supportsIntegrityEnhancementFacility false "); + if (Driver.logDebug) Driver.debug("supportsIntegrityEnhancementFacility false "); return false; } @@ -813,7 +813,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean supportsOuterJoins() throws SQLException { boolean supportsOuterJoins = connection.haveMinimumServerVersion("7.1"); - Driver.debug("supportsOuterJoins " + supportsOuterJoins); + if (Driver.logDebug) Driver.debug("supportsOuterJoins " + supportsOuterJoins); return supportsOuterJoins; } @@ -826,7 +826,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean supportsFullOuterJoins() throws SQLException { boolean supportsFullOuterJoins = connection.haveMinimumServerVersion("7.1"); - Driver.debug("supportsFullOuterJoins " + supportsFullOuterJoins); + if (Driver.logDebug) Driver.debug("supportsFullOuterJoins " + supportsFullOuterJoins); return supportsFullOuterJoins; } @@ -839,7 +839,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData public boolean supportsLimitedOuterJoins() throws SQLException { boolean supportsLimitedOuterJoins = connection.haveMinimumServerVersion("7.1"); - Driver.debug("supportsFullOuterJoins " + supportsLimitedOuterJoins); + if (Driver.logDebug) Driver.debug("supportsFullOuterJoins " + supportsLimitedOuterJoins); return supportsLimitedOuterJoins; } @@ -853,7 +853,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public String getSchemaTerm() throws SQLException { - Driver.debug("getSchemaTerm schema"); + if (Driver.logDebug) Driver.debug("getSchemaTerm schema"); return "schema"; } @@ -866,7 +866,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public String getProcedureTerm() throws SQLException { - Driver.debug("getProcedureTerm function "); + if (Driver.logDebug) Driver.debug("getProcedureTerm function "); return "function"; } @@ -878,7 +878,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public String getCatalogTerm() throws SQLException { - Driver.debug("getCatalogTerm database "); + if (Driver.logDebug) Driver.debug("getCatalogTerm database "); return "database"; } @@ -893,7 +893,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData { // return true here; we return false for every other catalog function // so it won't matter what we return here D.C. - Driver.debug("isCatalogAtStart not implemented"); + if (Driver.logDebug) Driver.debug("isCatalogAtStart not implemented"); return true; } @@ -907,7 +907,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData { // Give them something to work with here // everything else returns false so it won't matter what we return here D.C. - Driver.debug("getCatalogSeparator not implemented "); + if (Driver.logDebug) Driver.debug("getCatalogSeparator not implemented "); return "."; } @@ -919,7 +919,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsSchemasInDataManipulation() throws SQLException { - Driver.debug("supportsSchemasInDataManipulation false"); + if (Driver.logDebug) Driver.debug("supportsSchemasInDataManipulation false"); return false; } @@ -931,7 +931,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsSchemasInProcedureCalls() throws SQLException { - Driver.debug("supportsSchemasInProcedureCalls false"); + if (Driver.logDebug) Driver.debug("supportsSchemasInProcedureCalls false"); return false; } @@ -945,7 +945,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData { boolean schemas = connection.haveMinimumServerVersion("7.3"); - Driver.debug("supportsSchemasInTableDefinitions " + schemas); + if (Driver.logDebug) Driver.debug("supportsSchemasInTableDefinitions " + schemas); return schemas; } @@ -957,7 +957,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsSchemasInIndexDefinitions() throws SQLException { - Driver.debug("supportsSchemasInIndexDefinitions false"); + if (Driver.logDebug) Driver.debug("supportsSchemasInIndexDefinitions false"); return false; } @@ -969,7 +969,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { - Driver.debug("supportsSchemasInPrivilegeDefinitions false"); + if (Driver.logDebug) Driver.debug("supportsSchemasInPrivilegeDefinitions false"); return false; } @@ -981,7 +981,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsCatalogsInDataManipulation() throws SQLException { - Driver.debug("supportsCatalogsInDataManipulation false"); + if (Driver.logDebug) Driver.debug("supportsCatalogsInDataManipulation false"); return false; } @@ -993,7 +993,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsCatalogsInProcedureCalls() throws SQLException { - Driver.debug("supportsCatalogsInDataManipulation false"); + if (Driver.logDebug) Driver.debug("supportsCatalogsInDataManipulation false"); return false; } @@ -1005,7 +1005,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsCatalogsInTableDefinitions() throws SQLException { - Driver.debug("supportsCatalogsInTableDefinitions false"); + if (Driver.logDebug) Driver.debug("supportsCatalogsInTableDefinitions false"); return false; } @@ -1017,7 +1017,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsCatalogsInIndexDefinitions() throws SQLException { - Driver.debug("supportsCatalogsInIndexDefinitions false"); + if (Driver.logDebug) Driver.debug("supportsCatalogsInIndexDefinitions false"); return false; } @@ -1029,7 +1029,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { - Driver.debug("supportsCatalogsInPrivilegeDefinitions false"); + if (Driver.logDebug) Driver.debug("supportsCatalogsInPrivilegeDefinitions false"); return false; } @@ -1042,7 +1042,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsPositionedDelete() throws SQLException { - Driver.debug("supportsPositionedDelete false"); + if (Driver.logDebug) Driver.debug("supportsPositionedDelete false"); return false; // For now... } @@ -1054,7 +1054,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData */ public boolean supportsPositionedUpdate() throws SQLException { - Driver.debug("supportsPositionedUpdate false"); + if (Driver.logDebug) Driver.debug("supportsPositionedUpdate false"); return false; // For now... } @@ -2212,7 +2212,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData { byte[][] tuple = new byte[8][0]; tuple[0] = tuple[1] = "".getBytes(); - DriverManager.println("relname=\"" + r.getString(1) + "\" relacl=\"" + r.getString(2) + "\""); + if (Driver.logDebug) Driver.debug("relname=\"" + r.getString(1) + "\" relacl=\"" + r.getString(2) + "\""); // For now, don't add to the result as relacl needs to be processed. //v.addElement(tuple); @@ -2275,7 +2275,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData { byte[][] tuple = new byte[8][0]; tuple[0] = tuple[1] = "".getBytes(); - DriverManager.println("relname=\"" + r.getString(1) + "\" relacl=\"" + r.getString(2) + "\""); + if (Driver.logDebug) Driver.debug("relname=\"" + r.getString(1) + "\" relacl=\"" + r.getString(2) + "\""); // For now, don't add to the result as relacl needs to be processed. //v.addElement(tuple); diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java index dec1de55f0..e5296189cd 100644 --- a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java +++ b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java @@ -1,5 +1,6 @@ package org.postgresql.largeobject; +import org.postgresql.Driver; import java.io.*; import java.lang.*; import java.net.*; @@ -117,7 +118,7 @@ public class LargeObjectManager fp.addFunctions(res); res.close(); - DriverManager.println("Large Object initialised"); + if (Driver.logDebug) Driver.debug("Large Object initialised"); } /* diff --git a/src/interfaces/jdbc/org/postgresql/util/Serialize.java b/src/interfaces/jdbc/org/postgresql/util/Serialize.java index 59d9c03206..80d10bc541 100644 --- a/src/interfaces/jdbc/org/postgresql/util/Serialize.java +++ b/src/interfaces/jdbc/org/postgresql/util/Serialize.java @@ -1,5 +1,6 @@ package org.postgresql.util; +import org.postgresql.Driver; import java.io.*; import java.lang.*; import java.lang.reflect.*; @@ -128,14 +129,14 @@ public class Serialize try { conn = c; - DriverManager.println("Serialize: initializing instance for type: " + type); + if (Driver.logDebug) Driver.debug("Serialize: initializing instance for type: " + type); tableName = toPostgreSQL(type); className = type; ourClass = Class.forName(className); } catch (ClassNotFoundException cnfe) { - DriverManager.println("Serialize: " + className + " java class not found"); + if (Driver.logDebug) Driver.debug("Serialize: " + className + " java class not found"); throw new PSQLException("postgresql.serial.noclass", type); } @@ -147,14 +148,14 @@ public class Serialize if (rs.next()) { status = true; - DriverManager.println("Serialize: " + tableName + " table found"); + if (Driver.logDebug) Driver.debug("Serialize: " + tableName + " table found"); } rs.close(); } // This should never occur, as org.postgresql has it's own internal checks if (!status) { - DriverManager.println("Serialize: " + tableName + " table not found"); + if (Driver.logDebug) Driver.debug("Serialize: " + tableName + " table not found"); throw new PSQLException("postgresql.serial.table", type); } // Finally cache the fields within the table @@ -186,9 +187,9 @@ public class Serialize { try { - DriverManager.println("Serialize.fetch: " + "attempting to instantiate object of type: " + ourClass.getName() ); + if (Driver.logDebug) Driver.debug("Serialize.fetch: " + "attempting to instantiate object of type: " + ourClass.getName() ); Object obj = ourClass.newInstance(); - DriverManager.println("Serialize.fetch: " + "instantiated object of type: " + ourClass.getName() ); + if (Driver.logDebug) Driver.debug("Serialize.fetch: " + "instantiated object of type: " + ourClass.getName() ); // NB: we use java.lang.reflect here to prevent confusion with // the org.postgresql.Field @@ -219,7 +220,7 @@ public class Serialize sb.append(" where oid="); sb.append(oid); - DriverManager.println("Serialize.fetch: " + sb.toString()); + if (Driver.logDebug) Driver.debug("Serialize.fetch: " + sb.toString()); ResultSet rs = conn.ExecSQL(sb.toString()); if (rs != null) @@ -388,7 +389,7 @@ public class Serialize sb.append(')'); } - DriverManager.println("Serialize.store: " + sb.toString() ); + if (Driver.logDebug) Driver.debug("Serialize.store: " + sb.toString() ); org.postgresql.ResultSet rs = (org.postgresql.ResultSet) conn.ExecSQL(sb.toString()); // fetch the OID for returning @@ -495,13 +496,13 @@ public class Serialize ResultSet rs = con.ExecSQL("select relname from pg_class where relname = '" + tableName + "'"); if ( rs.next() ) { - DriverManager.println("Serialize.create: table " + tableName + " exists, skipping"); + if (Driver.logDebug) Driver.debug("Serialize.create: table " + tableName + " exists, skipping"); rs.close(); return; } // else table not found, so create it - DriverManager.println("Serialize.create: table " + tableName + " not found, creating" ); + if (Driver.logDebug) Driver.debug("Serialize.create: table " + tableName + " not found, creating" ); // No entries returned, so the table doesn't exist StringBuffer sb = new StringBuffer("create table "); @@ -547,7 +548,7 @@ public class Serialize sb.append(")"); // Now create the table - DriverManager.println("Serialize.create: " + sb ); + if (Driver.logDebug) Driver.debug("Serialize.create: " + sb ); con.ExecSQL(sb.toString()); } -- 2.11.0