[JDBC] Patch for handling long null terminated strings in JDBC driver

2001-07-12 Thread Barry Lind

The attached patch fixes problems with the JDBC driver handling long 
null terminated strings.  The FE/BE protocol sends in some cases null 
terminated strings to the client.  The docs for the FE/BE protocol state 
that there is no limit on the size of a null terminated string sent to 
the client and a client should be coded using an expanding buffer to 
deal with large strings.  The old code did not do this and gave an error 
if a null terminated string was greater than either 4 or 8K.  It appears 
that with the advent of TOAST very long SQL statements are becoming more 
common, and apparently some error messages from the backend include the 
SQL statement thus easily exceeding the 8K limit in the old code.

In fixing I also cleaned up some calls in the JDBC fastpath code that 
were not doing character set conversion under multibyte, and removed 
some methods that were no longer needed.  I also removed a potential 
threading problem with a shared variable that was being used in 
Connection.java.

Thanks to Steve Wampler for discovering the problem and sending the 
initial diffs that were the basis of this patch.

thanks,
--Barry


*** ./interfaces/jdbc/org/postgresql/Connection.java.orig   Thu Jul 12 13:37:28 
2001
--- ./interfaces/jdbc/org/postgresql/Connection.javaThu Jul 12 13:32:55 2001
***
*** 82,92 
  public int pid;
  public int ckey;
  
- // This receive_sbuf should be used by the different methods
- // that call pg_stream.ReceiveString() in this Connection, so
- // so we avoid uneccesary new allocations.
- byte receive_sbuf[] = new byte[8192];
- 
  /**
   * This is called by Class.forName() from within org.postgresql.Driver
   */
--- 82,87 
***
*** 167,174 
// The most common one to be thrown here is:
// User authentication failed
//
!   throw new SQLException(pg_stream.ReceiveString
!(receive_sbuf, 4096, getEncoding()));
  
  case 'R':
// Get the type of request
--- 162,168 
  // The most common one to be thrown here is:
  // User authentication failed
  //
! throw new SQLException(pg_stream.ReceiveString(getEncoding()));
  
case 'R':
  // Get the type of request
***
*** 238,245 
break;
case 'E':
case 'N':
!throw new SQLException(pg_stream.ReceiveString
!   (receive_sbuf, 4096, getEncoding()));
  default:
throw new PSQLException(postgresql.con.setup);
}
--- 232,238 
break;
  case 'E':
  case 'N':
!throw new SQLException(pg_stream.ReceiveString(getEncoding()));
  default:
throw new PSQLException(postgresql.con.setup);
}
***
*** 251,257 
   break;
case 'E':
case 'N':
!throw new SQLException(pg_stream.ReceiveString(receive_sbuf, 4096, 
getEncoding()));
  default:
throw new PSQLException(postgresql.con.setup);
}
--- 244,250 
 break;
  case 'E':
  case 'N':
!throw new SQLException(pg_stream.ReceiveString(getEncoding()));
  default:
throw new PSQLException(postgresql.con.setup);
}
***
*** 491,497 
{
case 'A':   // Asynchronous Notify
pid = pg_stream.ReceiveInteger(4);
!   msg = 
pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
break;
case 'B':   // Binary Data Transfer
if (fields == null)
--- 484,490 
  {
  case 'A': // Asynchronous Notify
  pid = pg_stream.ReceiveInteger(4);
! msg = pg_stream.ReceiveString(getEncoding());
  break;
  case 'B': // Binary Data Transfer
  if (fields == null)
***
*** 502,508 
tuples.addElement(tup);
break;
case 'C':   // Command Status
!   recv_status = 
pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
  
// Now handle the update count correctly.
if(recv_status.startsWith(INSERT) || 
recv_status.startsWith(UPDATE) || recv_status.startsWith(DELETE) || 
recv_status.startsWith(MOVE)) {
--- 495,501 
  tuples.addElement(tup);
  break;
  case 'C': // 

Re: [JDBC] Patch for handling long null terminated strings in JDBC driver

2001-07-12 Thread Bruce Momjian

Your patch has been added to the PostgreSQL unapplied patches list at:

http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

 The attached patch fixes problems with the JDBC driver handling long 
 null terminated strings.  The FE/BE protocol sends in some cases null 
 terminated strings to the client.  The docs for the FE/BE protocol state 
 that there is no limit on the size of a null terminated string sent to 
 the client and a client should be coded using an expanding buffer to 
 deal with large strings.  The old code did not do this and gave an error 
 if a null terminated string was greater than either 4 or 8K.  It appears 
 that with the advent of TOAST very long SQL statements are becoming more 
 common, and apparently some error messages from the backend include the 
 SQL statement thus easily exceeding the 8K limit in the old code.
 
 In fixing I also cleaned up some calls in the JDBC fastpath code that 
 were not doing character set conversion under multibyte, and removed 
 some methods that were no longer needed.  I also removed a potential 
 threading problem with a shared variable that was being used in 
 Connection.java.
 
 Thanks to Steve Wampler for discovering the problem and sending the 
 initial diffs that were the basis of this patch.
 
 thanks,
 --Barry

 *** ./interfaces/jdbc/org/postgresql/Connection.java.orig Thu Jul 12 13:37:28 
2001
 --- ./interfaces/jdbc/org/postgresql/Connection.java  Thu Jul 12 13:32:55 2001
 ***
 *** 82,92 
   public int pid;
   public int ckey;
   
 - // This receive_sbuf should be used by the different methods
 - // that call pg_stream.ReceiveString() in this Connection, so
 - // so we avoid uneccesary new allocations.
 - byte receive_sbuf[] = new byte[8192];
 - 
   /**
* This is called by Class.forName() from within org.postgresql.Driver
*/
 --- 82,87 
 ***
 *** 167,174 
   // The most common one to be thrown here is:
   // User authentication failed
   //
 ! throw new SQLException(pg_stream.ReceiveString
 !(receive_sbuf, 4096, getEncoding()));
   
 case 'R':
   // Get the type of request
 --- 162,168 
   // The most common one to be thrown here is:
   // User authentication failed
   //
 ! throw new SQLException(pg_stream.ReceiveString(getEncoding()));
   
 case 'R':
   // Get the type of request
 ***
 *** 238,245 
 break;
   case 'E':
   case 'N':
 !throw new SQLException(pg_stream.ReceiveString
 !   (receive_sbuf, 4096, getEncoding()));
   default:
 throw new PSQLException(postgresql.con.setup);
 }
 --- 232,238 
 break;
   case 'E':
   case 'N':
 !throw new SQLException(pg_stream.ReceiveString(getEncoding()));
   default:
 throw new PSQLException(postgresql.con.setup);
 }
 ***
 *** 251,257 
  break;
   case 'E':
   case 'N':
 !throw new SQLException(pg_stream.ReceiveString(receive_sbuf, 4096, 
getEncoding()));
   default:
 throw new PSQLException(postgresql.con.setup);
 }
 --- 244,250 
  break;
   case 'E':
   case 'N':
 !throw new SQLException(pg_stream.ReceiveString(getEncoding()));
   default:
 throw new PSQLException(postgresql.con.setup);
 }
 ***
 *** 491,497 
   {
   case 'A':   // Asynchronous Notify
   pid = pg_stream.ReceiveInteger(4);
 ! msg = 
pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
   break;
   case 'B':   // Binary Data Transfer
   if (fields == null)
 --- 484,490 
   {
   case 'A':   // Asynchronous Notify
   pid = pg_stream.ReceiveInteger(4);
 ! msg = pg_stream.ReceiveString(getEncoding());
   break;
   case 'B':   // Binary Data Transfer
   if (fields == null)
 ***
 *** 502,508 
   tuples.addElement(tup);
   break;
   case 'C':   // Command Status
 ! recv_status = 
pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
   
   // Now handle the update count correctly.
   if(recv_status.startsWith(INSERT) ||