Thread: JDBC SQLStatus for Dynamic SQL, unsupported feature, invalid transaction state and others

This patch includes all the others and adds SQLState support for the following
additional conditions:

     public static final PSQLState parameter_mismatch = new PSQLState("07001");
     public static final PSQLState inv_parameter_type = new PSQLState("07006");
     public static final PSQLState unable_to_connect = new PSQLState("08001");
     public static final PSQLState inexistent_connection = new PSQLState("08003");
     public static final PSQLState connection_rejected = new PSQLState("08004");
     public static final PSQLState connection_failure = new PSQLState("08006");
     public static final PSQLState feature_not_supported = new PSQLState("0A000");
     public static final PSQLState data_exception = new PSQLState("22000");
     public static final PSQLState inv_transaction_state = new PSQLState("25000");

--
Fernando Nasser
Red Hat - Toronto                       E-Mail:  fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario   M4P 2C9
? src/interfaces/jdbc/org/postgresql/util/PSQLState.java
Index: src/interfaces/jdbc/org/postgresql/PG_Stream.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/PG_Stream.java,v
retrieving revision 1.17
diff -c -p -r1.17 PG_Stream.java
*** src/interfaces/jdbc/org/postgresql/PG_Stream.java    2002/08/20 04:26:02    1.17
--- src/interfaces/jdbc/org/postgresql/PG_Stream.java    2002/11/25 22:17:47
*************** public class PG_Stream
*** 137,147 ****
          {
              c = pg_input.read();
              if (c < 0)
!                 throw new PSQLException("postgresql.stream.eof");
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", e);
          }
          return c;
      }
--- 137,147 ----
          {
              c = pg_input.read();
              if (c < 0)
!                 throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
          }
          return c;
      }
*************** public class PG_Stream
*** 164,176 ****
                  int b = pg_input.read();

                  if (b < 0)
!                     throw new PSQLException("postgresql.stream.eof");
                  n = n | (b << (8 * i)) ;
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", e);
          }
          return n;
      }
--- 164,176 ----
                  int b = pg_input.read();

                  if (b < 0)
!                     throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
                  n = n | (b << (8 * i)) ;
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
          }
          return n;
      }
*************** public class PG_Stream
*** 193,205 ****
                  int b = pg_input.read();

                  if (b < 0)
!                     throw new PSQLException("postgresql.stream.eof");
                  n = b | (n << 8);
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", e);
          }
          return n;
      }
--- 193,205 ----
                  int b = pg_input.read();

                  if (b < 0)
!                     throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
                  n = b | (n << 8);
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
          }
          return n;
      }
*************** public class PG_Stream
*** 227,233 ****
                  {
                      int c = pg_input.read();
                      if (c < 0)
!                         throw new PSQLException("postgresql.stream.eof");
                      else if (c == 0)
                      {
                          rst[s] = 0;
--- 227,233 ----
                  {
                      int c = pg_input.read();
                      if (c < 0)
!                         throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
                      else if (c == 0)
                      {
                          rst[s] = 0;
*************** public class PG_Stream
*** 250,256 ****
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", e);
          }
          return encoding.decode(rst, 0, s);
      }
--- 250,256 ----
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
          }
          return encoding.decode(rst, 0, s);
      }
*************** public class PG_Stream
*** 330,342 ****
              {
                  int w = pg_input.read(b, off + s, siz - s);
                  if (w < 0)
!                     throw new PSQLException("postgresql.stream.eof");
                  s += w;
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", e);
          }
      }

--- 330,342 ----
              {
                  int w = pg_input.read(b, off + s, siz - s);
                  if (w < 0)
!                     throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
                  s += w;
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
          }
      }

*************** public class PG_Stream
*** 353,359 ****
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.flush", e);
          }
      }

--- 353,359 ----
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.flush", PSQLException.comm_link_error, e);
          }
      }

Index: src/interfaces/jdbc/org/postgresql/errors.properties
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/errors.properties,v
retrieving revision 1.15
diff -c -p -r1.15 errors.properties
*** src/interfaces/jdbc/org/postgresql/errors.properties    2002/11/14 05:35:45    1.15
--- src/interfaces/jdbc/org/postgresql/errors.properties    2002/11/25 22:17:47
*************** postgresql.updateable.beforestartdelete:
*** 83,89 ****
  postgresql.updateable.afterlastdelete:After end of result set. Can not call deleteRow().
  postgresql.updateable.notoninsertrow:Not on insert row.
  postgresql.updateable.inputstream:Input Stream is null.
! postgresql.updateable.ioerror:Input Stream Error.
  postgresql.call.noreturntype:A CallableStatement Function was declared but no call to 'registerOutParameter (1,
<some_type>)'was made. 
  postgresql.call.noinout:PostgreSQL only supports function return value [@ 1] (no OUT or INOUT arguments)
  postgresql.call.procasfunc:This Statement [{0}] defines a procedure call (needs ?= call <stmt> to be considered a
function.
--- 83,89 ----
  postgresql.updateable.afterlastdelete:After end of result set. Can not call deleteRow().
  postgresql.updateable.notoninsertrow:Not on insert row.
  postgresql.updateable.inputstream:Input Stream is null.
! postgresql.updateable.ioerror:Input Stream Error - {0}
  postgresql.call.noreturntype:A CallableStatement Function was declared but no call to 'registerOutParameter (1,
<some_type>)'was made. 
  postgresql.call.noinout:PostgreSQL only supports function return value [@ 1] (no OUT or INOUT arguments)
  postgresql.call.procasfunc:This Statement [{0}] defines a procedure call (needs ?= call <stmt> to be considered a
function.
Index: src/interfaces/jdbc/org/postgresql/core/Encoding.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/core/Encoding.java,v
retrieving revision 1.8
diff -c -p -r1.8 Encoding.java
*** src/interfaces/jdbc/org/postgresql/core/Encoding.java    2002/11/14 05:35:45    1.8
--- src/interfaces/jdbc/org/postgresql/core/Encoding.java    2002/11/25 22:17:47
*************** public class Encoding
*** 72,82 ****
      }

      /*
!      * Get an Encoding for from the given database encoding and
       * the encoding passed in by the user.
       */
!     public static Encoding getEncoding(String databaseEncoding,
!                                        String passedEncoding)
      {
          if (passedEncoding != null)
          {
--- 72,82 ----
      }

      /*
!      * Get an Encoding from the given database encoding and
       * the encoding passed in by the user.
+      * Return null if cannot find a suitable one.
       */
!     public static Encoding getEncoding(String databaseEncoding, String passedEncoding)
      {
          if (passedEncoding != null)
          {
*************** public class Encoding
*** 86,121 ****
              }
              else
              {
!                 return defaultEncoding();
              }
          }
          else
          {
!             return encodingForDatabaseEncoding(databaseEncoding);
!         }
!     }
!
!     /*
!      * Get an Encoding matching the given database encoding.
!      */
!     private static Encoding encodingForDatabaseEncoding(String databaseEncoding)
!     {
!         // If the backend encoding is known and there is a suitable
!         // encoding in the JVM we use that. Otherwise we fall back
!         // to the default encoding of the JVM.
!
!         if (encodings.containsKey(databaseEncoding))
!         {
!             String[] candidates = (String[]) encodings.get(databaseEncoding);
!             for (int i = 0; i < candidates.length; i++)
              {
!                 if (isAvailable(candidates[i]))
                  {
!                     return new Encoding(candidates[i]);
                  }
              }
          }
-         return defaultEncoding();
      }

      /*
--- 86,116 ----
              }
              else
              {
!                 // Requested encoding not available in the JVM
!                 return null;
              }
          }
          else
          {
!             // Get an Encoding matching the given database encoding.
!             // If the backend encoding is known and there is a suitable
!             // encoding in the JVM we return that.
!
!             if (encodings.containsKey(databaseEncoding))
              {
!                 String[] candidates = (String[]) encodings.get(databaseEncoding);
!                 for (int i = 0; i < candidates.length; i++)
                  {
!                     if (isAvailable(candidates[i]))
!                     {
!                         return new Encoding(candidates[i]);
!                     }
                  }
              }
+
+             // Bakend encoding UNKNOWN or not available in the JVM
+             return null;
          }
      }

      /*
*************** public class Encoding
*** 144,150 ****
          }
          catch (UnsupportedEncodingException e)
          {
!             throw new PSQLException("postgresql.stream.encoding", e);
          }
      }

--- 139,146 ----
          }
          catch (UnsupportedEncodingException e)
          {
!             // This will never happen as we made sure that the encoding is valid when the connection was created
!             throw new PSQLException("postgresql.stream.encoding", PSQLException.data_exception, e);
          }
      }

*************** public class Encoding
*** 169,175 ****
          }
          catch (UnsupportedEncodingException e)
          {
!             throw new PSQLException("postgresql.stream.encoding", e);
          }
      }

--- 165,172 ----
          }
          catch (UnsupportedEncodingException e)
          {
!             // This will never happen as we made sure that the encoding is valid when the connection was created
!             throw new PSQLException("postgresql.stream.encoding", PSQLException.data_exception, e);
          }
      }

*************** public class Encoding
*** 199,205 ****
          }
          catch (UnsupportedEncodingException e)
          {
!             throw new PSQLException("postgresql.res.encoding", e);
          }
      }

--- 196,203 ----
          }
          catch (UnsupportedEncodingException e)
          {
!             // This will never happen as we made sure that the encoding is valid when the connection was created
!             throw new PSQLException("postgresql.res.encoding", PSQLException.data_exception, e);
          }
      }

Index: src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java,v
retrieving revision 1.17
diff -c -p -r1.17 QueryExecutor.java
*** src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java    2002/11/14 05:35:45    1.17
--- src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java    2002/11/25 22:17:47
*************** public class QueryExecutor
*** 61,67 ****

          if (pg_stream == null)
          {
!             throw new PSQLException("postgresql.con.closed");
          }

          synchronized (pg_stream)
--- 61,67 ----

          if (pg_stream == null)
          {
!             throw new PSQLException("postgresql.con.closed", PSQLException.inexistent_connection);
          }

          synchronized (pg_stream)
*************** public class QueryExecutor
*** 120,126 ****
                          l_endQuery = true;
                          break;
                      default:
!                         throw new PSQLException("postgresql.con.type",
                                                  new Character((char) c));
                  }

--- 120,126 ----
                          l_endQuery = true;
                          break;
                      default:
!                         throw new PSQLException("postgresql.con.type", PSQLException.connection_failure,
                                                  new Character((char) c));
                  }

*************** public class QueryExecutor
*** 145,151 ****
              for (int i = 0 ; i < m_binds.length ; ++i)
              {
                  if (m_binds[i] == null)
!                     throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
                  pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i]));
                  pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString()));
              }
--- 145,151 ----
              for (int i = 0 ; i < m_binds.length ; ++i)
              {
                  if (m_binds[i] == null)
!                     throw new PSQLException("postgresql.prep.param", PSQLException.parameter_mismatch, new Integer(i
+1)); 
                  pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i]));
                  pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString()));
              }
*************** public class QueryExecutor
*** 156,162 ****
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.con.ioerror", e);
          }
      }

--- 156,162 ----
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.con.ioerror", PSQLException.comm_link_error, e);
          }
      }

*************** public class QueryExecutor
*** 168,174 ****
      private void receiveTuple(boolean isBinary) throws SQLException
      {
          if (fields == null)
!             throw new PSQLException("postgresql.con.tuple");
          Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
          if (isBinary)
              binaryCursor = true;
--- 168,174 ----
      private void receiveTuple(boolean isBinary) throws SQLException
      {
          if (fields == null)
!             throw new PSQLException("postgresql.con.tuple", PSQLException.connection_failure);
          Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
          if (isBinary)
              binaryCursor = true;
*************** public class QueryExecutor
*** 199,205 ****
          }
          catch (NumberFormatException nfe)
          {
!             throw new PSQLException("postgresql.con.fathom", status);
          }
      }

--- 199,205 ----
          }
          catch (NumberFormatException nfe)
          {
!             throw new PSQLException("postgresql.con.fathom", PSQLException.connection_failure, status);
          }
      }

*************** public class QueryExecutor
*** 209,215 ****
      private void receiveFields() throws SQLException
      {
          if (fields != null)
!             throw new PSQLException("postgresql.con.multres");

          int size = pg_stream.ReceiveIntegerR(2);
          fields = new Field[size];
--- 209,215 ----
      private void receiveFields() throws SQLException
      {
          if (fields != null)
!             throw new PSQLException("postgresql.con.multres", PSQLException.connection_failure);

          int size = pg_stream.ReceiveIntegerR(2);
          fields = new Field[size];
Index: src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java,v
retrieving revision 1.11
diff -c -p -r1.11 Fastpath.java
*** src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java    2002/09/06 21:23:05    1.11
--- src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java    2002/11/25 22:17:47
*************** public class Fastpath
*** 81,87 ****
              }
              catch (IOException ioe)
              {
!                 throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe);
              }

              // Now handle the result
--- 81,89 ----
              }
              catch (IOException ioe)
              {
!                 throw new PSQLException("postgresql.fp.send",
!                                         PSQLException.comm_link_error,
!                                         new Integer(fnid), ioe);
              }

              // Now handle the result
Index: src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java,v
retrieving revision 1.13
diff -c -p -r1.13 AbstractJdbc1Connection.java
*** src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java    2002/11/14 05:35:45    1.13
--- src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java    2002/11/25 22:17:47
*************** public abstract class AbstractJdbc1Conne
*** 104,110 ****
          // 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 = (org.postgresql.Driver)d;
          this_url = url;
--- 104,110 ----
          // 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", PSQLException.connection_rejected);

          this_driver = (org.postgresql.Driver)d;
          this_url = url;
*************** public abstract class AbstractJdbc1Conne
*** 164,174 ****
              // Added by Peter Mount <peter@retep.org.uk>
              // 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
--- 164,174 ----
              // Added by Peter Mount <peter@retep.org.uk>
              // 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", PSQLException.connection_rejected);
          }
          catch (IOException e)
          {
!             throw new PSQLException ("postgresql.con.failed", PSQLException.unable_to_connect, e);
          }

          // Now we need to construct and send a startup packet
*************** public abstract class AbstractJdbc1Conne
*** 199,205 ****
                          // 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
--- 199,206 ----
                          // The most common one to be thrown here is:
                          // "User authentication failed"
                          //
!                         throw new PSQLException("postgresql.con.misc", PSQLException.connection_rejected,
!                                                 pg_stream.ReceiveString(encoding));

                      case 'R':
                          // Get the type of request
*************** public abstract class AbstractJdbc1Conne
*** 237,248 ****
                              case AUTH_REQ_KRB4:
                                  if (org.postgresql.Driver.logDebug)
                                      org.postgresql.Driver.debug("postgresql: KRB4");
!                                 throw new PSQLException("postgresql.con.kerb4");

                              case AUTH_REQ_KRB5:
                                  if (org.postgresql.Driver.logDebug)
                                      org.postgresql.Driver.debug("postgresql: KRB5");
!                                 throw new PSQLException("postgresql.con.kerb5");

                              case AUTH_REQ_PASSWORD:
                                  if (org.postgresql.Driver.logDebug)
--- 238,249 ----
                              case AUTH_REQ_KRB4:
                                  if (org.postgresql.Driver.logDebug)
                                      org.postgresql.Driver.debug("postgresql: KRB4");
!                                 throw new PSQLException("postgresql.con.kerb4", PSQLException.connection_rejected);

                              case AUTH_REQ_KRB5:
                                  if (org.postgresql.Driver.logDebug)
                                      org.postgresql.Driver.debug("postgresql: KRB5");
!                                 throw new PSQLException("postgresql.con.kerb5", PSQLException.connection_rejected);

                              case AUTH_REQ_PASSWORD:
                                  if (org.postgresql.Driver.logDebug)
*************** public abstract class AbstractJdbc1Conne
*** 274,285 ****
                                  break;

                              default:
!                                 throw new PSQLException("postgresql.con.auth", new Integer(areq));
                          }
                          break;

                      default:
!                         throw new PSQLException("postgresql.con.authfail");
                  }
              }
              while (areq != AUTH_REQ_OK);
--- 275,287 ----
                                  break;

                              default:
!                                 throw new PSQLException("postgresql.con.auth", PSQLException.connection_rejected,
!                                                         new Integer(areq));
                          }
                          break;

                      default:
!                         throw new PSQLException("postgresql.con.authfail", PSQLException.connection_rejected);
                  }
              }
              while (areq != AUTH_REQ_OK);
*************** public abstract class AbstractJdbc1Conne
*** 287,293 ****
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.con.failed", e);
          }


--- 289,295 ----
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.con.failed", PSQLException.unable_to_connect, e);
          }


*************** public abstract class AbstractJdbc1Conne
*** 303,314 ****
                      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');
--- 305,317 ----
                      ckey = pg_stream.ReceiveIntegerR(4);
                      break;
                  case 'E':
!                     throw new PSQLException("postgresql.con.backend", PSQLException.unable_to_connect,
!                                             pg_stream.ReceiveString(encoding));
                  case 'N':
                      addWarning(pg_stream.ReceiveString(encoding));
                      break;
                  default:
!                     throw new PSQLException("postgresql.con.setup", PSQLException.unable_to_connect);
              }
          }
          while (beresp == 'N');
*************** public abstract class AbstractJdbc1Conne
*** 325,333 ****
                      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');
--- 328,337 ----
                      addWarning(pg_stream.ReceiveString(encoding));
                      break;
                  case 'E':
!                     throw new PSQLException("postgresql.con.backend", PSQLException.unable_to_connect,
!                                             pg_stream.ReceiveString(encoding));
                  default:
!                     throw new PSQLException("postgresql.con.setup", PSQLException.unable_to_connect);
              }
          }
          while (beresp == 'N');
*************** public abstract class AbstractJdbc1Conne
*** 355,367 ****

          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"));
          //In 7.3 we are forced to do a second roundtrip to handle the case
          //where a database may not be running in autocommit mode
          //jdbc by default assumes autocommit is on until setAutoCommit(false)
--- 359,372 ----

          if (! resultSet.next())
          {
!             throw new PSQLException("postgresql.con.failed", PSQLException.unable_to_connect,
!                                     "failed getting backend encoding");
          }
          String version = resultSet.getString(1);
          dbVersionNumber = extractVersionNumber(version);

          String dbEncoding = resultSet.getString(2);
!
          //In 7.3 we are forced to do a second roundtrip to handle the case
          //where a database may not be running in autocommit mode
          //jdbc by default assumes autocommit is on until setAutoCommit(false)
*************** public abstract class AbstractJdbc1Conne
*** 377,386 ****

              //set encoding to be unicode
              encoding = Encoding.getEncoding("UNICODE", null);

              if (!acRset.next())
              {
!                 throw new PSQLException("postgresql.con.failed", "failed getting autocommit status");
              }
              //if autocommit is currently off we need to turn it on
              //note that we will be in a transaction because the select above
--- 382,396 ----

              //set encoding to be unicode
              encoding = Encoding.getEncoding("UNICODE", null);
+             if (info.getProperty("charSet") != null)
+             {
+                 addWarning("Obsolete charSet connection property ignored");
+             }

              if (!acRset.next())
              {
!                 throw new PSQLException("postgresql.con.failed", PSQLException.unable_to_connect,
!                                         "failed getting autocommit status");
              }
              //if autocommit is currently off we need to turn it on
              //note that we will be in a transaction because the select above
*************** public abstract class AbstractJdbc1Conne
*** 391,396 ****
--- 401,424 ----
                  ExecSQL("set autocommit = on; commit;");
              }
          }
+         else
+         {
+             // Try setting the encoding to the requested encoding or backend encoding
+             encoding = Encoding.getEncoding(dbEncoding, info.getProperty("charSet"));
+
+             if (encoding == null)
+             {
+                 if (info.getProperty("charSet") != null)
+                 {
+                     addWarning("Requested encoding not available in the JVM - using JVM default encoding");
+                 }
+                 else
+                 {
+                     addWarning("Backend encoding unknown or not available in the JVM - using JVM default encoding");
+                 }
+                 encoding = Encoding.defaultEncoding();
+             }
+         }

          // Initialise object handling
          initObjectTypes();
*************** public abstract class AbstractJdbc1Conne
*** 477,483 ****
      {
          if (isClosed())
          {
!             throw new PSQLException("postgresql.con.closed");
          }
          return new QueryExecutor(new String[] {sql}, EMPTY_OBJECT_ARRAY, stat, pg_stream,
(java.sql.Connection)this).execute();
      }
--- 505,511 ----
      {
          if (isClosed())
          {
!             throw new PSQLException("postgresql.con.closed", PSQLException.inexistent_connection);
          }
          return new QueryExecutor(new String[] {sql}, EMPTY_OBJECT_ARRAY, stat, pg_stream,
(java.sql.Connection)this).execute();
      }
*************** public abstract class AbstractJdbc1Conne
*** 500,506 ****
      {
          if (isClosed())
          {
!             throw new PSQLException("postgresql.con.closed");
          }
          return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute();
      }
--- 528,534 ----
      {
          if (isClosed())
          {
!             throw new PSQLException("postgresql.con.closed", PSQLException.inexistent_connection);
          }
          return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute();
      }
*************** public abstract class AbstractJdbc1Conne
*** 695,701 ****
          }
          catch (Exception ex)
          {
!             throw new PSQLException("postgresql.con.creobj", type, ex);
          }

          // should never be reached
--- 723,729 ----
          }
          catch (Exception ex)
          {
!             throw new PSQLException("postgresql.con.creobj", PSQLException.connection_failure, type, ex);
          }

          // should never be reached
*************** public abstract class AbstractJdbc1Conne
*** 744,750 ****
                  return ((Serialize)x).storeObject(o);

              // Thow an exception because the type is unknown
!             throw new PSQLException("postgresql.con.strobj");

          }
          catch (SQLException sx)
--- 772,778 ----
                  return ((Serialize)x).storeObject(o);

              // Thow an exception because the type is unknown
!             throw new PSQLException("postgresql.con.strobj", PSQLException.data_exception);

          }
          catch (SQLException sx)
*************** public abstract class AbstractJdbc1Conne
*** 1117,1123 ****
                      isolationLevelSQL += "SERIALIZABLE";
                      break;
                  default:
!                     throw new PSQLException("postgresql.con.isolevel",
                                              new Integer(isolationLevel));
              }
          }
--- 1145,1151 ----
                      isolationLevelSQL += "SERIALIZABLE";
                      break;
                  default:
!                     throw new PSQLException("postgresql.con.isolevel", PSQLException.inv_transaction_state,
                                              new Integer(isolationLevel));
              }
          }
*************** public abstract class AbstractJdbc1Conne
*** 1154,1160 ****
                  break;

              default:
!                 throw new PSQLException("postgresql.con.isolevel", new Integer(isolationLevel));
          }
          return sb.toString();
      }
--- 1182,1189 ----
                  break;

              default:
!                 throw new PSQLException("postgresql.con.isolevel", PSQLException.inv_transaction_state,
!                                         new Integer(isolationLevel));
          }
          return sb.toString();
      }
Index: src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java,v
retrieving revision 1.7
diff -c -p -r1.7 AbstractJdbc1ResultSet.java
*** src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java    2002/10/19 22:10:36    1.7
--- src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java    2002/11/25 22:17:48
*************** public abstract class AbstractJdbc1Resul
*** 60,66 ****
      public boolean next() throws SQLException
      {
          if (rows == null)
!             throw new PSQLException("postgresql.con.closed");

          if (++current_row >= rows.size())
              return false;
--- 60,66 ----
      public boolean next() throws SQLException
      {
          if (rows == null)
!             throw new PSQLException("postgresql.con.closed", PSQLException.inexistent_connection);

          if (++current_row >= rows.size())
              return false;
Index: src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java,v
retrieving revision 1.14
diff -c -p -r1.14 AbstractJdbc1Statement.java
*** src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java    2002/11/20 07:34:32    1.14
--- src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java    2002/11/25 22:17:48
*************** public abstract class AbstractJdbc1State
*** 1378,1384 ****
                  }
                  else
                  {
!                     throw new PSQLException("postgresql.prep.type");
                  }
                  break;
              case Types.BINARY:
--- 1378,1384 ----
                  }
                  else
                  {
!                     throw new PSQLException("postgresql.prep.type", PSQLException.inv_parameter_type);
                  }
                  break;
              case Types.BINARY:
*************** public abstract class AbstractJdbc1State
*** 1389,1395 ****
                  setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT);
                  break;
              default:
!                 throw new PSQLException("postgresql.prep.type");
          }
      }

--- 1389,1395 ----
                  setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT);
                  break;
              default:
!                 throw new PSQLException("postgresql.prep.type", PSQLException.inv_parameter_type);
          }
      }

*************** public abstract class AbstractJdbc1State
*** 1798,1804 ****
      protected void bind(int paramIndex, Object s, String type) throws SQLException
      {
          if (paramIndex < 1 || paramIndex > m_binds.length)
!             throw new PSQLException("postgresql.prep.range");
          if (paramIndex == 1 && isFunction) // need to registerOut instead
              throw new PSQLException ("postgresql.call.funcover");
          m_binds[paramIndex - 1] = s;
--- 1798,1804 ----
      protected void bind(int paramIndex, Object s, String type) throws SQLException
      {
          if (paramIndex < 1 || paramIndex > m_binds.length)
!             throw new PSQLException("postgresql.prep.range", PSQLException.parameter_mismatch);
          if (paramIndex == 1 && isFunction) // need to registerOut instead
              throw new PSQLException ("postgresql.call.funcover");
          m_binds[paramIndex - 1] = s;
Index: src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java,v
retrieving revision 1.2
diff -c -p -r1.2 AbstractJdbc2Connection.java
*** src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java    2002/09/06 21:23:06    1.2
--- src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java    2002/11/25 22:17:48
*************** public abstract class AbstractJdbc2Conne
*** 64,74 ****
              // Added by Peter Mount <peter@retep.org.uk>
              // 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
--- 64,74 ----
              // Added by Peter Mount <peter@retep.org.uk>
              // 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", PSQLException.connection_rejected);
          }
          catch (IOException e)
          {
!             throw new PSQLException ("postgresql.con.failed", PSQLException.unable_to_connect, e);
          }

          // Now we need to construct and send a cancel packet
*************** public abstract class AbstractJdbc2Conne
*** 82,88 ****
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.con.failed", e);
          }
          finally
          {
--- 82,88 ----
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.con.failed", PSQLException.comm_link_error, e);
          }
          finally
          {
Index: src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java,v
retrieving revision 1.10
diff -c -p -r1.10 AbstractJdbc2ResultSet.java
*** src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java    2002/11/04 06:42:33    1.10
--- src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java    2002/11/25 22:17:48
*************** public abstract class AbstractJdbc2Resul
*** 399,405 ****
      public Ref getRef(int i) throws SQLException
      {
          //The backend doesn't yet have SQL3 REF types
!         throw new PSQLException("postgresql.psqlnotimp");
      }


--- 399,405 ----
      public Ref getRef(int i) throws SQLException
      {
          //The backend doesn't yet have SQL3 REF types
!         throw new PSQLException("postgresql.psqlnotimp", PSQLException.feature_not_supported);
      }


*************** public abstract class AbstractJdbc2Resul
*** 491,497 ****

      public void setFetchDirection(int direction) throws SQLException
      {
!         throw new PSQLException("postgresql.psqlnotimp");
      }


--- 491,497 ----

      public void setFetchDirection(int direction) throws SQLException
      {
!         throw new PSQLException("postgresql.psqlnotimp", PSQLException.feature_not_supported);
      }


*************** public abstract class AbstractJdbc2Resul
*** 750,756 ****
          }
          catch (IOException ie)
          {
!             throw new PSQLException("postgresql.updateable.ioerror" + ie);
          }

          updateValue(columnIndex, theData);
--- 750,756 ----
          }
          catch (IOException ie)
          {
!             throw new PSQLException("postgresql.updateable.ioerror", ie);
          }

          updateValue(columnIndex, theData);
*************** public abstract class AbstractJdbc2Resul
*** 784,790 ****
          }
          catch (IOException ie)
          {
!             throw new PSQLException("postgresql.updateable.ioerror" + ie);
          }
          updateValue(columnIndex, theData);

--- 784,790 ----
          }
          catch (IOException ie)
          {
!             throw new PSQLException("postgresql.updateable.ioerror", ie);
          }
          updateValue(columnIndex, theData);

*************** public abstract class AbstractJdbc2Resul
*** 832,838 ****
          }
          catch (IOException ie)
          {
!             throw new PSQLException("postgresql.updateable.ioerror" + ie);
          }
          updateValue(columnIndex, theData);
      }
--- 832,838 ----
          }
          catch (IOException ie)
          {
!             throw new PSQLException("postgresql.updateable.ioerror", ie);
          }
          updateValue(columnIndex, theData);
      }
Index: src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v
retrieving revision 1.9
diff -c -p -r1.9 AbstractJdbc2Statement.java
*** src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java    2002/11/20 07:34:32    1.9
--- src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java    2002/11/25 22:17:48
*************** public abstract class AbstractJdbc2State
*** 128,134 ****

      public int getFetchDirection() throws SQLException
      {
!         throw new PSQLException("postgresql.psqlnotimp");
      }

      public int getFetchSize() throws SQLException
--- 128,134 ----

      public int getFetchDirection() throws SQLException
      {
!         throw new PSQLException("postgresql.psqlnotimp", PSQLException.feature_not_supported);
      }

      public int getFetchSize() throws SQLException
Index: src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java,v
retrieving revision 1.2
diff -c -p -r1.2 AbstractJdbc3DatabaseMetaData.java
*** src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java    2002/09/06 21:23:06    1.2
--- src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java    2002/11/25 22:17:49
*************** public abstract class AbstractJdbc3Datab
*** 323,329 ****
       */
      public int getSQLStateType() throws SQLException
      {
!         throw org.postgresql.Driver.notImplemented();
      }

      /**
--- 323,329 ----
       */
      public int getSQLStateType() throws SQLException
      {
!         return DatabaseMetaData.sqlStateXOpen;
      }

      /**
Index: src/interfaces/jdbc/org/postgresql/util/PSQLException.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/util/PSQLException.java,v
retrieving revision 1.7
diff -c -p -r1.7 PSQLException.java
*** src/interfaces/jdbc/org/postgresql/util/PSQLException.java    2001/11/19 22:33:39    1.7
--- src/interfaces/jdbc/org/postgresql/util/PSQLException.java    2002/11/25 22:17:51
*************** public class PSQLException extends SQLEx
*** 11,16 ****
--- 11,33 ----
      private String message;

      /*
+      * PSQLState constants
+      *
+      * Using the constants make the code more legible.
+      */
+
+     public static final PSQLState parameter_mismatch = new PSQLState("07001");
+     public static final PSQLState inv_parameter_type = new PSQLState("07006");
+     public static final PSQLState unable_to_connect = new PSQLState("08001");
+     public static final PSQLState inexistent_connection = new PSQLState("08003");
+     public static final PSQLState connection_rejected = new PSQLState("08004");
+     public static final PSQLState connection_failure = new PSQLState("08006");
+     public static final PSQLState comm_link_error = new PSQLState("08S01");
+     public static final PSQLState feature_not_supported = new PSQLState("0A000");
+     public static final PSQLState data_exception = new PSQLState("22000");
+     public static final PSQLState inv_transaction_state = new PSQLState("25000");
+
+     /*
       * This provides the same functionality to SQLException
       * @param error Error string
       */
*************** public class PSQLException extends SQLEx
*** 21,26 ****
--- 38,54 ----
      }

      /*
+      * Like the above, but sets SQLState
+      * @param error Error string
+      * @param sqlstate PSQLState constant
+      */
+     public PSQLException(String error, PSQLState sqlstate)
+     {
+         super("", sqlstate.toString());
+         translate(error, null);
+     }
+
+     /*
       * A more generic entry point.
       * @param error Error string or standard message id
       * @param args Array of arguments
*************** public class PSQLException extends SQLEx
*** 74,84 ****
--- 102,155 ----
      }

      /*
+      * Like the above, but sets the SQLState
+      */
+     public PSQLException(String error, PSQLState sqlstate, Exception ex)
+     {
+         super("", sqlstate.toString());
+
+         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();
+         }
+
+         translate(error, argv);
+     }
+
+     /*
       * 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);
+     }
+
+     /*
+      * Like the above, but sets SQLState
+      * @param error Error string
+      * @param sqlstate PSQLState constant
+      */
+     public PSQLException(String error, PSQLState sqlstate, Object arg1, Object arg2)
+     {
+         super("", sqlstate.toString());
          Object[] argv = new Object[2];
          argv[0] = arg1;
          argv[1] = arg2;

Re: JDBC SQLStatus for Dynamic SQL, unsupported feature,

From
Barry Lind
Date:
Fernando,

Can you provide a reason these patches are necessary?  Are there some
specific use cases that are trying to be addressed?

I am very reluctant to apply all of this.  The reason being, that
without a commitment on how error codes are going to be implemented in
the backend, I don't want to partially implement them in the jdbc
driver.  There needs to be a consistent implementation between the jdbc
driver and the backend (since the jdbc driver will end up passing the
backend's codes to the client).  Depending on what the backend
implementation is, that might even mean that the jdbc driver will
support error codes in a non-standard way.  I am much more concerned
with consistency between the two sets of error codes than I am with
following the standard at the moment.  I really want to avoid needing to
have the reinterpret all the backend error codes to conform to how these
patches think error codes should be handled.  That will be a maintenance
nightmare.

I think this patch goes beyond what I am comfortable applying without
any guidance on how/when/if error codes are going to be implemented in
the backend.

thanks,
--Barry



Fernando Nasser wrote:
> This patch includes all the others and adds SQLState support for the
> following additional conditions:
>
>     public static final PSQLState parameter_mismatch = new
> PSQLState("07001");
>     public static final PSQLState inv_parameter_type = new
> PSQLState("07006");
>     public static final PSQLState unable_to_connect = new
> PSQLState("08001");
>     public static final PSQLState inexistent_connection = new
> PSQLState("08003");
>     public static final PSQLState connection_rejected = new
> PSQLState("08004");
>     public static final PSQLState connection_failure = new
> PSQLState("08006");
>     public static final PSQLState feature_not_supported = new
> PSQLState("0A000");
>     public static final PSQLState data_exception = new PSQLState("22000");
>     public static final PSQLState inv_transaction_state = new
> PSQLState("25000");
>
>
> ------------------------------------------------------------------------
>
> ? src/interfaces/jdbc/org/postgresql/util/PSQLState.java
> Index: src/interfaces/jdbc/org/postgresql/PG_Stream.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/PG_Stream.java,v
> retrieving revision 1.17
> diff -c -p -r1.17 PG_Stream.java
> *** src/interfaces/jdbc/org/postgresql/PG_Stream.java    2002/08/20 04:26:02    1.17
> --- src/interfaces/jdbc/org/postgresql/PG_Stream.java    2002/11/25 22:17:47
> *************** public class PG_Stream
> *** 137,147 ****
>           {
>               c = pg_input.read();
>               if (c < 0)
> !                 throw new PSQLException("postgresql.stream.eof");
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", e);
>           }
>           return c;
>       }
> --- 137,147 ----
>           {
>               c = pg_input.read();
>               if (c < 0)
> !                 throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
>           }
>           return c;
>       }
> *************** public class PG_Stream
> *** 164,176 ****
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   n = n | (b << (8 * i)) ;
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", e);
>           }
>           return n;
>       }
> --- 164,176 ----
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
>                   n = n | (b << (8 * i)) ;
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
>           }
>           return n;
>       }
> *************** public class PG_Stream
> *** 193,205 ****
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   n = b | (n << 8);
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", e);
>           }
>           return n;
>       }
> --- 193,205 ----
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
>                   n = b | (n << 8);
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
>           }
>           return n;
>       }
> *************** public class PG_Stream
> *** 227,233 ****
>                   {
>                       int c = pg_input.read();
>                       if (c < 0)
> !                         throw new PSQLException("postgresql.stream.eof");
>                       else if (c == 0)
>                       {
>                           rst[s] = 0;
> --- 227,233 ----
>                   {
>                       int c = pg_input.read();
>                       if (c < 0)
> !                         throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
>                       else if (c == 0)
>                       {
>                           rst[s] = 0;
> *************** public class PG_Stream
> *** 250,256 ****
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", e);
>           }
>           return encoding.decode(rst, 0, s);
>       }
> --- 250,256 ----
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
>           }
>           return encoding.decode(rst, 0, s);
>       }
> *************** public class PG_Stream
> *** 330,342 ****
>               {
>                   int w = pg_input.read(b, off + s, siz - s);
>                   if (w < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   s += w;
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", e);
>           }
>       }
>
> --- 330,342 ----
>               {
>                   int w = pg_input.read(b, off + s, siz - s);
>                   if (w < 0)
> !                     throw new PSQLException("postgresql.stream.eof", PSQLException.comm_link_error);
>                   s += w;
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", PSQLException.comm_link_error, e);
>           }
>       }
>
> *************** public class PG_Stream
> *** 353,359 ****
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.flush", e);
>           }
>       }
>
> --- 353,359 ----
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.flush", PSQLException.comm_link_error, e);
>           }
>       }
>
> Index: src/interfaces/jdbc/org/postgresql/errors.properties
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/errors.properties,v
> retrieving revision 1.15
> diff -c -p -r1.15 errors.properties
> *** src/interfaces/jdbc/org/postgresql/errors.properties    2002/11/14 05:35:45    1.15
> --- src/interfaces/jdbc/org/postgresql/errors.properties    2002/11/25 22:17:47
> *************** postgresql.updateable.beforestartdelete:
> *** 83,89 ****
>   postgresql.updateable.afterlastdelete:After end of result set. Can not call deleteRow().
>   postgresql.updateable.notoninsertrow:Not on insert row.
>   postgresql.updateable.inputstream:Input Stream is null.
> ! postgresql.updateable.ioerror:Input Stream Error.
>   postgresql.call.noreturntype:A CallableStatement Function was declared but no call to 'registerOutParameter (1,
<some_type>)'was made. 
>   postgresql.call.noinout:PostgreSQL only supports function return value [@ 1] (no OUT or INOUT arguments)
>   postgresql.call.procasfunc:This Statement [{0}] defines a procedure call (needs ?= call <stmt> to be considered a
function.
> --- 83,89 ----
>   postgresql.updateable.afterlastdelete:After end of result set. Can not call deleteRow().
>   postgresql.updateable.notoninsertrow:Not on insert row.
>   postgresql.updateable.inputstream:Input Stream is null.
> ! postgresql.updateable.ioerror:Input Stream Error - {0}
>   postgresql.call.noreturntype:A CallableStatement Function was declared but no call to 'registerOutParameter (1,
<some_type>)'was made. 
>   postgresql.call.noinout:PostgreSQL only supports function return value [@ 1] (no OUT or INOUT arguments)
>   postgresql.call.procasfunc:This Statement [{0}] defines a procedure call (needs ?= call <stmt> to be considered a
function.
> Index: src/interfaces/jdbc/org/postgresql/core/Encoding.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/core/Encoding.java,v
> retrieving revision 1.8
> diff -c -p -r1.8 Encoding.java
> *** src/interfaces/jdbc/org/postgresql/core/Encoding.java    2002/11/14 05:35:45    1.8
> --- src/interfaces/jdbc/org/postgresql/core/Encoding.java    2002/11/25 22:17:47
> *************** public class Encoding
> *** 72,82 ****
>       }
>
>       /*
> !      * Get an Encoding for from the given database encoding and
>        * the encoding passed in by the user.
>        */
> !     public static Encoding getEncoding(String databaseEncoding,
> !                                        String passedEncoding)
>       {
>           if (passedEncoding != null)
>           {
> --- 72,82 ----
>       }
>
>       /*
> !      * Get an Encoding from the given database encoding and
>        * the encoding passed in by the user.
> +      * Return null if cannot find a suitable one.
>        */
> !     public static Encoding getEncoding(String databaseEncoding, String passedEncoding)
>       {
>           if (passedEncoding != null)
>           {
> *************** public class Encoding
> *** 86,121 ****
>               }
>               else
>               {
> !                 return defaultEncoding();
>               }
>           }
>           else
>           {
> !             return encodingForDatabaseEncoding(databaseEncoding);
> !         }
> !     }
> !
> !     /*
> !      * Get an Encoding matching the given database encoding.
> !      */
> !     private static Encoding encodingForDatabaseEncoding(String databaseEncoding)
> !     {
> !         // If the backend encoding is known and there is a suitable
> !         // encoding in the JVM we use that. Otherwise we fall back
> !         // to the default encoding of the JVM.
> !
> !         if (encodings.containsKey(databaseEncoding))
> !         {
> !             String[] candidates = (String[]) encodings.get(databaseEncoding);
> !             for (int i = 0; i < candidates.length; i++)
>               {
> !                 if (isAvailable(candidates[i]))
>                   {
> !                     return new Encoding(candidates[i]);
>                   }
>               }
>           }
> -         return defaultEncoding();
>       }
>
>       /*
> --- 86,116 ----
>               }
>               else
>               {
> !                 // Requested encoding not available in the JVM
> !                 return null;
>               }
>           }
>           else
>           {
> !             // Get an Encoding matching the given database encoding.
> !             // If the backend encoding is known and there is a suitable
> !             // encoding in the JVM we return that.
> !
> !             if (encodings.containsKey(databaseEncoding))
>               {
> !                 String[] candidates = (String[]) encodings.get(databaseEncoding);
> !                 for (int i = 0; i < candidates.length; i++)
>                   {
> !                     if (isAvailable(candidates[i]))
> !                     {
> !                         return new Encoding(candidates[i]);
> !                     }
>                   }
>               }
> +
> +             // Bakend encoding UNKNOWN or not available in the JVM
> +             return null;
>           }
>       }
>
>       /*
> *************** public class Encoding
> *** 144,150 ****
>           }
>           catch (UnsupportedEncodingException e)
>           {
> !             throw new PSQLException("postgresql.stream.encoding", e);
>           }
>       }
>
> --- 139,146 ----
>           }
>           catch (UnsupportedEncodingException e)
>           {
> !             // This will never happen as we made sure that the encoding is valid when the connection was created
> !             throw new PSQLException("postgresql.stream.encoding", PSQLException.data_exception, e);
>           }
>       }
>
> *************** public class Encoding
> *** 169,175 ****
>           }
>           catch (UnsupportedEncodingException e)
>           {
> !             throw new PSQLException("postgresql.stream.encoding", e);
>           }
>       }
>
> --- 165,172 ----
>           }
>           catch (UnsupportedEncodingException e)
>           {
> !             // This will never happen as we made sure that the encoding is valid when the connection was created
> !             throw new PSQLException("postgresql.stream.encoding", PSQLException.data_exception, e);
>           }
>       }
>
> *************** public class Encoding
> *** 199,205 ****
>           }
>           catch (UnsupportedEncodingException e)
>           {
> !             throw new PSQLException("postgresql.res.encoding", e);
>           }
>       }
>
> --- 196,203 ----
>           }
>           catch (UnsupportedEncodingException e)
>           {
> !             // This will never happen as we made sure that the encoding is valid when the connection was created
> !             throw new PSQLException("postgresql.res.encoding", PSQLException.data_exception, e);
>           }
>       }
>
> Index: src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java,v
> retrieving revision 1.17
> diff -c -p -r1.17 QueryExecutor.java
> *** src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java    2002/11/14 05:35:45    1.17
> --- src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java    2002/11/25 22:17:47
> *************** public class QueryExecutor
> *** 61,67 ****
>
>           if (pg_stream == null)
>           {
> !             throw new PSQLException("postgresql.con.closed");
>           }
>
>           synchronized (pg_stream)
> --- 61,67 ----
>
>           if (pg_stream == null)
>           {
> !             throw new PSQLException("postgresql.con.closed", PSQLException.inexistent_connection);
>           }
>
>           synchronized (pg_stream)
> *************** public class QueryExecutor
> *** 120,126 ****
>                           l_endQuery = true;
>                           break;
>                       default:
> !                         throw new PSQLException("postgresql.con.type",
>                                                   new Character((char) c));
>                   }
>
> --- 120,126 ----
>                           l_endQuery = true;
>                           break;
>                       default:
> !                         throw new PSQLException("postgresql.con.type", PSQLException.connection_failure,
>                                                   new Character((char) c));
>                   }
>
> *************** public class QueryExecutor
> *** 145,151 ****
>               for (int i = 0 ; i < m_binds.length ; ++i)
>               {
>                   if (m_binds[i] == null)
> !                     throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
>                   pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i]));
>                   pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString()));
>               }
> --- 145,151 ----
>               for (int i = 0 ; i < m_binds.length ; ++i)
>               {
>                   if (m_binds[i] == null)
> !                     throw new PSQLException("postgresql.prep.param", PSQLException.parameter_mismatch, new
Integer(i+ 1)); 
>                   pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i]));
>                   pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString()));
>               }
> *************** public class QueryExecutor
> *** 156,162 ****
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.con.ioerror", e);
>           }
>       }
>
> --- 156,162 ----
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.con.ioerror", PSQLException.comm_link_error, e);
>           }
>       }
>
> *************** public class QueryExecutor
> *** 168,174 ****
>       private void receiveTuple(boolean isBinary) throws SQLException
>       {
>           if (fields == null)
> !             throw new PSQLException("postgresql.con.tuple");
>           Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
>           if (isBinary)
>               binaryCursor = true;
> --- 168,174 ----
>       private void receiveTuple(boolean isBinary) throws SQLException
>       {
>           if (fields == null)
> !             throw new PSQLException("postgresql.con.tuple", PSQLException.connection_failure);
>           Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
>           if (isBinary)
>               binaryCursor = true;
> *************** public class QueryExecutor
> *** 199,205 ****
>           }
>           catch (NumberFormatException nfe)
>           {
> !             throw new PSQLException("postgresql.con.fathom", status);
>           }
>       }
>
> --- 199,205 ----
>           }
>           catch (NumberFormatException nfe)
>           {
> !             throw new PSQLException("postgresql.con.fathom", PSQLException.connection_failure, status);
>           }
>       }
>
> *************** public class QueryExecutor
> *** 209,215 ****
>       private void receiveFields() throws SQLException
>       {
>           if (fields != null)
> !             throw new PSQLException("postgresql.con.multres");
>
>           int size = pg_stream.ReceiveIntegerR(2);
>           fields = new Field[size];
> --- 209,215 ----
>       private void receiveFields() throws SQLException
>       {
>           if (fields != null)
> !             throw new PSQLException("postgresql.con.multres", PSQLException.connection_failure);
>
>           int size = pg_stream.ReceiveIntegerR(2);
>           fields = new Field[size];
> Index: src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java,v
> retrieving revision 1.11
> diff -c -p -r1.11 Fastpath.java
> *** src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java    2002/09/06 21:23:05    1.11
> --- src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java    2002/11/25 22:17:47
> *************** public class Fastpath
> *** 81,87 ****
>               }
>               catch (IOException ioe)
>               {
> !                 throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe);
>               }
>
>               // Now handle the result
> --- 81,89 ----
>               }
>               catch (IOException ioe)
>               {
> !                 throw new PSQLException("postgresql.fp.send",
> !                                         PSQLException.comm_link_error,
> !                                         new Integer(fnid), ioe);
>               }
>
>               // Now handle the result
> Index: src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java,v
> retrieving revision 1.13
> diff -c -p -r1.13 AbstractJdbc1Connection.java
> *** src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java    2002/11/14 05:35:45    1.13
> --- src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java    2002/11/25 22:17:47
> *************** public abstract class AbstractJdbc1Conne
> *** 104,110 ****
>           // 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 = (org.postgresql.Driver)d;
>           this_url = url;
> --- 104,110 ----
>           // 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", PSQLException.connection_rejected);
>
>           this_driver = (org.postgresql.Driver)d;
>           this_url = url;
> *************** public abstract class AbstractJdbc1Conne
> *** 164,174 ****
>               // Added by Peter Mount <peter@retep.org.uk>
>               // 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
> --- 164,174 ----
>               // Added by Peter Mount <peter@retep.org.uk>
>               // 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", PSQLException.connection_rejected);
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException ("postgresql.con.failed", PSQLException.unable_to_connect, e);
>           }
>
>           // Now we need to construct and send a startup packet
> *************** public abstract class AbstractJdbc1Conne
> *** 199,205 ****
>                           // 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
> --- 199,206 ----
>                           // The most common one to be thrown here is:
>                           // "User authentication failed"
>                           //
> !                         throw new PSQLException("postgresql.con.misc", PSQLException.connection_rejected,
> !                                                 pg_stream.ReceiveString(encoding));
>
>                       case 'R':
>                           // Get the type of request
> *************** public abstract class AbstractJdbc1Conne
> *** 237,248 ****
>                               case AUTH_REQ_KRB4:
>                                   if (org.postgresql.Driver.logDebug)
>                                       org.postgresql.Driver.debug("postgresql: KRB4");
> !                                 throw new PSQLException("postgresql.con.kerb4");
>
>                               case AUTH_REQ_KRB5:
>                                   if (org.postgresql.Driver.logDebug)
>                                       org.postgresql.Driver.debug("postgresql: KRB5");
> !                                 throw new PSQLException("postgresql.con.kerb5");
>
>                               case AUTH_REQ_PASSWORD:
>                                   if (org.postgresql.Driver.logDebug)
> --- 238,249 ----
>                               case AUTH_REQ_KRB4:
>                                   if (org.postgresql.Driver.logDebug)
>                                       org.postgresql.Driver.debug("postgresql: KRB4");
> !                                 throw new PSQLException("postgresql.con.kerb4", PSQLException.connection_rejected);
>
>                               case AUTH_REQ_KRB5:
>                                   if (org.postgresql.Driver.logDebug)
>                                       org.postgresql.Driver.debug("postgresql: KRB5");
> !                                 throw new PSQLException("postgresql.con.kerb5", PSQLException.connection_rejected);
>
>                               case AUTH_REQ_PASSWORD:
>                                   if (org.postgresql.Driver.logDebug)
> *************** public abstract class AbstractJdbc1Conne
> *** 274,285 ****
>                                   break;
>
>                               default:
> !                                 throw new PSQLException("postgresql.con.auth", new Integer(areq));
>                           }
>                           break;
>
>                       default:
> !                         throw new PSQLException("postgresql.con.authfail");
>                   }
>               }
>               while (areq != AUTH_REQ_OK);
> --- 275,287 ----
>                                   break;
>
>                               default:
> !                                 throw new PSQLException("postgresql.con.auth", PSQLException.connection_rejected,
> !                                                         new Integer(areq));
>                           }
>                           break;
>
>                       default:
> !                         throw new PSQLException("postgresql.con.authfail", PSQLException.connection_rejected);
>                   }
>               }
>               while (areq != AUTH_REQ_OK);
> *************** public abstract class AbstractJdbc1Conne
> *** 287,293 ****
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.con.failed", e);
>           }
>
>
> --- 289,295 ----
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.con.failed", PSQLException.unable_to_connect, e);
>           }
>
>
> *************** public abstract class AbstractJdbc1Conne
> *** 303,314 ****
>                       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');
> --- 305,317 ----
>                       ckey = pg_stream.ReceiveIntegerR(4);
>                       break;
>                   case 'E':
> !                     throw new PSQLException("postgresql.con.backend", PSQLException.unable_to_connect,
> !                                             pg_stream.ReceiveString(encoding));
>                   case 'N':
>                       addWarning(pg_stream.ReceiveString(encoding));
>                       break;
>                   default:
> !                     throw new PSQLException("postgresql.con.setup", PSQLException.unable_to_connect);
>               }
>           }
>           while (beresp == 'N');
> *************** public abstract class AbstractJdbc1Conne
> *** 325,333 ****
>                       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');
> --- 328,337 ----
>                       addWarning(pg_stream.ReceiveString(encoding));
>                       break;
>                   case 'E':
> !                     throw new PSQLException("postgresql.con.backend", PSQLException.unable_to_connect,
> !                                             pg_stream.ReceiveString(encoding));
>                   default:
> !                     throw new PSQLException("postgresql.con.setup", PSQLException.unable_to_connect);
>               }
>           }
>           while (beresp == 'N');
> *************** public abstract class AbstractJdbc1Conne
> *** 355,367 ****
>
>           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"));
>           //In 7.3 we are forced to do a second roundtrip to handle the case
>           //where a database may not be running in autocommit mode
>           //jdbc by default assumes autocommit is on until setAutoCommit(false)
> --- 359,372 ----
>
>           if (! resultSet.next())
>           {
> !             throw new PSQLException("postgresql.con.failed", PSQLException.unable_to_connect,
> !                                     "failed getting backend encoding");
>           }
>           String version = resultSet.getString(1);
>           dbVersionNumber = extractVersionNumber(version);
>
>           String dbEncoding = resultSet.getString(2);
> !
>           //In 7.3 we are forced to do a second roundtrip to handle the case
>           //where a database may not be running in autocommit mode
>           //jdbc by default assumes autocommit is on until setAutoCommit(false)
> *************** public abstract class AbstractJdbc1Conne
> *** 377,386 ****
>
>               //set encoding to be unicode
>               encoding = Encoding.getEncoding("UNICODE", null);
>
>               if (!acRset.next())
>               {
> !                 throw new PSQLException("postgresql.con.failed", "failed getting autocommit status");
>               }
>               //if autocommit is currently off we need to turn it on
>               //note that we will be in a transaction because the select above
> --- 382,396 ----
>
>               //set encoding to be unicode
>               encoding = Encoding.getEncoding("UNICODE", null);
> +             if (info.getProperty("charSet") != null)
> +             {
> +                 addWarning("Obsolete charSet connection property ignored");
> +             }
>
>               if (!acRset.next())
>               {
> !                 throw new PSQLException("postgresql.con.failed", PSQLException.unable_to_connect,
> !                                         "failed getting autocommit status");
>               }
>               //if autocommit is currently off we need to turn it on
>               //note that we will be in a transaction because the select above
> *************** public abstract class AbstractJdbc1Conne
> *** 391,396 ****
> --- 401,424 ----
>                   ExecSQL("set autocommit = on; commit;");
>               }
>           }
> +         else
> +         {
> +             // Try setting the encoding to the requested encoding or backend encoding
> +             encoding = Encoding.getEncoding(dbEncoding, info.getProperty("charSet"));
> +
> +             if (encoding == null)
> +             {
> +                 if (info.getProperty("charSet") != null)
> +                 {
> +                     addWarning("Requested encoding not available in the JVM - using JVM default encoding");
> +                 }
> +                 else
> +                 {
> +                     addWarning("Backend encoding unknown or not available in the JVM - using JVM default
encoding");
> +                 }
> +                 encoding = Encoding.defaultEncoding();
> +             }
> +         }
>
>           // Initialise object handling
>           initObjectTypes();
> *************** public abstract class AbstractJdbc1Conne
> *** 477,483 ****
>       {
>           if (isClosed())
>           {
> !             throw new PSQLException("postgresql.con.closed");
>           }
>           return new QueryExecutor(new String[] {sql}, EMPTY_OBJECT_ARRAY, stat, pg_stream,
(java.sql.Connection)this).execute();
>       }
> --- 505,511 ----
>       {
>           if (isClosed())
>           {
> !             throw new PSQLException("postgresql.con.closed", PSQLException.inexistent_connection);
>           }
>           return new QueryExecutor(new String[] {sql}, EMPTY_OBJECT_ARRAY, stat, pg_stream,
(java.sql.Connection)this).execute();
>       }
> *************** public abstract class AbstractJdbc1Conne
> *** 500,506 ****
>       {
>           if (isClosed())
>           {
> !             throw new PSQLException("postgresql.con.closed");
>           }
>           return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute();
>       }
> --- 528,534 ----
>       {
>           if (isClosed())
>           {
> !             throw new PSQLException("postgresql.con.closed", PSQLException.inexistent_connection);
>           }
>           return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute();
>       }
> *************** public abstract class AbstractJdbc1Conne
> *** 695,701 ****
>           }
>           catch (Exception ex)
>           {
> !             throw new PSQLException("postgresql.con.creobj", type, ex);
>           }
>
>           // should never be reached
> --- 723,729 ----
>           }
>           catch (Exception ex)
>           {
> !             throw new PSQLException("postgresql.con.creobj", PSQLException.connection_failure, type, ex);
>           }
>
>           // should never be reached
> *************** public abstract class AbstractJdbc1Conne
> *** 744,750 ****
>                   return ((Serialize)x).storeObject(o);
>
>               // Thow an exception because the type is unknown
> !             throw new PSQLException("postgresql.con.strobj");
>
>           }
>           catch (SQLException sx)
> --- 772,778 ----
>                   return ((Serialize)x).storeObject(o);
>
>               // Thow an exception because the type is unknown
> !             throw new PSQLException("postgresql.con.strobj", PSQLException.data_exception);
>
>           }
>           catch (SQLException sx)
> *************** public abstract class AbstractJdbc1Conne
> *** 1117,1123 ****
>                       isolationLevelSQL += "SERIALIZABLE";
>                       break;
>                   default:
> !                     throw new PSQLException("postgresql.con.isolevel",
>                                               new Integer(isolationLevel));
>               }
>           }
> --- 1145,1151 ----
>                       isolationLevelSQL += "SERIALIZABLE";
>                       break;
>                   default:
> !                     throw new PSQLException("postgresql.con.isolevel", PSQLException.inv_transaction_state,
>                                               new Integer(isolationLevel));
>               }
>           }
> *************** public abstract class AbstractJdbc1Conne
> *** 1154,1160 ****
>                   break;
>
>               default:
> !                 throw new PSQLException("postgresql.con.isolevel", new Integer(isolationLevel));
>           }
>           return sb.toString();
>       }
> --- 1182,1189 ----
>                   break;
>
>               default:
> !                 throw new PSQLException("postgresql.con.isolevel", PSQLException.inv_transaction_state,
> !                                         new Integer(isolationLevel));
>           }
>           return sb.toString();
>       }
> Index: src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java,v
> retrieving revision 1.7
> diff -c -p -r1.7 AbstractJdbc1ResultSet.java
> *** src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java    2002/10/19 22:10:36    1.7
> --- src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java    2002/11/25 22:17:48
> *************** public abstract class AbstractJdbc1Resul
> *** 60,66 ****
>       public boolean next() throws SQLException
>       {
>           if (rows == null)
> !             throw new PSQLException("postgresql.con.closed");
>
>           if (++current_row >= rows.size())
>               return false;
> --- 60,66 ----
>       public boolean next() throws SQLException
>       {
>           if (rows == null)
> !             throw new PSQLException("postgresql.con.closed", PSQLException.inexistent_connection);
>
>           if (++current_row >= rows.size())
>               return false;
> Index: src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java,v
> retrieving revision 1.14
> diff -c -p -r1.14 AbstractJdbc1Statement.java
> *** src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java    2002/11/20 07:34:32    1.14
> --- src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java    2002/11/25 22:17:48
> *************** public abstract class AbstractJdbc1State
> *** 1378,1384 ****
>                   }
>                   else
>                   {
> !                     throw new PSQLException("postgresql.prep.type");
>                   }
>                   break;
>               case Types.BINARY:
> --- 1378,1384 ----
>                   }
>                   else
>                   {
> !                     throw new PSQLException("postgresql.prep.type", PSQLException.inv_parameter_type);
>                   }
>                   break;
>               case Types.BINARY:
> *************** public abstract class AbstractJdbc1State
> *** 1389,1395 ****
>                   setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT);
>                   break;
>               default:
> !                 throw new PSQLException("postgresql.prep.type");
>           }
>       }
>
> --- 1389,1395 ----
>                   setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT);
>                   break;
>               default:
> !                 throw new PSQLException("postgresql.prep.type", PSQLException.inv_parameter_type);
>           }
>       }
>
> *************** public abstract class AbstractJdbc1State
> *** 1798,1804 ****
>       protected void bind(int paramIndex, Object s, String type) throws SQLException
>       {
>           if (paramIndex < 1 || paramIndex > m_binds.length)
> !             throw new PSQLException("postgresql.prep.range");
>           if (paramIndex == 1 && isFunction) // need to registerOut instead
>               throw new PSQLException ("postgresql.call.funcover");
>           m_binds[paramIndex - 1] = s;
> --- 1798,1804 ----
>       protected void bind(int paramIndex, Object s, String type) throws SQLException
>       {
>           if (paramIndex < 1 || paramIndex > m_binds.length)
> !             throw new PSQLException("postgresql.prep.range", PSQLException.parameter_mismatch);
>           if (paramIndex == 1 && isFunction) // need to registerOut instead
>               throw new PSQLException ("postgresql.call.funcover");
>           m_binds[paramIndex - 1] = s;
> Index: src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java,v
> retrieving revision 1.2
> diff -c -p -r1.2 AbstractJdbc2Connection.java
> *** src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java    2002/09/06 21:23:06    1.2
> --- src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java    2002/11/25 22:17:48
> *************** public abstract class AbstractJdbc2Conne
> *** 64,74 ****
>               // Added by Peter Mount <peter@retep.org.uk>
>               // 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
> --- 64,74 ----
>               // Added by Peter Mount <peter@retep.org.uk>
>               // 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", PSQLException.connection_rejected);
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException ("postgresql.con.failed", PSQLException.unable_to_connect, e);
>           }
>
>           // Now we need to construct and send a cancel packet
> *************** public abstract class AbstractJdbc2Conne
> *** 82,88 ****
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.con.failed", e);
>           }
>           finally
>           {
> --- 82,88 ----
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.con.failed", PSQLException.comm_link_error, e);
>           }
>           finally
>           {
> Index: src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java,v
> retrieving revision 1.10
> diff -c -p -r1.10 AbstractJdbc2ResultSet.java
> *** src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java    2002/11/04 06:42:33    1.10
> --- src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java    2002/11/25 22:17:48
> *************** public abstract class AbstractJdbc2Resul
> *** 399,405 ****
>       public Ref getRef(int i) throws SQLException
>       {
>           //The backend doesn't yet have SQL3 REF types
> !         throw new PSQLException("postgresql.psqlnotimp");
>       }
>
>
> --- 399,405 ----
>       public Ref getRef(int i) throws SQLException
>       {
>           //The backend doesn't yet have SQL3 REF types
> !         throw new PSQLException("postgresql.psqlnotimp", PSQLException.feature_not_supported);
>       }
>
>
> *************** public abstract class AbstractJdbc2Resul
> *** 491,497 ****
>
>       public void setFetchDirection(int direction) throws SQLException
>       {
> !         throw new PSQLException("postgresql.psqlnotimp");
>       }
>
>
> --- 491,497 ----
>
>       public void setFetchDirection(int direction) throws SQLException
>       {
> !         throw new PSQLException("postgresql.psqlnotimp", PSQLException.feature_not_supported);
>       }
>
>
> *************** public abstract class AbstractJdbc2Resul
> *** 750,756 ****
>           }
>           catch (IOException ie)
>           {
> !             throw new PSQLException("postgresql.updateable.ioerror" + ie);
>           }
>
>           updateValue(columnIndex, theData);
> --- 750,756 ----
>           }
>           catch (IOException ie)
>           {
> !             throw new PSQLException("postgresql.updateable.ioerror", ie);
>           }
>
>           updateValue(columnIndex, theData);
> *************** public abstract class AbstractJdbc2Resul
> *** 784,790 ****
>           }
>           catch (IOException ie)
>           {
> !             throw new PSQLException("postgresql.updateable.ioerror" + ie);
>           }
>           updateValue(columnIndex, theData);
>
> --- 784,790 ----
>           }
>           catch (IOException ie)
>           {
> !             throw new PSQLException("postgresql.updateable.ioerror", ie);
>           }
>           updateValue(columnIndex, theData);
>
> *************** public abstract class AbstractJdbc2Resul
> *** 832,838 ****
>           }
>           catch (IOException ie)
>           {
> !             throw new PSQLException("postgresql.updateable.ioerror" + ie);
>           }
>           updateValue(columnIndex, theData);
>       }
> --- 832,838 ----
>           }
>           catch (IOException ie)
>           {
> !             throw new PSQLException("postgresql.updateable.ioerror", ie);
>           }
>           updateValue(columnIndex, theData);
>       }
> Index: src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v
> retrieving revision 1.9
> diff -c -p -r1.9 AbstractJdbc2Statement.java
> *** src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java    2002/11/20 07:34:32    1.9
> --- src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java    2002/11/25 22:17:48
> *************** public abstract class AbstractJdbc2State
> *** 128,134 ****
>
>       public int getFetchDirection() throws SQLException
>       {
> !         throw new PSQLException("postgresql.psqlnotimp");
>       }
>
>       public int getFetchSize() throws SQLException
> --- 128,134 ----
>
>       public int getFetchDirection() throws SQLException
>       {
> !         throw new PSQLException("postgresql.psqlnotimp", PSQLException.feature_not_supported);
>       }
>
>       public int getFetchSize() throws SQLException
> Index: src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java
> ===================================================================
> RCS file:
/projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java,v
> retrieving revision 1.2
> diff -c -p -r1.2 AbstractJdbc3DatabaseMetaData.java
> *** src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java    2002/09/06 21:23:06    1.2
> --- src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java    2002/11/25 22:17:49
> *************** public abstract class AbstractJdbc3Datab
> *** 323,329 ****
>        */
>       public int getSQLStateType() throws SQLException
>       {
> !         throw org.postgresql.Driver.notImplemented();
>       }
>
>       /**
> --- 323,329 ----
>        */
>       public int getSQLStateType() throws SQLException
>       {
> !         return DatabaseMetaData.sqlStateXOpen;
>       }
>
>       /**
> Index: src/interfaces/jdbc/org/postgresql/util/PSQLException.java
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/util/PSQLException.java,v
> retrieving revision 1.7
> diff -c -p -r1.7 PSQLException.java
> *** src/interfaces/jdbc/org/postgresql/util/PSQLException.java    2001/11/19 22:33:39    1.7
> --- src/interfaces/jdbc/org/postgresql/util/PSQLException.java    2002/11/25 22:17:51
> *************** public class PSQLException extends SQLEx
> *** 11,16 ****
> --- 11,33 ----
>       private String message;
>
>       /*
> +      * PSQLState constants
> +      *
> +      * Using the constants make the code more legible.
> +      */
> +
> +     public static final PSQLState parameter_mismatch = new PSQLState("07001");
> +     public static final PSQLState inv_parameter_type = new PSQLState("07006");
> +     public static final PSQLState unable_to_connect = new PSQLState("08001");
> +     public static final PSQLState inexistent_connection = new PSQLState("08003");
> +     public static final PSQLState connection_rejected = new PSQLState("08004");
> +     public static final PSQLState connection_failure = new PSQLState("08006");
> +     public static final PSQLState comm_link_error = new PSQLState("08S01");
> +     public static final PSQLState feature_not_supported = new PSQLState("0A000");
> +     public static final PSQLState data_exception = new PSQLState("22000");
> +     public static final PSQLState inv_transaction_state = new PSQLState("25000");
> +
> +     /*
>        * This provides the same functionality to SQLException
>        * @param error Error string
>        */
> *************** public class PSQLException extends SQLEx
> *** 21,26 ****
> --- 38,54 ----
>       }
>
>       /*
> +      * Like the above, but sets SQLState
> +      * @param error Error string
> +      * @param sqlstate PSQLState constant
> +      */
> +     public PSQLException(String error, PSQLState sqlstate)
> +     {
> +         super("", sqlstate.toString());
> +         translate(error, null);
> +     }
> +
> +     /*
>        * A more generic entry point.
>        * @param error Error string or standard message id
>        * @param args Array of arguments
> *************** public class PSQLException extends SQLEx
> *** 74,84 ****
> --- 102,155 ----
>       }
>
>       /*
> +      * Like the above, but sets the SQLState
> +      */
> +     public PSQLException(String error, PSQLState sqlstate, Exception ex)
> +     {
> +         super("", sqlstate.toString());
> +
> +         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();
> +         }
> +
> +         translate(error, argv);
> +     }
> +
> +     /*
>        * 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);
> +     }
> +
> +     /*
> +      * Like the above, but sets SQLState
> +      * @param error Error string
> +      * @param sqlstate PSQLState constant
> +      */
> +     public PSQLException(String error, PSQLState sqlstate, Object arg1, Object arg2)
> +     {
> +         super("", sqlstate.toString());
>           Object[] argv = new Object[2];
>           argv[0] = arg1;
>           argv[1] = arg2;
>
>
> ------------------------------------------------------------------------
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)




Re: JDBC SQLStatus for Dynamic SQL, unsupported feature,

From
Fernando Nasser
Date:
Barry Lind wrote:
> Fernando,
>
> Can you provide a reason these patches are necessary?  Are there some
> specific use cases that are trying to be addressed?
>

The most concrete case for the need of SQLState is the one I gave in the
first patch.  We have a GUI tool that connects to remotes databases and,
sometimes, due to a network problem or a backend problem (there was an
assertion failure in one occasion and the backend was aborted), the
connection goes away.  Without a proper SQLState, we have to parse the
error message to check if the connection is gone so that we can re-set
the GUI properly (i.e., indicate that we are disconnected, disable some
buttons etc.).  If we don't do this, the user can continue to try and
send things (as the GUI still reports being connected) and things get
really inconsistent (nothing hapens, the previous error message is
repeated when is not applicable anymore, stack traces show up in the
console etc.).


> I am very reluctant to apply all of this.  The reason being, that
> without a commitment on how error codes are going to be implemented in
> the backend, I don't want to partially implement them in the jdbc
> driver.

All the error codes I've been adding so far are driver generated ones,
i.e., conditions detected at the client side.  They are not going to
change regardless of whayt the backend does.  Please read on for my
thinking on the bacend part.

> There needs to be a consistent implementation between the jdbc
> driver and the backend (since the jdbc driver will end up passing the
> backend's codes to the client).

We have to be X/Open compliant anyway (for JDBC1 and JDBC2).  We do have
the option of using the ANSI codes for JDBC3, which would add a few
extra standard error codes when compared with the X/Open.  Most of the
codes are common to both specs.

>  Depending on what the backend
> implementation is, that might even mean that the jdbc driver will
> support error codes in a non-standard way.  I am much more concerned
> with consistency between the two sets of error codes than I am with
> following the standard at the moment.   I really want to avoid needing to
> have the reinterpret all the backend error codes to conform to how these
> patches think error codes should be handled.  That will be a maintenance
> nightmare.
>

The backend will either follow the ANSI or the X/Open standards, and
there are just a few extra ANSI codes that we would have to map back to
X/Open or use implementation-defined codes.  If the backend uses some
non standard coding (which I doubt it will do as we are trying to get as
SQL compliant as possible), it would not be advisable for the JDBC
driver to blindly pass those on.  Some of the value of the JDBC is to be
as standard as possible.

The codes that will have to be invented by the backend will follow the
ANSI conventions for implementation-defined error codes.  And here is
were we are lucky: the rules are the same for both ANSI and X/Open.  Any
  valid implementation-defined ANSI code is also a valid
implementation-defined X/Open code.  So, except for a few extra standard
codes defined in the SQL99, we can pass all others on irrespectively of
what we are using for JDBC3: X/Open or ANSI style SQLState.

P.S. We can always decide to use ANSI style SQLState for JDBC3 if we
want.  We would have top abstract the PSQLException class but it is not
difficult to support bothe the X/Open for JDBC1,2 and ANSI for JDBC3.
I just find it very confusing for application to handle both sets and
there is absolutely no advantage in switching to the ANSI one (just for
a few extra codes).


> I think this patch goes beyond what I am comfortable applying without
> any guidance on how/when/if error codes are going to be implemented in
> the backend.
>

I would say that it is independent of the backend.  We only have two
choices to be compliant with JDBC: X/Open and ANSI.  All codes in the
patch are both ANSI and X/Open standard (plus the de facto 08S01 one,
which is an implementation-defined one anyway).  The only real choice
made was to return XOpen in the getSQLStateType() routine, which can be
altered at any time (JDBC3 applications are supposed to check that anyway).



--
Fernando Nasser
Red Hat Canada Ltd.                     E-Mail:  fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario   M4P 2C9