Using BigInteger as argument to AbstractJdbc2Statement.setObject - Mailing list pgsql-jdbc

From Sylvain Leroux
Subject Using BigInteger as argument to AbstractJdbc2Statement.setObject
Date
Msg-id 4A79587F.6010603@wanadoo.fr
Whole thread Raw
Responses Re: Using BigInteger as argument to AbstractJdbc2Statement.setObject  (Oliver Jowett <oliver@opencloud.com>)
List pgsql-jdbc
Hi,

I am using Jython to access a PostgreSQL database throught the JDBC driver.

I have a problem with a code fragment like that:
>         stmt = self.conn.prepareStatement("INSERT INTO campagne(id) VALUES(?)")
>         stmt.setObject(1, 123456899999)

Of course, in the real code, the value 123456899999 is not hard wired.
Anyway, Jython ``autobox'' such values into a java.math.BigInteger object.
But AbstractJdbc2Statement.setObject does not handle that kind of
object. Which leads to the error:
>     stmt.setObject(1, 123456899999)
>         at org.postgresql.jdbc2.AbstractJdbc2Statement.setObject(AbstractJdbc2Statement.java:1735)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>         at java.lang.reflect.Method.invoke(Method.java:597)
>
> org.postgresql.util.PSQLException: org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance
of 
> java.math.BigInteger. Use setObject() with an explicit Types value to specify the type to use.

Since the column campagne(id) is a NUMERIC, as the error message
suggests, I could write something like that instead:
>         stmt.setObject(1, 123456899999, Types.NUMERIC)

But this defeats the purpose of using a scripting language both for
simplicity and dynamic typing.

Moreover other scripting languages for the Java platform may exhibit the
same behavior. So, it would be great if we have support for passing
BigInteger as argument to the setObject method in prepared statements.
Even if it's not required by the JDBC API.

Best of all, the patch is trivial as you will see: I send the result of
a ``cvs diff -u8pN'' as an attachment.


Best regards,
Sylvain Leroux

--
Website: http://www.chicoree.fr
Index: org/postgresql/jdbc2/AbstractJdbc2Statement.java
===================================================================
RCS file: /cvsroot/jdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v
retrieving revision 1.114
diff -u -8 -p -r1.114 AbstractJdbc2Statement.java
--- org/postgresql/jdbc2/AbstractJdbc2Statement.java    27 May 2009 23:55:19 -0000    1.114
+++ org/postgresql/jdbc2/AbstractJdbc2Statement.java    5 Aug 2009 09:30:00 -0000
@@ -1224,16 +1224,36 @@ public abstract class AbstractJdbc2State
      */
     public void setDouble(int parameterIndex, double x) throws SQLException
     {
         checkClosed();
         bindLiteral(parameterIndex, Double.toString(x), Oid.FLOAT8);
     }

     /*
+     * Set a parameter to a java.lang.BigInteger value.  The driver
+     * converts this to a SQL NUMERIC value when it sends it to the
+     * database.
+     *
+     * <b>This is an extension to the JDBC API!</b>
+     *
+     * @param parameterIndex the first parameter is 1...
+     * @param x the parameter value
+     * @exception SQLException if a database access error occurs
+     */
+    public void setBigInteger(int parameterIndex, BigInteger x) throws SQLException
+    {
+        checkClosed();
+        if (x == null)
+            setNull(parameterIndex, Types.DECIMAL);
+        else
+            bindLiteral(parameterIndex, x.toString(), Oid.NUMERIC);
+    }
+
+    /*
      * 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
      */
@@ -1731,16 +1751,18 @@ public abstract class AbstractJdbc2State
     {
         checkClosed();
         if (x == null)
             setNull(parameterIndex, Types.OTHER);
         else if (x instanceof String)
             setString(parameterIndex, (String)x);
         else if (x instanceof BigDecimal)
             setBigDecimal(parameterIndex, (BigDecimal)x);
+        else if (x instanceof BigInteger)
+            setBigInteger(parameterIndex, (BigInteger)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());

pgsql-jdbc by date:

Previous
From: Michael Schwipps
Date:
Subject: float4 or real in function parameter -> PSQLException: ERROR function in_test4(double precision) does not exist
Next
From: Oliver Jowett
Date:
Subject: Re: Using BigInteger as argument to AbstractJdbc2Statement.setObject