diff --git a/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java b/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java index 4737fb329bf6995b6eefa98a4e5bc6296192fae5..8824f8c0f0a644d62cb12c4be0dc033b49115298 100644 --- a/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java +++ b/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -812,101 +812,119 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { } } - /** - * Inserts a row that has been inserted into the given - * CachedRowSet object into the data source from which - * the rowset is derived, returning false if the insertion - * was successful. - * - * @param crs the CachedRowSet object that has had a row inserted - * and to whose underlying data source the row will be inserted - * @param pstmt the PreparedStatement object that will be used - * to execute the insertion - * @return false to indicate that the insertion was successful; - * true otherwise - * @throws SQLException if a database access error occurs - */ - private boolean insertNewRow(CachedRowSet crs, - PreparedStatement pstmt, CachedRowSetImpl crsRes) throws SQLException { - int i = 0; - int icolCount = crs.getMetaData().getColumnCount(); - - boolean returnVal = false; - PreparedStatement pstmtSel = con.prepareStatement(selectCmd, - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); - ResultSet rs, rs2 = null; - DatabaseMetaData dbmd = con.getMetaData(); - rs = pstmtSel.executeQuery(); - String table = crs.getTableName(); - rs2 = dbmd.getPrimaryKeys(null, null, table); - String [] primaryKeys = new String[icolCount]; - int k = 0; - while(rs2.next()) { - String pkcolname = rs2.getString("COLUMN_NAME"); - primaryKeys[k] = pkcolname; - k++; - } - - if(rs.next()) { - for(int j=0;jCachedRowSet object into the data source from which + * the rowset is derived, returning false if the insertion + * was successful. + * + * @param crs the CachedRowSet object that has had a row inserted + * and to whose underlying data source the row will be inserted + * @param pstmt the PreparedStatement object that will be used + * to execute the insertion + * @return false to indicate that the insertion was successful; + * true otherwise + * @throws SQLException if a database access error occurs + */ + private boolean insertNewRow(CachedRowSet crs, + PreparedStatement pstmt, CachedRowSetImpl crsRes) throws SQLException { + + boolean returnVal = false; + + try (PreparedStatement pstmtSel = con.prepareStatement(selectCmd, + ResultSet.TYPE_SCROLL_SENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet rs = pstmtSel.executeQuery(); + ResultSet rs2 = con.getMetaData().getPrimaryKeys(null, null, + crs.getTableName()) + ) { + + ResultSetMetaData rsmd = crs.getMetaData(); + int icolCount = rsmd.getColumnCount(); + String[] primaryKeys = new String[icolCount]; + int k = 0; + while (rs2.next()) { + primaryKeys[k] = rs2.getString("COLUMN_NAME"); + k++; + } + + if (rs.next()) { + for (String pkName : primaryKeys) { + if (!isPKNameValid(pkName, rsmd)) { + + /* We came here as one of the the primary keys + * of the table is not present in the cached + * rowset object, it should be an autoincrement column + * and not included while creating CachedRowSet + * Object, proceed to check for other primary keys + */ + continue; + } + + Object crsPK = crs.getObject(pkName); + if (crsPK == null) { + /* + * It is possible that the PK is null on some databases + * and will be filled in at insert time (MySQL for example) + */ + break; + } + + String rsPK = rs.getObject(pkName).toString(); + if (crsPK.toString().equals(rsPK)) { + returnVal = true; + this.crsResolve.moveToInsertRow(); + for (int i = 1; i <= icolCount; i++) { + String colname = (rs.getMetaData()).getColumnName(i); + if (colname.equals(pkName)) + this.crsResolve.updateObject(i,rsPK); + else + this.crsResolve.updateNull(i); + } + this.crsResolve.insertRow(); + this.crsResolve.moveToCurrentRow(); + } + } + } + + if (returnVal) { + return returnVal; + } + + try { + for (int i = 1; i <= icolCount; i++) { + Object obj = crs.getObject(i); + if (obj != null) { + pstmt.setObject(i, obj); + } else { + pstmt.setNull(i,crs.getMetaData().getColumnType(i)); + } + } - for(i = 1; i <= icolCount; i++) { - this.crsResolve.updateNull(i); - } + pstmt.executeUpdate(); + return false; + + } catch (SQLException ex) { + /* + * Cursor will come here if executeUpdate fails. + * There can be many reasons why the insertion failed, + * one can be violation of primary key. + * Hence we cannot exactly identify why the insertion failed, + * present the current row as a null row to the caller. + */ + this.crsResolve.moveToInsertRow(); + + for (int i = 1; i <= icolCount; i++) { + this.crsResolve.updateNull(i); + } - this.crsResolve.insertRow(); - this.crsResolve.moveToCurrentRow(); + this.crsResolve.insertRow(); + this.crsResolve.moveToCurrentRow(); - return true; - } - } + return true; + } + } + } /** * Deletes the row in the underlying data source that corresponds to @@ -1437,4 +1455,25 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { } static final long serialVersionUID =-8506030970299413976L; + + /** + * Validate whether the Primary Key is known to the CachedRowSet. If it is + * not, it is an auto-generated key + * @param pk - Primary Key to validate + * @param rsmd - ResultSetMetadata for the RowSet + * @return true if found, false otherwise (auto generated key) + */ + private boolean isPKNameValid(String pk, ResultSetMetaData rsmd) throws SQLException { + boolean isValid = false; + int cols = rsmd.getColumnCount(); + for(int i = 1; i<= cols; i++) { + String colName = rsmd.getColumnClassName(i); + if(colName.equalsIgnoreCase(pk)) { + isValid = true; + break; + } + } + + return isValid; + } }