Fix database metadata tuple copying to work with binary data - Mailing list pgsql-jdbc

From Mikko Tiihonen
Subject Fix database metadata tuple copying to work with binary data
Date
Msg-id 1185176305.1632.97.camel@dual.local
Whole thread Raw
List pgsql-jdbc
Hi,

The following patch makes DatabaseMetaData work if result set can contain tuples in binary format.
An alternative to copying the OID + format flag is to just always do getString() and re-encode it.
But it can be now changed easily in one place at the copyValue method.

The patch just fixes the only thing unit tests revealed when running with binary transfer patches.
Most probably the copyValue should be used in lots of other places too. If this patch is acceptable
I can comb through the remaining copies and convert them.

Index: org/postgresql/jdbc2/AbstractJdbc2DatabaseMetaData.java
===================================================================
RCS file: /usr/local/cvsroot/pgjdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2DatabaseMetaData.java,v
retrieving revision 1.36
diff -u -r1.36 AbstractJdbc2DatabaseMetaData.java
--- org/postgresql/jdbc2/AbstractJdbc2DatabaseMetaData.java    15 Jul 2007 15:33:33 -0000    1.36
+++ org/postgresql/jdbc2/AbstractJdbc2DatabaseMetaData.java    23 Jul 2007 07:25:36 -0000
@@ -2321,9 +2321,9 @@
             int typeMod = rs.getInt("atttypmod");

             tuple[0] = null;     // Catalog name, not supported
-            tuple[1] = rs.getBytes("nspname"); // Schema
-            tuple[2] = rs.getBytes("relname"); // Table name
-            tuple[3] = rs.getBytes("attname"); // Column name
+            copyValue(rs, "nspname", 1, f, tuple); // Schema
+            copyValue(rs, "relname", 2, f, tuple); // Table name
+            copyValue(rs, "attname", 3, f, tuple); // Column name
             tuple[4] = connection.encodeString(Integer.toString(connection.getSQLType(typeOid)));
             String pgType = connection.getPGType(typeOid);
             tuple[5] = connection.encodeString(pgType); // Type name
@@ -2364,12 +2364,12 @@
             }

             tuple[10] = connection.encodeString(Integer.toString(rs.getBoolean("attnotnull") ?
java.sql.DatabaseMetaData.columnNoNulls: java.sql.DatabaseMetaData.columnNullable)); // Nullable 
-            tuple[11] = rs.getBytes("description");    // Description (if any)
-            tuple[12] = rs.getBytes("adsrc");    // Column default
+            copyValue(rs, "description", 11, f, tuple);    // Description (if any)
+            copyValue(rs, "adsrc", 12, f, tuple);          // Column default
             tuple[13] = null;      // sql data type (unused)
             tuple[14] = null;      // sql datetime sub (unused)
             tuple[15] = tuple[6];     // char octet length
-            tuple[16] = rs.getBytes("attnum");  // ordinal position
+            copyValue(rs, "attnum", 16, f, tuple); // ordinal position
             tuple[17] = connection.encodeString(rs.getBoolean("attnotnull") ? "NO" : "YES"); // Is nullable

             v.addElement(tuple);
@@ -4024,4 +4024,29 @@
         return ((AbstractJdbc2Connection)connection).createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,
java.sql.ResultSet.CONCUR_READ_ONLY);
     }

+    /**
+     * Copies one value from real result set to target result set under
+     * construction.
+     *
+     * @param rs The source.
+     * @param columnName The name of the column to copy.
+     * @param pos The position in target result set.
+     * @param f The fields of the target result set.
+     * @param tuple The values of the target result set.
+     * @throws SQLException If an error occurs.
+     */
+    protected void copyValue(ResultSet rs, String columnName, int pos,
+                             Field[] f, byte[][] tuple) throws SQLException {
+        int col = rs.findColumn(columnName) - 1;
+        AbstractJdbc2ResultSet res = (AbstractJdbc2ResultSet) rs;
+        Field fromField = res.fields[col];
+        if (fromField.getFormat() != Field.TEXT_FORMAT) {
+            // The OID must match for binary types
+            if (fromField.getOID() != f[pos].getOID()) {
+                f[pos] = new Field(f[pos].getColumnLabel(), fromField.getOID());
+            }
+            f[pos].setFormat(fromField.getFormat());
+        }
+        tuple[pos] = res.this_row[col];
+    }
 }



pgsql-jdbc by date:

Previous
From: Dave Cramer
Date:
Subject: Re: Problem with ResultSet retrieved with SELECT * FROM pg_indexes WHERE tablename
Next
From: Mikko Tiihonen
Date:
Subject: Make time/timestamp tests fair for binary transfers