jdbc bug/feature? - Mailing list pgsql-jdbc

From Marko Štrukelj
Subject jdbc bug/feature?
Date
Msg-id EE047BABDB69D6119C6200508B8B7F5E093C64@triglav.parsek.net
Whole thread Raw
List pgsql-jdbc

Hello,

There is a bug (I say) or a lack of proper functionality in JDBC driver regarding batch updates.

The following code is expected to work by some library that I use and it does work with inet tds driver for M$ SQL server. It however does not work with the latest jdbc from cvs or anything older than that either.

PreparedStatements st = c.prepareStatement("insert into my_table (field1, field2) values (?, ?)");

// we have say 30 inserts to do
Iterator it = inserts.iterator();
int i=0;
while(it.hasNext()) {

        // there is a maximum batch size of 15, so we must periodically execute it
        if(i==batchMax) {
                st.executeBatch();
                i=0;

                // the problem - after this call a PreparedStatement is empty and consequtive binds fail
        }

        Object [] binds = (Object [])it.next();
        st.setString(binds[0]);
        st.setString(binds[1]);
        st.addBatch();
        i++;
}

Upon some research I discovered the problem and found a very simple solution:

In org.postgresql.jdbc2.AbstractJdbc2Statement:

        public int[] executeBatch() throws SQLException
        {
System.out.println("### executeBatch");
                if (batch == null)
                        batch = new Vector();
                int size = batch.size();
                int[] result = new int[size];
                int i = 0;

// >>> added
                // save m_binds and m_sqlFragments because executeUpdate(String) will destroy them
                String [] oldFrags = m_sqlFragments;
                Object [] oldMBinds = m_binds;
// <<

                try
                {                      
                        for (i = 0;i < size;i++)
                                result[i] = this.executeUpdate((String)batch.elementAt(i));

                }
                catch (SQLException e)
                {
                        int[] resultSucceeded = new int[i];
                        System.arraycopy(result, 0, resultSucceeded, 0, i);

                        PBatchUpdateException updex =
                                new PBatchUpdateException("postgresql.stat.batch.error",
                                                                                  new Integer(i), batch.elementAt(i), resultSucceeded);

                        updex.setNextException(e);

                        throw updex;
                }
                finally
                {
                        batch.removeAllElements();
// >> added                    
                        // restore m_binds and m_sqlFragments
                        m_sqlFragments = oldFrags;
                        m_binds = oldMBinds;
// <<
                }
                return result;
        }


Please consider this as a bug, and patch it in cvs. I did not test this very well, so the described patch may possibly cause some incosistencies somewhere - the people who wrote that class will know best. It does work for my case though.

And thanks for PostgreSQL, I've just started using it and I love it.

- Marko

pgsql-jdbc by date:

Previous
From: Nic Ferrier
Date:
Subject: Re: streaming result sets: progress
Next
From: Harald Krake
Date:
Subject: why not type casting by default in prepared statements?