Author: dfabulich
Date: Tue Feb 10 06:41:05 2009
New Revision: 742865

URL: http://svn.apache.org/viewvc?rev=742865&view=rev
Log:
[DBUTILS-14] [DBUTILS-31] [DBUTILS-39] [DBUTILS-41] [DBUTILS-44] setNull 
problems with Postgres and Oracle.

With this change, we now attempt to use ParameterMetaData.getParameterType to 
determine the SQL type of a null parameter.  On Oracle, this will fail, so 
we'll try it once (at most), and record the failure in a volatile boolean so we 
won't try it again unnecessarily.

Modified:
    
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java

Modified: 
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java
URL: 
http://svn.apache.org/viewvc/commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java?rev=742865&r1=742864&r2=742865&view=diff
==============================================================================
--- 
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java
 (original)
+++ 
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java
 Tue Feb 10 06:41:05 2009
@@ -17,6 +17,7 @@
 package org.apache.commons.dbutils;
 
 import java.sql.Connection;
+import java.sql.ParameterMetaData;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -35,6 +36,11 @@
 public class QueryRunner {
 
     /**
+     * Is {...@link ParameterMetaData#getParameterType(int)} broken (have we 
tried it yet)?
+     */
+    private volatile boolean pmdKnownBroken = false;
+    
+    /**
      * The DataSource to retrieve connections from.
      */
     protected DataSource ds = null;
@@ -47,7 +53,18 @@
     }
 
     /**
-     * Constructor for QueryRunner.  Methods that do not take a 
+     * Constructor for QueryRunner, allows workaround for Oracle drivers
+     * @param pmdKnownBroken Oracle drivers don't support {...@link 
ParameterMetaData#getParameterType(int) };
+     * if <code>pmdKnownBroken</code> is set to true, we won't even try it; if 
false, we'll try it,
+     * and if it breaks, we'll remember not to use it again.
+     */
+    public QueryRunner(boolean pmdKnownBroken) {
+        super();
+        this.pmdKnownBroken = pmdKnownBroken; 
+    }
+    
+    /**
+     * Constructor for QueryRunner, allows workaround for Oracle drivers.  
Methods that do not take a 
      * <code>Connection</code> parameter will retrieve connections from this
      * <code>DataSource</code>.
      * 
@@ -59,6 +76,22 @@
     }
     
     /**
+     * Constructor for QueryRunner, allows workaround for Oracle drivers.  
Methods that do not take a 
+     * <code>Connection</code> parameter will retrieve connections from this
+     * <code>DataSource</code>.
+     * 
+     * @param ds The <code>DataSource</code> to retrieve connections from.
+     * @param pmdKnownBroken Oracle drivers don't support {...@link 
ParameterMetaData#getParameterType(int) };
+     * if <code>pmdKnownBroken</code> is set to true, we won't even try it; if 
false, we'll try it,
+     * and if it breaks, we'll remember not to use it again.
+     */
+    public QueryRunner(DataSource ds, boolean pmdKnownBroken) {
+        super();
+        this.pmdKnownBroken = pmdKnownBroken;
+        setDataSource(ds);
+    }
+    
+    /**
      * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
      * 
      * @param conn The Connection to use to run the query.  The caller is
@@ -130,7 +163,12 @@
         if (params == null) {
             return;
         }
-
+        
+        ParameterMetaData pmd = stmt.getParameterMetaData();
+        if (pmd.getParameterCount() < params.length) {
+            throw new SQLException("Too many parameters: expected "
+                    + pmd.getParameterCount() + ", was given " + 
params.length);
+        }
         for (int i = 0; i < params.length; i++) {
             if (params[i] != null) {
                 stmt.setObject(i + 1, params[i]);
@@ -138,7 +176,15 @@
                 // VARCHAR works with many drivers regardless
                 // of the actual column type.  Oddly, NULL and 
                 // OTHER don't work with Oracle's drivers.
-                stmt.setNull(i + 1, Types.VARCHAR);
+                int sqlType = Types.VARCHAR;
+                if (!pmdKnownBroken) {
+                    try {
+                        sqlType = pmd.getParameterType(i + 1);
+                    } catch (SQLException e) {
+                        pmdKnownBroken = true;
+                    }
+                }
+                stmt.setNull(i + 1, sqlType);
             }
         }
     }


Reply via email to