OSDN Git Service

Second phase of restructuring to add jdbc3 support.
authorBarry Lind <barry@xythos.com>
Wed, 24 Jul 2002 22:08:45 +0000 (22:08 +0000)
committerBarry Lind <barry@xythos.com>
Wed, 24 Jul 2002 22:08:45 +0000 (22:08 +0000)
13 files changed:
src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java [new file with mode: 0644]
src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java
src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java [deleted file]
src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
src/interfaces/jdbc/org/postgresql/jdbc2/CallableStatement.java
src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java [new file with mode: 0644]
src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java
src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java [deleted file]

index 9c4d2b1..6b06cc8 100644 (file)
@@ -1,9 +1,14 @@
 package org.postgresql.jdbc1;
 
+import java.io.*;
+
+import java.math.BigDecimal;
 import java.sql.*;
-import org.postgresql.util.PSQLException;
+import java.util.Vector;
+import org.postgresql.largeobject.*;
+import org.postgresql.util.*;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.2 2002/07/24 22:08:39 barry Exp $
  * This class defines methods of the jdbc1 specification.  This class is
  * extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
  * methods.  The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement
@@ -34,6 +39,56 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
        private static final short BACKSLASH = 2;
        private static final short ESC_TIMEDATE = 3;
 
+       // Some performance caches
+       private StringBuffer sbuf = new StringBuffer();
+
+        //Used by the preparedstatement style methods
+       protected String sql;
+       protected String[] templateStrings;
+       protected String[] inStrings;
+
+
+
+       public AbstractJdbc1Statement (AbstractJdbc1Connection connection)
+       {
+               this.connection = connection;
+       }
+
+       public AbstractJdbc1Statement (AbstractJdbc1Connection connection, String sql) throws SQLException
+       {
+               this.sql = sql;
+               this.connection = connection;
+                parseSqlStmt();  // this allows Callable stmt to override
+       }
+
+       protected void parseSqlStmt () throws SQLException {
+               Vector v = new Vector();
+               boolean inQuotes = false;
+               int lastParmEnd = 0, i;
+
+               for (i = 0; i < sql.length(); ++i)
+               {
+                       int c = sql.charAt(i);
+
+                       if (c == '\'')
+                               inQuotes = !inQuotes;
+                       if (c == '?' && !inQuotes)
+                       {
+                               v.addElement(sql.substring (lastParmEnd, i));
+                               lastParmEnd = i + 1;
+                       }
+               }
+               v.addElement(sql.substring (lastParmEnd, sql.length()));
+
+               templateStrings = new String[v.size()];
+               inStrings = new String[v.size() - 1];
+               clearParameters();
+
+               for (i = 0 ; i < templateStrings.length; ++i)
+                       templateStrings[i] = (String)v.elementAt(i);
+       }
+
+
        /*
         * Execute a SQL statement that retruns a single ResultSet
         *
@@ -52,6 +107,18 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
        }
 
        /*
+        * A Prepared SQL query is executed and its ResultSet is returned
+        *
+        * @return a ResultSet that contains the data produced by the
+        *               *      query - never null
+        * @exception SQLException if a database access error occurs
+        */
+       public java.sql.ResultSet executeQuery() throws SQLException
+       {
+           return executeQuery(compileQuery());
+       }
+
+       /*
         * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition
         * SQL statements that return nothing such as SQL DDL statements
         * can be executed
@@ -69,6 +136,20 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
        }
 
        /*
+        * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition,
+        * SQL statements that return nothing such as SQL DDL statements can
+        * be executed.
+        *
+        * @return either the row count for INSERT, UPDATE or DELETE; or
+        *               *      0 for SQL statements that return nothing.
+        * @exception SQLException if a database access error occurs
+        */
+       public int executeUpdate() throws SQLException
+       {
+           return executeUpdate(compileQuery());
+       }
+
+       /*
         * Execute a SQL statement that may return multiple results. We
         * don't have to worry about this since we do not support multiple
         * ResultSets.   You can use getResultSet or getUpdateCount to
@@ -102,6 +183,20 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
        }
 
        /*
+        * Some prepared statements return multiple results; the execute method
+        * handles these complex statements as well as the simpler form of
+        * 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
+        * @exception SQLException if a database access error occurs
+        */
+       public boolean execute() throws SQLException
+       {
+           return execute(compileQuery());
+       }
+
+       /*
         * setCursorName defines the SQL cursor name that will be used by
         * subsequent execute methods.  This name can then be used in SQL
         * positioned update/delete statements to identify the current row
@@ -466,6 +561,743 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
                return ((AbstractJdbc1ResultSet)result).getLastOID();
        }
 
+       /*
+        * Set a parameter to SQL NULL
+        *
+        * <p><B>Note:</B> You must specify the parameters SQL type (although
+        * PostgreSQL ignores it)
+        *
+        * @param parameterIndex the first parameter is 1, etc...
+        * @param sqlType the SQL type code defined in java.sql.Types
+        * @exception SQLException if a database access error occurs
+        */
+       public void setNull(int parameterIndex, int sqlType) throws SQLException
+       {
+               set(parameterIndex, "null");
+       }
+
+       /*
+        * Set a parameter to a Java boolean value.  The driver converts this
+        * to a SQL BIT value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setBoolean(int parameterIndex, boolean x) throws SQLException
+       {
+               set(parameterIndex, x ? "'t'" : "'f'");
+       }
+
+       /*
+        * Set a parameter to a Java byte value.  The driver converts this to
+        * a SQL TINYINT value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setByte(int parameterIndex, byte x) throws SQLException
+       {
+               set(parameterIndex, Integer.toString(x));
+       }
+
+       /*
+        * Set a parameter to a Java short value.  The driver converts this
+        * to a SQL SMALLINT value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setShort(int parameterIndex, short x) throws SQLException
+       {
+               set(parameterIndex, Integer.toString(x));
+       }
+
+       /*
+        * Set a parameter to a Java int value.  The driver converts this to
+        * a SQL INTEGER value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setInt(int parameterIndex, int x) throws SQLException
+       {
+               set(parameterIndex, Integer.toString(x));
+       }
+
+       /*
+        * Set a parameter to a Java long value.  The driver converts this to
+        * a SQL BIGINT value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setLong(int parameterIndex, long x) throws SQLException
+       {
+               set(parameterIndex, Long.toString(x));
+       }
+
+       /*
+        * Set a parameter to a Java float value.  The driver converts this
+        * to a SQL FLOAT value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setFloat(int parameterIndex, float x) throws SQLException
+       {
+               set(parameterIndex, Float.toString(x));
+       }
+
+       /*
+        * Set a parameter to a Java double value.      The driver converts this
+        * to a SQL DOUBLE value when it sends it to the database
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setDouble(int parameterIndex, double x) throws SQLException
+       {
+               set(parameterIndex, Double.toString(x));
+       }
+
+       /*
+        * Set a parameter to a java.lang.BigDecimal value.  The driver
+        * converts this to a SQL NUMERIC value when it sends it to the
+        * database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
+       {
+               if (x == null)
+                       setNull(parameterIndex, Types.OTHER);
+               else
+               {
+                   set(parameterIndex, x.toString());
+               }
+       }
+
+       /*
+        * Set a parameter to a Java String value.      The driver converts this
+        * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
+        * size relative to the driver's limits on VARCHARs) when it sends it
+        * to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setString(int parameterIndex, String x) throws SQLException
+       {
+               // if the passed string is null, then set this column to null
+               if (x == null)
+                       setNull(parameterIndex, Types.OTHER);
+               else
+               {
+                       // use the shared buffer object. Should never clash but this makes
+                       // us thread safe!
+                       synchronized (sbuf)
+                       {
+                               sbuf.setLength(0);
+                               int i;
+
+                               sbuf.append('\'');
+                               for (i = 0 ; i < x.length() ; ++i)
+                               {
+                                       char c = x.charAt(i);
+                                       if (c == '\\' || c == '\'')
+                                               sbuf.append((char)'\\');
+                                       sbuf.append(c);
+                               }
+                               sbuf.append('\'');
+                               set(parameterIndex, sbuf.toString());
+                       }
+               }
+       }
+
+       /*
+        * Set a parameter to a Java array of bytes.  The driver converts this
+        * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
+        * size relative to the driver's limits on VARBINARYs) when it sends
+        * it to the database.
+        *
+        * <p>Implementation note:
+        * <br>With org.postgresql, this creates a large object, and stores the
+        * objects oid in this column.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       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);
+               }
+       }
+
+       /*
+        * Set a parameter to a java.sql.Date value.  The driver converts this
+        * to a SQL DATE value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
+       {
+               if (null == x)
+               {
+                       setNull(parameterIndex, Types.OTHER);
+               }
+               else
+               {
+                       set(parameterIndex, "'" + x.toString() + "'");
+               }
+       }
+
+       /*
+        * Set a parameter to a java.sql.Time value.  The driver converts
+        * this to a SQL TIME value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...));
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setTime(int parameterIndex, Time x) throws SQLException
+       {
+               if (null == x)
+               {
+                       setNull(parameterIndex, Types.OTHER);
+               }
+               else
+               {
+                       set(parameterIndex, "'" + x.toString() + "'");
+               }
+       }
+
+       /*
+        * Set a parameter to a java.sql.Timestamp value.  The driver converts
+        * this to a SQL TIMESTAMP value when it sends it to the database.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
+       {
+               if (null == x)
+               {
+                       setNull(parameterIndex, Types.OTHER);
+               }
+               else
+                   {
+                       // Use the shared StringBuffer
+                       synchronized (sbuf)
+                       {
+                               sbuf.setLength(0);
+                               sbuf.append("'");
+                                //format the timestamp
+                                //we do our own formating so that we can get a format
+                                //that works with both timestamp with time zone and
+                                //timestamp without time zone datatypes.
+                                //The format is '2002-01-01 23:59:59.123456-0130'
+                                //we need to include the local time and timezone offset
+                                //so that timestamp without time zone works correctly
+                               int l_year = x.getYear() + 1900;
+                                sbuf.append(l_year);
+                                sbuf.append('-');
+                               int l_month = x.getMonth() + 1;
+                                if (l_month < 10) sbuf.append('0');
+                                sbuf.append(l_month);
+                                sbuf.append('-');
+                               int l_day = x.getDate();
+                                if (l_day < 10) sbuf.append('0');
+                                sbuf.append(l_day);
+                                sbuf.append(' ');
+                               int l_hours = x.getHours();
+                                if (l_hours < 10) sbuf.append('0');
+                                sbuf.append(l_hours);
+                                sbuf.append(':');
+                               int l_minutes = x.getMinutes();
+                                if (l_minutes < 10) sbuf.append('0');
+                                sbuf.append(l_minutes);
+                                sbuf.append(':');
+                                int l_seconds = x.getSeconds();
+                                if (l_seconds < 10) sbuf.append('0');
+                                sbuf.append(l_seconds);
+                                // Make decimal from nanos.
+                                char[] l_decimal = {'0','0','0','0','0','0','0','0','0'};
+                                char[] l_nanos = Integer.toString(x.getNanos()).toCharArray();
+                                System.arraycopy(l_nanos, 0, l_decimal, l_decimal.length - l_nanos.length, l_nanos.length);
+                                sbuf.append('.');
+                                if (connection.haveMinimumServerVersion("7.2")) {
+                                  sbuf.append(l_decimal,0,6);
+                                } else {
+                                  // Because 7.1 include bug that "hh:mm:59.999" becomes "hh:mm:60.00".
+                                  sbuf.append(l_decimal,0,2);
+                                }
+                                //add timezone offset
+                                int l_offset = -(x.getTimezoneOffset());
+                                int l_houros = l_offset/60;
+                                if (l_houros >= 0) {
+                                  sbuf.append('+');
+                                } else {
+                                  sbuf.append('-');
+                                }
+                                if (l_houros > -10 && l_houros < 10) sbuf.append('0');
+                                if (l_houros >= 0) {
+                                  sbuf.append(l_houros);
+                                } else {
+                                  sbuf.append(-l_houros);
+                                }
+                                int l_minos = l_offset - (l_houros *60);
+                                if (l_minos != 0) {
+                                  if (l_minos < 10) sbuf.append('0');
+                                  sbuf.append(l_minos);
+                                }
+                               sbuf.append("'");
+                               set(parameterIndex, sbuf.toString());
+                       }
+
+               }
+       }
+
+       /*
+        * When a very large ASCII value is input to a LONGVARCHAR parameter,
+        * it may be more practical to send it via a java.io.InputStream.
+        * JDBC will read the data from the stream as needed, until it reaches
+        * end-of-file.  The JDBC driver will do any necessary conversion from
+        * ASCII to the database char format.
+        *
+        * <P><B>Note:</B> This stream object can either be a standard Java
+        * stream object or your own subclass that implements the standard
+        * interface.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @param length the number of bytes in the stream
+        * @exception SQLException if a database access error occurs
+        */
+       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,
+        * it may be more practical to send it via a java.io.InputStream.
+        * JDBC will read the data from the stream as needed, until it reaches
+        * end-of-file.  The JDBC driver will do any necessary conversion from
+        * UNICODE to the database char format.
+        *
+        * <P><B>Note:</B> This stream object can either be a standard Java
+        * stream object or your own subclass that implements the standard
+        * interface.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       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,
+        * it may be more practical to send it via a java.io.InputStream.
+        * JDBC will read the data from the stream as needed, until it reaches
+        * end-of-file.
+        *
+        * <P><B>Note:</B> This stream object can either be a standard Java
+        * stream object or your own subclass that implements the standard
+        * interface.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the parameter value
+        * @exception SQLException if a database access error occurs
+        */
+       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);
+                       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);
+               }
+       }
+
+
+       /*
+        * In general, parameter values remain in force for repeated used of a
+        * Statement.  Setting a parameter value automatically clears its
+        * previous value.      However, in coms cases, it is useful to immediately
+        * release the resources used by the current parameter values; this
+        * can be done by calling clearParameters
+        *
+        * @exception SQLException if a database access error occurs
+        */
+       public void clearParameters() throws SQLException
+       {
+               int i;
+
+               for (i = 0 ; i < inStrings.length ; i++)
+                       inStrings[i] = null;
+       }
+
+       /*
+        * Set the value of a parameter using an object; use the java.lang
+        * equivalent objects for integral values.
+        *
+        * <P>The given Java object will be converted to the targetSqlType before
+        * being sent to the database.
+        *
+        * <P>note that this method may be used to pass database-specific
+        * abstract data types.  This is done by using a Driver-specific
+        * Java type and using a targetSqlType of java.sql.Types.OTHER
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @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.
+        * @exception SQLException if a database access error occurs
+        */
+       public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
+       {
+               if (x == null)
+               {
+                       setNull(parameterIndex, Types.OTHER);
+                       return;
+               }
+               switch (targetSqlType)
+               {
+                       case Types.TINYINT:
+                       case Types.SMALLINT:
+                       case Types.INTEGER:
+                       case Types.BIGINT:
+                       case Types.REAL:
+                       case Types.FLOAT:
+                       case Types.DOUBLE:
+                       case Types.DECIMAL:
+                       case Types.NUMERIC:
+                               if (x instanceof Boolean)
+                                       set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
+                               else
+                                       set(parameterIndex, x.toString());
+                               break;
+                       case Types.CHAR:
+                       case Types.VARCHAR:
+                       case Types.LONGVARCHAR:
+                               setString(parameterIndex, x.toString());
+                               break;
+                       case Types.DATE:
+                               setDate(parameterIndex, (java.sql.Date)x);
+                               break;
+                       case Types.TIME:
+                               setTime(parameterIndex, (Time)x);
+                               break;
+                       case Types.TIMESTAMP:
+                               setTimestamp(parameterIndex, (Timestamp)x);
+                               break;
+                       case Types.BIT:
+                               if (x instanceof Boolean)
+                               {
+                                       set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
+                               }
+                               else
+                               {
+                                       throw new PSQLException("postgresql.prep.type");
+                               }
+                               break;
+                       case Types.BINARY:
+                       case Types.VARBINARY:
+                               setObject(parameterIndex, x);
+                               break;
+                       case Types.OTHER:
+                               setString(parameterIndex, ((PGobject)x).getValue());
+                               break;
+                       default:
+                               throw new PSQLException("postgresql.prep.type");
+               }
+       }
+
+       public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
+       {
+               setObject(parameterIndex, x, targetSqlType, 0);
+       }
+
+       /*
+        * This stores an Object into a parameter.
+        * <p>New for 6.4, if the object is not recognised, but it is
+        * Serializable, then the object is serialised using the
+        * org.postgresql.util.Serialize class.
+        */
+       public void setObject(int parameterIndex, Object x) throws SQLException
+       {
+               if (x == null)
+               {
+                       setNull(parameterIndex, Types.OTHER);
+                       return;
+               }
+               if (x instanceof String)
+                       setString(parameterIndex, (String)x);
+               else if (x instanceof BigDecimal)
+                       setBigDecimal(parameterIndex, (BigDecimal)x);
+               else if (x instanceof Short)
+                       setShort(parameterIndex, ((Short)x).shortValue());
+               else if (x instanceof Integer)
+                       setInt(parameterIndex, ((Integer)x).intValue());
+               else if (x instanceof Long)
+                       setLong(parameterIndex, ((Long)x).longValue());
+               else if (x instanceof Float)
+                       setFloat(parameterIndex, ((Float)x).floatValue());
+               else if (x instanceof Double)
+                       setDouble(parameterIndex, ((Double)x).doubleValue());
+               else if (x instanceof byte[])
+                       setBytes(parameterIndex, (byte[])x);
+               else if (x instanceof java.sql.Date)
+                       setDate(parameterIndex, (java.sql.Date)x);
+               else if (x instanceof Time)
+                       setTime(parameterIndex, (Time)x);
+               else if (x instanceof Timestamp)
+                       setTimestamp(parameterIndex, (Timestamp)x);
+               else if (x instanceof Boolean)
+                       setBoolean(parameterIndex, ((Boolean)x).booleanValue());
+               else if (x instanceof PGobject)
+                       setString(parameterIndex, ((PGobject)x).getValue());
+               else
+                       // Try to store java object in database
+                       setSerialize(parameterIndex, connection.storeObject(x), x.getClass().getName() );
+       }
+
+       /*
+        * Returns the SQL statement with the current template values
+        * substituted.
+                       * NB: This is identical to compileQuery() except instead of throwing
+                       * SQLException if a parameter is null, it places ? instead.
+        */
+       public String toString()
+       {
+               synchronized (sbuf)
+               {
+                       sbuf.setLength(0);
+                       int i;
+
+                       for (i = 0 ; i < inStrings.length ; ++i)
+                       {
+                               if (inStrings[i] == null)
+                                       sbuf.append( '?' );
+                               else
+                                       sbuf.append (templateStrings[i]);
+                               sbuf.append (inStrings[i]);
+                       }
+                       sbuf.append(templateStrings[inStrings.length]);
+                       return sbuf.toString();
+               }
+       }
+
+       /*
+        * There are a lot of setXXX classes which all basically do
+        * the same thing.      We need a method which actually does the
+        * set for us.
+        *
+        * @param paramIndex the index into the inString
+        * @param s a string to be stored
+        * @exception SQLException if something goes wrong
+        */
+       protected void set(int paramIndex, String s) throws SQLException
+       {
+               if (paramIndex < 1 || paramIndex > inStrings.length)
+                       throw new PSQLException("postgresql.prep.range");
+               inStrings[paramIndex - 1] = s;
+       }
+
+       /*
+        * Helper - this compiles the SQL query from the various parameters
+        * This is identical to toString() except it throws an exception if a
+        * parameter is unused.
+        */
+       protected synchronized String compileQuery()
+       throws SQLException
+       {
+               sbuf.setLength(0);
+               int i;
+
+               for (i = 0 ; i < inStrings.length ; ++i)
+               {
+                       if (inStrings[i] == null)
+                               throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
+                       sbuf.append (templateStrings[i]).append (inStrings[i]);
+               }
+               sbuf.append(templateStrings[inStrings.length]);
+               return sbuf.toString();
+       }
+
+       /*
+        * Set a parameter to a tablerow-type oid reference.
+        *
+        * @param parameterIndex the first parameter is 1...
+        * @param x the oid of the object from org.postgresql.util.Serialize.store
+        * @param classname the classname of the java object x
+        * @exception SQLException if a database access error occurs
+        */
+       private void setSerialize(int parameterIndex, long x, String classname) throws SQLException
+       {
+               // converts . to _, toLowerCase, and ensures length<32
+               String tablename = Serialize.toPostgreSQL( classname );
+               DriverManager.println("setSerialize: setting " + x + "::" + tablename );
+
+               // OID reference to tablerow-type must be cast like:  <oid>::<tablename>
+               // Note that postgres support for tablerow data types is incomplete/broken.
+               // This cannot be just a plain OID because then there would be ambiguity
+               // between when you want the oid itself and when you want the object
+               // an oid references.
+               set(parameterIndex, Long.toString(x) + "::" + tablename );
+       }
 
 
 }
index 10e8c5f..dab157f 100644 (file)
@@ -39,7 +39,7 @@ import java.math.*;
  * @see ResultSet
  */
 
-public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement
+public class CallableStatement extends Jdbc1PreparedStatement implements java.sql.CallableStatement
 {
        /*
         * @exception SQLException on failure
index 55e527b..249a410 100644 (file)
@@ -6,7 +6,7 @@ import java.sql.*;
 import org.postgresql.Field;
 import org.postgresql.util.PSQLException;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.2 2002/07/24 22:08:40 barry Exp $
  * This class implements the java.sql.Connection interface for JDBC1.
  * However most of the implementation is really done in 
  * org.postgresql.jdbc1.AbstractJdbc1Connection
@@ -21,7 +21,7 @@ public class Jdbc1Connection extends org.postgresql.jdbc1.AbstractJdbc1Connectio
 
        public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
        {
-               return new org.postgresql.jdbc1.PreparedStatement(this, sql);
+               return new org.postgresql.jdbc1.Jdbc1PreparedStatement(this, sql);
        }
 
 //BJL TODO - merge callable statement logic from jdbc2 to jdbc1
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java
new file mode 100644 (file)
index 0000000..b065b57
--- /dev/null
@@ -0,0 +1,14 @@
+package org.postgresql.jdbc1;
+
+
+import java.sql.*;
+
+public class Jdbc1PreparedStatement extends AbstractJdbc1Statement implements PreparedStatement
+{
+
+       public Jdbc1PreparedStatement(Jdbc1Connection connection, String sql) throws SQLException
+       {
+               super(connection, sql);
+       }
+
+}
index bb073ea..f56841b 100644 (file)
@@ -3,7 +3,7 @@ package org.postgresql.jdbc1;
 
 import java.sql.*;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.2 2002/07/24 22:08:40 barry Exp $
  * This class implements the java.sql.Statement interface for JDBC1.
  * However most of the implementation is really done in 
  * org.postgresql.jdbc1.AbstractJdbc1Statement
@@ -13,7 +13,7 @@ public class Jdbc1Statement extends org.postgresql.jdbc1.AbstractJdbc1Statement
 
        public Jdbc1Statement (Jdbc1Connection c)
        {
-               connection = c;
+           super(c);
        }
 
 }
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
deleted file mode 100644 (file)
index 9ef9a42..0000000
+++ /dev/null
@@ -1,843 +0,0 @@
-package org.postgresql.jdbc1;
-
-// IMPORTANT NOTE: This file implements the JDBC 1 version of the driver.
-// If you make any modifications to this file, you must make sure that the
-// changes are also made (if relevent) to the related JDBC 2 class in the
-// org.postgresql.jdbc2 package.
-
-import java.io.*;
-import java.math.*;
-import java.sql.*;
-import java.text.*;
-import java.util.*;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
-
-/*
- * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
- * This object can then be used to efficiently execute this statement multiple
- * times.
- *
- * <p><B>Note:</B> The setXXX methods for setting IN parameter values must
- * specify types that are compatible with the defined SQL type of the input
- * parameter.  For instance, if the IN parameter has SQL type Integer, then
- * setInt should be used.
- *
- * <p>If arbitrary parameter type conversions are required, then the setObject
- * method should be used with a target SQL type.
- *
- * @see ResultSet
- * @see java.sql.PreparedStatement
- */
-public class PreparedStatement extends Jdbc1Statement implements java.sql.PreparedStatement
-{
-       String sql;
-       String[] templateStrings;
-       String[] inStrings;
-       Jdbc1Connection connection;
-
-       // Some performance caches
-       private StringBuffer sbuf = new StringBuffer();
-
-       /*
-        * Constructor for the PreparedStatement class.
-        * Split the SQL statement into segments - separated by the arguments.
-        * When we rebuild the thing with the arguments, we can substitute the
-        * args and join the whole thing together.
-        *
-        * @param conn the instanatiating connection
-        * @param sql the SQL statement with ? for IN markers
-        * @exception SQLException if something bad occurs
-        */
-       public PreparedStatement(Jdbc1Connection connection, String sql) throws SQLException
-       {
-               super(connection);
-
-               Vector v = new Vector();
-               boolean inQuotes = false;
-               int lastParmEnd = 0, i;
-
-               this.sql = sql;
-               this.connection = connection;
-               for (i = 0; i < sql.length(); ++i)
-               {
-                       int c = sql.charAt(i);
-
-                       if (c == '\'')
-                               inQuotes = !inQuotes;
-                       if (c == '?' && !inQuotes)
-                       {
-                               v.addElement(sql.substring (lastParmEnd, i));
-                               lastParmEnd = i + 1;
-                       }
-               }
-               v.addElement(sql.substring (lastParmEnd, sql.length()));
-
-               templateStrings = new String[v.size()];
-               inStrings = new String[v.size() - 1];
-               clearParameters();
-
-               for (i = 0 ; i < templateStrings.length; ++i)
-                       templateStrings[i] = (String)v.elementAt(i);
-       }
-
-       /*
-        * A Prepared SQL query is executed and its ResultSet is returned
-        *
-        * @return a ResultSet that contains the data produced by the
-        *               *      query - never null
-        * @exception SQLException if a database access error occurs
-        */
-       public java.sql.ResultSet executeQuery() throws SQLException
-       {
-               StringBuffer s = new StringBuffer();
-               int i;
-
-               for (i = 0 ; i < inStrings.length ; ++i)
-               {
-                       if (inStrings[i] == null)
-                               throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
-                       s.append (templateStrings[i]);
-                       s.append (inStrings[i]);
-               }
-               s.append(templateStrings[inStrings.length]);
-               return super.executeQuery(s.toString());        // in Statement class
-       }
-
-       /*
-        * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition,
-        * SQL statements that return nothing such as SQL DDL statements can
-        * be executed.
-        *
-        * @return either the row count for INSERT, UPDATE or DELETE; or
-        *               *      0 for SQL statements that return nothing.
-        * @exception SQLException if a database access error occurs
-        */
-       public int executeUpdate() throws SQLException
-       {
-               StringBuffer s = new StringBuffer();
-               int i;
-
-               for (i = 0 ; i < inStrings.length ; ++i)
-               {
-                       if (inStrings[i] == null)
-                               throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
-                       s.append (templateStrings[i]);
-                       s.append (inStrings[i]);
-               }
-               s.append(templateStrings[inStrings.length]);
-               return super.executeUpdate(s.toString());       // in Statement class
-       }
-
-       /*
-        * Set a parameter to SQL NULL
-        *
-        * <p><B>Note:</B> You must specify the parameters SQL type (although
-        * PostgreSQL ignores it)
-        *
-        * @param parameterIndex the first parameter is 1, etc...
-        * @param sqlType the SQL type code defined in java.sql.Types
-        * @exception SQLException if a database access error occurs
-        */
-       public void setNull(int parameterIndex, int sqlType) throws SQLException
-       {
-               set(parameterIndex, "null");
-       }
-
-       /*
-        * Set a parameter to a Java boolean value.  The driver converts this
-        * to a SQL BIT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setBoolean(int parameterIndex, boolean x) throws SQLException
-       {
-               set(parameterIndex, x ? "'t'" : "'f'");
-       }
-
-       /*
-        * Set a parameter to a Java byte value.  The driver converts this to
-        * a SQL TINYINT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setByte(int parameterIndex, byte x) throws SQLException
-       {
-               set(parameterIndex, Integer.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java short value.  The driver converts this
-        * to a SQL SMALLINT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setShort(int parameterIndex, short x) throws SQLException
-       {
-               set(parameterIndex, Integer.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java int value.  The driver converts this to
-        * a SQL INTEGER value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setInt(int parameterIndex, int x) throws SQLException
-       {
-               set(parameterIndex, Integer.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java long value.  The driver converts this to
-        * a SQL BIGINT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setLong(int parameterIndex, long x) throws SQLException
-       {
-               set(parameterIndex, Long.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java float value.  The driver converts this
-        * to a SQL FLOAT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setFloat(int parameterIndex, float x) throws SQLException
-       {
-               set(parameterIndex, Float.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java double value.      The driver converts this
-        * to a SQL DOUBLE value when it sends it to the database
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setDouble(int parameterIndex, double x) throws SQLException
-       {
-               set(parameterIndex, Double.toString(x));
-       }
-
-       /*
-        * Set a parameter to a java.lang.BigDecimal value.  The driver
-        * converts this to a SQL NUMERIC value when it sends it to the
-        * database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
-       {
-               if (x == null)
-                       setNull(parameterIndex, Types.OTHER);
-               else
-               {
-                   set(parameterIndex, x.toString());
-               }
-       }
-
-       /*
-        * Set a parameter to a Java String value.      The driver converts this
-        * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
-        * size relative to the driver's limits on VARCHARs) when it sends it
-        * to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setString(int parameterIndex, String x) throws SQLException
-       {
-               // if the passed string is null, then set this column to null
-               if (x == null)
-                       setNull(parameterIndex, Types.OTHER);
-               else
-               {
-                       StringBuffer b = new StringBuffer();
-                       int i;
-
-                       b.append('\'');
-                       for (i = 0 ; i < x.length() ; ++i)
-                       {
-                               char c = x.charAt(i);
-                               if (c == '\\' || c == '\'')
-                                       b.append((char)'\\');
-                               b.append(c);
-                       }
-                       b.append('\'');
-                       set(parameterIndex, b.toString());
-               }
-       }
-
-       /*
-        * Set a parameter to a Java array of bytes.  The driver converts this
-        * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
-        * size relative to the driver's limits on VARBINARYs) when it sends
-        * it to the database.
-        *
-        * <p>Implementation note:
-        * <br>With org.postgresql, this creates a large object, and stores the
-        * objects oid in this column.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       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);
-               }
-       }
-
-       /*
-        * Set a parameter to a java.sql.Date value.  The driver converts this
-        * to a SQL DATE value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
-       {
-               if (null == x)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-               }
-               else
-               {
-                       set(parameterIndex, "'" + x.toString() + "'");
-               }
-       }
-
-       /*
-        * Set a parameter to a java.sql.Time value.  The driver converts
-        * this to a SQL TIME value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...));
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setTime(int parameterIndex, Time x) throws SQLException
-       {
-               if (null == x)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-               }
-               else
-               {
-                       set(parameterIndex, "'" + x.toString() + "'");
-               }
-       }
-
-       /*
-        * Set a parameter to a java.sql.Timestamp value.  The driver converts
-        * this to a SQL TIMESTAMP value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
-       {
-               if (null == x)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-               }
-               else
-                   {
-                       // Use the shared StringBuffer
-                       synchronized (sbuf)
-                       {
-                               sbuf.setLength(0);
-                               sbuf.append("'");
-                                //format the timestamp
-                                //we do our own formating so that we can get a format
-                                //that works with both timestamp with time zone and
-                                //timestamp without time zone datatypes.
-                                //The format is '2002-01-01 23:59:59.123456-0130'
-                                //we need to include the local time and timezone offset
-                                //so that timestamp without time zone works correctly
-                               int l_year = x.getYear() + 1900;
-                                sbuf.append(l_year);
-                                sbuf.append('-');
-                               int l_month = x.getMonth() + 1;
-                                if (l_month < 10) sbuf.append('0');
-                                sbuf.append(l_month);
-                                sbuf.append('-');
-                               int l_day = x.getDate();
-                                if (l_day < 10) sbuf.append('0');
-                                sbuf.append(l_day);
-                                sbuf.append(' ');
-                               int l_hours = x.getHours();
-                                if (l_hours < 10) sbuf.append('0');
-                                sbuf.append(l_hours);
-                                sbuf.append(':');
-                               int l_minutes = x.getMinutes();
-                                if (l_minutes < 10) sbuf.append('0');
-                                sbuf.append(l_minutes);
-                                sbuf.append(':');
-                                int l_seconds = x.getSeconds();
-                                if (l_seconds < 10) sbuf.append('0');
-                                sbuf.append(l_seconds);
-                                // Make decimal from nanos.
-                                char[] l_decimal = {'0','0','0','0','0','0','0','0','0'};
-                                char[] l_nanos = Integer.toString(x.getNanos()).toCharArray();
-                                System.arraycopy(l_nanos, 0, l_decimal, l_decimal.length - l_nanos.length, l_nanos.length);
-                                sbuf.append('.');
-                                if (connection.haveMinimumServerVersion("7.2")) {
-                                  sbuf.append(l_decimal,0,6);
-                                } else {
-                                  // Because 7.1 include bug that "hh:mm:59.999" becomes "hh:mm:60.00".
-                                  sbuf.append(l_decimal,0,2);
-                                }
-                                //add timezone offset
-                                int l_offset = -(x.getTimezoneOffset());
-                                int l_houros = l_offset/60;
-                                if (l_houros >= 0) {
-                                  sbuf.append('+');
-                                } else {
-                                  sbuf.append('-');
-                                }
-                                if (l_houros > -10 && l_houros < 10) sbuf.append('0');
-                                if (l_houros >= 0) {
-                                  sbuf.append(l_houros);
-                                } else {
-                                  sbuf.append(-l_houros);
-                                }
-                                int l_minos = l_offset - (l_houros *60);
-                                if (l_minos != 0) {
-                                  if (l_minos < 10) sbuf.append('0');
-                                  sbuf.append(l_minos);
-                                }
-                               sbuf.append("'");
-                               set(parameterIndex, sbuf.toString());
-                       }
-
-               }
-       }
-
-       /*
-        * When a very large ASCII value is input to a LONGVARCHAR parameter,
-        * it may be more practical to send it via a java.io.InputStream.
-        * JDBC will read the data from the stream as needed, until it reaches
-        * end-of-file.  The JDBC driver will do any necessary conversion from
-        * ASCII to the database char format.
-        *
-        * <P><B>Note:</B> This stream object can either be a standard Java
-        * stream object or your own subclass that implements the standard
-        * interface.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @param length the number of bytes in the stream
-        * @exception SQLException if a database access error occurs
-        */
-       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,
-        * it may be more practical to send it via a java.io.InputStream.
-        * JDBC will read the data from the stream as needed, until it reaches
-        * end-of-file.  The JDBC driver will do any necessary conversion from
-        * UNICODE to the database char format.
-        *
-        * <P><B>Note:</B> This stream object can either be a standard Java
-        * stream object or your own subclass that implements the standard
-        * interface.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       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,
-        * it may be more practical to send it via a java.io.InputStream.
-        * JDBC will read the data from the stream as needed, until it reaches
-        * end-of-file.
-        *
-        * <P><B>Note:</B> This stream object can either be a standard Java
-        * stream object or your own subclass that implements the standard
-        * interface.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       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);
-                       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);
-               }
-       }
-
-       /*
-        * In general, parameter values remain in force for repeated used of a
-        * Statement.  Setting a parameter value automatically clears its
-        * previous value.      However, in coms cases, it is useful to immediately
-        * release the resources used by the current parameter values; this
-        * can be done by calling clearParameters
-        *
-        * @exception SQLException if a database access error occurs
-        */
-       public void clearParameters() throws SQLException
-       {
-               int i;
-
-               for (i = 0 ; i < inStrings.length ; i++)
-                       inStrings[i] = null;
-       }
-
-       /*
-        * Set the value of a parameter using an object; use the java.lang
-        * equivalent objects for integral values.
-        *
-        * <P>The given Java object will be converted to the targetSqlType before
-        * being sent to the database.
-        *
-        * <P>note that this method may be used to pass database-specific
-        * abstract data types.  This is done by using a Driver-specific
-        * Java type and using a targetSqlType of java.sql.Types.OTHER
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @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.
-        * @exception SQLException if a database access error occurs
-        */
-       public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
-       {
-               if (x == null)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-                       return;
-               }
-               switch (targetSqlType)
-               {
-                       case Types.TINYINT:
-                       case Types.SMALLINT:
-                       case Types.INTEGER:
-                       case Types.BIGINT:
-                       case Types.REAL:
-                       case Types.FLOAT:
-                       case Types.DOUBLE:
-                       case Types.DECIMAL:
-                       case Types.NUMERIC:
-                               if (x instanceof Boolean)
-                                       set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
-                               else
-                                       set(parameterIndex, x.toString());
-                               break;
-                       case Types.CHAR:
-                       case Types.VARCHAR:
-                       case Types.LONGVARCHAR:
-                               setString(parameterIndex, x.toString());
-                               break;
-                       case Types.DATE:
-                               setDate(parameterIndex, (java.sql.Date)x);
-                               break;
-                       case Types.TIME:
-                               setTime(parameterIndex, (Time)x);
-                               break;
-                       case Types.TIMESTAMP:
-                               setTimestamp(parameterIndex, (Timestamp)x);
-                               break;
-                       case Types.BIT:
-                               if (x instanceof Boolean)
-                               {
-                                       set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
-                               }
-                               else
-                               {
-                                       throw new PSQLException("postgresql.prep.type");
-                               }
-                               break;
-                       case Types.BINARY:
-                       case Types.VARBINARY:
-                               setObject(parameterIndex, x);
-                               break;
-                       case Types.OTHER:
-                               setString(parameterIndex, ((PGobject)x).getValue());
-                               break;
-                       default:
-                               throw new PSQLException("postgresql.prep.type");
-               }
-       }
-
-       public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
-       {
-               setObject(parameterIndex, x, targetSqlType, 0);
-       }
-
-       /*
-        * This stores an Object into a parameter.
-        * <p>New for 6.4, if the object is not recognised, but it is
-        * Serializable, then the object is serialised using the
-        * org.postgresql.util.Serialize class.
-        */
-       public void setObject(int parameterIndex, Object x) throws SQLException
-       {
-               if (x == null)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-                       return;
-               }
-               if (x instanceof String)
-                       setString(parameterIndex, (String)x);
-               else if (x instanceof BigDecimal)
-                       setBigDecimal(parameterIndex, (BigDecimal)x);
-               else if (x instanceof Short)
-                       setShort(parameterIndex, ((Short)x).shortValue());
-               else if (x instanceof Integer)
-                       setInt(parameterIndex, ((Integer)x).intValue());
-               else if (x instanceof Long)
-                       setLong(parameterIndex, ((Long)x).longValue());
-               else if (x instanceof Float)
-                       setFloat(parameterIndex, ((Float)x).floatValue());
-               else if (x instanceof Double)
-                       setDouble(parameterIndex, ((Double)x).doubleValue());
-               else if (x instanceof byte[])
-                       setBytes(parameterIndex, (byte[])x);
-               else if (x instanceof java.sql.Date)
-                       setDate(parameterIndex, (java.sql.Date)x);
-               else if (x instanceof Time)
-                       setTime(parameterIndex, (Time)x);
-               else if (x instanceof Timestamp)
-                       setTimestamp(parameterIndex, (Timestamp)x);
-               else if (x instanceof Boolean)
-                       setBoolean(parameterIndex, ((Boolean)x).booleanValue());
-               else if (x instanceof PGobject)
-                       setString(parameterIndex, ((PGobject)x).getValue());
-               else
-                       setLong(parameterIndex, connection.storeObject(x));
-       }
-
-       /*
-        * Some prepared statements return multiple results; the execute method
-        * handles these complex statements as well as the simpler form of
-        * 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
-        * @exception SQLException if a database access error occurs
-        */
-       public boolean execute() throws SQLException
-       {
-               StringBuffer s = new StringBuffer();
-               int i;
-
-               for (i = 0 ; i < inStrings.length ; ++i)
-               {
-                       if (inStrings[i] == null)
-                               throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
-                       s.append (templateStrings[i]);
-                       s.append (inStrings[i]);
-               }
-               s.append(templateStrings[inStrings.length]);
-               return super.execute(s.toString());             // in Statement class
-       }
-
-       /*
-        * Returns the SQL statement with the current template values
-        * substituted.
-        */
-       public String toString()
-       {
-               StringBuffer s = new StringBuffer();
-               int i;
-
-               for (i = 0 ; i < inStrings.length ; ++i)
-               {
-                       if (inStrings[i] == null)
-                               s.append( '?' );
-                       else
-                               s.append (templateStrings[i]);
-                       s.append (inStrings[i]);
-               }
-               s.append(templateStrings[inStrings.length]);
-               return s.toString();
-       }
-
-       // **************************************************************
-       //      END OF PUBLIC INTERFACE
-       // **************************************************************
-
-       /*
-        * There are a lot of setXXX classes which all basically do
-        * the same thing.      We need a method which actually does the
-        * set for us.
-        *
-        * @param paramIndex the index into the inString
-        * @param s a string to be stored
-        * @exception SQLException if something goes wrong
-        */
-       private void set(int paramIndex, String s) throws SQLException
-       {
-               if (paramIndex < 1 || paramIndex > inStrings.length)
-                       throw new PSQLException("postgresql.prep.range");
-               inStrings[paramIndex - 1] = s;
-       }
-}
index 50c5d94..d2c5ee0 100644 (file)
@@ -13,14 +13,14 @@ import org.postgresql.largeobject.*;
 import org.postgresql.util.PGbytea;
 import org.postgresql.util.PSQLException;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.2 2002/07/24 22:08:42 barry Exp $
  * This class defines methods of the jdbc2 specification.  This class extends
  * org.postgresql.jdbc1.AbstractJdbc1ResultSet which provides the jdbc1
  * methods.  The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2ResultSet
  */
 public class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet
 {
-       protected Jdbc2Statement statement;
+       protected Statement statement;
 
        protected String sqlQuery=null;
 
@@ -373,7 +373,7 @@ public class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1Re
        }
 
        // This one needs some thought, as not all ResultSets come from a statement
-       public java.sql.Statement getStatement() throws SQLException
+       public Statement getStatement() throws SQLException
        {
                return statement;
        }
@@ -740,7 +740,7 @@ public class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1Re
         * It's used currently by getStatement() but may also with the new core
         * package.
         */
-       public void setStatement(Jdbc2Statement statement)
+       public void setStatement(Statement statement)
        {
                this.statement = statement;
        }
index 3d6f655..47c2c77 100644 (file)
@@ -1,11 +1,13 @@
 package org.postgresql.jdbc2;
 
 
+import java.io.*;
 import java.sql.*;
 import java.util.Vector;
+import org.postgresql.largeobject.*;
 import org.postgresql.util.PSQLException;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.2 2002/07/24 22:08:42 barry Exp $
  * This class defines methods of the jdbc2 specification.  This class extends
  * org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1
  * methods.  The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement
@@ -17,6 +19,18 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
        protected int resultsettype;             // the resultset type to return
        protected int concurrency;               // is it updateable or not?
 
+       public AbstractJdbc2Statement (AbstractJdbc2Connection c)
+       {
+               super(c);
+               resultsettype = java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
+               concurrency = java.sql.ResultSet.CONCUR_READ_ONLY;
+       }
+
+       public AbstractJdbc2Statement(AbstractJdbc2Connection connection, String sql) throws SQLException
+       {
+               super(connection, sql);
+       }
+
        /*
         * Execute a SQL statement that may return multiple results. We
         * don't have to worry about this since we do not support multiple
@@ -31,10 +45,9 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
        public boolean execute(String sql) throws SQLException
        {
                boolean l_return = super.execute(sql);
-
                 //Now do the jdbc2 specific stuff
                //required for ResultSet.getStatement() to work
-               ((AbstractJdbc2ResultSet)result).setStatement((Jdbc2Statement)this);
+               ((AbstractJdbc2ResultSet)result).setStatement((Statement)this);
 
                // Added this so that the Updateable resultset knows the query that gave this
                ((AbstractJdbc2ResultSet)result).setSQLQuery(sql);
@@ -139,4 +152,183 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
                resultsettype = value;
        }
 
+       public void addBatch() throws SQLException
+       {
+               addBatch(compileQuery());
+       }
+
+       public java.sql.ResultSetMetaData getMetaData() throws SQLException
+       {
+               java.sql.ResultSet rs = getResultSet();
+               if (rs != null)
+                       return rs.getMetaData();
+
+               // Does anyone really know what this method does?
+               return null;
+       }
+
+       public void setArray(int i, java.sql.Array x) throws SQLException
+       {
+               setString(i, x.toString());
+       }
+
+       public void setBlob(int i, Blob x) throws SQLException
+       {
+               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);
+       }
+
+       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);
+                       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(i, oid);
+               }
+       }
+
+       public void setClob(int i, Clob x) throws SQLException
+       {
+               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);
+       }
+
+       public void setNull(int i, int t, String s) throws SQLException
+       {
+               setNull(i, t);
+       }
+
+       public void setRef(int i, Ref x) throws SQLException
+       {
+               throw org.postgresql.Driver.notImplemented();
+       }
+
+       public void setDate(int i, java.sql.Date d, java.util.Calendar cal) throws SQLException
+       {
+               if (cal == null)
+                       setDate(i, d);
+               else
+               {
+                       cal.setTime(d);
+                       setDate(i, new java.sql.Date(cal.getTime().getTime()));
+               }
+       }
+
+       public void setTime(int i, Time t, java.util.Calendar cal) throws SQLException
+       {
+               if (cal == null)
+                       setTime(i, t);
+               else
+               {
+                       cal.setTime(t);
+                       setTime(i, new java.sql.Time(cal.getTime().getTime()));
+               }
+       }
+
+       public void setTimestamp(int i, Timestamp t, java.util.Calendar cal) throws SQLException
+       {
+               if (cal == null)
+                       setTimestamp(i, t);
+               else
+               {
+                       cal.setTime(t);
+                       setTimestamp(i, new java.sql.Timestamp(cal.getTime().getTime()));
+               }
+       }
 }
index 9d37bf0..51dd9b2 100644 (file)
@@ -40,7 +40,7 @@ import org.postgresql.util.*;
  * @author Paul Bethe (implementer)
  */
 
-public class CallableStatement extends org.postgresql.jdbc2.PreparedStatement implements java.sql.CallableStatement
+public class CallableStatement extends org.postgresql.jdbc2.Jdbc2PreparedStatement implements java.sql.CallableStatement
 {
        /*
         * @exception SQLException on failure
index cfbb348..787b14e 100644 (file)
@@ -5,7 +5,7 @@ import java.sql.*;
 import java.util.Vector;
 import org.postgresql.Field;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.2 2002/07/24 22:08:42 barry Exp $
  * This class implements the java.sql.Connection interface for JDBC2.
  * However most of the implementation is really done in 
  * org.postgresql.jdbc2.AbstractJdbc2Connection or one of it's parents
@@ -24,7 +24,7 @@ public class Jdbc2Connection extends org.postgresql.jdbc2.AbstractJdbc2Connectio
 
         public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
         {
-                org.postgresql.jdbc2.PreparedStatement s = new org.postgresql.jdbc2.PreparedStatement(this, sql);
+                Jdbc2PreparedStatement s = new Jdbc2PreparedStatement(this, sql);
                 s.setResultSetType(resultSetType);
                 s.setResultSetConcurrency(resultSetConcurrency);
                 return s;
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java
new file mode 100644 (file)
index 0000000..0472007
--- /dev/null
@@ -0,0 +1,15 @@
+package org.postgresql.jdbc2;
+
+
+import java.sql.*;
+
+public class Jdbc2PreparedStatement extends AbstractJdbc2Statement implements java.sql.PreparedStatement
+{
+
+       public Jdbc2PreparedStatement(Jdbc2Connection connection, String sql) throws SQLException
+       {
+               super(connection, sql);
+       }
+
+}
+
index 31cec93..4f63d10 100644 (file)
@@ -3,7 +3,7 @@ package org.postgresql.jdbc2;
 
 import java.sql.*;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.2 2002/07/24 22:08:43 barry Exp $
  * This class implements the java.sql.Statement interface for JDBC2.
  * However most of the implementation is really done in 
  * org.postgresql.jdbc2.AbstractJdbc2Statement or one of it's parents
@@ -13,9 +13,7 @@ public class Jdbc2Statement extends org.postgresql.jdbc2.AbstractJdbc2Statement
 
        public Jdbc2Statement (Jdbc2Connection c)
        {
-               connection = c;
-               resultsettype = java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
-               concurrency = java.sql.ResultSet.CONCUR_READ_ONLY;
+               super(c);
        }
 
 }
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
deleted file mode 100644 (file)
index 21aba8d..0000000
+++ /dev/null
@@ -1,1086 +0,0 @@
-package org.postgresql.jdbc2;
-
-// IMPORTANT NOTE: This file implements the JDBC 2 version of the driver.
-// If you make any modifications to this file, you must make sure that the
-// changes are also made (if relevent) to the related JDBC 1 class in the
-// org.postgresql.jdbc1 package.
-
-import java.io.*;
-import java.math.*;
-import java.sql.*;
-import java.text.*;
-import java.util.*;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
-
-/*
- * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
- * This object can then be used to efficiently execute this statement multiple
- * times.
- *
- * <p><B>Note:</B> The setXXX methods for setting IN parameter values must
- * specify types that are compatible with the defined SQL type of the input
- * parameter.  For instance, if the IN parameter has SQL type Integer, then
- * setInt should be used.
- *
- * <p>If arbitrary parameter type conversions are required, then the setObject
- * method should be used with a target SQL type.
- *
- * @see ResultSet
- * @see java.sql.PreparedStatement
- */
-public class PreparedStatement extends Jdbc2Statement implements java.sql.PreparedStatement
-{
-       String sql;
-       String[] templateStrings;
-       String[] inStrings;
-       Jdbc2Connection connection;
-
-       // Some performance caches
-       private StringBuffer sbuf = new StringBuffer();
-
-       /*
-        * Constructor for the PreparedStatement class.
-        * Split the SQL statement into segments - separated by the arguments.
-        * When we rebuild the thing with the arguments, we can substitute the
-        * args and join the whole thing together.
-        *
-        * @param conn the instanatiating connection
-        * @param sql the SQL statement with ? for IN markers
-        * @exception SQLException if something bad occurs
-        */
-       public PreparedStatement(Jdbc2Connection connection, String sql) throws SQLException
-       {
-               super(connection);
-
-               this.sql = sql;
-               this.connection = connection;
-               parseSqlStmt (); // this allows Callable stmt to override
-       }
-
-       protected void parseSqlStmt () throws SQLException {
-               Vector v = new Vector();
-               boolean inQuotes = false;
-               int lastParmEnd = 0, i;
-
-               for (i = 0; i < sql.length(); ++i)
-               {
-                       int c = sql.charAt(i);
-
-                       if (c == '\'')
-                               inQuotes = !inQuotes;
-                       if (c == '?' && !inQuotes)
-                       {
-                               v.addElement(sql.substring (lastParmEnd, i));
-                               lastParmEnd = i + 1;
-                       }
-               }
-               v.addElement(sql.substring (lastParmEnd, sql.length()));
-
-               templateStrings = new String[v.size()];
-               inStrings = new String[v.size() - 1];
-               clearParameters();
-
-               for (i = 0 ; i < templateStrings.length; ++i)
-                       templateStrings[i] = (String)v.elementAt(i);
-       }
-
-       /*
-        * A Prepared SQL query is executed and its ResultSet is returned
-        *
-        * @return a ResultSet that contains the data produced by the
-                       *                         *                     query - never null
-        * @exception SQLException if a database access error occurs
-        */
-       public java.sql.ResultSet executeQuery() throws SQLException
-       {
-               return super.executeQuery(compileQuery());      // in Statement class
-       }
-
-       /*
-        * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition,
-        * SQL statements that return nothing such as SQL DDL statements can
-        * be executed.
-        *
-        * @return either the row count for INSERT, UPDATE or DELETE; or
-                       *                         *                     0 for SQL statements that return nothing.
-        * @exception SQLException if a database access error occurs
-        */
-       public int executeUpdate() throws SQLException
-       {
-               return super.executeUpdate(compileQuery());             // in Statement class
-       }
-
-       /*
-        * Helper - this compiles the SQL query from the various parameters
-        * This is identical to toString() except it throws an exception if a
-        * parameter is unused.
-        */
-       protected synchronized String compileQuery()
-       throws SQLException
-       {
-               sbuf.setLength(0);
-               int i;
-
-               for (i = 0 ; i < inStrings.length ; ++i)
-               {
-                       if (inStrings[i] == null)
-                               throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
-                       sbuf.append (templateStrings[i]).append (inStrings[i]);
-               }
-               sbuf.append(templateStrings[inStrings.length]);
-               return sbuf.toString();
-       }
-
-       /*
-        * Set a parameter to SQL NULL
-        *
-        * <p><B>Note:</B> You must specify the parameters SQL type (although
-        * PostgreSQL ignores it)
-        *
-        * @param parameterIndex the first parameter is 1, etc...
-        * @param sqlType the SQL type code defined in java.sql.Types
-        * @exception SQLException if a database access error occurs
-        */
-       public void setNull(int parameterIndex, int sqlType) throws SQLException
-       {
-               set(parameterIndex, "null");
-       }
-
-       /*
-        * Set a parameter to a Java boolean value.  The driver converts this
-        * to a SQL BIT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setBoolean(int parameterIndex, boolean x) throws SQLException
-       {
-               set(parameterIndex, x ? "'t'" : "'f'");
-       }
-
-       /*
-        * Set a parameter to a Java byte value.  The driver converts this to
-        * a SQL TINYINT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setByte(int parameterIndex, byte x) throws SQLException
-       {
-               set(parameterIndex, Integer.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java short value.  The driver converts this
-        * to a SQL SMALLINT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setShort(int parameterIndex, short x) throws SQLException
-       {
-               set(parameterIndex, Integer.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java int value.  The driver converts this to
-        * a SQL INTEGER value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setInt(int parameterIndex, int x) throws SQLException
-       {
-               set(parameterIndex, Integer.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java long value.  The driver converts this to
-        * a SQL BIGINT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setLong(int parameterIndex, long x) throws SQLException
-       {
-               set(parameterIndex, Long.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java float value.  The driver converts this
-        * to a SQL FLOAT value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setFloat(int parameterIndex, float x) throws SQLException
-       {
-               set(parameterIndex, Float.toString(x));
-       }
-
-       /*
-        * Set a parameter to a Java double value.      The driver converts this
-        * to a SQL DOUBLE value when it sends it to the database
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setDouble(int parameterIndex, double x) throws SQLException
-       {
-               set(parameterIndex, Double.toString(x));
-       }
-
-       /*
-        * Set a parameter to a java.lang.BigDecimal value.  The driver
-        * converts this to a SQL NUMERIC value when it sends it to the
-        * database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
-       {
-           if (x == null) {
-               setNull(parameterIndex, Types.OTHER);
-            } else {
-               set(parameterIndex, x.toString());
-           }
-       }
-
-       /*
-        * Set a parameter to a Java String value.      The driver converts this
-        * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
-        * size relative to the driver's limits on VARCHARs) when it sends it
-        * to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setString(int parameterIndex, String x) throws SQLException
-       {
-               // if the passed string is null, then set this column to null
-               if (x == null)
-                       setNull(parameterIndex, Types.OTHER);
-               else
-               {
-                       // use the shared buffer object. Should never clash but this makes
-                       // us thread safe!
-                       synchronized (sbuf)
-                       {
-                               sbuf.setLength(0);
-                               int i;
-
-                               sbuf.append('\'');
-                               for (i = 0 ; i < x.length() ; ++i)
-                               {
-                                       char c = x.charAt(i);
-                                       if (c == '\\' || c == '\'')
-                                               sbuf.append((char)'\\');
-                                       sbuf.append(c);
-                               }
-                               sbuf.append('\'');
-                               set(parameterIndex, sbuf.toString());
-                       }
-               }
-       }
-
-       /*
-        * Set a parameter to a Java array of bytes.  The driver converts this
-        * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
-        * size relative to the driver's limits on VARBINARYs) when it sends
-        * it to the database.
-        *
-        * <p>Implementation note:
-        * <br>With org.postgresql, this creates a large object, and stores the
-        * objects oid in this column.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       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);
-               }
-       }
-
-       /*
-        * Set a parameter to a java.sql.Date value.  The driver converts this
-        * to a SQL DATE value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
-       {
-               if (null == x)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-               }
-               else
-               {
-                       set(parameterIndex, "'" + x.toString() + "'");
-               }
-       }
-
-       /*
-        * Set a parameter to a java.sql.Time value.  The driver converts
-        * this to a SQL TIME value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...));
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setTime(int parameterIndex, Time x) throws SQLException
-       {
-               if (null == x)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-               }
-               else
-               {
-                       set(parameterIndex, "'" + x.toString() + "'");
-               }
-       }
-
-       /*
-        * Set a parameter to a java.sql.Timestamp value.  The driver converts
-        * this to a SQL TIMESTAMP value when it sends it to the database.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
-       {
-               if (null == x)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-               }
-               else
-                   {
-                       // Use the shared StringBuffer
-                       synchronized (sbuf)
-                       {
-                               sbuf.setLength(0);
-                               sbuf.append("'");
-                                //format the timestamp
-                                //we do our own formating so that we can get a format
-                                //that works with both timestamp with time zone and
-                                //timestamp without time zone datatypes.
-                                //The format is '2002-01-01 23:59:59.123456-0130'
-                                //we need to include the local time and timezone offset
-                                //so that timestamp without time zone works correctly
-                               int l_year = x.getYear() + 1900;
-                                sbuf.append(l_year);
-                                sbuf.append('-');
-                               int l_month = x.getMonth() + 1;
-                                if (l_month < 10) sbuf.append('0');
-                                sbuf.append(l_month);
-                                sbuf.append('-');
-                               int l_day = x.getDate();
-                                if (l_day < 10) sbuf.append('0');
-                                sbuf.append(l_day);
-                                sbuf.append(' ');
-                               int l_hours = x.getHours();
-                                if (l_hours < 10) sbuf.append('0');
-                                sbuf.append(l_hours);
-                                sbuf.append(':');
-                               int l_minutes = x.getMinutes();
-                                if (l_minutes < 10) sbuf.append('0');
-                                sbuf.append(l_minutes);
-                                sbuf.append(':');
-                                int l_seconds = x.getSeconds();
-                                if (l_seconds < 10) sbuf.append('0');
-                                sbuf.append(l_seconds);
-                                // Make decimal from nanos.
-                                char[] l_decimal = {'0','0','0','0','0','0','0','0','0'};
-                                char[] l_nanos = Integer.toString(x.getNanos()).toCharArray();
-                                System.arraycopy(l_nanos, 0, l_decimal, l_decimal.length - l_nanos.length, l_nanos.length);
-                                sbuf.append('.');
-                                if (connection.haveMinimumServerVersion("7.2")) {
-                                  sbuf.append(l_decimal,0,6);
-                                } else {
-                                  // Because 7.1 include bug that "hh:mm:59.999" becomes "hh:mm:60.00".
-                                  sbuf.append(l_decimal,0,2);
-                                }
-                                //add timezone offset
-                                int l_offset = -(x.getTimezoneOffset());
-                                int l_houros = l_offset/60;
-                                if (l_houros >= 0) {
-                                  sbuf.append('+');
-                                } else {
-                                  sbuf.append('-');
-                                }
-                                if (l_houros > -10 && l_houros < 10) sbuf.append('0');
-                                if (l_houros >= 0) {
-                                  sbuf.append(l_houros);
-                                } else {
-                                  sbuf.append(-l_houros);
-                                }
-                                int l_minos = l_offset - (l_houros *60);
-                                if (l_minos != 0) {
-                                  if (l_minos < 10) sbuf.append('0');
-                                  sbuf.append(l_minos);
-                                }
-                               sbuf.append("'");
-                               set(parameterIndex, sbuf.toString());
-                       }
-
-               }
-       }
-
-       /*
-        * When a very large ASCII value is input to a LONGVARCHAR parameter,
-        * it may be more practical to send it via a java.io.InputStream.
-        * JDBC will read the data from the stream as needed, until it reaches
-        * end-of-file.  The JDBC driver will do any necessary conversion from
-        * ASCII to the database char format.
-        *
-        * <P><B>Note:</B> This stream object can either be a standard Java
-        * stream object or your own subclass that implements the standard
-        * interface.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @param length the number of bytes in the stream
-        * @exception SQLException if a database access error occurs
-        */
-       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,
-        * it may be more practical to send it via a java.io.InputStream.
-        * JDBC will read the data from the stream as needed, until it reaches
-        * end-of-file.  The JDBC driver will do any necessary conversion from
-        * UNICODE to the database char format.
-        *
-        * ** DEPRECIATED IN JDBC 2 **
-        *
-        * <P><B>Note:</B> This stream object can either be a standard Java
-        * stream object or your own subclass that implements the standard
-        * interface.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        * @deprecated
-        */
-       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,
-        * it may be more practical to send it via a java.io.InputStream.
-        * JDBC will read the data from the stream as needed, until it reaches
-        * end-of-file.
-        *
-        * <P><B>Note:</B> This stream object can either be a standard Java
-        * stream object or your own subclass that implements the standard
-        * interface.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the parameter value
-        * @exception SQLException if a database access error occurs
-        */
-       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);
-                       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);
-               }
-       }
-
-       /*
-        * In general, parameter values remain in force for repeated used of a
-        * Statement.  Setting a parameter value automatically clears its
-        * previous value.      However, in coms cases, it is useful to immediately
-        * release the resources used by the current parameter values; this
-        * can be done by calling clearParameters
-        *
-        * @exception SQLException if a database access error occurs
-        */
-       public void clearParameters() throws SQLException
-       {
-               int i;
-
-               for (i = 0 ; i < inStrings.length ; i++)
-                       inStrings[i] = null;
-       }
-
-       /*
-        * Set the value of a parameter using an object; use the java.lang
-        * equivalent objects for integral values.
-        *
-        * <P>The given Java object will be converted to the targetSqlType before
-        * being sent to the database.
-        *
-        * <P>note that this method may be used to pass database-specific
-        * abstract data types.  This is done by using a Driver-specific
-        * Java type and using a targetSqlType of java.sql.Types.OTHER
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @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.
-        * @exception SQLException if a database access error occurs
-        */
-       public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
-       {
-               if (x == null)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-                       return;
-               }
-               switch (targetSqlType)
-               {
-                       case Types.TINYINT:
-                       case Types.SMALLINT:
-                       case Types.INTEGER:
-                       case Types.BIGINT:
-                       case Types.REAL:
-                       case Types.FLOAT:
-                       case Types.DOUBLE:
-                       case Types.DECIMAL:
-                       case Types.NUMERIC:
-                               if (x instanceof Boolean)
-                                       set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
-                               else
-                                       set(parameterIndex, x.toString());
-                               break;
-                       case Types.CHAR:
-                       case Types.VARCHAR:
-                       case Types.LONGVARCHAR:
-                               setString(parameterIndex, x.toString());
-                               break;
-                       case Types.DATE:
-                               setDate(parameterIndex, (java.sql.Date)x);
-                               break;
-                       case Types.TIME:
-                               setTime(parameterIndex, (Time)x);
-                               break;
-                       case Types.TIMESTAMP:
-                               setTimestamp(parameterIndex, (Timestamp)x);
-                               break;
-                       case Types.BIT:
-                               if (x instanceof Boolean)
-                               {
-                                       set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
-                               }
-                               else
-                               {
-                                       throw new PSQLException("postgresql.prep.type");
-                               }
-                               break;
-                       case Types.BINARY:
-                       case Types.VARBINARY:
-                               setObject(parameterIndex, x);
-                               break;
-                       case Types.OTHER:
-                               setString(parameterIndex, ((PGobject)x).getValue());
-                               break;
-                       default:
-                               throw new PSQLException("postgresql.prep.type");
-               }
-       }
-
-       public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
-       {
-               setObject(parameterIndex, x, targetSqlType, 0);
-       }
-
-       /*
-        * This stores an Object into a parameter.
-        * <p>New for 6.4, if the object is not recognised, but it is
-        * Serializable, then the object is serialised using the
-        * org.postgresql.util.Serialize class.
-        */
-       public void setObject(int parameterIndex, Object x) throws SQLException
-       {
-               if (x == null)
-               {
-                       setNull(parameterIndex, Types.OTHER);
-                       return;
-               }
-               if (x instanceof String)
-                       setString(parameterIndex, (String)x);
-               else if (x instanceof BigDecimal)
-                       setBigDecimal(parameterIndex, (BigDecimal)x);
-               else if (x instanceof Short)
-                       setShort(parameterIndex, ((Short)x).shortValue());
-               else if (x instanceof Integer)
-                       setInt(parameterIndex, ((Integer)x).intValue());
-               else if (x instanceof Long)
-                       setLong(parameterIndex, ((Long)x).longValue());
-               else if (x instanceof Float)
-                       setFloat(parameterIndex, ((Float)x).floatValue());
-               else if (x instanceof Double)
-                       setDouble(parameterIndex, ((Double)x).doubleValue());
-               else if (x instanceof byte[])
-                       setBytes(parameterIndex, (byte[])x);
-               else if (x instanceof java.sql.Date)
-                       setDate(parameterIndex, (java.sql.Date)x);
-               else if (x instanceof Time)
-                       setTime(parameterIndex, (Time)x);
-               else if (x instanceof Timestamp)
-                       setTimestamp(parameterIndex, (Timestamp)x);
-               else if (x instanceof Boolean)
-                       setBoolean(parameterIndex, ((Boolean)x).booleanValue());
-               else if (x instanceof PGobject)
-                       setString(parameterIndex, ((PGobject)x).getValue());
-               else
-                       // Try to store java object in database
-                       setSerialize(parameterIndex, connection.storeObject(x), x.getClass().getName() );
-       }
-
-       /*
-        * Some prepared statements return multiple results; the execute method
-        * handles these complex statements as well as the simpler form of
-        * 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
-        * @exception SQLException if a database access error occurs
-        */
-       public boolean execute() throws SQLException
-       {
-               return super.execute(compileQuery());   // in Statement class
-       }
-
-       /*
-        * Returns the SQL statement with the current template values
-        * substituted.
-                       * NB: This is identical to compileQuery() except instead of throwing
-                       * SQLException if a parameter is null, it places ? instead.
-        */
-       public String toString()
-       {
-               synchronized (sbuf)
-               {
-                       sbuf.setLength(0);
-                       int i;
-
-                       for (i = 0 ; i < inStrings.length ; ++i)
-                       {
-                               if (inStrings[i] == null)
-                                       sbuf.append( '?' );
-                               else
-                                       sbuf.append (templateStrings[i]);
-                               sbuf.append (inStrings[i]);
-                       }
-                       sbuf.append(templateStrings[inStrings.length]);
-                       return sbuf.toString();
-               }
-       }
-
-       // **************************************************************
-       //      END OF PUBLIC INTERFACE
-       // **************************************************************
-
-       /*
-        * There are a lot of setXXX classes which all basically do
-        * the same thing.      We need a method which actually does the
-        * set for us.
-        *
-        * @param paramIndex the index into the inString
-        * @param s a string to be stored
-        * @exception SQLException if something goes wrong
-        */
-       protected void set(int paramIndex, String s) throws SQLException
-       {
-               if (paramIndex < 1 || paramIndex > inStrings.length)
-                       throw new PSQLException("postgresql.prep.range");
-               inStrings[paramIndex - 1] = s;
-       }
-
-       /*
-        * Set a parameter to a tablerow-type oid reference.
-        *
-        * @param parameterIndex the first parameter is 1...
-        * @param x the oid of the object from org.postgresql.util.Serialize.store
-        * @param classname the classname of the java object x
-        * @exception SQLException if a database access error occurs
-        */
-       private void setSerialize(int parameterIndex, long x, String classname) throws SQLException
-       {
-               // converts . to _, toLowerCase, and ensures length<32
-               String tablename = Serialize.toPostgreSQL( classname );
-               DriverManager.println("setSerialize: setting " + x + "::" + tablename );
-
-               // OID reference to tablerow-type must be cast like:  <oid>::<tablename>
-               // Note that postgres support for tablerow data types is incomplete/broken.
-               // This cannot be just a plain OID because then there would be ambiguity
-               // between when you want the oid itself and when you want the object
-               // an oid references.
-               set(parameterIndex, Long.toString(x) + "::" + tablename );
-       }
-
-
-       // ** JDBC 2 Extensions **
-
-       /*
-        * This parses the query and adds it to the current batch
-        */
-       public void addBatch() throws SQLException
-       {
-               super.addBatch(compileQuery());
-       }
-
-       /*
-        * Not sure what this one does, so I'm saying this returns the MetaData for
-        * the last ResultSet returned!
-        */
-       public java.sql.ResultSetMetaData getMetaData() throws SQLException
-       {
-               java.sql.ResultSet rs = getResultSet();
-               if (rs != null)
-                       return rs.getMetaData();
-
-               // Does anyone really know what this method does?
-               return null;
-       }
-
-       public void setArray(int i, java.sql.Array x) throws SQLException
-       {
-               setString(i, x.toString());
-       }
-
-       /*
-        * Sets a Blob
-        */
-       public void setBlob(int i, Blob x) throws SQLException
-       {
-               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);
-       }
-
-       /*
-        * This is similar to setBinaryStream except it uses a Reader instead of
-        * InputStream.
-        */
-       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);
-                       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(i, oid);
-               }
-       }
-
-       /*
-        * New in 7.1
-        */
-       public void setClob(int i, Clob x) throws SQLException
-       {
-               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);
-       }
-
-       /*
-        * At least this works as in PostgreSQL null represents anything null ;-)
-        *
-        * New in 7,1
-        */
-       public void setNull(int i, int t, String s) throws SQLException
-       {
-               setNull(i, t);
-       }
-
-       public void setRef(int i, Ref x) throws SQLException
-       {
-               throw org.postgresql.Driver.notImplemented();
-       }
-
-       /*
-        * New in 7,1
-        */
-       public void setDate(int i, java.sql.Date d, java.util.Calendar cal) throws SQLException
-       {
-               if (cal == null)
-                       setDate(i, d);
-               else
-               {
-                       cal.setTime(d);
-                       setDate(i, new java.sql.Date(cal.getTime().getTime()));
-               }
-       }
-
-       /*
-        * New in 7,1
-        */
-       public void setTime(int i, Time t, java.util.Calendar cal) throws SQLException
-       {
-               if (cal == null)
-                       setTime(i, t);
-               else
-               {
-                       cal.setTime(t);
-                       setTime(i, new java.sql.Time(cal.getTime().getTime()));
-               }
-       }
-
-       /*
-        * New in 7,1
-        */
-       public void setTimestamp(int i, Timestamp t, java.util.Calendar cal) throws SQLException
-       {
-               if (cal == null)
-                       setTimestamp(i, t);
-               else
-               {
-                       cal.setTime(t);
-                       setTimestamp(i, new java.sql.Timestamp(cal.getTime().getTime()));
-               }
-       }
-
-}
-