Bug #19451 UpdatableResultSet.moveToInsertRow causes java.lang.ClassCastException
Submitted: 30 Apr 2006 23:16 Modified: 2 Oct 2007 19:26
Reporter: Jamie Garton Email Updates:
Status: Can't repeat Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:Connector/J 3.1.12 OS:Windows (Windows XP Pro SP2)
Assigned to: CPU Architecture:Any

[30 Apr 2006 23:16] Jamie Garton
Description:
When trying to insert a row into a resultset that has atleast one record in it (i.e. the error does not occur if the resultset is empty) the following error occurs.

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object;
    at com.mysql.jdbc.UpdatableResultSet.moveToInsertRow(UpdatableResultSet.java:912)
    at com.sun.rowset.JdbcRowSetImpl.moveToInsertRow(JdbcRowSetImpl.java:3151)
    at com.rjg.test.TestInsert.<init>(TestInsert.java:43)
    at com.rjg.test.TestInsert.main(TestInsert.java:101)

This error does not occur when using mysql-connector-java-3.0.17-ga-bin.jar library.

OS: Windows XP SP2
MySQL server version: 5.0.15-nt
Connector/J version: 3.1.12
Java version:
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

How to repeat:
Populate test table.

USE test;

DROP TABLE IF EXISTS time_sheet;

CREATE TABLE time_sheet (
    time_sheet_id INT AUTO_INCREMENT,
    time_code_id INT NOT NULL,
    start_time TIMESTAMP NOT NULL,
    finish_time TIMESTAMP NOT NULL,
    comment VARCHAR(100) default NULL,
    PRIMARY KEY (time_sheet_id)
);

insert into time_sheet 
values
(null, 1, '2006-05-01 07:55:00', '2006-05-01 09:55:00', null);

Run this test class.

import java.sql.Timestamp;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.ResultSetMetaData;
import javax.sql.rowset.spi.SyncProviderException;

import javax.sql.rowset.JdbcRowSet;
import com.sun.rowset.JdbcRowSetImpl;

public class TestInsert {

    private final String DB_URL = 
            "jdbc:mysql://localhost:3306/test?dumpQueriesOnException=true";
    private final String USERNAME = "username";
    private final String PASSWORD = "password";

    private JdbcRowSetImpl  rowSet = null;
    private ResultSetMetaData metaData = null;

//==============================================================================

   public TestInsert( ) {

        try {

            Class.forName( "com.mysql.jdbc.Driver" ); // load database driver class
            rowSet = new JdbcRowSetImpl ();
            rowSet.setConcurrency(ResultSet.CONCUR_UPDATABLE);
            rowSet.setUrl(DB_URL);        // set database URL
            rowSet.setUsername(USERNAME); // set username
            rowSet.setPassword(PASSWORD); // set password
            rowSet.setCommand("select * from time_sheet");   // set query
            rowSet.execute();
            metaData = rowSet.getMetaData();
            showTable();

            rowSet.moveToInsertRow();
            rowSet.updateNull("time_sheet_id");
            rowSet.updateInt("time_code_id", 1);
            rowSet.updateTimestamp("start_time", Timestamp.valueOf("2006-05-01 07:55:00"));
            rowSet.updateTimestamp("finish_time", Timestamp.valueOf("2006-05-01 09:55:00"));
            rowSet.updateNull("comment");

            rowSet.insertRow();
            rowSet.moveToCurrentRow();

            showTable();

            rowSet.close();

        } catch ( SQLException sqlException ) {
            sqlException.printStackTrace();
            System.exit( 1 );
        } catch ( ClassNotFoundException classNotFound ) {
            classNotFound.printStackTrace();            
            System.exit( 1 );
        }// catch. 

   }// Constructor.

//==============================================================================

    private void showTable( ) {

       try {
       
            int numberOfColumns = metaData.getColumnCount();
            rowSet.beforeFirst();

            // display rowset header
            for ( int i = 1; i <= numberOfColumns; i++ ) {
                System.err.print(metaData.getColumnName(i) + "\t");
            }
            System.err.println();

            // display each row
            while ( rowSet.next() ) {
                for ( int i = 1; i <= numberOfColumns; i++ ) {
                    System.err.print(rowSet.getObject(i)+ "\t");
                }// for.
                System.err.println();
            } // end while           
       
        } catch ( SQLException sqlException ) {
            sqlException.printStackTrace();
            System.exit( 1 );
        }// catch. 

    }// showTable.

//==============================================================================

   public static void main(String[] args) {

        new TestInsert();

   }// main.

//==============================================================================

}// TestCachedRowSet.

Suggested fix:
None known.
[5 May 2006 9:53] Tonci Grgin
Hi Jamie. Thanks for excellent problem report containing all rellevant information.
There seems to be a problem with your showTable() procedure. It moves cursor beyond eof so that moveToInsertRow() does not reposition well resulting in exception in InsertRow. That's why your code works on empty dataset.
Solution:
  modify your code like this
...
            metaData = rowSet.getMetaData();
            showTable();
>>>      rowSet.beforeFirst();
...
My output with corrected code:
time_sheet_id	time_code_id	start_time	finish_time	comment	
1	1	2006-05-01 07:55:00.0	2006-05-01 09:55:00.0	null	
time_sheet_id	time_code_id	start_time	finish_time	comment	
1	1	2006-05-01 07:55:00.0	2006-05-01 09:55:00.0	null	
2	1	2006-05-01 07:55:00.0	2006-05-01 09:55:00.0	null	
BUILD SUCCESSFUL (total time: 1 second)
[6 May 2006 4:29] Jamie Garton
Thanks for the help Tonci.
That did the trick.
[11 Apr 2007 15:26] Tonci Grgin
Even though the problem is solved, I've done some consults. This *is* a bug although the spec are not clear about "where" the insert row "lives", but you should be able to insert data even in result sets that aren't empty. There are some corner cases / gray areas, though, we'll have to deal with.
[2 Oct 2007 19:26] Mark Matthews
This doesn't seem repeatable with the latest 5.0 version of the driver.