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;
}
}
Aggregations