Search in sources :

Example 11 with SerialStruct

use of javax.sql.rowset.serial.SerialStruct in project jdk8u_jdk by JetBrains.

the class CachedRowSetWriter method updateOriginalRow.

//end writeData
/**
 * Updates the given <code>CachedRowSet</code> object's underlying data
 * source so that updates to the rowset are reflected in the original
 * data source, and returns <code>false</code> if the update was successful.
 * A return value of <code>true</code> indicates that there is a conflict,
 * meaning that a value updated in the rowset has already been changed by
 * someone else in the underlying data source.  A conflict can also exist
 * if, for example, more than one row in the data source would be affected
 * by the update or if no rows would be affected.  In any case, if there is
 * a conflict, this method does not update the underlying data source.
 * <P>
 * This method is called internally by the method <code>writeData</code>
 * if a row in the <code>CachedRowSet</code> object for which this
 * <code>CachedRowSetWriter</code> object is the writer has been updated.
 *
 * @return <code>false</code> if the update to the underlying data source is
 *         successful; <code>true</code> otherwise
 * @throws SQLException if a database access error occurs
 */
private boolean updateOriginalRow(CachedRowSet crs) throws SQLException {
    PreparedStatement pstmt;
    int i = 0;
    int idx = 0;
    // Select the row from the database.
    ResultSet origVals = crs.getOriginalRow();
    origVals.next();
    try {
        updateWhere = buildWhereClause(updateWhere, origVals);
        /**
              *  The following block of code is for checking a particular type of
              *  query where in there is a where clause. Without this block, if a
              *  SQL statement is built the "where" clause will appear twice hence
              *  the DB errors out and a SQLException is thrown. This code also
              *  considers that the where clause is in the right place as the
              *  CachedRowSet object would already have been populated with this
              *  query before coming to this point.
              **/
        String tempselectCmd = selectCmd.toLowerCase();
        int idxWhere = tempselectCmd.indexOf("where");
        if (idxWhere != -1) {
            String tempSelect = selectCmd.substring(0, idxWhere);
            selectCmd = tempSelect;
        }
        pstmt = con.prepareStatement(selectCmd + updateWhere, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
        for (i = 0; i < keyCols.length; i++) {
            if (params[i] != null) {
                pstmt.setObject(++idx, params[i]);
            } else {
                continue;
            }
        }
        try {
            pstmt.setMaxRows(crs.getMaxRows());
            pstmt.setMaxFieldSize(crs.getMaxFieldSize());
            pstmt.setEscapeProcessing(crs.getEscapeProcessing());
            pstmt.setQueryTimeout(crs.getQueryTimeout());
        } catch (Exception ex) {
        // Older driver don't support these operations.
        }
        ResultSet rs = null;
        rs = pstmt.executeQuery();
        ResultSetMetaData rsmd = rs.getMetaData();
        if (rs.next()) {
            if (rs.next()) {
                return true;
            }
            // don't close the rs
            // we require the record in rs to be used.
            // rs.close();
            // pstmt.close();
            rs.first();
            // how many fields need to be updated
            int colsNotChanged = 0;
            Vector<Integer> cols = new Vector<>();
            String updateExec = updateCmd;
            Object orig;
            Object curr;
            Object rsval;
            boolean boolNull = true;
            Object objVal = null;
            // There's only one row and the cursor
            // needs to be on that row.
            boolean first = true;
            boolean flag = true;
            this.crsResolve.moveToInsertRow();
            for (i = 1; i <= callerColumnCount; i++) {
                orig = origVals.getObject(i);
                curr = crs.getObject(i);
                rsval = rs.getObject(i);
                /*
                 * the following block creates equivalent objects
                 * that would have been created if this rs is populated
                 * into a CachedRowSet so that comparison of the column values
                 * from the ResultSet and CachedRowSet are possible
                 */
                Map<String, Class<?>> map = (crs.getTypeMap() == null) ? con.getTypeMap() : crs.getTypeMap();
                if (rsval instanceof Struct) {
                    Struct s = (Struct) rsval;
                    // look up the class in the map
                    Class<?> c = null;
                    c = map.get(s.getSQLTypeName());
                    if (c != null) {
                        // create new instance of the class
                        SQLData obj = null;
                        try {
                            obj = (SQLData) ReflectUtil.newInstance(c);
                        } catch (Exception ex) {
                            throw new SQLException("Unable to Instantiate: ", ex);
                        }
                        // get the attributes from the struct
                        Object[] attribs = s.getAttributes(map);
                        // create the SQLInput "stream"
                        SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
                        // read the values...
                        obj.readSQL(sqlInput, s.getSQLTypeName());
                        rsval = obj;
                    }
                } else if (rsval instanceof SQLData) {
                    rsval = new SerialStruct((SQLData) rsval, map);
                } else if (rsval instanceof Blob) {
                    rsval = new SerialBlob((Blob) rsval);
                } else if (rsval instanceof Clob) {
                    rsval = new SerialClob((Clob) rsval);
                } else if (rsval instanceof java.sql.Array) {
                    rsval = new SerialArray((java.sql.Array) rsval, map);
                }
                // reset boolNull if it had been set
                boolNull = true;
                if (rsval == null && orig != null) {
                    // value in db has changed
                    // don't proceed with synchronization
                    // get the value in db and pass it to the resolver.
                    iChangedValsinDbOnly++;
                    // Set the boolNull to false,
                    // in order to set the actual value;
                    boolNull = false;
                    objVal = rsval;
                } else if (rsval != null && (!rsval.equals(orig))) {
                    // value in db has changed
                    // don't proceed with synchronization
                    // get the value in db and pass it to the resolver.
                    iChangedValsinDbOnly++;
                    // Set the boolNull to false,
                    // in order to set the actual value;
                    boolNull = false;
                    objVal = rsval;
                } else if ((orig == null || curr == null)) {
                    if (first == false || flag == false) {
                        updateExec += ", ";
                    }
                    updateExec += crs.getMetaData().getColumnName(i);
                    cols.add(i);
                    updateExec += " = ? ";
                    first = false;
                /** Adding the extra condition for orig to be "not" null as the
                 *  condition for orig to be null is take prior to this, if this
                 *  is not added it will result in a NullPointerException when
                 *  the values are compared.
                 **/
                } else if (orig.equals(curr)) {
                    colsNotChanged++;
                //nothing to update in this case since values are equal
                /** Adding the extra condition for orig to be "not" null as the
                 *  condition for orig to be null is take prior to this, if this
                 *  is not added it will result in a NullPointerException when
                 *  the values are compared.
                 **/
                } else if (orig.equals(curr) == false) {
                    if (crs.columnUpdated(i)) {
                        if (rsval.equals(orig)) {
                            // what is in db now and has not changed
                            if (flag == false || first == false) {
                                updateExec += ", ";
                            }
                            updateExec += crs.getMetaData().getColumnName(i);
                            cols.add(i);
                            updateExec += " = ? ";
                            flag = false;
                        } else {
                            // Here the value has changed in the db after
                            // data was fetched
                            // Plus store this row from CachedRowSet and keep it
                            // in a new CachedRowSet
                            boolNull = false;
                            objVal = rsval;
                            iChangedValsInDbAndCRS++;
                        }
                    }
                }
                if (!boolNull) {
                    this.crsResolve.updateObject(i, objVal);
                } else {
                    this.crsResolve.updateNull(i);
                }
            }
            //end for
            rs.close();
            pstmt.close();
            this.crsResolve.insertRow();
            this.crsResolve.moveToCurrentRow();
            /**
                 * if nothing has changed return now - this can happen
                 * if column is updated to the same value.
                 * if colsNotChanged == callerColumnCount implies we are updating
                 * the database with ALL COLUMNS HAVING SAME VALUES,
                 * so skip going to database, else do as usual.
                 **/
            if ((first == false && cols.size() == 0) || colsNotChanged == callerColumnCount) {
                return false;
            }
            if (iChangedValsInDbAndCRS != 0 || iChangedValsinDbOnly != 0) {
                return true;
            }
            updateExec += updateWhere;
            pstmt = con.prepareStatement(updateExec);
            // Comments needed here
            for (i = 0; i < cols.size(); i++) {
                Object obj = crs.getObject(cols.get(i));
                if (obj != null)
                    pstmt.setObject(i + 1, obj);
                else
                    pstmt.setNull(i + 1, crs.getMetaData().getColumnType(i + 1));
            }
            idx = i;
            // Comments needed here
            for (i = 0; i < keyCols.length; i++) {
                if (params[i] != null) {
                    pstmt.setObject(++idx, params[i]);
                } else {
                    continue;
                }
            }
            i = pstmt.executeUpdate();
            return false;
        } else {
            /**
                 * Cursor will be here, if the ResultSet may not return even a single row
                 * i.e. we can't find the row where to update because it has been deleted
                 * etc. from the db.
                 * Present the whole row as null to user, to force null to be sync'ed
                 * and hence nothing to be synced.
                 *
                 * NOTE:
                 * ------
                 * In the database if a column that is mapped to java.sql.Types.REAL stores
                 * a Double value and is compared with value got from ResultSet.getFloat()
                 * no row is retrieved and will throw a SyncProviderException. For details
                 * see bug Id 5053830
                 **/
            return true;
        }
    } catch (SQLException ex) {
        ex.printStackTrace();
        // if executeUpdate fails it will come here,
        // update crsResolve with null rows
        this.crsResolve.moveToInsertRow();
        for (i = 1; i <= callerColumnCount; i++) {
            this.crsResolve.updateNull(i);
        }
        this.crsResolve.insertRow();
        this.crsResolve.moveToCurrentRow();
        return true;
    }
}
Also used : SerialBlob(javax.sql.rowset.serial.SerialBlob) SerialStruct(javax.sql.rowset.serial.SerialStruct) SerialStruct(javax.sql.rowset.serial.SerialStruct) SQLInputImpl(javax.sql.rowset.serial.SQLInputImpl) SerialArray(javax.sql.rowset.serial.SerialArray) SerialBlob(javax.sql.rowset.serial.SerialBlob) SerialClob(javax.sql.rowset.serial.SerialClob) SerialArray(javax.sql.rowset.serial.SerialArray) SerialClob(javax.sql.rowset.serial.SerialClob)

Aggregations

SerialStruct (javax.sql.rowset.serial.SerialStruct)11 Test (org.testng.annotations.Test)10 BaseTest (util.BaseTest)10 Struct (java.sql.Struct)1 SQLInputImpl (javax.sql.rowset.serial.SQLInputImpl)1 SerialArray (javax.sql.rowset.serial.SerialArray)1 SerialBlob (javax.sql.rowset.serial.SerialBlob)1 SerialClob (javax.sql.rowset.serial.SerialClob)1 StubStruct (util.StubStruct)1