Re: [PATCHES] Anoter JDBC Error

From: Barry Lind <blind(at)xythos(dot)com>
To: Kris Jurka <books(at)ejurka(dot)com>
Cc: Aaron Mulder <ammulder(at)alumni(dot)princeton(dot)edu>, PostgreSQL JDBC <pgsql-jdbc(at)postgresql(dot)org>, pgsql-patches(at)postgresql(dot)org
Subject: Re: [PATCHES] Anoter JDBC Error
Date: 2002-10-25 02:57:45
Message-ID: 3DB8B329.7020506@xythos.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-jdbc 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

In response to

Browse pgsql-jdbc by date

  From Date Subject
Next Message Dave Cramer 2002-10-25 09:23:48 Re: UPDATE_RULE
Previous Message Raymund 2002-10-24 08:20:37 how to insert the letter "ñ"

Browse pgsql-patches by date

  From Date Subject
Next Message Dennis Björklund 2002-10-26 05:30:36 Re: swedish translation
Previous Message Bruce Momjian 2002-10-23 23:33:01 Re: patch for pgsql/doc/src/sgml/ref/postgres-ref.sgml