src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java

Print this page


   1 /*
   2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 811             return true;
 812         }
 813     }
 814 
 815     /**
 816          * Inserts a row that has been inserted into the given
 817          * <code>CachedRowSet</code> object into the data source from which
 818          * the rowset is derived, returning <code>false</code> if the insertion
 819          * was successful.
 820          *
 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
 823          * @param pstmt the <code>PreparedStatement</code> object that will be used
 824          *              to execute the insertion
 825          * @return <code>false</code> to indicate that the insertion was successful;
 826          *         <code>true</code> otherwise
 827          * @throws SQLException if a database access error occurs
 828          */
 829     private boolean insertNewRow(CachedRowSet crs,
 830         PreparedStatement pstmt, CachedRowSetImpl crsRes) throws SQLException {
 831         int i = 0;
 832         int icolCount = crs.getMetaData().getColumnCount();
 833 
 834         boolean returnVal = false;
 835         PreparedStatement pstmtSel = con.prepareStatement(selectCmd,
 836                         ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
 837         ResultSet rs, rs2 = null;
 838         DatabaseMetaData dbmd = con.getMetaData();
 839         rs = pstmtSel.executeQuery();
 840         String table = crs.getTableName();
 841         rs2 = dbmd.getPrimaryKeys(null, null, table);
 842         String [] primaryKeys = new String[icolCount];




 843         int k = 0;
 844         while(rs2.next()) {
 845             String pkcolname = rs2.getString("COLUMN_NAME");
 846             primaryKeys[k] = pkcolname;
 847             k++;
 848         }
 849 
 850         if(rs.next()) {
 851             for(int j=0;j<primaryKeys.length;j++) {
 852                 if(primaryKeys[j] != null) {
 853                     if(crs.getObject(primaryKeys[j]) == null){















 854                         break;
 855                     }
 856                     String crsPK = (crs.getObject(primaryKeys[j])).toString();
 857                     String rsPK = (rs.getObject(primaryKeys[j])).toString();
 858                     if(crsPK.equals(rsPK)) {
 859                         returnVal = true;
 860                         this.crsResolve.moveToInsertRow();
 861                         for(i = 1; i <= icolCount; i++) {
 862                             String colname = (rs.getMetaData()).getColumnName(i);
 863                             if(colname.equals(primaryKeys[j]))
 864                                 this.crsResolve.updateObject(i,rsPK);
 865                             else
 866                                 this.crsResolve.updateNull(i);
 867                         }
 868                         this.crsResolve.insertRow();
 869                         this.crsResolve.moveToCurrentRow();
 870                     }
 871                 }
 872             }
 873         }
 874         if(returnVal)
 875             return returnVal;

 876 
 877         try {
 878             for (i = 1; i <= icolCount; i++) {
 879                 Object obj = crs.getObject(i);
 880                 if (obj != null) {
 881                     pstmt.setObject(i, obj);
 882                 } else {
 883                     pstmt.setNull(i,crs.getMetaData().getColumnType(i));
 884                 }
 885             }
 886 
 887              i = pstmt.executeUpdate();
 888              return false;
 889 
 890         } catch (SQLException ex) {
 891             /**
 892              * Cursor will come here if executeUpdate fails.
 893              * There can be many reasons why the insertion failed,
 894              * one can be violation of primary key.
 895              * Hence we cannot exactly identify why the insertion failed
 896              * Present the current row as a null row to the user.
 897              **/
 898             this.crsResolve.moveToInsertRow();
 899 
 900             for(i = 1; i <= icolCount; i++) {
 901                this.crsResolve.updateNull(i);
 902             }
 903 
 904             this.crsResolve.insertRow();
 905             this.crsResolve.moveToCurrentRow();
 906 
 907             return true;
 908         }
 909     }

 910 
 911 /**
 912  * 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
 914  * and returns <code>false</code> if the deletion was successful.
 915  * <P>
 916  * This method is called internally by this writer's <code>writeData</code>
 917  * method when a row in the rowset has been deleted. The values in the
 918  * deleted row are the same as those that are stored in the original row
 919  * of the given <code>CachedRowSet</code> object.  If the values in the
 920  * original row differ from the row in the underlying data source, the row
 921  * in the data source is not deleted, and <code>deleteOriginalRow</code>
 922  * returns <code>true</code> to indicate that there was a conflict.
 923  *
 924  *
 925  * @return <code>false</code> if the deletion was successful, which means that
 926  *         there was no conflict; <code>true</code> otherwise
 927  * @throws SQLException if there was a database access error
 928  */
 929     private boolean deleteOriginalRow(CachedRowSet crs, CachedRowSetImpl crsRes) throws SQLException {


1420     public void rollback(Savepoint s) throws SQLException {
1421         con.rollback(s);
1422         if (reader.getCloseConnection() == true) {
1423             con.close();
1424         }
1425     }
1426 
1427     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1428         // Default state initialization happens here
1429         ois.defaultReadObject();
1430         // Initialization of  Res Bundle happens here .
1431         try {
1432            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
1433         } catch(IOException ioe) {
1434             throw new RuntimeException(ioe);
1435         }
1436 
1437     }
1438 
1439     static final long serialVersionUID =-8506030970299413976L;





















1440 }
   1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 811             return true;
 812         }
 813     }
 814 
 815    /**
 816     * Inserts a row that has been inserted into the given
 817     * <code>CachedRowSet</code> object into the data source from which
 818     * the rowset is derived, returning <code>false</code> if the insertion
 819     * was successful.
 820     *
 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
 823     * @param pstmt the <code>PreparedStatement</code> object that will be used
 824     *              to execute the insertion
 825     * @return <code>false</code> to indicate that the insertion was successful;
 826     *         <code>true</code> otherwise
 827     * @throws SQLException if a database access error occurs
 828     */
 829    private boolean insertNewRow(CachedRowSet crs,
 830        PreparedStatement pstmt, CachedRowSetImpl crsRes) throws SQLException {


 831 
 832        boolean returnVal = false;
 833 
 834        try (PreparedStatement pstmtSel = con.prepareStatement(selectCmd,
 835                        ResultSet.TYPE_SCROLL_SENSITIVE,
 836                        ResultSet.CONCUR_READ_ONLY);
 837             ResultSet rs = pstmtSel.executeQuery();
 838             ResultSet rs2 = con.getMetaData().getPrimaryKeys(null, null,
 839                        crs.getTableName())
 840        ) {
 841 
 842            ResultSetMetaData rsmd = crs.getMetaData();
 843            int icolCount = rsmd.getColumnCount();
 844            String[] primaryKeys = new String[icolCount];
 845            int k = 0;
 846            while (rs2.next()) {
 847                primaryKeys[k] = rs2.getString("COLUMN_NAME");

 848                k++;
 849            }
 850 
 851            if (rs.next()) {
 852                for (String pkName : primaryKeys) {
 853                    if (!isPKNameValid(pkName, rsmd)) {
 854 
 855                        /* We came here as one of the the primary keys
 856                         * of the table is not present in the cached
 857                         * rowset object, it should be an autoincrement column
 858                         * and not included while creating CachedRowSet
 859                         * Object, proceed to check for other primary keys
 860                         */
 861                        continue;
 862                    }
 863 
 864                    Object crsPK = crs.getObject(pkName);
 865                    if (crsPK == null) {
 866                        /*
 867                         * It is possible that the PK is null on some databases
 868                         * and will be filled in at insert time (MySQL for example)
 869                         */
 870                        break;
 871                    }
 872 
 873                    String rsPK = rs.getObject(pkName).toString();
 874                    if (crsPK.toString().equals(rsPK)) {
 875                        returnVal = true;
 876                        this.crsResolve.moveToInsertRow();
 877                        for (int i = 1; i <= icolCount; i++) {
 878                            String colname = (rs.getMetaData()).getColumnName(i);
 879                            if (colname.equals(pkName))
 880                                this.crsResolve.updateObject(i,rsPK);
 881                            else
 882                                this.crsResolve.updateNull(i);
 883                        }
 884                        this.crsResolve.insertRow();
 885                        this.crsResolve.moveToCurrentRow();
 886                    }
 887                }
 888            }
 889 
 890            if (returnVal) {
 891                return returnVal;
 892            }
 893 
 894            try {
 895                for (int i = 1; i <= icolCount; i++) {
 896                    Object obj = crs.getObject(i);
 897                    if (obj != null) {
 898                        pstmt.setObject(i, obj);
 899                    } else {
 900                        pstmt.setNull(i,crs.getMetaData().getColumnType(i));
 901                    }
 902                }
 903 
 904                pstmt.executeUpdate();
 905                return false;
 906 
 907            } catch (SQLException ex) {
 908                /*
 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 user.
 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    }
 928 
 929 /**
 930  * Deletes the row in the underlying data source that corresponds to
 931  * a row that has been deleted in the given <code> CachedRowSet</code> object
 932  * and returns <code>false</code> if the deletion was successful.
 933  * <P>
 934  * This method is called internally by this writer's <code>writeData</code>
 935  * method when a row in the rowset has been deleted. The values in the
 936  * deleted row are the same as those that are stored in the original row
 937  * of the given <code>CachedRowSet</code> object.  If the values in the
 938  * original row differ from the row in the underlying data source, the row
 939  * in the data source is not deleted, and <code>deleteOriginalRow</code>
 940  * returns <code>true</code> to indicate that there was a conflict.
 941  *
 942  *
 943  * @return <code>false</code> if the deletion was successful, which means that
 944  *         there was no conflict; <code>true</code> otherwise
 945  * @throws SQLException if there was a database access error
 946  */
 947     private boolean deleteOriginalRow(CachedRowSet crs, CachedRowSetImpl crsRes) throws SQLException {


1438     public void rollback(Savepoint s) throws SQLException {
1439         con.rollback(s);
1440         if (reader.getCloseConnection() == true) {
1441             con.close();
1442         }
1443     }
1444 
1445     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1446         // Default state initialization happens here
1447         ois.defaultReadObject();
1448         // Initialization of  Res Bundle happens here .
1449         try {
1450            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
1451         } catch(IOException ioe) {
1452             throw new RuntimeException(ioe);
1453         }
1454 
1455     }
1456 
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     }
1479 }