Thread: JDBC Emit SQLError code for communication errors

JDBC Emit SQLError code for communication errors

From
Fernando Nasser
Date:
Applications can't rely on the text of the SQLException error message to
detect that there was a communication error as it is localized (and
error messages are prone to change anyway).  So, a JDBC application
cannot take the appropriate actions when an IO error occurs.

This patch makes the JDBC driver report an eof and other communication
errors using the standard SQLSTATE value:

   "08S01"  (connection exception-communication link failure)

which can be safely tested for in applications.  Without this patch we
get null, instead of the "08S01" string, when calling getSQLState() as
the driver never sets that value.

The behavior of applications when we lose connection with the backend is
currently very bad, as there is no way to distinguish this problem from
a regular SQL error.

--
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/19 22:21:33
*************** public class PG_Stream
*** 137,143 ****
          {
              c = pg_input.read();
              if (c < 0)
!                 throw new PSQLException("postgresql.stream.eof");
          }
          catch (IOException e)
          {
--- 137,143 ----
          {
              c = pg_input.read();
              if (c < 0)
!                 throw new PSQLException("postgresql.stream.eof", "08S01");
          }
          catch (IOException e)
          {
*************** public class PG_Stream
*** 164,170 ****
                  int b = pg_input.read();

                  if (b < 0)
!                     throw new PSQLException("postgresql.stream.eof");
                  n = n | (b << (8 * i)) ;
              }
          }
--- 164,170 ----
                  int b = pg_input.read();

                  if (b < 0)
!                     throw new PSQLException("postgresql.stream.eof", "08S01");
                  n = n | (b << (8 * i)) ;
              }
          }
*************** public class PG_Stream
*** 193,199 ****
                  int b = pg_input.read();

                  if (b < 0)
!                     throw new PSQLException("postgresql.stream.eof");
                  n = b | (n << 8);
              }
          }
--- 193,199 ----
                  int b = pg_input.read();

                  if (b < 0)
!                     throw new PSQLException("postgresql.stream.eof", "08S01");
                  n = b | (n << 8);
              }
          }
*************** 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", "08S01");
                      else if (c == 0)
                      {
                          rst[s] = 0;
*************** public class PG_Stream
*** 330,336 ****
              {
                  int w = pg_input.read(b, off + s, siz - s);
                  if (w < 0)
!                     throw new PSQLException("postgresql.stream.eof");
                  s += w;
              }
          }
--- 330,336 ----
              {
                  int w = pg_input.read(b, off + s, siz - s);
                  if (w < 0)
!                     throw new PSQLException("postgresql.stream.eof", "08S01");
                  s += w;
              }
          }
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/19 22:21:33
*************** 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", "08S01", e);
          }
      }

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/19 22:21:33
*************** public class PSQLException extends SQLEx
*** 21,26 ****
--- 21,37 ----
      }

      /*
+      * Like the above, but sets SQLState
+      * @param error Error string
+      * @param sqlstate SQLState string
+      */
+     public PSQLException(String error, String sqlstate)
+     {
+         super("", sqlstate);
+         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
*** 50,55 ****
--- 61,95 ----
      public PSQLException(String error, Exception ex)
      {
          super();
+
+         Object[] argv = new Object[1];
+
+         try
+         {
+             ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             PrintWriter pw = new PrintWriter(baos);
+             pw.println("Exception: " + ex.toString() + "\nStack Trace:\n");
+             ex.printStackTrace(pw);
+             pw.println("End of Stack Trace");
+             pw.flush();
+             argv[0] = baos.toString();
+             pw.close();
+             baos.close();
+         }
+         catch (Exception ioe)
+         {
+             argv[0] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString();
+         }
+
+         translate(error, argv);
+     }
+
+     /*
+      * Like the above, but sets the SQLState
+      */
+     public PSQLException(String error, String sqlstate, Exception ex)
+     {
+         super("", sqlstate);

          Object[] argv = new Object[1];


Re: JDBC Emit SQLError code for communication errors

From
Fernando Nasser
Date:
Please consider this version of the patch.  The extra cases
(postgresql.stream.ioerror:An I/O error occurred while reading from
backend) also should result in "08S01"s.

I left postgresql.updateable.ioerror:Input Stream Error as the "08S01"
does not seem completely appropriate for those.

Regards,
Fernando

Fernando Nasser wrote:
> Applications can't rely on the text of the SQLException error message to
> detect that there was a communication error as it is localized (and
> error messages are prone to change anyway).  So, a JDBC application
> cannot take the appropriate actions when an IO error occurs.
>
> This patch makes the JDBC driver report an eof and other communication
> errors using the standard SQLSTATE value:
>
>   "08S01"  (connection exception-communication link failure)
>
> which can be safely tested for in applications.  Without this patch we
> get null, instead of the "08S01" string, when calling getSQLState() as
> the driver never sets that value.
>
> The behavior of applications when we lose connection with the backend is
> currently very bad, as there is no way to distinguish this problem from
> a regular SQL error.
>
>
> ------------------------------------------------------------------------
>
> 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/19 22:21:33
> *************** public class PG_Stream
> *** 137,143 ****
>           {
>               c = pg_input.read();
>               if (c < 0)
> !                 throw new PSQLException("postgresql.stream.eof");
>           }
>           catch (IOException e)
>           {
> --- 137,143 ----
>           {
>               c = pg_input.read();
>               if (c < 0)
> !                 throw new PSQLException("postgresql.stream.eof", "08S01");
>           }
>           catch (IOException e)
>           {
> *************** public class PG_Stream
> *** 164,170 ****
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   n = n | (b << (8 * i)) ;
>               }
>           }
> --- 164,170 ----
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof", "08S01");
>                   n = n | (b << (8 * i)) ;
>               }
>           }
> *************** public class PG_Stream
> *** 193,199 ****
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   n = b | (n << 8);
>               }
>           }
> --- 193,199 ----
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof", "08S01");
>                   n = b | (n << 8);
>               }
>           }
> *************** 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", "08S01");
>                       else if (c == 0)
>                       {
>                           rst[s] = 0;
> *************** public class PG_Stream
> *** 330,336 ****
>               {
>                   int w = pg_input.read(b, off + s, siz - s);
>                   if (w < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   s += w;
>               }
>           }
> --- 330,336 ----
>               {
>                   int w = pg_input.read(b, off + s, siz - s);
>                   if (w < 0)
> !                     throw new PSQLException("postgresql.stream.eof", "08S01");
>                   s += w;
>               }
>           }
> 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/19 22:21:33
> *************** 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", "08S01", e);
>           }
>       }
>
> 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/19 22:21:33
> *************** public class PSQLException extends SQLEx
> *** 21,26 ****
> --- 21,37 ----
>       }
>
>       /*
> +      * Like the above, but sets SQLState
> +      * @param error Error string
> +      * @param sqlstate SQLState string
> +      */
> +     public PSQLException(String error, String sqlstate)
> +     {
> +         super("", sqlstate);
> +         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
> *** 50,55 ****
> --- 61,95 ----
>       public PSQLException(String error, Exception ex)
>       {
>           super();
> +
> +         Object[] argv = new Object[1];
> +
> +         try
> +         {
> +             ByteArrayOutputStream baos = new ByteArrayOutputStream();
> +             PrintWriter pw = new PrintWriter(baos);
> +             pw.println("Exception: " + ex.toString() + "\nStack Trace:\n");
> +             ex.printStackTrace(pw);
> +             pw.println("End of Stack Trace");
> +             pw.flush();
> +             argv[0] = baos.toString();
> +             pw.close();
> +             baos.close();
> +         }
> +         catch (Exception ioe)
> +         {
> +             argv[0] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString();
> +         }
> +
> +         translate(error, argv);
> +     }
> +
> +     /*
> +      * Like the above, but sets the SQLState
> +      */
> +     public PSQLException(String error, String sqlstate, Exception ex)
> +     {
> +         super("", sqlstate);
>
>           Object[] argv = new Object[1];
>
>
>
> ------------------------------------------------------------------------
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org


--
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/20 01:20:16
*************** 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", "08S01");
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
                  n = n | (b << (8 * i)) ;
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
                  n = b | (n << 8);
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
                      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", "08S01", 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", "08S01");
                  s += w;
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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/20 01:20:16
*************** 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", "08S01", e);
          }
      }

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/20 01:20:16
*************** public class PSQLException extends SQLEx
*** 21,26 ****
--- 21,37 ----
      }

      /*
+      * Like the above, but sets SQLState
+      * @param error Error string
+      * @param sqlstate SQLState string
+      */
+     public PSQLException(String error, String sqlstate)
+     {
+         super("", sqlstate);
+         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
*** 50,55 ****
--- 61,95 ----
      public PSQLException(String error, Exception ex)
      {
          super();
+
+         Object[] argv = new Object[1];
+
+         try
+         {
+             ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             PrintWriter pw = new PrintWriter(baos);
+             pw.println("Exception: " + ex.toString() + "\nStack Trace:\n");
+             ex.printStackTrace(pw);
+             pw.println("End of Stack Trace");
+             pw.flush();
+             argv[0] = baos.toString();
+             pw.close();
+             baos.close();
+         }
+         catch (Exception ioe)
+         {
+             argv[0] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString();
+         }
+
+         translate(error, argv);
+     }
+
+     /*
+      * Like the above, but sets the SQLState
+      */
+     public PSQLException(String error, String sqlstate, Exception ex)
+     {
+         super("", sqlstate);

          Object[] argv = new Object[1];


Re: JDBC Emit SQLError code for communication errors

From
Barry Lind
Date:
Fernando,

I have a couple of questions about this patch.

1)  Where did you get the sql state value you are using here?  According
to the jdbc3 docs the value can either be the XOPEN value or the SQL99
value.  (For jdbc1 and jdbc2 the value must be the XOPEN value).  Also
could you provide me a link to someplace so that I can read more about
the possible values?

2)  This patch should also include changes to DatabaseMetaData to
correctly report the answer to the above question in getSqlStateType()

thanks,
--Barry

Fernando Nasser wrote:
> Applications can't rely on the text of the SQLException error message to
> detect that there was a communication error as it is localized (and
> error messages are prone to change anyway).  So, a JDBC application
> cannot take the appropriate actions when an IO error occurs.
>
> This patch makes the JDBC driver report an eof and other communication
> errors using the standard SQLSTATE value:
>
>   "08S01"  (connection exception-communication link failure)
>
> which can be safely tested for in applications.  Without this patch we
> get null, instead of the "08S01" string, when calling getSQLState() as
> the driver never sets that value.
>
> The behavior of applications when we lose connection with the backend is
> currently very bad, as there is no way to distinguish this problem from
> a regular SQL error.
>
>
> ------------------------------------------------------------------------
>
> 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/19 22:21:33
> *************** public class PG_Stream
> *** 137,143 ****
>           {
>               c = pg_input.read();
>               if (c < 0)
> !                 throw new PSQLException("postgresql.stream.eof");
>           }
>           catch (IOException e)
>           {
> --- 137,143 ----
>           {
>               c = pg_input.read();
>               if (c < 0)
> !                 throw new PSQLException("postgresql.stream.eof", "08S01");
>           }
>           catch (IOException e)
>           {
> *************** public class PG_Stream
> *** 164,170 ****
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   n = n | (b << (8 * i)) ;
>               }
>           }
> --- 164,170 ----
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof", "08S01");
>                   n = n | (b << (8 * i)) ;
>               }
>           }
> *************** public class PG_Stream
> *** 193,199 ****
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   n = b | (n << 8);
>               }
>           }
> --- 193,199 ----
>                   int b = pg_input.read();
>
>                   if (b < 0)
> !                     throw new PSQLException("postgresql.stream.eof", "08S01");
>                   n = b | (n << 8);
>               }
>           }
> *************** 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", "08S01");
>                       else if (c == 0)
>                       {
>                           rst[s] = 0;
> *************** public class PG_Stream
> *** 330,336 ****
>               {
>                   int w = pg_input.read(b, off + s, siz - s);
>                   if (w < 0)
> !                     throw new PSQLException("postgresql.stream.eof");
>                   s += w;
>               }
>           }
> --- 330,336 ----
>               {
>                   int w = pg_input.read(b, off + s, siz - s);
>                   if (w < 0)
> !                     throw new PSQLException("postgresql.stream.eof", "08S01");
>                   s += w;
>               }
>           }
> 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/19 22:21:33
> *************** 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", "08S01", e);
>           }
>       }
>
> 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/19 22:21:33
> *************** public class PSQLException extends SQLEx
> *** 21,26 ****
> --- 21,37 ----
>       }
>
>       /*
> +      * Like the above, but sets SQLState
> +      * @param error Error string
> +      * @param sqlstate SQLState string
> +      */
> +     public PSQLException(String error, String sqlstate)
> +     {
> +         super("", sqlstate);
> +         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
> *** 50,55 ****
> --- 61,95 ----
>       public PSQLException(String error, Exception ex)
>       {
>           super();
> +
> +         Object[] argv = new Object[1];
> +
> +         try
> +         {
> +             ByteArrayOutputStream baos = new ByteArrayOutputStream();
> +             PrintWriter pw = new PrintWriter(baos);
> +             pw.println("Exception: " + ex.toString() + "\nStack Trace:\n");
> +             ex.printStackTrace(pw);
> +             pw.println("End of Stack Trace");
> +             pw.flush();
> +             argv[0] = baos.toString();
> +             pw.close();
> +             baos.close();
> +         }
> +         catch (Exception ioe)
> +         {
> +             argv[0] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString();
> +         }
> +
> +         translate(error, argv);
> +     }
> +
> +     /*
> +      * Like the above, but sets the SQLState
> +      */
> +     public PSQLException(String error, String sqlstate, Exception ex)
> +     {
> +         super("", sqlstate);
>
>           Object[] argv = new Object[1];
>
>
>
> ------------------------------------------------------------------------
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org




Re: JDBC Emit SQLError code for communication errors

From
Fernando Nasser
Date:
Barry, please find attached the patch including the change to getSqlStateType()
as you requested.  I knew I had to change it but I end up forgetting.  Sorry.

See other comments below.

Barry Lind wrote:> Fernando,
>
> I have a couple of questions about this patch.
>
> 1)  Where did you get the sql state value you are using here?  According
> to the jdbc3 docs the value can either be the XOPEN value or the SQL99
> value.  (For jdbc1 and jdbc2 the value must be the XOPEN value).

It is the X/Open one.  If we were to issue SQL99 (for JDBC3) I would have to
make extensive changes so that PSQLException would work different depending if
it is a JDBC1/2 or JDBC3.

Also, there is a basic flaw in the getSqlStateType() approach.  If my
application is not certain that it is a JDBC3 driver it can't use it.  And I
believe there is no way to check what level of JDBC you have either.  Is that
correct?

Anyway, if the backend eventually sends us SQL99 codes for the SQLExceptions we
do not interpret, we can convert to equivalent X/Open codes.


>  Also
> could you provide me a link to someplace so that I can read more about
> the possible values?
>

It is the X/Open standard document.  Unfortunately it is not available online
and you have to pay USD43 to download.  See www.opengroup.org


> 2)  This patch should also include changes to DatabaseMetaData to
> correctly report the answer to the above question in getSqlStateType()
>

Done.


Thanks for the comments and for catching the getSqlStateType() omission.

Regards,
Fernando



--
Fernando Nasser
Red Hat - Toronto                       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/20 17:54:25
*************** 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", "08S01");
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
                  n = n | (b << (8 * i)) ;
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
                  n = b | (n << 8);
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
                      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", "08S01", 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", "08S01");
                  s += w;
              }
          }
          catch (IOException e)
          {
!             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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/20 17:54:25
*************** 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", "08S01", e);
          }
      }

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/20 17:54:26
*************** 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/20 17:54:26
*************** public class PSQLException extends SQLEx
*** 21,26 ****
--- 21,37 ----
      }

      /*
+      * Like the above, but sets SQLState
+      * @param error Error string
+      * @param sqlstate SQLState string
+      */
+     public PSQLException(String error, String sqlstate)
+     {
+         super("", sqlstate);
+         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
*** 50,55 ****
--- 61,95 ----
      public PSQLException(String error, Exception ex)
      {
          super();
+
+         Object[] argv = new Object[1];
+
+         try
+         {
+             ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             PrintWriter pw = new PrintWriter(baos);
+             pw.println("Exception: " + ex.toString() + "\nStack Trace:\n");
+             ex.printStackTrace(pw);
+             pw.println("End of Stack Trace");
+             pw.flush();
+             argv[0] = baos.toString();
+             pw.close();
+             baos.close();
+         }
+         catch (Exception ioe)
+         {
+             argv[0] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString();
+         }
+
+         translate(error, argv);
+     }
+
+     /*
+      * Like the above, but sets the SQLState
+      */
+     public PSQLException(String error, String sqlstate, Exception ex)
+     {
+         super("", sqlstate);

          Object[] argv = new Object[1];


Re: JDBC Emit SQLError code for communication errors

From
Fernando Nasser
Date:
I am withdrawing this patch temporarily.  It has a problem that I have
to fix and I would like to add a couple of more 08S01 conditions.

Sorry for the inconvenience.

Regards,
Fernando

Fernando Nasser wrote:
> Barry, please find attached the patch including the change to
> getSqlStateType() as you requested.  I knew I had to change it but I end
> up forgetting.  Sorry.
>
> See other comments below.
>
> Barry Lind wrote:> Fernando,
>
>>
>> I have a couple of questions about this patch.
>>
>> 1)  Where did you get the sql state value you are using here?
>> According to the jdbc3 docs the value can either be the XOPEN value or
>> the SQL99 value.  (For jdbc1 and jdbc2 the value must be the XOPEN
>> value).
>
>
> It is the X/Open one.  If we were to issue SQL99 (for JDBC3) I would
> have to make extensive changes so that PSQLException would work
> different depending if it is a JDBC1/2 or JDBC3.
>
> Also, there is a basic flaw in the getSqlStateType() approach.  If my
> application is not certain that it is a JDBC3 driver it can't use it.
> And I believe there is no way to check what level of JDBC you have
> either.  Is that correct?
>
> Anyway, if the backend eventually sends us SQL99 codes for the
> SQLExceptions we do not interpret, we can convert to equivalent X/Open
> codes.
>
>
>>  Also could you provide me a link to someplace so that I can read more
>> about the possible values?
>>
>
> It is the X/Open standard document.  Unfortunately it is not available
> online and you have to pay USD43 to download.  See www.opengroup.org
>
>
>> 2)  This patch should also include changes to DatabaseMetaData to
>> correctly report the answer to the above question in getSqlStateType()
>>
>
> Done.
>
>
> Thanks for the comments and for catching the getSqlStateType() omission.
>
> Regards,
> Fernando
>
>
>
>
> ------------------------------------------------------------------------
>
> 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/20 17:54:25
> *************** 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", "08S01");
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
>                   n = n | (b << (8 * i)) ;
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
>                   n = b | (n << 8);
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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", "08S01");
>                       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", "08S01", 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", "08S01");
>                   s += w;
>               }
>           }
>           catch (IOException e)
>           {
> !             throw new PSQLException("postgresql.stream.ioerror", "08S01", 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/20 17:54:25
> *************** 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", "08S01", e);
>           }
>       }
>
> 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/20 17:54:26
> *************** 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/20 17:54:26
> *************** public class PSQLException extends SQLEx
> *** 21,26 ****
> --- 21,37 ----
>       }
>
>       /*
> +      * Like the above, but sets SQLState
> +      * @param error Error string
> +      * @param sqlstate SQLState string
> +      */
> +     public PSQLException(String error, String sqlstate)
> +     {
> +         super("", sqlstate);
> +         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
> *** 50,55 ****
> --- 61,95 ----
>       public PSQLException(String error, Exception ex)
>       {
>           super();
> +
> +         Object[] argv = new Object[1];
> +
> +         try
> +         {
> +             ByteArrayOutputStream baos = new ByteArrayOutputStream();
> +             PrintWriter pw = new PrintWriter(baos);
> +             pw.println("Exception: " + ex.toString() + "\nStack Trace:\n");
> +             ex.printStackTrace(pw);
> +             pw.println("End of Stack Trace");
> +             pw.flush();
> +             argv[0] = baos.toString();
> +             pw.close();
> +             baos.close();
> +         }
> +         catch (Exception ioe)
> +         {
> +             argv[0] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString();
> +         }
> +
> +         translate(error, argv);
> +     }
> +
> +     /*
> +      * Like the above, but sets the SQLState
> +      */
> +     public PSQLException(String error, String sqlstate, Exception ex)
> +     {
> +         super("", sqlstate);
>
>           Object[] argv = new Object[1];
>
>
>
> ------------------------------------------------------------------------
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to majordomo@postgresql.org so that your
> message can get through to the mailing list cleanly


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