diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java
index fc03116f43c30040986770423b0ffef86d58e341..aba2849171ce0e305e9df05e7c0dca4f6bde92a0 100644
--- a/src/interfaces/jdbc/org/postgresql/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/Connection.java
@@ -11,7 +11,7 @@ import org.postgresql.util.*;
 import org.postgresql.core.*;
 
 /**
- * $Id: Connection.java,v 1.28 2001/09/07 22:17:02 momjian Exp $
+ * $Id: Connection.java,v 1.29 2001/09/10 15:07:05 momjian Exp $
  *
  * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
  * JDBC2 versions of the Connection class.
@@ -22,15 +22,13 @@ public abstract class Connection
   // This is the network stream associated with this connection
   public PG_Stream pg_stream;
 
-  // This is set by org.postgresql.Statement.setMaxRows()
-  //public int maxrows = 0;		// maximum no. of rows; 0 = unlimited
-
   private String PG_HOST;
   private int PG_PORT;
   private String PG_USER;
   private String PG_PASSWORD;
   private String PG_DATABASE;
   private boolean PG_STATUS;
+  private String compatible;
 
   /**
    *  The encoding to use for this connection.
@@ -123,6 +121,11 @@ public abstract class Connection
     PG_PORT = port;
     PG_HOST = host;
     PG_STATUS = CONNECTION_BAD;
+    if(info.getProperty("compatible")==null) {
+      compatible = d.getMajorVersion() + "." + d.getMinorVersion();
+    } else {
+      compatible = info.getProperty("compatible");
+    }
 
     // Now make the initial connection
     try
@@ -968,6 +971,23 @@ public abstract class Connection
       return (getDBVersionNumber().compareTo(ver) >= 0);
   }
 
+  /**
+   * This method returns true if the compatible level set in the connection
+   * (which can be passed into the connection or specified in the URL)
+   * is at least the value passed to this method.  This is used to toggle
+   * between different functionality as it changes across different releases
+   * of the jdbc driver code.  The values here are versions of the jdbc client
+   * and not server versions.  For example in 7.1 get/setBytes worked on
+   * LargeObject values, in 7.2 these methods were changed to work on bytea
+   * values.  This change in functionality could be disabled by setting the
+   * "compatible" level to be 7.1, in which case the driver will revert to
+   * the 7.1 functionality.
+   */
+  public boolean haveMinimumCompatibleVersion(String ver) throws SQLException
+  {
+      return (compatible.compareTo(ver) >= 0);
+  }
+
 
   /**
    * This returns the java.sql.Types type for a PG type oid
diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java.in b/src/interfaces/jdbc/org/postgresql/Driver.java.in
index c243a2f284f27b1a42e168a2c6ec07943e5d85af..a0d5c6e70b68cd2f2522d10ab2dea1b21769c6d7 100644
--- a/src/interfaces/jdbc/org/postgresql/Driver.java.in
+++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in
@@ -85,12 +85,26 @@ public class Driver implements java.sql.Driver
    * database.
    *
    * <p>The java.util.Properties argument can be used to pass arbitrary
-   * string tag/value pairs as connection arguments.  Normally, at least
+   * string tag/value pairs as connection arguments.  
+   *
+   * user - (optional) The user to connect as
+   * password - (optional) The password for the user
+   * charSet - (optional) The character set to be used for converting 
+   *   to/from the database to unicode.  If multibyte is enabled on the 
+   *   server then the character set of the database is used as the default,
+   *   otherwise the jvm character encoding is used as the default.
+   * compatible - This is used to toggle
+   *   between different functionality as it changes across different releases
+   *   of the jdbc driver code.  The values here are versions of the jdbc 
+   *   client and not server versions.  For example in 7.1 get/setBytes 
+   *   worked on LargeObject values, in 7.2 these methods were changed 
+   *   to work on bytea values.  This change in functionality could 
+   *   be disabled by setting the compatible level to be "7.1", in 
+   *   which case the driver will revert to the 7.1 functionality.
+   *
+   * <p>Normally, at least
    * "user" and "password" properties should be included in the
-   * properties.  In addition, the "charSet" property can be used to
-   * set a character set encoding (e.g. "utf-8") other than the platform
-   * default (typically Latin1).  This is necessary in particular if storing
-   * multibyte characters in the database.  For a list of supported
+   * properties.  For a list of supported
    * character encoding , see
    * http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html
    * Note that you will probably want to have set up the Postgres database
diff --git a/src/interfaces/jdbc/org/postgresql/ResultSet.java b/src/interfaces/jdbc/org/postgresql/ResultSet.java
index bea07e639b135321b81d9d7c1a42cab2952991b9..8757d21c7ec944f41759de25ef9a093deb14fd24 100644
--- a/src/interfaces/jdbc/org/postgresql/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/ResultSet.java
@@ -192,7 +192,8 @@ public abstract class ResultSet
       String s = getString(col);
 
       // Handle SQL Null
-      if(s==null)
+      wasNullFlag = (this_row[col - 1] == null);
+      if(wasNullFlag)
         return null;
 
       // Handle Money
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
index cf2b4bfd29f823ad838a399d71e1b836d401b834..814d693df5b29bbfce14293effdd797bd1b23fc5 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
@@ -17,7 +17,7 @@ import org.postgresql.largeobject.*;
 import org.postgresql.util.*;
 
 /**
- * $Id: Connection.java,v 1.9 2001/09/06 03:13:34 momjian Exp $
+ * $Id: Connection.java,v 1.10 2001/09/10 15:07:05 momjian Exp $
  *
  * A Connection represents a session with a specific database.  Within the
  * context of a Connection, SQL statements are executed and results are
@@ -174,6 +174,7 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co
     "float8",
     "bpchar","char","char2","char4","char8","char16",
     "varchar","text","name","filename",
+    "bytea",
     "bool",
     "date",
     "time",
@@ -197,6 +198,7 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co
     Types.DOUBLE,
     Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
     Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,
+    Types.BINARY,
     Types.BIT,
     Types.DATE,
     Types.TIME,
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
index b2b68d50a55e9605c2c7a343db43f4cfb50da06c..0c850e36ea0d43005084ea35cbb9d62e3af16699 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
@@ -82,7 +82,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * A Prepared SQL query is executed and its ResultSet is returned
 	 *
 	 * @return a ResultSet that contains the data produced by the
-	 *	query - never null
+	 *     	 *	query - never null
 	 * @exception SQLException if a database access error occurs
 	 */
 	public java.sql.ResultSet executeQuery() throws SQLException
@@ -107,7 +107,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * be executed.
 	 *
 	 * @return either the row count for INSERT, UPDATE or DELETE; or
-	 * 	0 for SQL statements that return nothing.
+	 *     	 * 	0 for SQL statements that return nothing.
 	 * @exception SQLException if a database access error occurs
 	 */
 	public int executeUpdate() throws SQLException
@@ -294,12 +294,22 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
    */
   public void setBytes(int parameterIndex, byte x[]) throws SQLException
   {
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports the bytea datatype for byte arrays
+      if(null == x){
+        setNull(parameterIndex,Types.OTHER);
+      } else {
+        setString(parameterIndex, PGbytea.toPGString(x));
+      }
+    } else {
+      //Version 7.1 and earlier support done as LargeObjects
     LargeObjectManager lom = connection.getLargeObjectAPI();
     int oid = lom.create();
     LargeObject lob = lom.open(oid);
     lob.write(x);
     lob.close();
     setInt(parameterIndex,oid);
+  }
   }
 
 	/**
@@ -386,8 +396,29 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 */
 	public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
 	{
+          if (connection.haveMinimumCompatibleVersion("7.2")) {
+            //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
+            //As the spec/javadoc for this method indicate this is to be used for
+            //large String values (i.e. LONGVARCHAR)  PG doesn't have a separate
+            //long varchar datatype, but with toast all text datatypes are capable of
+            //handling very large values.  Thus the implementation ends up calling
+            //setString() since there is no current way to stream the value to the server
+            try {
+              InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
+              char[] l_chars = new char[length];
+              int l_charsRead = l_inStream.read(l_chars,0,length);
+              setString(parameterIndex, new String(l_chars,0,l_charsRead));
+            } catch (UnsupportedEncodingException l_uee) {
+              throw new PSQLException("postgresql.unusual",l_uee);
+            } catch (IOException l_ioe) {
+              throw new PSQLException("postgresql.unusual",l_ioe);
+            }
+          } else {
+            //Version 7.1 supported only LargeObjects by treating everything
+            //as binary data
 		setBinaryStream(parameterIndex, x, length);
 	}
+        }
 
 	/**
 	 * When a very large Unicode value is input to a LONGVARCHAR parameter,
@@ -406,8 +437,29 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 */
 	public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
 	{
+          if (connection.haveMinimumCompatibleVersion("7.2")) {
+            //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
+            //As the spec/javadoc for this method indicate this is to be used for
+            //large String values (i.e. LONGVARCHAR)  PG doesn't have a separate
+            //long varchar datatype, but with toast all text datatypes are capable of
+            //handling very large values.  Thus the implementation ends up calling
+            //setString() since there is no current way to stream the value to the server
+            try {
+              InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
+              char[] l_chars = new char[length];
+              int l_charsRead = l_inStream.read(l_chars,0,length);
+              setString(parameterIndex, new String(l_chars,0,l_charsRead));
+            } catch (UnsupportedEncodingException l_uee) {
+              throw new PSQLException("postgresql.unusual",l_uee);
+            } catch (IOException l_ioe) {
+              throw new PSQLException("postgresql.unusual",l_ioe);
+            }
+          } else {
+            //Version 7.1 supported only LargeObjects by treating everything
+            //as binary data
 		setBinaryStream(parameterIndex, x, length);
 	}
+        }
 
 	/**
 	 * When a very large binary value is input to a LONGVARBINARY parameter,
@@ -425,7 +477,54 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 */
 	public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
 	{
-	    throw org.postgresql.Driver.notImplemented();
+          if (connection.haveMinimumCompatibleVersion("7.2")) {
+            //Version 7.2 supports BinaryStream for for the PG bytea type
+            //As the spec/javadoc for this method indicate this is to be used for
+            //large binary values (i.e. LONGVARBINARY)  PG doesn't have a separate
+            //long binary datatype, but with toast the bytea datatype is capable of
+            //handling very large values.  Thus the implementation ends up calling
+            //setBytes() since there is no current way to stream the value to the server
+            byte[] l_bytes = new byte[length];
+            int l_bytesRead;
+            try {
+              l_bytesRead = x.read(l_bytes,0,length);
+            } catch (IOException l_ioe) {
+              throw new PSQLException("postgresql.unusual",l_ioe);
+            }
+            if (l_bytesRead == length) {
+              setBytes(parameterIndex, l_bytes);
+            } else {
+              //the stream contained less data than they said
+              byte[] l_bytes2 = new byte[l_bytesRead];
+              System.arraycopy(l_bytes,0,l_bytes2,0,l_bytesRead);
+              setBytes(parameterIndex, l_bytes2);
+            }
+          } else {
+            //Version 7.1 only supported streams for LargeObjects
+            //but the jdbc spec indicates that streams should be
+            //available for LONGVARBINARY instead
+            LargeObjectManager lom = connection.getLargeObjectAPI();
+            int oid = lom.create();
+            LargeObject lob = lom.open(oid);
+            OutputStream los = lob.getOutputStream();
+            try {
+              // could be buffered, but then the OutputStream returned by LargeObject
+              // is buffered internally anyhow, so there would be no performance
+              // boost gained, if anything it would be worse!
+              int c=x.read();
+              int p=0;
+              while(c>-1 && p<length) {
+                los.write(c);
+                c=x.read();
+                p++;
+              }
+              los.close();
+            } catch(IOException se) {
+              throw new PSQLException("postgresql.unusual",se);
+            }
+            // lob is closed by the stream so don't call lob.close()
+            setInt(parameterIndex,oid);
+          }
 	}
 
 	/**
@@ -460,8 +559,8 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * @param x the object containing the input parameter value
 	 * @param targetSqlType The SQL type to be send to the database
 	 * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
-	 *	types this is the number of digits after the decimal.  For 
-	 *	all other types this value will be ignored.
+	 *     	 *	types this is the number of digits after the decimal.  For
+	 *     	 *	all other types this value will be ignored.
 	 * @exception SQLException if a database access error occurs
 	 */
 	public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
@@ -572,7 +671,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * statements handled by executeQuery and executeUpdate
 	 *
 	 * @return true if the next result is a ResultSet; false if it is an
-	 *	update count or there are no more results
+	 *     	 *	update count or there are no more results
 	 * @exception SQLException if a database access error occurs
 	 */
 	public boolean execute() throws SQLException
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
index f1c5fe1fcb4b903edab0096274b98fa95097b35f..8949eabc75b114192d2a429754f862534914c110 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
@@ -374,10 +374,15 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
   {
     if (columnIndex < 1 || columnIndex > fields.length)
       throw new PSQLException("postgresql.res.colrange");
-    wasNullFlag = (this_row[columnIndex - 1] == null);
     
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports the bytea datatype for byte arrays
+      return PGbytea.toBytes(getString(columnIndex));
+    } else {
+      //Version 7.1 and earlier supports LargeObjects for byte arrays
+      wasNullFlag = (this_row[columnIndex - 1] == null);
     // Handle OID's as BLOBS
-    if(!wasNullFlag)
+      if(!wasNullFlag) {
       if( fields[columnIndex - 1].getOID() == 26) {
 	LargeObjectManager lom = connection.getLargeObjectAPI();
 	LargeObject lob = lom.open(getInt(columnIndex));
@@ -385,8 +390,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 	lob.close();
 	return buf;
       }
-    
-    return this_row[columnIndex - 1];
+      }
+    }
+    return null;
   }
   
   /**
@@ -545,8 +551,27 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
    */
   public InputStream getAsciiStream(int columnIndex) throws SQLException
   {
+    wasNullFlag = (this_row[columnIndex - 1] == null);
+    if (wasNullFlag)
+      return null;
+
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports AsciiStream for all the PG text types
+      //As the spec/javadoc for this method indicate this is to be used for
+      //large text values (i.e. LONGVARCHAR)  PG doesn't have a separate
+      //long string datatype, but with toast the text datatype is capable of
+      //handling very large values.  Thus the implementation ends up calling
+      //getString() since there is no current way to stream the value from the server
+      try {
+        return new ByteArrayInputStream(getString(columnIndex).getBytes("ASCII"));
+      } catch (UnsupportedEncodingException l_uee) {
+        throw new PSQLException("postgresql.unusual", l_uee);
+      }
+    } else {
+      // In 7.1 Handle as BLOBS so return the LargeObject input stream
     return getBinaryStream(columnIndex);
   }
+  }
   
   /**
    * A column value can also be retrieved as a stream of Unicode
@@ -562,8 +587,27 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
    */
   public InputStream getUnicodeStream(int columnIndex) throws SQLException
   {
+    wasNullFlag = (this_row[columnIndex - 1] == null);
+    if (wasNullFlag)
+      return null;
+
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports AsciiStream for all the PG text types
+      //As the spec/javadoc for this method indicate this is to be used for
+      //large text values (i.e. LONGVARCHAR)  PG doesn't have a separate
+      //long string datatype, but with toast the text datatype is capable of
+      //handling very large values.  Thus the implementation ends up calling
+      //getString() since there is no current way to stream the value from the server
+      try {
+        return new ByteArrayInputStream(getString(columnIndex).getBytes("UTF-8"));
+      } catch (UnsupportedEncodingException l_uee) {
+        throw new PSQLException("postgresql.unusual", l_uee);
+      }
+    } else {
+      // In 7.1 Handle as BLOBS so return the LargeObject input stream
     return getBinaryStream(columnIndex);
   }
+  }
   
   /**
    * A column value can also be retrieved as a binary strea.  This
@@ -579,11 +623,29 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
    */
   public InputStream getBinaryStream(int columnIndex) throws SQLException
   {
-    byte b[] = getBytes(columnIndex);
+    wasNullFlag = (this_row[columnIndex - 1] == null);
+    if (wasNullFlag)
+      return null;
     
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports BinaryStream for all PG bytea type
+      //As the spec/javadoc for this method indicate this is to be used for
+      //large binary values (i.e. LONGVARBINARY)  PG doesn't have a separate
+      //long binary datatype, but with toast the bytea datatype is capable of
+      //handling very large values.  Thus the implementation ends up calling
+      //getBytes() since there is no current way to stream the value from the server
+      byte b[] = getBytes(columnIndex);
     if (b != null)
       return new ByteArrayInputStream(b);
-    return null;		// SQL NULL
+    } else {
+      // In 7.1 Handle as BLOBS so return the LargeObject input stream
+      if( fields[columnIndex - 1].getOID() == 26) {
+        LargeObjectManager lom = connection.getLargeObjectAPI();
+        LargeObject lob = lom.open(getInt(columnIndex));
+        return lob.getInputStream();
+      }
+    }
+    return null;
   }
   
   /**
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
index f705693983c0d229bb0719d32dd5723b3d1af108..9aa98cdbb628a42841fc18c858e8b98ba7c012a8 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
@@ -17,7 +17,7 @@ import org.postgresql.largeobject.*;
 import org.postgresql.util.*;
 
 /**
- * $Id: Connection.java,v 1.11 2001/09/06 03:13:34 momjian Exp $
+ * $Id: Connection.java,v 1.12 2001/09/10 15:07:05 momjian Exp $
  *
  * A Connection represents a session with a specific database.  Within the
  * context of a Connection, SQL statements are executed and results are
@@ -291,12 +291,15 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co
     "float8",
     "bpchar","char","char2","char4","char8","char16",
     "varchar","text","name","filename",
+    "bytea",
     "bool",
     "date",
     "time",
     "abstime","timestamp",
-    "_bool", "_char", "_int2", "_int4", "_text", "_oid", "_varchar", "_int8",
-    "_float4", "_float8", "_abstime", "_date", "_time", "_timestamp", "_numeric"
+    "_bool", "_char", "_int2", "_int4", "_text", 
+    "_oid", "_varchar", "_int8", "_float4", "_float8", 
+    "_abstime", "_date", "_time", "_timestamp", "_numeric", 
+    "_bytea"
   };
 
   /**
@@ -316,12 +319,15 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co
     Types.DOUBLE,
     Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
     Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,
+    Types.BINARY,
     Types.BIT,
     Types.DATE,
     Types.TIME,
     Types.TIMESTAMP,Types.TIMESTAMP,
-    Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
-    Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY
+    Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, 
+    Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, 
+    Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
+    Types.ARRAY
   };
 
 
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
index aabb49230975e7f73d74bd2337cd33b17a08c253..16b07ab5b66196097506fc599fc42693704a1006 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
@@ -91,7 +91,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * A Prepared SQL query is executed and its ResultSet is returned
 	 *
 	 * @return a ResultSet that contains the data produced by the
-	 *	query - never null
+         *             *     	query - never null
 	 * @exception SQLException if a database access error occurs
 	 */
 	public java.sql.ResultSet executeQuery() throws SQLException
@@ -105,7 +105,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * be executed.
 	 *
 	 * @return either the row count for INSERT, UPDATE or DELETE; or
-	 * 	0 for SQL statements that return nothing.
+         *             *     	0 for SQL statements that return nothing.
 	 * @exception SQLException if a database access error occurs
 	 */
 	public int executeUpdate() throws SQLException
@@ -305,12 +305,22 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
    */
   public void setBytes(int parameterIndex, byte x[]) throws SQLException
   {
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports the bytea datatype for byte arrays
+      if(null == x){
+        setNull(parameterIndex,Types.OTHER);
+      } else {
+        setString(parameterIndex, PGbytea.toPGString(x));
+      }
+    } else {
+      //Version 7.1 and earlier support done as LargeObjects
     LargeObjectManager lom = connection.getLargeObjectAPI();
     int oid = lom.create();
     LargeObject lob = lom.open(oid);
     lob.write(x);
     lob.close();
     setInt(parameterIndex,oid);
+  }
   }
 
 	/**
@@ -413,8 +423,29 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 */
 	public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
 	{
+          if (connection.haveMinimumCompatibleVersion("7.2")) {
+            //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
+            //As the spec/javadoc for this method indicate this is to be used for
+            //large String values (i.e. LONGVARCHAR)  PG doesn't have a separate
+            //long varchar datatype, but with toast all text datatypes are capable of
+            //handling very large values.  Thus the implementation ends up calling
+            //setString() since there is no current way to stream the value to the server
+            try {
+              InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
+              char[] l_chars = new char[length];
+              int l_charsRead = l_inStream.read(l_chars,0,length);
+              setString(parameterIndex, new String(l_chars,0,l_charsRead));
+            } catch (UnsupportedEncodingException l_uee) {
+              throw new PSQLException("postgresql.unusual",l_uee);
+            } catch (IOException l_ioe) {
+              throw new PSQLException("postgresql.unusual",l_ioe);
+            }
+          } else {
+            //Version 7.1 supported only LargeObjects by treating everything
+            //as binary data
 		setBinaryStream(parameterIndex, x, length);
 	}
+        }
 
 	/**
 	 * When a very large Unicode value is input to a LONGVARCHAR parameter,
@@ -436,8 +467,29 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 */
 	public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
 	{
+          if (connection.haveMinimumCompatibleVersion("7.2")) {
+            //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
+            //As the spec/javadoc for this method indicate this is to be used for
+            //large String values (i.e. LONGVARCHAR)  PG doesn't have a separate
+            //long varchar datatype, but with toast all text datatypes are capable of
+            //handling very large values.  Thus the implementation ends up calling
+            //setString() since there is no current way to stream the value to the server
+            try {
+              InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
+              char[] l_chars = new char[length];
+              int l_charsRead = l_inStream.read(l_chars,0,length);
+              setString(parameterIndex, new String(l_chars,0,l_charsRead));
+            } catch (UnsupportedEncodingException l_uee) {
+              throw new PSQLException("postgresql.unusual",l_uee);
+            } catch (IOException l_ioe) {
+              throw new PSQLException("postgresql.unusual",l_ioe);
+            }
+          } else {
+            //Version 7.1 supported only LargeObjects by treating everything
+            //as binary data
 		setBinaryStream(parameterIndex, x, length);
 	}
+        }
 
 	/**
 	 * When a very large binary value is input to a LONGVARBINARY parameter,
@@ -455,6 +507,32 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 */
 	public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
 	{
+          if (connection.haveMinimumCompatibleVersion("7.2")) {
+            //Version 7.2 supports BinaryStream for for the PG bytea type
+            //As the spec/javadoc for this method indicate this is to be used for
+            //large binary values (i.e. LONGVARBINARY)  PG doesn't have a separate
+            //long binary datatype, but with toast the bytea datatype is capable of
+            //handling very large values.  Thus the implementation ends up calling
+            //setBytes() since there is no current way to stream the value to the server
+            byte[] l_bytes = new byte[length];
+            int l_bytesRead;
+            try {
+              l_bytesRead = x.read(l_bytes,0,length);
+            } catch (IOException l_ioe) {
+              throw new PSQLException("postgresql.unusual",l_ioe);
+            }
+            if (l_bytesRead == length) {
+              setBytes(parameterIndex, l_bytes);
+            } else {
+              //the stream contained less data than they said
+              byte[] l_bytes2 = new byte[l_bytesRead];
+              System.arraycopy(l_bytes,0,l_bytes2,0,l_bytesRead);
+              setBytes(parameterIndex, l_bytes2);
+            }
+          } else {
+            //Version 7.1 only supported streams for LargeObjects
+            //but the jdbc spec indicates that streams should be
+            //available for LONGVARBINARY instead
           LargeObjectManager lom = connection.getLargeObjectAPI();
           int oid = lom.create();
           LargeObject lob = lom.open(oid);
@@ -472,11 +550,12 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
             }
             los.close();
           } catch(IOException se) {
-            throw new PSQLException("postgresql.prep.is",se);
+              throw new PSQLException("postgresql.unusual",se);
           }
           // lob is closed by the stream so don't call lob.close()
           setInt(parameterIndex,oid);
 	}
+        }
 
 	/**
 	 * In general, parameter values remain in force for repeated used of a
@@ -728,11 +807,33 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
     }
 
     /**
-     * Sets a Blob - basically its similar to setBinaryStream()
+     * Sets a Blob
      */
     public void setBlob(int i,Blob x) throws SQLException
     {
-      setBinaryStream(i,x.getBinaryStream(),(int)x.length());
+            InputStream l_inStream = x.getBinaryStream();
+            int l_length = (int) x.length();
+            LargeObjectManager lom = connection.getLargeObjectAPI();
+            int oid = lom.create();
+            LargeObject lob = lom.open(oid);
+            OutputStream los = lob.getOutputStream();
+            try {
+              // could be buffered, but then the OutputStream returned by LargeObject
+              // is buffered internally anyhow, so there would be no performance
+              // boost gained, if anything it would be worse!
+              int c=l_inStream.read();
+              int p=0;
+              while(c>-1 && p<l_length) {
+                los.write(c);
+                c=l_inStream.read();
+                p++;
+              }
+              los.close();
+            } catch(IOException se) {
+              throw new PSQLException("postgresql.unusual",se);
+            }
+            // lob is closed by the stream so don't call lob.close()
+            setInt(i,oid);
     }
 
     /**
@@ -741,6 +842,25 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
      */
     public void setCharacterStream(int i,java.io.Reader x,int length) throws SQLException
     {
+          if (connection.haveMinimumCompatibleVersion("7.2")) {
+            //Version 7.2 supports CharacterStream for for the PG text types
+            //As the spec/javadoc for this method indicate this is to be used for
+            //large text values (i.e. LONGVARCHAR)  PG doesn't have a separate
+            //long varchar datatype, but with toast all the text datatypes are capable of
+            //handling very large values.  Thus the implementation ends up calling
+            //setString() since there is no current way to stream the value to the server
+            char[] l_chars = new char[length];
+            int l_charsRead;
+            try {
+              l_charsRead = x.read(l_chars,0,length);
+            } catch (IOException l_ioe) {
+              throw new PSQLException("postgresql.unusual",l_ioe);
+            }
+            setString(i, new String(l_chars,0,l_charsRead));
+          } else {
+            //Version 7.1 only supported streams for LargeObjects
+            //but the jdbc spec indicates that streams should be
+            //available for LONGVARCHAR instead
           LargeObjectManager lom = connection.getLargeObjectAPI();
           int oid = lom.create();
           LargeObject lob = lom.open(oid);
@@ -758,18 +878,41 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
             }
             los.close();
           } catch(IOException se) {
-            throw new PSQLException("postgresql.prep.is",se);
+              throw new PSQLException("postgresql.unusual",se);
           }
           // lob is closed by the stream so don't call lob.close()
           setInt(i,oid);
     }
+    }
 
     /**
      * New in 7.1
      */
     public void setClob(int i,Clob x) throws SQLException
     {
-      setBinaryStream(i,x.getAsciiStream(),(int)x.length());
+            InputStream l_inStream = x.getAsciiStream();
+            int l_length = (int) x.length();
+            LargeObjectManager lom = connection.getLargeObjectAPI();
+            int oid = lom.create();
+            LargeObject lob = lom.open(oid);
+            OutputStream los = lob.getOutputStream();
+            try {
+              // could be buffered, but then the OutputStream returned by LargeObject
+              // is buffered internally anyhow, so there would be no performance
+              // boost gained, if anything it would be worse!
+              int c=l_inStream.read();
+              int p=0;
+              while(c>-1 && p<l_length) {
+                los.write(c);
+                c=l_inStream.read();
+                p++;
+              }
+              los.close();
+            } catch(IOException se) {
+              throw new PSQLException("postgresql.unusual",se);
+            }
+            // lob is closed by the stream so don't call lob.close()
+            setInt(i,oid);
     }
 
     /**
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
index 45df06aa35d29bfab1ed42ceba38eb6bb35df63f..bf412571115c4311070a19eb2f521eb76d3aab4a 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
@@ -312,10 +312,15 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
   {
     if (columnIndex < 1 || columnIndex > fields.length)
       throw new PSQLException("postgresql.res.colrange");
-    wasNullFlag = (this_row[columnIndex - 1] == null);
 
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports the bytea datatype for byte arrays
+      return PGbytea.toBytes(getString(columnIndex));
+    } else {
+      //Version 7.1 and earlier supports LargeObjects for byte arrays
+      wasNullFlag = (this_row[columnIndex - 1] == null);
     // Handle OID's as BLOBS
-    if(!wasNullFlag)
+      if(!wasNullFlag) {
       if( fields[columnIndex - 1].getOID() == 26) {
 	LargeObjectManager lom = connection.getLargeObjectAPI();
 	LargeObject lob = lom.open(getInt(columnIndex));
@@ -323,8 +328,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 	lob.close();
 	return buf;
       }
-
-    return this_row[columnIndex - 1];
+      }
+    }
+    return null;
   }
 
   /**
@@ -392,8 +398,27 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
    */
   public InputStream getAsciiStream(int columnIndex) throws SQLException
   {
+    wasNullFlag = (this_row[columnIndex - 1] == null);
+    if (wasNullFlag)
+      return null;
+
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports AsciiStream for all the PG text types
+      //As the spec/javadoc for this method indicate this is to be used for
+      //large text values (i.e. LONGVARCHAR)  PG doesn't have a separate
+      //long string datatype, but with toast the text datatype is capable of
+      //handling very large values.  Thus the implementation ends up calling
+      //getString() since there is no current way to stream the value from the server
+      try {
+        return new ByteArrayInputStream(getString(columnIndex).getBytes("ASCII"));
+      } catch (UnsupportedEncodingException l_uee) {
+        throw new PSQLException("postgresql.unusual", l_uee);
+      }
+    } else {
+      // In 7.1 Handle as BLOBS so return the LargeObject input stream
     return getBinaryStream(columnIndex);
   }
+  }
 
   /**
    * A column value can also be retrieved as a stream of Unicode
@@ -412,8 +437,27 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
    */
   public InputStream getUnicodeStream(int columnIndex) throws SQLException
   {
+    wasNullFlag = (this_row[columnIndex - 1] == null);
+    if (wasNullFlag)
+      return null;
+
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports AsciiStream for all the PG text types
+      //As the spec/javadoc for this method indicate this is to be used for
+      //large text values (i.e. LONGVARCHAR)  PG doesn't have a separate
+      //long string datatype, but with toast the text datatype is capable of
+      //handling very large values.  Thus the implementation ends up calling
+      //getString() since there is no current way to stream the value from the server
+      try {
+        return new ByteArrayInputStream(getString(columnIndex).getBytes("UTF-8"));
+      } catch (UnsupportedEncodingException l_uee) {
+        throw new PSQLException("postgresql.unusual", l_uee);
+      }
+    } else {
+      // In 7.1 Handle as BLOBS so return the LargeObject input stream
     return getBinaryStream(columnIndex);
   }
+  }
 
   /**
    * A column value can also be retrieved as a binary strea.  This
@@ -429,20 +473,29 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
    */
   public InputStream getBinaryStream(int columnIndex) throws SQLException
   {
-    // New in 7.1 Handle OID's as BLOBS so return the input stream
-    if(!wasNullFlag)
+    wasNullFlag = (this_row[columnIndex - 1] == null);
+    if (wasNullFlag)
+      return null;
+
+    if (connection.haveMinimumCompatibleVersion("7.2")) {
+      //Version 7.2 supports BinaryStream for all PG bytea type
+      //As the spec/javadoc for this method indicate this is to be used for
+      //large binary values (i.e. LONGVARBINARY)  PG doesn't have a separate
+      //long binary datatype, but with toast the bytea datatype is capable of
+      //handling very large values.  Thus the implementation ends up calling
+      //getBytes() since there is no current way to stream the value from the server
+      byte b[] = getBytes(columnIndex);
+      if (b != null)
+        return new ByteArrayInputStream(b);
+    } else {
+      // In 7.1 Handle as BLOBS so return the LargeObject input stream
       if( fields[columnIndex - 1].getOID() == 26) {
 	LargeObjectManager lom = connection.getLargeObjectAPI();
 	LargeObject lob = lom.open(getInt(columnIndex));
         return lob.getInputStream();
       }
-
-    // Not an OID so fake the stream
-    byte b[] = getBytes(columnIndex);
-
-    if (b != null)
-      return new ByteArrayInputStream(b);
-    return null;		// SQL NULL
+    }
+    return null;
   }
 
   /**
@@ -731,7 +784,7 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 	//if index<0, count from the end of the result set, but check
 	//to be sure that it is not beyond the first index
 	if (index<0)
-	    if (index > -rows_size)
+	    if (index >= -rows_size)
 		internalIndex = rows_size+index;
 	    else {
 		beforeFirst();
@@ -794,6 +847,10 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 
     public java.sql.Array getArray(int i) throws SQLException
     {
+        wasNullFlag = (this_row[i - 1] == null);
+        if(wasNullFlag)
+          return null;
+
     	if (i < 1 || i > fields.length)
       		throw new PSQLException("postgresql.res.colrange");
 		return (java.sql.Array) new org.postgresql.jdbc2.Array( connection, i, fields[i-1], this );
@@ -826,10 +883,25 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 
     public java.io.Reader getCharacterStream(int i) throws SQLException
     {
+      wasNullFlag = (this_row[i - 1] == null);
+      if (wasNullFlag)
+        return null;
+
+      if (connection.haveMinimumCompatibleVersion("7.2")) {
+        //Version 7.2 supports AsciiStream for all the PG text types
+        //As the spec/javadoc for this method indicate this is to be used for
+        //large text values (i.e. LONGVARCHAR)  PG doesn't have a separate
+        //long string datatype, but with toast the text datatype is capable of
+        //handling very large values.  Thus the implementation ends up calling
+        //getString() since there is no current way to stream the value from the server
+        return new CharArrayReader(getString(i).toCharArray());
+      } else {
+        // In 7.1 Handle as BLOBS so return the LargeObject input stream
 	Encoding encoding = connection.getEncoding();
 	InputStream input = getBinaryStream(i);
 	return encoding.getDecodingReader(input);
     }
+    }
 
     /**
      * New in 7.1
@@ -1485,4 +1557,7 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
 			}
 		}
 	}
+
+
 }
+
diff --git a/src/interfaces/jdbc/org/postgresql/util/PGbytea.java b/src/interfaces/jdbc/org/postgresql/util/PGbytea.java
new file mode 100644
index 0000000000000000000000000000000000000000..e994fce5bcd8d71b7877b0a922ef4ebe5946d7a2
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/util/PGbytea.java
@@ -0,0 +1,86 @@
+package org.postgresql.util;
+
+import java.sql.*;
+
+/**
+ * Converts to and from the postgresql bytea datatype used by the backend.
+ *
+ * $Id: PGbytea.java,v 1.1 2001/09/10 15:07:05 momjian Exp $
+ */
+
+public class PGbytea {
+
+        /**
+         * Converts a PG bytea string (i.e. the text representation
+         * of the bytea data type) into a java byte[]
+         */
+        public static byte[] toBytes(String s) throws SQLException {
+          if(s==null)
+            return null;
+          int slength = s.length();
+          byte[] buf = new byte[slength];
+          int bufpos = 0;
+          int thebyte;
+          char nextchar;
+          char secondchar;
+          for (int i = 0; i < slength; i++) {
+            nextchar = s.charAt(i);
+            if (nextchar == '\\') {
+              secondchar = s.charAt(++i);
+              if (secondchar == '\\') {
+                //escaped \
+                buf[bufpos++] = (byte)'\\';
+              } else {
+                thebyte = (secondchar-48)*64 + (s.charAt(++i)-48)*8 + (s.charAt(++i)-48);
+                if (thebyte > 127)
+                  thebyte -= 256;
+                buf[bufpos++] = (byte)thebyte;
+              }
+            } else {
+              buf[bufpos++] = (byte)nextchar;
+            }
+          }
+          byte[] l_return = new byte[bufpos];
+          System.arraycopy(buf,0,l_return,0,bufpos);
+          return l_return;
+        }
+
+        /**
+         * Converts a java byte[] into a PG bytea string (i.e. the text
+         * representation of the bytea data type)
+         */
+        public static String toPGString(byte[] p_buf) throws SQLException
+        {
+          if(p_buf==null)
+            return null;
+          StringBuffer l_strbuf = new StringBuffer();
+          for (int i = 0; i < p_buf.length; i++) {
+            int l_int = (int)p_buf[i];
+            if (l_int < 0) {
+              l_int = 256 + l_int;
+            }
+            //we escape the same non-printable characters as the backend
+            //we must escape all 8bit characters otherwise when convering
+            //from java unicode to the db character set we may end up with
+            //question marks if the character set is SQL_ASCII
+            if (l_int < 040 || l_int > 0176) {
+              //escape charcter with the form \000, but need two \\ because of
+              //the parser
+              l_strbuf.append("\\");
+              l_strbuf.append((char)(((l_int >> 6) & 0x3)+48));
+              l_strbuf.append((char)(((l_int >> 3) & 0x7)+48));
+              l_strbuf.append((char)((l_int & 0x07)+48));
+            } else if (p_buf[i] == (byte)'\\') {
+              //escape the backslash character as \\, but need four \\\\ because
+              //of the parser
+              l_strbuf.append("\\\\");
+            } else {
+              //other characters are left alone
+              l_strbuf.append((char)p_buf[i]);
+            }
+          }
+          return l_strbuf.toString();
+        }
+
+
+}