Re: [JDBC] Anoter JDBC Error - Mailing list pgsql-patches

From Barry Lind
Subject Re: [JDBC] Anoter JDBC Error
Date
Msg-id 3DB8B329.7020506@xythos.com
Whole thread Raw
In response to Re: [JDBC] Anoter JDBC Error  (Kris Jurka <books@ejurka.com>)
List pgsql-patches
Patch applied.

thanks,
--Barry


Kris Jurka wrote:
> The following patch fixes this bug and the potential source of similar
> bugs.  When creating the ResultSets for DatabaseMetaData calls, the code
> creates byte arrays for each row something like...
>
> byte tuple[][] = new byte[18][0];
>
> Unless a call "tuple[n] = null;" is made then it has an array of zero
> length which does in fact get turned into the zero length string being
> seen.  I have changed these allocations to...
>
> byte tuple[][] = new byte[18][];
>
> Kris Jurka
>
>
> On Sat, 19 Oct 2002, Aaron Mulder wrote:
>
>
>>    Ahh, never mind.  I tried again a few minutes later, and got the
>>new behavior, which is to say a SQLException.  But I don't
>>understand why this is happening.  Here's what I'm doing:
>>
>>    I create the database "test" (in my PG 7.2.2 DB) with a table with
>>3 columns, all integers.  I connect using the JDBC3 driver, get a
>>connection, get the databasemetadata, call
>>
>>    dbmd.getColumns("test",null,"tablename","%");
>>
>>    I get back a ResultSet.  Column 9 is an integer column,
>>DECIMAL_DIGITS.  If I call getObject, it tries to get an Integer object,
>>so even the ResultSet thinks it's an integer column.  However, the result
>>of getString/getFixedString used for new Integer(getFixedString()) is
>>apparently an empty String, causing the SQLException due to a badly
>>formatted Integer value.
>>
>>    So now I'm confused.  What's an empty String doing in an integer
>>column when (if you believe the logic in getFixedString) the value was not
>>null?  Is this broken null handling?  Test program and results attached...
>>
>>Aaron
>>
>>import java.sql.*;
>>
>>public class PostgresTest{
>>    public static void main(String args[]) {
>>        try {
>>            Class.forName("org.postgresql.Driver");
>>            Connection con =
>>DriverManager.getConnection("jdbc:postgresql://localhost/test", "test",
>>"password");
>>            DatabaseMetaData dmd = con.getMetaData();
>>            ResultSet rs = dmd.getColumns("test", null, "tablename", "%");
>>            rs.next();
>>            System.out.println("Col 9: "+rs.getInt(9)); // getObject(9)
>>            rs.close();
>>            con.close();
>>        } catch(Exception e) {
>>            e.printStackTrace();
>>        }
>>    }
>>}
>>
>>
>>Bad Integer
>>    at
>>org.postgresql.jdbc1.AbstractJdbc1ResultSet.toInt(AbstractJdbc1ResultSet.java:708)
>>    at
>>org.postgresql.jdbc1.AbstractJdbc1ResultSet.getInt(AbstractJdbc1ResultSet.java:148)
>>    at PostgresTest.main(PostgresTest.java:12)
>>
>>
>>---------------------------(end of broadcast)---------------------------
>>TIP 6: Have you searched our list archives?
>>
>>http://archives.postgresql.org
>>
>
>
>
> ------------------------------------------------------------------------
>
> Index: src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java
> ===================================================================
> RCS file:
/projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java,v
> retrieving revision 1.8
> diff -c -r1.8 AbstractJdbc1DatabaseMetaData.java
> *** src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java    2002/10/08 01:47:55    1.8
> --- src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java    2002/10/22 21:00:52
> ***************
> *** 1854,1860 ****
>
>               // decide if we are returning a single column result.
>               if (!returnTypeType.equals("c")) {
> !                 byte[][] tuple = new byte[13][0];
>                   tuple[0] = null;
>                   tuple[1] = schema;
>                   tuple[2] = procedureName;
> --- 1854,1860 ----
>
>               // decide if we are returning a single column result.
>               if (!returnTypeType.equals("c")) {
> !                 byte[][] tuple = new byte[13][];
>                   tuple[0] = null;
>                   tuple[1] = schema;
>                   tuple[2] = procedureName;
> ***************
> *** 1874,1880 ****
>               // Add a row for each argument.
>               for (int i=0; i<argTypes.size(); i++) {
>                   int argOid = ((Integer)argTypes.elementAt(i)).intValue();
> !                 byte[][] tuple = new byte[13][0];
>                   tuple[0] = null;
>                   tuple[1] = schema;
>                   tuple[2] = procedureName;
> --- 1874,1880 ----
>               // Add a row for each argument.
>               for (int i=0; i<argTypes.size(); i++) {
>                   int argOid = ((Integer)argTypes.elementAt(i)).intValue();
> !                 byte[][] tuple = new byte[13][];
>                   tuple[0] = null;
>                   tuple[1] = schema;
>                   tuple[2] = procedureName;
> ***************
> *** 1897,1903 ****
>                   ResultSet columnrs = connection.createStatement().executeQuery(columnsql);
>                   while (columnrs.next()) {
>                       int columnTypeOid = columnrs.getInt("atttypid");
> !                     byte[][] tuple = new byte[13][0];
>                       tuple[0] = null;
>                       tuple[1] = schema;
>                       tuple[2] = procedureName;
> --- 1897,1903 ----
>                   ResultSet columnrs = connection.createStatement().executeQuery(columnsql);
>                   while (columnrs.next()) {
>                       int columnTypeOid = columnrs.getInt("atttypid");
> !                     byte[][] tuple = new byte[13][];
>                       tuple[0] = null;
>                       tuple[1] = schema;
>                       tuple[2] = procedureName;
> ***************
> *** 2199,2205 ****
>           f[0] = new Field(connection, new String("TABLE_TYPE"), iVarcharOid, getMaxNameLength());
>           for (i=0; i < types.length; i++)
>           {
> !             byte[][] tuple = new byte[1][0];
>               tuple[0] = types[i].getBytes();
>               v.addElement(tuple);
>           }
> --- 2199,2205 ----
>           f[0] = new Field(connection, new String("TABLE_TYPE"), iVarcharOid, getMaxNameLength());
>           for (i=0; i < types.length; i++)
>           {
> !             byte[][] tuple = new byte[1][];
>               tuple[0] = types[i].getBytes();
>               v.addElement(tuple);
>           }
> ***************
> *** 2318,2324 ****
>           ResultSet rs = connection.createStatement().executeQuery(sql);
>           while (rs.next())
>           {
> !             byte[][] tuple = new byte[18][0];
>               int typeOid = rs.getInt("atttypid");
>
>               tuple[0] = null;                    // Catalog name, not supported
> --- 2318,2324 ----
>           ResultSet rs = connection.createStatement().executeQuery(sql);
>           while (rs.next())
>           {
> !             byte[][] tuple = new byte[18][];
>               int typeOid = rs.getInt("atttypid");
>
>               tuple[0] = null;                    // Catalog name, not supported
> ***************
> *** 2329,2334 ****
> --- 2329,2339 ----
>               String pgType = connection.getPGType(typeOid);
>               tuple[5] = pgType.getBytes();        // Type name
>
> +             // by default no decimal_digits
> +             // if the type is numeric or decimal we will
> +             // overwrite later.
> +             tuple[8] = "0".getBytes();
> +
>               if (pgType.equals("bpchar") || pgType.equals("varchar"))
>               {
>                   int atttypmod = rs.getInt("atttypmod");
> ***************
> *** 2465,2471 ****
>                   for (int j=0; j<grantees.size(); j++) {
>                       String grantee = (String)grantees.elementAt(j);
>                       String grantable = owner.equals(grantee) ? "YES" : "NO";
> !                     byte[][] tuple = new byte[8][0];
>                       tuple[0] = null;
>                       tuple[1] = schemaName;
>                       tuple[2] = tableName;
> --- 2470,2476 ----
>                   for (int j=0; j<grantees.size(); j++) {
>                       String grantee = (String)grantees.elementAt(j);
>                       String grantable = owner.equals(grantee) ? "YES" : "NO";
> !                     byte[][] tuple = new byte[8][];
>                       tuple[0] = null;
>                       tuple[1] = schemaName;
>                       tuple[2] = tableName;
> ***************
> *** 2567,2573 ****
>                   for (int j=0; j<grantees.size(); j++) {
>                       String grantee = (String)grantees.elementAt(j);
>                       String grantable = owner.equals(grantee) ? "YES" : "NO";
> !                     byte[][] tuple = new byte[7][0];
>                       tuple[0] = null;
>                       tuple[1] = schema;
>                       tuple[2] = table;
> --- 2572,2578 ----
>                   for (int j=0; j<grantees.size(); j++) {
>                       String grantee = (String)grantees.elementAt(j);
>                       String grantable = owner.equals(grantee) ? "YES" : "NO";
> !                     byte[][] tuple = new byte[7][];
>                       tuple[0] = null;
>                       tuple[1] = schema;
>                       tuple[2] = table;
> ***************
> *** 2819,2825 ****
>           f[6] = new Field(connection, "DECIMAL_DIGITS", iInt2Oid, 2);
>           f[7] = new Field(connection, "PSEUDO_COLUMN", iInt2Oid, 2);
>
> !         byte tuple[][] = new byte[8][0];
>
>           /* Postgresql does not have any column types that are
>            * automatically updated like some databases' timestamp type.
> --- 2824,2830 ----
>           f[6] = new Field(connection, "DECIMAL_DIGITS", iInt2Oid, 2);
>           f[7] = new Field(connection, "PSEUDO_COLUMN", iInt2Oid, 2);
>
> !         byte tuple[][] = new byte[8][];
>
>           /* Postgresql does not have any column types that are
>            * automatically updated like some databases' timestamp type.
>
>
> ------------------------------------------------------------------------
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html



pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: patch for pgsql/doc/src/sgml/ref/postgres-ref.sgml
Next
From: Dennis Björklund
Date:
Subject: Re: swedish translation