diff -uNr postgresql-7.3.1-orig/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java postgresql-7.3.1/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
--- postgresql-7.3.1-orig/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java	Wed Nov 13 23:54:39 2002
+++ postgresql-7.3.1/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java	Fri Jan 31 11:32:10 2003
@@ -3,6 +3,7 @@
 
 import java.util.Vector;
 import java.io.IOException;
+import java.io.Reader;
 import java.sql.*;
 import org.postgresql.*;
 import org.postgresql.util.PSQLException;
@@ -147,7 +148,23 @@
 				if (m_binds[i] == null)
 					throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
 				pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i]));
-				pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString()));
+
+                if (m_binds[i] instanceof java.io.Reader)
+                {
+                    Reader r = (Reader) m_binds[i];
+                    char[] buffer = new char[16384];
+                    int len;
+
+                    while ((len = r.read(buffer)) != -1)
+                    {
+                        String str = new String(buffer, 0, len);
+                        pg_stream.Send(connection.getEncoding().encode(str));
+                    }
+                }
+                else
+                {
+                    pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString()));
+                }
 			}
 			pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[m_binds.length]));
 			pg_stream.SendChar(0);
diff -uNr postgresql-7.3.1-orig/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java postgresql-7.3.1/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
--- postgresql-7.3.1-orig/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java	Wed Nov 20 01:54:27 2002
+++ postgresql-7.3.1/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java	Fri Jan 31 11:32:44 2003
@@ -109,7 +109,7 @@
 		v.addElement(l_sql.substring (lastParmEnd, l_sql.length()));
 
 		m_sqlFragments = new String[v.size()];
-		m_binds = new String[v.size() - 1];
+		m_binds = new Object[v.size() - 1];
 		m_bindTypes = new String[v.size() - 1];
 
 		for (i = 0 ; i < m_sqlFragments.length; ++i)
@@ -1237,27 +1237,30 @@
 			//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);
-			}
+			//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);
+			//}
+
+            // New code: bind directly to a java.io.Reader object.
+            bind(parameterIndex, new StreamingByteaReader(x, length), PG_TEXT);
 		}
 		else
 		{
diff -uNr postgresql-7.3.1-orig/src/interfaces/jdbc/org/postgresql/util/StreamingByteaReader.java postgresql-7.3.1/src/interfaces/jdbc/org/postgresql/util/StreamingByteaReader.java
--- postgresql-7.3.1-orig/src/interfaces/jdbc/org/postgresql/util/StreamingByteaReader.java	Wed Dec 31 18:00:00 1969
+++ postgresql-7.3.1/src/interfaces/jdbc/org/postgresql/util/StreamingByteaReader.java	Fri Jan 31 11:31:18 2003
@@ -0,0 +1,132 @@
+package org.postgresql.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.SQLException;
+
+/*
+ * A custom Reader that translates
+ */
+public class StreamingByteaReader extends Reader
+{
+    private InputStream in;
+    private int remainingLength;
+
+    private int state = STATE_BEGINNING;
+
+    private static final int STATE_BEGINNING = 0;
+    private static final int STATE_CONTENTS = 1;
+    private static final int STATE_END = 2;
+
+    private char[] charBuffer = new char[0];
+    private int charPos = charBuffer.length;
+
+    public StreamingByteaReader(InputStream in, int length)
+    {
+        this.in = in;
+        this.remainingLength = length;
+    }
+
+    public int read(char[] cbuf, int off, int len) throws IOException
+    {
+        int amountRead = 0;
+        boolean eos = false;
+
+        while (!eos && (amountRead < len))
+        {
+            switch (state)
+            {
+                case STATE_BEGINNING:
+                    charBuffer = new char[] { '\'' };
+                    charPos = 0;
+
+                    state = STATE_CONTENTS;
+                    break;
+
+                case STATE_CONTENTS:
+                    if (charPos >= charBuffer.length)
+                    {
+                        translateSome();
+
+                        if (charPos >= charBuffer.length)
+                        {
+                            charBuffer = new char[] { '\'' };
+                            charPos = 0;
+
+                            state = STATE_END;
+                        }
+                    }
+
+                    break;
+
+                case STATE_END:
+                    if (charPos >= charBuffer.length)
+                    {
+                        eos = true;
+                    }
+                    break;
+            }
+
+            int toCopy = Math.min(len - amountRead, charBuffer.length - charPos);
+            System.arraycopy(charBuffer, charPos, cbuf, off + amountRead, toCopy);
+
+            amountRead += toCopy;
+            charPos += toCopy;
+        }
+
+        if (amountRead == 0) return -1;
+        else return amountRead;
+    }
+
+    private void translateSome()
+        throws IOException
+    {
+        int bytesDesired = Math.min(remainingLength, 16384);
+
+        byte[] byteBuffer = new byte[bytesDesired];
+        int len = in.read(byteBuffer);
+
+        if (len == -1)
+        {
+            remainingLength = 0;
+            return;
+        }
+
+        remainingLength -= len;
+
+        if (len < byteBuffer.length)
+        {
+            byte[] oldBuf = byteBuffer;
+            byteBuffer = new byte[len];
+
+            System.arraycopy(oldBuf, 0, byteBuffer, 0, len);
+        }
+
+        try
+        {
+            String x = PGbytea.toPGString(byteBuffer);
+            StringBuffer sb = new StringBuffer(x.length());
+
+            for (int i = 0; i < x.length(); i++)
+            {
+                char c = x.charAt(i);
+
+                if (c == '\\' || c == '\'') sb.append('\\');
+                sb.append(c);
+            }
+
+            charBuffer = sb.toString().toCharArray();
+            charPos = 0;
+        }
+        catch (SQLException e)
+        {
+            throw new IOException(e.toString());
+        }
+    }
+
+    public void close() throws IOException
+    {
+    }
+}
