diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java.in b/src/interfaces/jdbc/org/postgresql/Driver.java.in index 27558e69ed5..85fea4cadc1 100644 --- a/src/interfaces/jdbc/org/postgresql/Driver.java.in +++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in @@ -6,7 +6,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/Driver.java.in,v 1.34 2003/07/24 00:30:38 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/Driver.java.in,v 1.35 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ import java.sql.*; import java.util.*; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; /* * The Java SQL framework allows for multiple database drivers. Each @@ -419,7 +420,7 @@ public class Driver implements java.sql.Driver */ public static SQLException notImplemented() { - return new PSQLException("postgresql.unimplemented"); + return new PSQLException("postgresql.unimplemented", PSQLState.NOT_IMPLEMENTED); } /** diff --git a/src/interfaces/jdbc/org/postgresql/core/Encoding.java b/src/interfaces/jdbc/org/postgresql/core/Encoding.java index 73ccde041d4..d3aabda3d7e 100644 --- a/src/interfaces/jdbc/org/postgresql/core/Encoding.java +++ b/src/interfaces/jdbc/org/postgresql/core/Encoding.java @@ -6,7 +6,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Encoding.java,v 1.11 2003/05/29 03:21:32 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Encoding.java,v 1.12 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ import java.io.UnsupportedEncodingException; import java.sql.SQLException; import java.util.Hashtable; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; public class Encoding { @@ -160,7 +161,7 @@ public class Encoding } catch (UnsupportedEncodingException e) { - throw new PSQLException("postgresql.stream.encoding", e); + throw new PSQLException("postgresql.stream.encoding", PSQLState.DATA_ERROR, e); } } @@ -185,7 +186,7 @@ public class Encoding } catch (UnsupportedEncodingException e) { - throw new PSQLException("postgresql.stream.encoding", e); + throw new PSQLException("postgresql.stream.encoding", PSQLState.DATA_ERROR, e); } } @@ -215,7 +216,7 @@ public class Encoding } catch (UnsupportedEncodingException e) { - throw new PSQLException("postgresql.res.encoding", e); + throw new PSQLException("postgresql.res.encoding", PSQLState.DATA_ERROR, e); } } diff --git a/src/interfaces/jdbc/org/postgresql/core/PGStream.java b/src/interfaces/jdbc/org/postgresql/core/PGStream.java index 016859f9fdc..fe710e9efbf 100644 --- a/src/interfaces/jdbc/org/postgresql/core/PGStream.java +++ b/src/interfaces/jdbc/org/postgresql/core/PGStream.java @@ -7,7 +7,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/PGStream.java,v 1.2 2003/05/29 03:21:32 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/PGStream.java,v 1.3 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ import java.io.IOException; import java.net.Socket; import java.sql.*; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; public class PGStream @@ -164,11 +165,11 @@ public class PGStream { c = pg_input.read(); if (c < 0) - throw new PSQLException("postgresql.stream.eof"); + throw new PSQLException("postgresql.stream.eof", PSQLState.COMMUNICATION_ERROR); } catch (IOException e) { - throw new PSQLException("postgresql.stream.ioerror", e); + throw new PSQLException("postgresql.stream.ioerror", PSQLState.COMMUNICATION_ERROR, e); } return c; } @@ -191,13 +192,13 @@ public class PGStream int b = pg_input.read(); if (b < 0) - throw new PSQLException("postgresql.stream.eof"); + throw new PSQLException("postgresql.stream.eof", PSQLState.COMMUNICATION_ERROR); n = n | (b << (8 * i)) ; } } catch (IOException e) { - throw new PSQLException("postgresql.stream.ioerror", e); + throw new PSQLException("postgresql.stream.ioerror", PSQLState.COMMUNICATION_ERROR, e); } return n; } @@ -220,13 +221,13 @@ public class PGStream int b = pg_input.read(); if (b < 0) - throw new PSQLException("postgresql.stream.eof"); + throw new PSQLException("postgresql.stream.eof", PSQLState.COMMUNICATION_ERROR); n = b | (n << 8); } } catch (IOException e) { - throw new PSQLException("postgresql.stream.ioerror", e); + throw new PSQLException("postgresql.stream.ioerror", PSQLState.COMMUNICATION_ERROR, e); } return n; } @@ -254,7 +255,7 @@ public class PGStream { int c = pg_input.read(); if (c < 0) - throw new PSQLException("postgresql.stream.eof"); + throw new PSQLException("postgresql.stream.eof", PSQLState.COMMUNICATION_ERROR); else if (c == 0) { rst[s] = 0; @@ -277,7 +278,7 @@ public class PGStream } catch (IOException e) { - throw new PSQLException("postgresql.stream.ioerror", e); + throw new PSQLException("postgresql.stream.ioerror", PSQLState.COMMUNICATION_ERROR, e); } return encoding.decode(rst, 0, s); } @@ -389,13 +390,13 @@ public class PGStream { int w = pg_input.read(b, off + s, siz - s); if (w < 0) - throw new PSQLException("postgresql.stream.eof"); + throw new PSQLException("postgresql.stream.eof", PSQLState.COMMUNICATION_ERROR); s += w; } } catch (IOException e) { - throw new PSQLException("postgresql.stream.ioerror", e); + throw new PSQLException("postgresql.stream.ioerror", PSQLState.COMMUNICATION_ERROR, e); } } @@ -412,7 +413,7 @@ public class PGStream } catch (IOException e) { - throw new PSQLException("postgresql.stream.flush", e); + throw new PSQLException("postgresql.stream.flush", PSQLState.COMMUNICATION_ERROR, e); } } diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java index 122497676d2..f2f9d29081a 100644 --- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java +++ b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java @@ -6,7 +6,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/QueryExecutor.java,v 1.23 2003/08/11 21:18:47 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/QueryExecutor.java,v 1.24 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ import java.io.IOException; import java.sql.*; import org.postgresql.Driver; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; public class QueryExecutor { @@ -108,11 +109,11 @@ public class QueryExecutor private BaseResultSet executeV3() throws SQLException { - StringBuffer errorMessage = null; + PSQLException error = null; if (pgStream == null) { - throw new PSQLException("postgresql.con.closed"); + throw new PSQLException("postgresql.con.closed", PSQLState.CONNECTION_DOES_NOT_EXIST); } synchronized (pgStream) @@ -148,11 +149,16 @@ public class QueryExecutor // so, append messages to a string buffer and keep processing // check at the bottom to see if we need to throw an exception - if ( errorMessage == null ) - errorMessage = new StringBuffer(); + int l_elen = pgStream.ReceiveIntegerR(4); + String totalMessage = connection.getEncoding().decode(pgStream.Receive(l_elen-4)); + PSQLException l_error = PSQLException.parseServerError(totalMessage); + + if (error != null) { + error.setNextException(l_error); + } else { + error = l_error; + } - int l_elen = pgStream.ReceiveIntegerR(4); - errorMessage.append(connection.getEncoding().decode(pgStream.Receive(l_elen-4))); // keep processing break; case 'I': // Empty Query @@ -178,22 +184,20 @@ public class QueryExecutor case 'Z': // read ReadyForQuery //TODO: use size better - if (pgStream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup"); + if (pgStream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); //TODO: handle transaction status char l_tStatus = (char)pgStream.ReceiveChar(); l_endQuery = true; break; default: - throw new PSQLException("postgresql.con.type", - new Character((char) c)); + throw new PSQLException("postgresql.con.type", PSQLState.CONNECTION_FAILURE, new Character((char) c)); } } // did we get an error during this query? - if ( errorMessage != null ) - throw new SQLException( errorMessage.toString().trim() ); - + if ( error != null ) + throw error; //if an existing result set was passed in reuse it, else //create a new one @@ -216,7 +220,7 @@ public class QueryExecutor if (pgStream == null) { - throw new PSQLException("postgresql.con.closed"); + throw new PSQLException("postgresql.con.closed", PSQLState.CONNECTION_DOES_NOT_EXIST); } synchronized (pgStream) @@ -275,8 +279,7 @@ public class QueryExecutor l_endQuery = true; break; default: - throw new PSQLException("postgresql.con.type", - new Character((char) c)); + throw new PSQLException("postgresql.con.type", PSQLState.CONNECTION_FAILURE, new Character((char) c)); } } @@ -308,7 +311,7 @@ public class QueryExecutor for ( int i = 0; i < m_binds.length ; i++ ) { if ( m_binds[i] == null ) - throw new PSQLException("postgresql.prep.param", new Integer(i + 1)); + throw new PSQLException("postgresql.prep.param", PSQLState.PARAMETER_ERROR, new Integer(i + 1)); } try { @@ -349,7 +352,7 @@ public class QueryExecutor for ( int i = 0; i < m_binds.length ; i++ ) { if ( m_binds[i] == null ) - throw new PSQLException("postgresql.prep.param", new Integer(i + 1)); + throw new PSQLException("postgresql.prep.param", PSQLState.PARAMETER_ERROR, new Integer(i + 1)); } try { @@ -379,7 +382,7 @@ public class QueryExecutor private void receiveTupleV3(boolean isBinary) throws SQLException { if (fields == null) - throw new PSQLException("postgresql.con.tuple"); + throw new PSQLException("postgresql.con.tuple", PSQLState.CONNECTION_FAILURE); Object tuple = pgStream.ReceiveTupleV3(fields.length, isBinary); if (isBinary) binaryCursor = true; @@ -395,7 +398,7 @@ public class QueryExecutor private void receiveTupleV2(boolean isBinary) throws SQLException { if (fields == null) - throw new PSQLException("postgresql.con.tuple"); + throw new PSQLException("postgresql.con.tuple", PSQLState.CONNECTION_FAILURE); Object tuple = pgStream.ReceiveTupleV2(fields.length, isBinary); if (isBinary) binaryCursor = true; @@ -429,7 +432,7 @@ public class QueryExecutor } catch (NumberFormatException nfe) { - throw new PSQLException("postgresql.con.fathom", status); + throw new PSQLException("postgresql.con.fathom", PSQLState.CONNECTION_FAILURE, status); } } /* @@ -455,7 +458,7 @@ public class QueryExecutor } catch (NumberFormatException nfe) { - throw new PSQLException("postgresql.con.fathom", status); + throw new PSQLException("postgresql.con.fathom", PSQLState.CONNECTION_FAILURE, status); } } @@ -467,7 +470,7 @@ public class QueryExecutor //TODO: use the msgSize //TODO: use the tableOid, and tablePosition if (fields != null) - throw new PSQLException("postgresql.con.multres"); + throw new PSQLException("postgresql.con.multres", PSQLState.CONNECTION_FAILURE); int l_msgSize = pgStream.ReceiveIntegerR(4); int size = pgStream.ReceiveIntegerR(2); fields = new Field[size]; @@ -491,7 +494,7 @@ public class QueryExecutor private void receiveFieldsV2() throws SQLException { if (fields != null) - throw new PSQLException("postgresql.con.multres"); + throw new PSQLException("postgresql.con.multres", PSQLState.CONNECTION_FAILURE); int size = pgStream.ReceiveIntegerR(2); fields = new Field[size]; diff --git a/src/interfaces/jdbc/org/postgresql/errors.properties b/src/interfaces/jdbc/org/postgresql/errors.properties index 6f5f2550ab3..9b8edc3a5f4 100644 --- a/src/interfaces/jdbc/org/postgresql/errors.properties +++ b/src/interfaces/jdbc/org/postgresql/errors.properties @@ -9,6 +9,8 @@ postgresql.con.invalidchar:Invalid character data was found. This is most likel postgresql.con.closed:Connection is closed. Operation is not permitted. postgresql.con.creobj:Failed to create object for {0} {1} postgresql.con.failed:The connection attempt failed because {0} +postgresql.con.failed.bad.encoding:The connection attempt failed trying to get the server encoding +postgresql.con.failed.bad.autocommit:The connection attempt failed trying to get the autocommit status postgresql.con.fathom:Unable to fathom update count {0} postgresql.con.garbled:Garbled data received. postgresql.con.ioerror:An IO erro occured while sending to the backend - {0} @@ -29,6 +31,11 @@ postgresql.con.isolevel:Transaction isolation level {0} is not supported. postgresql.con.tuple:Tuple received before MetaData. postgresql.con.type:Unknown Response Type {0} postgresql.con.user:The user property is missing. It is mandatory. +postgresql.error.detail:Detail: {0} +postgresql.error.hint:Hint: {0} +postgresql.error.position:Position: {0} +postgresql.error.where:Where: {0} +postgresql.error.location:Location: {0} postgresql.fp.error:FastPath call returned {0} postgresql.fp.expint:Fastpath call {0} - No result was returned and we expected an integer. postgresql.fp.protocol:FastPath protocol error: {0} diff --git a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java index 1b250a2bf70..08015d18dbf 100644 --- a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java +++ b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java @@ -6,7 +6,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/fastpath/Attic/Fastpath.java,v 1.14 2003/05/29 04:39:51 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/fastpath/Attic/Fastpath.java,v 1.15 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ import org.postgresql.Driver; import org.postgresql.core.BaseConnection; import org.postgresql.core.PGStream; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; /* * This class implements the Fastpath api. @@ -100,14 +101,14 @@ public class Fastpath } catch (IOException ioe) { - throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe); + throw new PSQLException("postgresql.fp.send", PSQLState.COMMUNICATION_ERROR, new Integer(fnid), ioe); } // Now handle the result // Now loop, reading the results Object result = null; // our result - StringBuffer errorMessage = null; + PSQLException error = null; int c; boolean l_endQuery = false; while (!l_endQuery) @@ -124,11 +125,16 @@ public class Fastpath //------------------------------ // Error message returned case 'E': - if ( errorMessage == null ) - errorMessage = new StringBuffer(); - int l_elen = stream.ReceiveIntegerR(4); - errorMessage.append(conn.getEncoding().decode(stream.Receive(l_elen-4))); + String totalMessage = conn.getEncoding().decode(stream.Receive(l_elen-4)); + PSQLException l_error = PSQLException.parseServerError(totalMessage); + + if (error != null) { + error.setNextException(l_error); + } else { + error = l_error; + } + break; //------------------------------ // Notice from backend @@ -165,7 +171,7 @@ public class Fastpath case 'Z': //TODO: use size better - if (stream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup"); + if (stream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); //TODO: handle transaction status char l_tStatus = (char)stream.ReceiveChar(); l_endQuery = true; @@ -176,8 +182,8 @@ public class Fastpath } } - if ( errorMessage != null ) - throw new PSQLException("postgresql.fp.error", errorMessage.toString()); + if ( error != null ) + throw error; return result; } @@ -208,7 +214,8 @@ public class Fastpath } catch (IOException ioe) { - throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe); + //Should be sending exception as second arg. + throw new PSQLException("postgresql.fp.send", PSQLState.COMMUNICATION_ERROR, new Integer(fnid), ioe); } // Now handle the result diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java index c3d644bdbf9..ba9acb9e5ac 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java @@ -9,7 +9,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.23 2003/08/15 18:36:58 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.24 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -34,6 +34,7 @@ import org.postgresql.largeobject.LargeObjectManager; import org.postgresql.util.MD5Digest; import org.postgresql.util.PGobject; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; import org.postgresql.util.UnixCrypt; public abstract class AbstractJdbc1Connection implements BaseConnection @@ -126,7 +127,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection // 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"); + throw new PSQLException("postgresql.con.user", PSQLState.CONNECTION_REJECTED); this_driver = (Driver)d; this_url = url; @@ -200,11 +201,11 @@ public abstract class AbstractJdbc1Connection implements BaseConnection // 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"); + throw new PSQLException ("postgresql.con.refused", PSQLState.CONNECTION_REJECTED); } catch (IOException e) { - throw new PSQLException ("postgresql.con.failed", e); + throw new PSQLException ("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } //Now do the protocol work @@ -247,7 +248,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection // The most common one to be thrown here is: // "User authentication failed" // - throw new PSQLException("postgresql.con.misc", pgStream.ReceiveString(encoding)); + throw new PSQLException("postgresql.con.misc", PSQLState.CONNECTION_REJECTED, pgStream.ReceiveString(encoding)); case 'N': // Server does not support ssl @@ -267,7 +268,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection } catch (IOException e) { - throw new PSQLException("postgresql.con.failed", e); + throw new PSQLException("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } @@ -313,16 +314,16 @@ public abstract class AbstractJdbc1Connection implements BaseConnection // 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"); + throw new PSQLException ("postgresql.con.refused", PSQLState.CONNECTION_REJECTED); } catch (IOException e) { - throw new PSQLException ("postgresql.con.failed", e); + throw new PSQLException ("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } openConnectionV2(p_host, p_port, p_info, p_database, p_url, p_d, p_password); return; } - throw new PSQLException("postgresql.con.misc",encoding.decode(pgStream.Receive(l_elen-4))); + throw new PSQLException("postgresql.con.misc", PSQLState.CONNECTION_REJECTED, PSQLException.parseServerError(encoding.decode(pgStream.Receive(l_elen-4)))); case 'R': // Get the message length @@ -362,12 +363,12 @@ public abstract class AbstractJdbc1Connection implements BaseConnection case AUTH_REQ_KRB4: if (Driver.logDebug) Driver.debug("postgresql: KRB4"); - throw new PSQLException("postgresql.con.kerb4"); + throw new PSQLException("postgresql.con.kerb4", PSQLState.CONNECTION_REJECTED); case AUTH_REQ_KRB5: if (Driver.logDebug) Driver.debug("postgresql: KRB5"); - throw new PSQLException("postgresql.con.kerb5"); + throw new PSQLException("postgresql.con.kerb5", PSQLState.CONNECTION_REJECTED); case AUTH_REQ_SCM: if (Driver.logDebug) @@ -408,12 +409,12 @@ public abstract class AbstractJdbc1Connection implements BaseConnection break; default: - throw new PSQLException("postgresql.con.auth", new Integer(areq)); + throw new PSQLException("postgresql.con.auth", PSQLState.CONNECTION_REJECTED, new Integer(areq)); } break; default: - throw new PSQLException("postgresql.con.authfail"); + throw new PSQLException("postgresql.con.authfail", PSQLState.CONNECTION_REJECTED); } } while (areq != AUTH_REQ_OK); @@ -421,7 +422,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection } catch (IOException e) { - throw new PSQLException("postgresql.con.failed", e); + throw new PSQLException("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } int beresp; @@ -435,13 +436,13 @@ public abstract class AbstractJdbc1Connection implements BaseConnection break; case 'K': int l_msgLen = pgStream.ReceiveIntegerR(4); - if (l_msgLen != 12) throw new PSQLException("postgresql.con.setup"); + if (l_msgLen != 12) throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); pid = pgStream.ReceiveIntegerR(4); ckey = pgStream.ReceiveIntegerR(4); break; case 'E': int l_elen = pgStream.ReceiveIntegerR(4); - throw new PSQLException("postgresql.con.backend",encoding.decode(pgStream.Receive(l_elen-4))); + throw new PSQLException("postgresql.con.backend", PSQLState.CONNECTION_UNABLE_TO_CONNECT, PSQLException.parseServerError(encoding.decode(pgStream.Receive(l_elen-4)))); case 'N': int l_nlen = pgStream.ReceiveIntegerR(4); addWarning(encoding.decode(pgStream.Receive(l_nlen-4))); @@ -456,12 +457,12 @@ public abstract class AbstractJdbc1Connection implements BaseConnection default: if (Driver.logDebug) Driver.debug("invalid state="+ (char)beresp); - throw new PSQLException("postgresql.con.setup"); + throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); } } while (beresp != 'Z'); // read ReadyForQuery - if (pgStream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup"); + if (pgStream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); //TODO: handle transaction status char l_tStatus = (char)pgStream.ReceiveChar(); @@ -490,7 +491,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection if (! resultSet.next()) { - throw new PSQLException("postgresql.con.failed", "failed getting backend encoding"); + throw new PSQLException("postgresql.con.failed.bad.encoding", PSQLState.CONNECTION_UNABLE_TO_CONNECT); } String version = resultSet.getString(1); dbVersionNumber = extractVersionNumber(version); @@ -554,7 +555,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection // The most common one to be thrown here is: // "User authentication failed" // - throw new PSQLException("postgresql.con.misc", pgStream.ReceiveString(encoding)); + throw new PSQLException("postgresql.con.misc", PSQLState.CONNECTION_REJECTED, pgStream.ReceiveString(encoding)); case 'N': // Server does not support ssl @@ -574,7 +575,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection } catch (IOException e) { - throw new PSQLException("postgresql.con.failed", e); + throw new PSQLException("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } @@ -606,7 +607,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection // The most common one to be thrown here is: // "User authentication failed" // - throw new PSQLException("postgresql.con.misc", pgStream.ReceiveString(encoding)); + throw new PSQLException("postgresql.con.misc", PSQLState.CONNECTION_REJECTED, pgStream.ReceiveString(encoding)); case 'R': // Get the type of request @@ -644,12 +645,12 @@ public abstract class AbstractJdbc1Connection implements BaseConnection case AUTH_REQ_KRB4: if (Driver.logDebug) Driver.debug("postgresql: KRB4"); - throw new PSQLException("postgresql.con.kerb4"); + throw new PSQLException("postgresql.con.kerb4", PSQLState.CONNECTION_REJECTED); case AUTH_REQ_KRB5: if (Driver.logDebug) Driver.debug("postgresql: KRB5"); - throw new PSQLException("postgresql.con.kerb5"); + throw new PSQLException("postgresql.con.kerb5", PSQLState.CONNECTION_REJECTED); case AUTH_REQ_PASSWORD: if (Driver.logDebug) @@ -681,12 +682,12 @@ public abstract class AbstractJdbc1Connection implements BaseConnection break; default: - throw new PSQLException("postgresql.con.auth", new Integer(areq)); + throw new PSQLException("postgresql.con.auth", PSQLState.CONNECTION_REJECTED, new Integer(areq)); } break; default: - throw new PSQLException("postgresql.con.authfail"); + throw new PSQLException("postgresql.con.authfail", PSQLState.CONNECTION_REJECTED); } } while (areq != AUTH_REQ_OK); @@ -694,7 +695,8 @@ public abstract class AbstractJdbc1Connection implements BaseConnection } catch (IOException e) { - throw new PSQLException("postgresql.con.failed", e); + //Should be passing exception as arg. + throw new PSQLException("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } @@ -710,12 +712,12 @@ public abstract class AbstractJdbc1Connection implements BaseConnection ckey = pgStream.ReceiveIntegerR(4); break; case 'E': - throw new PSQLException("postgresql.con.backend", pgStream.ReceiveString(encoding)); + throw new PSQLException("postgresql.con.backend", PSQLState.CONNECTION_UNABLE_TO_CONNECT, pgStream.ReceiveString(encoding)); case 'N': addWarning(pgStream.ReceiveString(encoding)); break; default: - throw new PSQLException("postgresql.con.setup"); + throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); } } while (beresp == 'N'); @@ -732,9 +734,9 @@ public abstract class AbstractJdbc1Connection implements BaseConnection addWarning(pgStream.ReceiveString(encoding)); break; case 'E': - throw new PSQLException("postgresql.con.backend", pgStream.ReceiveString(encoding)); + throw new PSQLException("postgresql.con.backend", PSQLState.CONNECTION_UNABLE_TO_CONNECT, pgStream.ReceiveString(encoding)); default: - throw new PSQLException("postgresql.con.setup"); + throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); } } while (beresp == 'N'); @@ -763,7 +765,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection if (! resultSet.next()) { - throw new PSQLException("postgresql.con.failed", "failed getting backend encoding"); + throw new PSQLException("postgresql.con.failed.bad.encoding", PSQLState.CONNECTION_UNABLE_TO_CONNECT); } String version = resultSet.getString(1); dbVersionNumber = extractVersionNumber(version); @@ -799,7 +801,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection if (!acRset.next()) { - throw new PSQLException("postgresql.con.failed", "failed getting autocommit status"); + throw new PSQLException("postgresql.con.failed.bad.autocommit", PSQLState.CONNECTION_UNABLE_TO_CONNECT); } //if autocommit is currently off we need to turn it on //note that we will be in a transaction because the select above @@ -1036,7 +1038,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection } catch (Exception ex) { - throw new PSQLException("postgresql.con.creobj", type, ex); + throw new PSQLException("postgresql.con.creobj", PSQLState.CONNECTION_FAILURE, type, ex); } // should never be reached @@ -1409,7 +1411,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection isolationLevelSQL += "SERIALIZABLE"; break; default: - throw new PSQLException("postgresql.con.isolevel", + throw new PSQLException("postgresql.con.isolevel", PSQLState.TRANSACTION_STATE_INVALID, new Integer(isolationLevel)); } } @@ -1446,7 +1448,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection break; default: - throw new PSQLException("postgresql.con.isolevel", new Integer(isolationLevel)); + throw new PSQLException("postgresql.con.isolevel", PSQLState.TRANSACTION_STATE_INVALID, new Integer(isolationLevel)); } return sb.toString(); } @@ -1785,11 +1787,11 @@ public abstract class AbstractJdbc1Connection implements BaseConnection // 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"); + throw new PSQLException ("postgresql.con.refused", PSQLState.CONNECTION_REJECTED); } catch (IOException e) { - throw new PSQLException ("postgresql.con.failed", e); + throw new PSQLException ("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } // Now we need to construct and send a cancel packet @@ -1803,7 +1805,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection } catch (IOException e) { - throw new PSQLException("postgresql.con.failed", e); + throw new PSQLException("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } finally { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java index 5a8994f7a42..10d73d4c043 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java @@ -9,7 +9,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.15 2003/08/24 22:10:09 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.16 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -32,6 +32,7 @@ import org.postgresql.largeobject.*; import org.postgresql.util.PGbytea; import org.postgresql.util.PGtokenizer; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; public abstract class AbstractJdbc1ResultSet implements BaseResultSet { @@ -115,7 +116,7 @@ public abstract class AbstractJdbc1ResultSet implements BaseResultSet public boolean next() throws SQLException { if (rows == null) - throw new PSQLException("postgresql.con.closed"); + throw new PSQLException("postgresql.con.closed", PSQLState.CONNECTION_DOES_NOT_EXIST); if (++current_row >= rows.size()) { @@ -1139,7 +1140,7 @@ public abstract class AbstractJdbc1ResultSet implements BaseResultSet } catch (ParseException e) { - throw new PSQLException("postgresql.res.badtimestamp", new Integer(e.getErrorOffset()), s); + throw new PSQLException("postgresql.res.badtimestamp", PSQLState.UNKNOWN_STATE, new Integer(e.getErrorOffset()), s); } } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java index 5048f015328..4e2e369d8ca 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java @@ -10,6 +10,7 @@ import org.postgresql.largeobject.LargeObjectManager; import org.postgresql.util.PGbytea; import org.postgresql.util.PGobject; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -25,7 +26,7 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.Vector; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.33 2003/08/26 06:50:39 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.34 2003/09/08 17:30:22 barry Exp $ * This class defines methods of the jdbc1 specification. This class is * extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2 * methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement @@ -676,7 +677,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement */ public void cancel() throws SQLException { - throw new PSQLException("postgresql.unimplemented"); + throw new PSQLException("postgresql.unimplemented", PSQLState.NOT_IMPLEMENTED); } /* @@ -1558,7 +1559,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement } else { - throw new PSQLException("postgresql.prep.type"); + throw new PSQLException("postgresql.prep.type", PSQLState.INVALID_PARAMETER_TYPE); } break; case Types.BINARY: @@ -1570,7 +1571,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT); break; default: - throw new PSQLException("postgresql.prep.type"); + throw new PSQLException("postgresql.prep.type", PSQLState.INVALID_PARAMETER_TYPE); } } @@ -1954,7 +1955,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement private void bind(int paramIndex, Object s, String type) throws SQLException { if (paramIndex < 1 || paramIndex > m_binds.length) - throw new PSQLException("postgresql.prep.range"); + throw new PSQLException("postgresql.prep.range", PSQLState.PARAMETER_ERROR); if (paramIndex == 1 && isFunction) // need to registerOut instead throw new PSQLException ("postgresql.call.funcover"); m_binds[paramIndex - 1] = s; @@ -2096,7 +2097,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement } catch (Exception e) { - throw new PSQLException("postgresql.format.baddate",s , "yyyy-MM-dd[-tz]"); + throw new PSQLException("postgresql.format.baddate", PSQLState.UNKNOWN_STATE, s , "yyyy-MM-dd[-tz]"); } timezone = 0; if (timezoneLocation>7 && timezoneLocation+3 == s.length()) @@ -2127,7 +2128,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement } catch (Exception e) { - throw new PSQLException("postgresql.format.badtime",s, "HH:mm:ss[-tz]"); + throw new PSQLException("postgresql.format.badtime", PSQLState.UNKNOWN_STATE, s, "HH:mm:ss[-tz]"); } timezone = 0; if (timezoneLocation != -1 && timezoneLocation+3 == s.length()) @@ -2166,7 +2167,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement } catch (Exception e) { - throw new PSQLException("postgresql.format.badtimestamp", s, "yyyy-MM-dd HH:mm:ss[.xxxxxx][-tz]"); + throw new PSQLException("postgresql.format.badtimestamp", PSQLState.UNKNOWN_STATE, s, "yyyy-MM-dd HH:mm:ss[.xxxxxx][-tz]"); } timezone = 0; if (nanospos != -1) diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java index d06adb543fe..3921516928b 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java @@ -9,7 +9,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.21 2003/08/11 21:33:50 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.22 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -30,6 +30,7 @@ import org.postgresql.core.BaseStatement; import org.postgresql.core.Field; import org.postgresql.core.Encoding; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet @@ -421,7 +422,7 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra public Ref getRef(int i) throws SQLException { //The backend doesn't yet have SQL3 REF types - throw new PSQLException("postgresql.psqlnotimp"); + throw new PSQLException("postgresql.psqlnotimp", PSQLState.NOT_IMPLEMENTED); } @@ -513,7 +514,7 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra public void setFetchDirection(int direction) throws SQLException { - throw new PSQLException("postgresql.psqlnotimp"); + throw new PSQLException("postgresql.psqlnotimp", PSQLState.NOT_IMPLEMENTED); } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java index 2512a9790ef..690741f64be 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java @@ -8,8 +8,9 @@ import java.util.Vector; import org.postgresql.Driver; import org.postgresql.largeobject.*; import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.15 2003/06/30 16:38:30 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.16 2003/09/08 17:30:22 barry Exp $ * This class defines methods of the jdbc2 specification. This class extends * org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1 * methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement @@ -129,7 +130,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra public int getFetchDirection() throws SQLException { - throw new PSQLException("postgresql.psqlnotimp"); + throw new PSQLException("postgresql.psqlnotimp", PSQLState.NOT_IMPLEMENTED); } public int getResultSetConcurrency() throws SQLException diff --git a/src/interfaces/jdbc/org/postgresql/util/MessageTranslator.java b/src/interfaces/jdbc/org/postgresql/util/MessageTranslator.java index bd1408fb6ac..621525a351a 100644 --- a/src/interfaces/jdbc/org/postgresql/util/MessageTranslator.java +++ b/src/interfaces/jdbc/org/postgresql/util/MessageTranslator.java @@ -6,7 +6,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/util/Attic/MessageTranslator.java,v 1.4 2003/03/07 18:39:46 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/util/Attic/MessageTranslator.java,v 1.5 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -56,6 +56,14 @@ public class MessageTranslator return translator._translate(id, args); } + public final static String translate(String id, Object arg) + { + MessageTranslator translator = MessageTranslator.getInstance(); + Object[] args = new Object[1]; + args[0] = arg; + return translator._translate(id, args); + } + private final String _translate(String id, Object[] args) { String message; diff --git a/src/interfaces/jdbc/org/postgresql/util/PSQLException.java b/src/interfaces/jdbc/org/postgresql/util/PSQLException.java index 84ccc60ca2c..18b70dc86c8 100644 --- a/src/interfaces/jdbc/org/postgresql/util/PSQLException.java +++ b/src/interfaces/jdbc/org/postgresql/util/PSQLException.java @@ -7,7 +7,7 @@ * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/util/Attic/PSQLException.java,v 1.12 2003/08/11 21:18:47 barry Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/util/Attic/PSQLException.java,v 1.13 2003/09/08 17:30:22 barry Exp $ * *------------------------------------------------------------------------- */ @@ -16,11 +16,141 @@ package org.postgresql.util; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import java.sql.SQLException; +import java.util.Hashtable; import org.postgresql.Driver; public class PSQLException extends SQLException { private String message; + private PSQLState state; + + //-------start new constructors------- + + public PSQLException(String msg, PSQLState state) + { + this.state = state; + translate(msg, null); + if (Driver.logDebug) + Driver.debug("Exception: " + this); + } + + public PSQLException(String msg, PSQLState state, Object[] argv) + { + this.state = state; + translate(msg, argv); + if (Driver.logDebug) + Driver.debug("Exception: " + this); + } + + //Helper version for one arg + public PSQLException(String msg, PSQLState state, Object arg1) + { + this.state = state; + Object[] argv = new Object[1]; + argv[0] = arg1; + translate(msg, argv); + if (Driver.logDebug) + Driver.debug("Exception: " + this); + } + + //Helper version for two args + public PSQLException(String msg, PSQLState state, Object arg1, Object arg2) + { + this.state = state; + Object[] argv = new Object[2]; + argv[0] = arg1; + argv[1] = arg2; + translate(msg, argv); + if (Driver.logDebug) + Driver.debug("Exception: " + this); + } + + //-------end new constructors------- + + public static PSQLException parseServerError(String p_serverError) + { + if (Driver.logDebug) + Driver.debug("Constructing exception from server message: " + p_serverError); + char[] l_chars = p_serverError.toCharArray(); + int l_pos = 0; + int l_length = l_chars.length; + Hashtable l_mesgParts = new Hashtable(); + while (l_pos < l_length) { + char l_mesgType = l_chars[l_pos]; + if (l_mesgType != '\0') { + l_pos++; + int l_startString = l_pos; + while (l_chars[l_pos] != '\0' && l_pos < l_length) { + l_pos++; + } + String l_mesgPart = new String(l_chars, l_startString, l_pos - l_startString); + l_mesgParts.put(new Character(l_mesgType),l_mesgPart); + } + l_pos++; + } + + //Now construct the message from what the server sent + //The general format is: + //SEVERITY: Message \n + // Detail: \n + // Hint: \n + // Position: \n + // Where: \n + // Location: File:Line:Routine \n + // SQLState: \n + // + //Normally only the message and detail is included. + //If INFO level logging is enabled then detail, hint, position and where are + //included. If DEBUG level logging is enabled then all information + //is included. + + StringBuffer l_totalMessage = new StringBuffer(); + String l_message = (String)l_mesgParts.get(MESSAGE_TYPE_S); + if (l_message != null) + l_totalMessage.append(l_message).append(": "); + l_message = (String)l_mesgParts.get(MESSAGE_TYPE_M); + if (l_message != null) + l_totalMessage.append(l_message).append('\n'); + if (Driver.logInfo) { + l_message = (String)l_mesgParts.get(MESSAGE_TYPE_D); + if (l_message != null) + l_totalMessage.append(" ").append(MessageTranslator.translate("postgresql.error.detail", l_message)).append('\n'); + l_message = (String)l_mesgParts.get(MESSAGE_TYPE_H); + if (l_message != null) + l_totalMessage.append(" ").append(MessageTranslator.translate("postgresql.error.hint", l_message)).append('\n'); + l_message = (String)l_mesgParts.get(MESSAGE_TYPE_P); + if (l_message != null) + l_totalMessage.append(" ").append(MessageTranslator.translate("postgresql.error.position", l_message)).append('\n'); + l_message = (String)l_mesgParts.get(MESSAGE_TYPE_W); + if (l_message != null) + l_totalMessage.append(" ").append(MessageTranslator.translate("postgresql.error.where", l_message)).append('\n'); + } + if (Driver.logDebug) { + String l_file = (String)l_mesgParts.get(MESSAGE_TYPE_F); + String l_line = (String)l_mesgParts.get(MESSAGE_TYPE_L); + String l_routine = (String)l_mesgParts.get(MESSAGE_TYPE_R); + if (l_file != null || l_line != null || l_routine != null) + l_totalMessage.append(" ").append(MessageTranslator.translate("postgresql.error.location", l_file+":"+l_line+":"+l_routine)).append('\n'); + l_message = (String)l_mesgParts.get(MESSAGE_TYPE_C); + if (l_message != null) + l_totalMessage.append(" ").append("ServerSQLState: " + l_message).append('\n'); + } + + PSQLException l_return = new PSQLException(l_totalMessage.toString(), PSQLState.UNKNOWN_STATE); + l_return.state = new PSQLState((String)l_mesgParts.get(MESSAGE_TYPE_C)); + return l_return; + } + + private static final Character MESSAGE_TYPE_S = new Character('S'); + private static final Character MESSAGE_TYPE_M = new Character('M'); + private static final Character MESSAGE_TYPE_D = new Character('D'); + private static final Character MESSAGE_TYPE_H = new Character('H'); + private static final Character MESSAGE_TYPE_P = new Character('P'); + private static final Character MESSAGE_TYPE_W = new Character('W'); + private static final Character MESSAGE_TYPE_F = new Character('F'); + private static final Character MESSAGE_TYPE_L = new Character('L'); + private static final Character MESSAGE_TYPE_R = new Character('R'); + private static final Character MESSAGE_TYPE_C = new Character('C'); /* * This provides the same functionality to SQLException @@ -28,31 +158,16 @@ public class PSQLException extends SQLException */ public PSQLException(String error) { - super(); translate(error, null); if (Driver.logDebug) Driver.debug("Exception: " + this); } - /* - * A more generic entry point. - * @param error Error string or standard message id - * @param args Array of arguments - */ - public PSQLException(String error, Object[] args) - { - super(); - translate(error, args); - if (Driver.logDebug) - Driver.debug("Exception: " + this); - } - /* * Helper version for 1 arg */ public PSQLException(String error, Object arg) { - super(); Object[] argv = new Object[1]; argv[0] = arg; translate(error, argv); @@ -60,56 +175,35 @@ public class PSQLException extends SQLException Driver.debug("Exception: " + this); } - /* - * Helper version for 1 arg. This is used for debug purposes only with - * some unusual Exception's. It allows the originiating Exceptions stack - * trace to be returned. - */ - public PSQLException(String error, Exception ex) - { - super(); - Object[] argv = new Object[1]; - - try - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintWriter pw = new PrintWriter(baos); - pw.println("Exception: " + ex.toString() + "\nStack Trace:\n"); - ex.printStackTrace(pw); - pw.println("End of Stack Trace"); - pw.flush(); - argv[0] = baos.toString(); - pw.close(); - baos.close(); - } - catch (Exception ioe) - { - argv[0] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString(); + private void translate(String error, Object[] args) { + //We convert exception objects to Strings that + //contain the full stack trace + if (args != null) { + for (int i = 0; i < args.length; i++) { + if (args[i] instanceof Exception && !(args[i] instanceof PSQLException)) { + Exception ex = (Exception) args[i]; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintWriter pw = new PrintWriter(baos); + pw.println("Exception: " + ex.toString() + "\nStack Trace:\n"); + ex.printStackTrace(pw); + pw.println("End of Stack Trace"); + pw.flush(); + args[i] = baos.toString(); + pw.close(); + baos.close(); + } + catch (Exception ioe) + { + args[i] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString(); + } + } + } } - translate(error, argv); - if (Driver.logDebug) - Driver.debug("Exception: " + this); - } - - /* - * Helper version for 2 args - */ - public PSQLException(String error, Object arg1, Object arg2) - { - super(); - Object[] argv = new Object[2]; - argv[0] = arg1; - argv[1] = arg2; - translate(error, argv); - if (Driver.logDebug) - Driver.debug("Exception: " + this); - } - - private void translate(String error, Object[] args) - { message = MessageTranslator.translate(error, args); + } /* @@ -127,4 +221,9 @@ public class PSQLException extends SQLException { return message; } + + public String getSQLState() + { + return state.getState(); + } }