jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java
changeset 13019 7bde6e4fff5c
parent 11129 f9ad1aadf3fa
child 14761 b31f1eaee88a
equal deleted inserted replaced
13018:92c86cea72a8 13019:7bde6e4fff5c
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
   810 
   810 
   811             return true;
   811             return true;
   812         }
   812         }
   813     }
   813     }
   814 
   814 
   815     /**
   815    /**
   816          * Inserts a row that has been inserted into the given
   816     * Inserts a row that has been inserted into the given
   817          * <code>CachedRowSet</code> object into the data source from which
   817     * <code>CachedRowSet</code> object into the data source from which
   818          * the rowset is derived, returning <code>false</code> if the insertion
   818     * the rowset is derived, returning <code>false</code> if the insertion
   819          * was successful.
   819     * was successful.
   820          *
   820     *
   821          * @param crs the <code>CachedRowSet</code> object that has had a row inserted
   821     * @param crs the <code>CachedRowSet</code> object that has had a row inserted
   822          *            and to whose underlying data source the row will be inserted
   822     *            and to whose underlying data source the row will be inserted
   823          * @param pstmt the <code>PreparedStatement</code> object that will be used
   823     * @param pstmt the <code>PreparedStatement</code> object that will be used
   824          *              to execute the insertion
   824     *              to execute the insertion
   825          * @return <code>false</code> to indicate that the insertion was successful;
   825     * @return <code>false</code> to indicate that the insertion was successful;
   826          *         <code>true</code> otherwise
   826     *         <code>true</code> otherwise
   827          * @throws SQLException if a database access error occurs
   827     * @throws SQLException if a database access error occurs
   828          */
   828     */
   829     private boolean insertNewRow(CachedRowSet crs,
   829    private boolean insertNewRow(CachedRowSet crs,
   830         PreparedStatement pstmt, CachedRowSetImpl crsRes) throws SQLException {
   830        PreparedStatement pstmt, CachedRowSetImpl crsRes) throws SQLException {
   831         int i = 0;
   831 
   832         int icolCount = crs.getMetaData().getColumnCount();
   832        boolean returnVal = false;
   833 
   833 
   834         boolean returnVal = false;
   834        try (PreparedStatement pstmtSel = con.prepareStatement(selectCmd,
   835         PreparedStatement pstmtSel = con.prepareStatement(selectCmd,
   835                        ResultSet.TYPE_SCROLL_SENSITIVE,
   836                         ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
   836                        ResultSet.CONCUR_READ_ONLY);
   837         ResultSet rs, rs2 = null;
   837             ResultSet rs = pstmtSel.executeQuery();
   838         DatabaseMetaData dbmd = con.getMetaData();
   838             ResultSet rs2 = con.getMetaData().getPrimaryKeys(null, null,
   839         rs = pstmtSel.executeQuery();
   839                        crs.getTableName())
   840         String table = crs.getTableName();
   840        ) {
   841         rs2 = dbmd.getPrimaryKeys(null, null, table);
   841 
   842         String [] primaryKeys = new String[icolCount];
   842            ResultSetMetaData rsmd = crs.getMetaData();
   843         int k = 0;
   843            int icolCount = rsmd.getColumnCount();
   844         while(rs2.next()) {
   844            String[] primaryKeys = new String[icolCount];
   845             String pkcolname = rs2.getString("COLUMN_NAME");
   845            int k = 0;
   846             primaryKeys[k] = pkcolname;
   846            while (rs2.next()) {
   847             k++;
   847                primaryKeys[k] = rs2.getString("COLUMN_NAME");
   848         }
   848                k++;
   849 
   849            }
   850         if(rs.next()) {
   850 
   851             for(int j=0;j<primaryKeys.length;j++) {
   851            if (rs.next()) {
   852                 if(primaryKeys[j] != null) {
   852                for (String pkName : primaryKeys) {
   853                     if(crs.getObject(primaryKeys[j]) == null){
   853                    if (!isPKNameValid(pkName, rsmd)) {
   854                         break;
   854 
   855                     }
   855                        /* We came here as one of the the primary keys
   856                     String crsPK = (crs.getObject(primaryKeys[j])).toString();
   856                         * of the table is not present in the cached
   857                     String rsPK = (rs.getObject(primaryKeys[j])).toString();
   857                         * rowset object, it should be an autoincrement column
   858                     if(crsPK.equals(rsPK)) {
   858                         * and not included while creating CachedRowSet
   859                         returnVal = true;
   859                         * Object, proceed to check for other primary keys
   860                         this.crsResolve.moveToInsertRow();
   860                         */
   861                         for(i = 1; i <= icolCount; i++) {
   861                        continue;
   862                             String colname = (rs.getMetaData()).getColumnName(i);
   862                    }
   863                             if(colname.equals(primaryKeys[j]))
   863 
   864                                 this.crsResolve.updateObject(i,rsPK);
   864                    Object crsPK = crs.getObject(pkName);
   865                             else
   865                    if (crsPK == null) {
   866                                 this.crsResolve.updateNull(i);
   866                        /*
   867                         }
   867                         * It is possible that the PK is null on some databases
   868                         this.crsResolve.insertRow();
   868                         * and will be filled in at insert time (MySQL for example)
   869                         this.crsResolve.moveToCurrentRow();
   869                         */
   870                     }
   870                        break;
   871                 }
   871                    }
   872             }
   872 
   873         }
   873                    String rsPK = rs.getObject(pkName).toString();
   874         if(returnVal)
   874                    if (crsPK.toString().equals(rsPK)) {
   875             return returnVal;
   875                        returnVal = true;
   876 
   876                        this.crsResolve.moveToInsertRow();
   877         try {
   877                        for (int i = 1; i <= icolCount; i++) {
   878             for (i = 1; i <= icolCount; i++) {
   878                            String colname = (rs.getMetaData()).getColumnName(i);
   879                 Object obj = crs.getObject(i);
   879                            if (colname.equals(pkName))
   880                 if (obj != null) {
   880                                this.crsResolve.updateObject(i,rsPK);
   881                     pstmt.setObject(i, obj);
   881                            else
   882                 } else {
   882                                this.crsResolve.updateNull(i);
   883                     pstmt.setNull(i,crs.getMetaData().getColumnType(i));
   883                        }
   884                 }
   884                        this.crsResolve.insertRow();
   885             }
   885                        this.crsResolve.moveToCurrentRow();
   886 
   886                    }
   887              i = pstmt.executeUpdate();
   887                }
   888              return false;
   888            }
   889 
   889 
   890         } catch (SQLException ex) {
   890            if (returnVal) {
   891             /**
   891                return returnVal;
   892              * Cursor will come here if executeUpdate fails.
   892            }
   893              * There can be many reasons why the insertion failed,
   893 
   894              * one can be violation of primary key.
   894            try {
   895              * Hence we cannot exactly identify why the insertion failed
   895                for (int i = 1; i <= icolCount; i++) {
   896              * Present the current row as a null row to the user.
   896                    Object obj = crs.getObject(i);
   897              **/
   897                    if (obj != null) {
   898             this.crsResolve.moveToInsertRow();
   898                        pstmt.setObject(i, obj);
   899 
   899                    } else {
   900             for(i = 1; i <= icolCount; i++) {
   900                        pstmt.setNull(i,crs.getMetaData().getColumnType(i));
   901                this.crsResolve.updateNull(i);
   901                    }
   902             }
   902                }
   903 
   903 
   904             this.crsResolve.insertRow();
   904                pstmt.executeUpdate();
   905             this.crsResolve.moveToCurrentRow();
   905                return false;
   906 
   906 
   907             return true;
   907            } catch (SQLException ex) {
   908         }
   908                /*
   909     }
   909                 * Cursor will come here if executeUpdate fails.
       
   910                 * There can be many reasons why the insertion failed,
       
   911                 * one can be violation of primary key.
       
   912                 * Hence we cannot exactly identify why the insertion failed,
       
   913                 * present the current row as a null row to the caller.
       
   914                 */
       
   915                this.crsResolve.moveToInsertRow();
       
   916 
       
   917                for (int i = 1; i <= icolCount; i++) {
       
   918                    this.crsResolve.updateNull(i);
       
   919                }
       
   920 
       
   921                this.crsResolve.insertRow();
       
   922                this.crsResolve.moveToCurrentRow();
       
   923 
       
   924                return true;
       
   925            }
       
   926        }
       
   927    }
   910 
   928 
   911 /**
   929 /**
   912  * Deletes the row in the underlying data source that corresponds to
   930  * Deletes the row in the underlying data source that corresponds to
   913  * a row that has been deleted in the given <code> CachedRowSet</code> object
   931  * a row that has been deleted in the given <code> CachedRowSet</code> object
   914  * and returns <code>false</code> if the deletion was successful.
   932  * and returns <code>false</code> if the deletion was successful.
  1435         }
  1453         }
  1436 
  1454 
  1437     }
  1455     }
  1438 
  1456 
  1439     static final long serialVersionUID =-8506030970299413976L;
  1457     static final long serialVersionUID =-8506030970299413976L;
       
  1458 
       
  1459     /**
       
  1460      * Validate whether the Primary Key is known to the CachedRowSet.  If it is
       
  1461      * not, it is an auto-generated key
       
  1462      * @param pk - Primary Key to validate
       
  1463      * @param rsmd - ResultSetMetadata for the RowSet
       
  1464      * @return true if found, false otherwise (auto generated key)
       
  1465      */
       
  1466     private boolean isPKNameValid(String pk, ResultSetMetaData rsmd) throws SQLException {
       
  1467         boolean isValid = false;
       
  1468         int cols = rsmd.getColumnCount();
       
  1469         for(int i = 1; i<= cols; i++) {
       
  1470             String colName = rsmd.getColumnClassName(i);
       
  1471             if(colName.equalsIgnoreCase(pk)) {
       
  1472                 isValid = true;
       
  1473                 break;
       
  1474             }
       
  1475         }
       
  1476 
       
  1477         return isValid;
       
  1478     }
  1440 }
  1479 }