JDBC Emit SQLStatus for communication link errors - Mailing list pgsql-patches

From Fernando Nasser
Subject JDBC Emit SQLStatus for communication link errors
Date
Msg-id 3DDE71E5.3040906@redhat.com
Whole thread Raw
List pgsql-patches
This is a repost of a previous patch with enhancements.

I had to create a specific object for SQLStatus as there are many calls
to PSQLException that pass a string as well, and it is not a SQLStatus
code.  Also, the code gets more legible with constants instead of just
the 5 character strings, so I've added those to PSQLException.

I've found 2 more cases where the "08S01" (communication link error)
apply, so I've added those as well.  I guess I've found all "08S01" now.

I will proceed with the other "08xxx" cases, now that I have the
official X/Open document in hands.  And so one until all cases where we
don't depend on the backend information are covered.

Answering Barry's question with some more detail:

The X/Open codes are basically the same as the ANSI (SQL99) ones.
They do not coder all cases, of course, so there is a provision for
implementation defined codes (some letters are reserved for this purpose).

The "08S01" is not in the standard, but is so common that it is used
everywhere.  ODBC defines it, as does DB2 and consequently IBM's JDBC.
Somehow people using MySQL see the same code, but I am not sure how they
were connected, so it may be just an ODBC code.  IMO we should use this
value for portability of applications.  BTW, Oracle 8i did not implement
SQLStatus (I don't know if that changed).

We will eventually need more custom codes.  I will see if the X/Open CLI
spec defines some more codes that we can use.  We can also re-use the
ODBC ones that match before inventing new ones.  I will also check how
other vendors organized their custom codes.

Anyway, the current patch is just for communication link errors and the
applications really need to be able to detect that the communication
link is broken  -- they behave very badly otherwise.

Regards,
Fernando


--
Fernando Nasser
Red Hat Canada Ltd.                     E-Mail:  fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario   M4P 2C9
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/22 17:32:35
*************** 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/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/22 17:32:35
*************** 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);
          }
      }

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/22 17:32:35
*************** 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/jdbc3/AbstractJdbc3DatabaseMetaData.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java,v
retrieving revision 1.3
diff -c -p -r1.3 AbstractJdbc3DatabaseMetaData.java
*** src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java    2002/11/20 20:37:53    1.3
--- src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3DatabaseMetaData.java    2002/11/22 17:32:35
*************** 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/22 17:32:35
*************** public class PSQLException extends SQLEx
*** 11,16 ****
--- 11,24 ----
      private String message;

      /*
+      * PSQLState constants
+      *
+      * Using the constants make the code more legible.
+      */
+
+     public static final PSQLState comm_link_error = new PSQLState("08S01");
+
+     /*
       * This provides the same functionality to SQLException
       * @param error Error string
       */
*************** public class PSQLException extends SQLEx
*** 21,26 ****
--- 29,45 ----
      }

      /*
+      * 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 ****
--- 93,146 ----
      }

      /*
+      * 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;

New file: src/interfaces/jdbc/org/postgresql/util/PSQLState.java
===================================================================
package org.postgresql.util;

/*
 * This class encapsulates a String, so that SQLState arguments have their own type
 * (for method overload resolution)
 */
public class PSQLState extends Object
{
    private String sqlstate;

    /*
     * We only instantiate this with the X/Open strintgs,
     * so we only provide this constructor.
     * @param sqlstate PSQLState constant
     */
    public PSQLState(String sqlstate)
    {
        this.sqlstate = sqlstate;
    }

    public String toString()
    {
        return sqlstate;
    }

    public boolean equals(String other)
    {
        return sqlstate.equals(other);
    }
}

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: Transaction safe Truncate
Next
From: Fernando Nasser
Date:
Subject: JDBC More SQLStatus for connections