]> granicus.if.org Git - postgresql/commitdiff
Applied patches from Oliver Jowett to fix the following bugs:
authorBarry Lind <barry@xythos.com>
Sun, 24 Aug 2003 22:10:09 +0000 (22:10 +0000)
committerBarry Lind <barry@xythos.com>
Sun, 24 Aug 2003 22:10:09 +0000 (22:10 +0000)
 - adds a finalizer method to AbstractJdbc1Statement to clean up in the case of
   poor user code which fails to close the statement object
 - fix ant build file to correctly detect dependencies across jdbc1/jdbc2/jdbc3
 - fix a coupld of server prepared statement bugs and added regression test for
   them
Applied patch from Kim Ho:
 - adds support for get/setMaxFieldSize().
Also fixed build.xml to provide a better error message in the event that an
older version of the driver exists in the classpath when trying to build.

src/interfaces/jdbc/build.xml
src/interfaces/jdbc/org/postgresql/core/BaseStatement.java
src/interfaces/jdbc/org/postgresql/errors.properties
src/interfaces/jdbc/org/postgresql/errors_de.properties
src/interfaces/jdbc/org/postgresql/errors_it.properties
src/interfaces/jdbc/org/postgresql/errors_nl.properties
src/interfaces/jdbc/org/postgresql/errors_zh_TW.properties
src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
src/interfaces/jdbc/org/postgresql/test/jdbc2/ServerPreparedStmtTest.java

index fed207ed8280656aee95e0be647d232a5ea561bc..633daa72db354b251e37f1bea33a5c8977530f51 100644 (file)
@@ -6,7 +6,7 @@
 
   This file now requires Ant 1.4.1.  2002-04-18
 
-  $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/build.xml,v 1.35 2003/08/11 23:42:04 barry Exp $
+  $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/build.xml,v 1.36 2003/08/24 22:10:09 barry Exp $
 
 -->
 
   </target>
 
 
-  <!-- This is the core of the driver.  It is common for all three versions. -->
   <target name="compile" depends="prepare,check_versions,driver">
-    <javac srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
-      <include name="${package}/**" />
-
-      <exclude name="${package}/jdbc1/**" unless="jdbc1"/>
-      <exclude name="${package}/jdbc2/**" unless="jdbc2"/>
-      <exclude name="${package}/jdbc3/**" unless="jdbc3"/>
 
-      <exclude name="${package}/jdbc2/optional/**" unless="jdbc2" />
-      <exclude name="${package}/jdbc2/optional/**" unless="datasource" />
+    <available classname="org.postgresql.Driver" property="old.driver.present" />
+    <fail message="Old driver was detected on classpath or in jre/lib/ext, please remove and try again." if="old.driver.present" />
+
+    <javac classpath="{$srcdir}" srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
+      <!-- This is the core of the driver.  It is common for all three versions. -->
+       <include name="${package}/*.java" />
+       <include name="${package}/core/**" />
+       <include name="${package}/fastpath/**" />
+       <include name="${package}/geometric/**" />
+       <include name="${package}/largeobject/**" />
+       <include name="${package}/util/**" />
+
+       <!--      
+       Each jdbcN subpackage is used only if the driver supports *at least* that
+       revision of JDBC. That is, a JDBC1 build uses only jdbc1, a JDBC2 build
+       uses both jdbc1 and jdbc2, etc.
+  
+       Within those subpackages, classes beginning with "JdbcN" are assumed to be
+       the concrete implementations for JDBC version N and are built only if the
+       driver supports *exactly* that version. For example, jdbc1/Jdbc1Statement.java
+       is built only if the driver build is a JDBC1 build.
+       -->
+       <!-- jdbc1 subpackage -->
+       <include name="${package}/jdbc1/**"/>
+       <exclude name="${package}/jdbc1/Jdbc1*.java" unless="jdbc1"/>
+       <!-- jdbc2 subpackage -->
+       <include name="${package}/jdbc2/**" if="jdbc2"/>
+       <include name="${package}/jdbc2/**" if="jdbc3"/>
+       <exclude name="${package}/jdbc2/Jdbc2*.java" unless="jdbc2"/>
+       <exclude name="${package}/jdbc2/optional/**" unless="datasource"/>
+       <!-- jdbc3 subpackage -->
+       <include name="${package}/jdbc3/*.java" if="jdbc3"/>
+       <exclude name="${package}/jdbc3/Jdbc3*.java" unless="jdbc3"/>
 
-      <exclude name="${package}/test/**"/>
     </javac>
   </target>
 
index 5811eb1dab8ddd48592fae406ca590ff8ca7fe01..c91e259e1d7668a08aa6c4b2e96399ec3d7226d6 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/BaseStatement.java,v 1.4 2003/08/11 20:54:55 barry Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/BaseStatement.java,v 1.5 2003/08/24 22:10:09 barry Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,9 +31,11 @@ public interface BaseStatement extends org.postgresql.PGStatement
        public void addWarning(String p_warning) throws SQLException;
        public void close() throws SQLException;
        public int getFetchSize() throws SQLException;
+       public int getMaxFieldSize() throws SQLException;
        public int getMaxRows() throws SQLException;
        public int getResultSetConcurrency() throws SQLException;
        public String getStatementName();
        public SQLWarning getWarnings() throws SQLException;
+       public void setMaxFieldSize(int max) throws SQLException;
 
 }
index 21b1a2941ca269c85e1d6286cb44b6971939f8d5..6f5f2550ab3219940690d2c6fa6f7b0a7277abfd 100644 (file)
@@ -71,7 +71,6 @@ postgresql.serial.noclass:No class found for {0}
 postgresql.serial.table:The table for {0} is not in the database. Contact the DBA, as the database is in an inconsistent state.
 postgresql.serial.underscore:Class names may not have _ in them. You supplied {0}.
 postgresql.stat.batch.error:Batch entry {0} {1} was aborted. Call getNextException() to see the cause.
-postgresql.stat.maxfieldsize:An attempt to setMaxFieldSize() failed - compile time default in force.
 postgresql.stat.noresult:No results were returned by the query.
 postgresql.stat.result:A result was returned when none was expected.
 postgresql.stream.eof:The backend has broken the connection. Possibly the action you have attempted has caused it to close.
@@ -103,3 +102,4 @@ postgresql.input.rows.gt0:Maximum number of rows must be a value greater than or
 postgresql.format.baddate:The date given: {0} does not match the format required: {1}.
 postgresql.format.badtime:The time given: {0} does not match the format required: {1}.
 postgresql.format.badtimestamp:The timestamp given {0} does not match the format required: {1}.
+postgresql.input.field.gt0:The maximum field size must be a value greater than or equal to 0.
index ed641e985a7369edab979cdc700e2e877bf276dc..11fd7bbcee86f4c6c68a6562723207e66ca297b4 100644 (file)
@@ -1,7 +1,7 @@
 # Message translation file for PostgreSQL JDBC driver
 # Peter Eisentraut <peter_e@gmx.net>, 2001.
 #
-# $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/errors_de.properties,v 1.4 2003/02/12 06:13:04 barry Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/errors_de.properties,v 1.5 2003/08/24 22:10:09 barry Exp $
 
 postgresql.con.auth:Der Authentifizierungstyp »{0}« wird nicht unterstützt.
 postgresql.con.authfail:Ein Fehler trat auf während die Authentifizierungsanfrage empfangen wurde.
@@ -66,7 +66,6 @@ postgresql.serial.noclass:Keine Klasse f
 postgresql.serial.table:Keine Tabelle für Typ »{0}« in der Datenbank gefunden. Die Datenbank ist in einem unbeständigen Zustand.
 postgresql.serial.underscore:Zu serialisierende Klassennamen dürfen keine Unterstriche (_) enthälten. Der angegebene Name war »{0}«.
 postgresql.stat.batch.error:Batch-Anweisung Nummer {0} ({1}) wurde abgebrochen.
-postgresql.stat.maxfieldsize:setMaxFieldSize() is nicht möglich; die Grenze ist fest eingebaut.
 postgresql.stat.noresult:Die Abfrage ergab kein Ergebnis.
 postgresql.stat.result:Die Anweisung ergab einen Abfrageergebnissatz, obwohl keiner erwartet wurde.
 postgresql.stream.encoding:Nicht unterstützte Kodierung: {0}
index 76e6168110e665294345f103865a9c99c01ba0f8..197eac24d69f3d56c61ba000ef3cf49b2212ab8c 100644 (file)
@@ -65,7 +65,6 @@ postgresql.serial.noclass:Nessuna classe trovata per {0}.
 postgresql.serial.table:La tabella per {0} non è nel database. Contattare l'amministratore del DB, visto che il database è in uno stato incosistente.
 postgresql.serial.underscore:Il nome di una classe non può contenere il carattere ``_''. E` stato fornito {0}.
 postgresql.stat.batch.error:L'operazione {0} {1} della sequenza è stata annullata.
-postgresql.stat.maxfieldsize:Fallito un tentativo a setMaxFieldSize() - verrà utilizzato il valore predefinito a tempo di compilazione.
 postgresql.stat.noresult:Nessun risultato è stato restituito dalla query.
 postgresql.stream.eof:Il backend ha interrotto la connessione. Probabilmente la tua azione ha causato la sua uscita.
 postgresql.stream.flush:Si è verificato un errore di I/O mentre si svuotava il buffer d'uscita - {0}
index 2e5388a2278e111fb08b3b85cff3de0593bac3ff..1dc93453bcc68442afae10f9b9b8ab69610a44a9 100644 (file)
@@ -55,7 +55,6 @@ postgresql.serial.noclass:Geen class gevonden voor {0}.
 postgresql.serial.table:De tabel voor {0} is niet in de database. Neem contact op met de DBA, omdat de database in een inconsistente staat verkeert.
 postgresql.serial.underscore:Class namen mogen geen _ in zich hebben. Jij voerde {0} in.
 postgresql.stat.batch.error:Batch invoer {0} {1} werd afgebroken.
-postgresql.stat.maxfieldsize:Een poging om setMaxFieldSize() faalde - compiletime standaardwaarde van kracht.
 postgresql.stat.noresult:Geen resultaten werden teruggegeven door de query.
 postgresql.stream.eof:De achterkant heeft de verbinding verbroken. Mogelijk was de actie die je probeerde de oorzaak hiervan.
 postgresql.stream.flush:Een I/O fout trad op tijdens het legen van de uitvoer - {0}
index 799893b100755633610fdfc4180896be82190fea..62279f395e4f49ce8f70c626b59cd806eb009b70 100644 (file)
@@ -70,7 +70,6 @@ postgresql.serial.noclass:\u627e\u4e0d\u5230\u985e\u5225{0}\u3002
 postgresql.serial.table:\u8655\u7406{0}\u6642\u627e\u4e0d\u5230\u8cc7\u6599\u8868\uff0c\u8cc7\u6599\u5eab\u72c0\u614b\u4e0d\u6b63\u5e38\uff0c\u8acb\u806f\u7d61DBA\u8655\u7406\u3002
 postgresql.serial.underscore:\u985e\u5225\u540d\u7a31\u4e0d\u80fd\u4f7f\u7528_\u5b57\u5143\uff0c\u60a8\u6240\u7528\u7684\u540d\u7a31\u662f{0}\u3002
 postgresql.stat.batch.error:\u6279\u6b21\u8655\u7406\u5ffd\u7565{0} {1}\u3002
-postgresql.stat.maxfieldsize:setMaxFieldSize()\u5931\u6557 - \u4f7f\u7528\u9810\u8a2d\u503c
 postgresql.stat.noresult:\u6c92\u6709\u50b3\u56de\u4efb\u4f55\u67e5\u8a62\u7d50\u679c\u3002
 postgresql.stat.result:\u50b3\u56de\u9810\u671f\u5916\u7684\u7d50\u679c\u3002
 postgresql.stream.eof:\u5f8c\u7aef\u7d50\u675f\u9023\u7dda\uff0c\u4e5f\u8a31\u662f\u56e0\u70ba\u60a8\u6240\u57f7\u884c\u7684\u52d5\u4f5c\u5c0e\u81f4\u9023\u7dda\u4e2d\u65b7\u3002
index c314b77d65a712ecb609dad0053332dbe6002f7c..5a8994f7a42583d80b273d577e9554adefb1832e 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright (c) 2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.14 2003/08/06 05:53:13 barry Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.15 2003/08/24 22:10:09 barry Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -176,7 +176,7 @@ public abstract class AbstractJdbc1ResultSet implements BaseResultSet
                        return null;
 
                Encoding encoding = connection.getEncoding();
-               return encoding.decode(this_row[columnIndex - 1]);
+               return trimString(columnIndex, encoding.decode(this_row[columnIndex-1]));
        }
 
        public boolean getBoolean(int columnIndex) throws SQLException
@@ -303,11 +303,11 @@ public abstract class AbstractJdbc1ResultSet implements BaseResultSet
                                //Version 7.2 supports the bytea datatype for byte arrays
                                if (fields[columnIndex - 1].getPGType().equals("bytea"))
                                {
-                                       return PGbytea.toBytes(this_row[columnIndex - 1]);
+                                       return trimBytes(columnIndex, PGbytea.toBytes(this_row[columnIndex - 1]));
                                }
                                else
                                {
-                                       return this_row[columnIndex - 1];
+                                       return trimBytes(columnIndex, this_row[columnIndex - 1]);
                                }
                        }
                        else
@@ -320,11 +320,11 @@ public abstract class AbstractJdbc1ResultSet implements BaseResultSet
                                        LargeObject lob = lom.open(getInt(columnIndex));
                                        byte buf[] = lob.read(lob.size());
                                        lob.close();
-                                       return buf;
+                                       return trimBytes(columnIndex, buf);
                                }
                                else
                                {
-                                       return this_row[columnIndex - 1];
+                                       return trimBytes(columnIndex, this_row[columnIndex - 1]);
                                }
                        }
                }
@@ -1143,7 +1143,54 @@ public abstract class AbstractJdbc1ResultSet implements BaseResultSet
                        }
                }
        }
+       
+       private boolean isColumnTrimmable(int columnIndex) throws SQLException
+       {
+               switch (fields[columnIndex-1].getSQLType())
+               {
+                       case Types.CHAR:
+                       case Types.VARCHAR:
+                       case Types.LONGVARCHAR:
+                       case Types.BINARY:
+                       case Types.VARBINARY:
+                       case Types.LONGVARBINARY:
+                               return true;
+               }
+               return false;
+       }
 
+       private byte[] trimBytes(int p_columnIndex, byte[] p_bytes) throws SQLException
+       {
+               int l_maxSize = statement.getMaxFieldSize();
+               //we need to trim if maxsize is set and the length is greater than maxsize and the
+               //type of this column is a candidate for trimming
+               if (l_maxSize > 0 && p_bytes.length > l_maxSize && isColumnTrimmable(p_columnIndex))
+               {
+                       byte[] l_bytes = new byte[l_maxSize];
+                       System.arraycopy (p_bytes, 0, l_bytes, 0, l_maxSize);
+                       return l_bytes;
+               }
+               else
+               {
+                       return p_bytes;
+               }
+       }
+
+       private String trimString(int p_columnIndex, String p_string) throws SQLException
+       {
+               int l_maxSize = statement.getMaxFieldSize();
+               //we need to trim if maxsize is set and the length is greater than maxsize and the
+               //type of this column is a candidate for trimming
+               if (l_maxSize > 0 && p_string.length() > l_maxSize && isColumnTrimmable(p_columnIndex))
+               {
+                       return p_string.substring(0,l_maxSize);
+               } 
+               else 
+               {
+                       return p_string;
+               }
+       }
+       
        public SimpleDateFormat getTimestampTZFormat() {
                if (m_tstzFormat == null) {
                        m_tstzFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
index e4ab3f7cf2c2a3d0a9d98c003a09269c0b735cf9..60b57083645edd0aed3a8bb0edf42d71e5e50ef2 100644 (file)
@@ -25,7 +25,7 @@ import java.sql.Timestamp;
 import java.sql.Types;
 import java.util.Vector;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.31 2003/08/11 21:12:00 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.32 2003/08/24 22:10:09 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
@@ -87,7 +87,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
        // returnTypeSet is true when a proper call to registerOutParameter has been made
        private boolean returnTypeSet;
        protected Object callResult;
-
+       protected static int maxfieldSize = 0;
 
        public abstract BaseResultSet createResultSet(Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException;
 
@@ -640,19 +640,19 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
         */
        public int getMaxFieldSize() throws SQLException
        {
-               return 8192;            // We cannot change this
+               return maxfieldSize;
        }
 
        /*
-        * Sets the maxFieldSize - NOT! - We throw an SQLException just
-        * to inform them to stop doing this.
+        * Sets the maxFieldSize 
         *
         * @param max the new max column size limit; zero means unlimited
         * @exception SQLException if a database access error occurs
         */
        public void setMaxFieldSize(int max) throws SQLException
        {
-               throw new PSQLException("postgresql.stat.maxfieldsize");
+               if (max < 0) throw new PSQLException("postgresql.input.field.gt0");
+               maxfieldSize = max;
        }
 
        /*
@@ -721,6 +721,15 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
                result = null;
        }
 
+       /**
+        * This finalizer ensures that statements that have allocated server-side
+        * resources free them when they become unreferenced.
+        */
+       protected void finalize() {
+               try { close(); }
+               catch (SQLException e) {}
+       }
        /*
         * Filter the SQL string of Java SQL Escape clauses.
         *
@@ -1088,7 +1097,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
                        }
                        else
                        {
-                               setString(parameterIndex, PGbytea.toPGString(x), PG_TEXT);
+                               setString(parameterIndex, PGbytea.toPGString(x), PG_BYTEA);
                        }
                }
                else
@@ -2055,7 +2064,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
         if (connection.haveMinimumServerVersion("7.3")) {
                        //If turning server prepared statements off deallocate statement
                        //and reset statement name
-                       if (m_useServerPrepare != flag && !flag)
+                       if (m_useServerPrepare != flag && !flag && m_statementName != null)
                                connection.execSQL("DEALLOCATE " + m_statementName);
                        m_statementName = null;
                        m_useServerPrepare = flag;
index dcd85572b7b645bcb395e25aa99d3237a52f81bf..ea819b3633382a6d6f89d4b36a4392805f86252d 100644 (file)
@@ -153,4 +153,26 @@ public class ServerPreparedStmtTest extends TestCase
                pstmt.close();
        }
 
+       public void testSPSToggle() throws Exception
+       {
+               // Verify we can toggle UseServerPrepare safely before a query is executed.
+               PreparedStatement pstmt = con.prepareStatement("SELECT * FROM testsps WHERE id = 2");
+        ((PGStatement)pstmt).setUseServerPrepare(true);
+        ((PGStatement)pstmt).setUseServerPrepare(false);
+       }
+
+       public void testBytea() throws Exception
+       {
+               // Verify we can use setBytes() with a server-prepared update.
+               try {
+                       TestUtil.createTable(con, "testsps_bytea", "data bytea");
+                       
+                       PreparedStatement pstmt = con.prepareStatement("INSERT INTO testsps_bytea(data) VALUES (?)");
+                       ((PGStatement)pstmt).setUseServerPrepare(true);
+                       pstmt.setBytes(1, new byte[100]);
+                       pstmt.executeUpdate();
+               } finally {
+                       TestUtil.dropTable(con, "testsps_bytea");
+               }
+       }
 }