use of com.servoy.j2db.query.TablePlaceholderKey in project servoy-client by Servoy.
the class RowManager method getRowUpdateInfo.
RowUpdateInfo getRowUpdateInfo(Row row, boolean tracking) throws ServoyException {
try {
if (row.getRowManager() != this) {
// $NON-NLS-1$
throw new IllegalArgumentException("I'm not the row manager from row");
}
if (adjustingForChangeByOtherPKHashKey.get() != null && adjustingForChangeByOtherPKHashKey.get().equals(row.getPKHashKey())) {
row.flagExistInDB();
// we ignore changes here because stored calc with time element are always changed,resulting in endlessloop between clients
return null;
}
if (row.getLastException() instanceof DataException) {
// cannot update an row which is not changed (which clears the dataexception)
return null;
}
if (!row.isChanged())
return null;
boolean mustRequeryRow = false;
List<Column> dbPKReturnValues = new ArrayList<Column>();
SQLSheet.SQLDescription sqlDesc = null;
int statement_action;
ISQLUpdate sqlUpdate = null;
IServer server = fsm.getApplication().getSolution().getServer(sheet.getServerName());
boolean oracleServer = SQLSheet.isOracleServer(server);
boolean usesLobs = false;
Table table = sheet.getTable();
boolean doesExistInDB = row.existInDB();
List<String> aggregatesToRemove = new ArrayList<String>(8);
List<String> changedColumns = null;
if (doesExistInDB) {
statement_action = ISQLActionTypes.UPDATE_ACTION;
sqlDesc = sheet.getSQLDescription(SQLSheet.UPDATE);
sqlUpdate = (QueryUpdate) AbstractBaseQuery.deepClone(sqlDesc.getSQLQuery());
List<String> req = sqlDesc.getRequiredDataProviderIDs();
List<String> old = sqlDesc.getOldRequiredDataProviderIDs();
Object[] olddata = row.getRawOldColumnData();
if (// for safety only, nothing changed
olddata == null) {
return null;
}
Object[] newdata = row.getRawColumnData();
for (int i = 0; i < olddata.length; i++) {
String dataProviderID = req.get(i);
Column c = table.getColumn(dataProviderID);
ColumnInfo ci = c.getColumnInfo();
if (ci != null && ci.isDBManaged()) {
mustRequeryRow = true;
} else {
Object modificationValue = c.getModificationValue(fsm.getApplication());
if (modificationValue != null) {
row.setRawValue(dataProviderID, modificationValue);
}
if (newdata[i] instanceof BlobMarkerValue) {
// because that would be a byte[]
continue;
}
if (!Utils.equalObjects(olddata[i], newdata[i])) {
if (sheet.isUsedByAggregate(dataProviderID)) {
aggregatesToRemove.addAll(sheet.getAggregateName(dataProviderID));
}
Object robj = c.getAsRightType(newdata[i]);
if (robj == null)
robj = ValueFactory.createNullValue(c.getType());
((QueryUpdate) sqlUpdate).addValue(c.queryColumn(((QueryUpdate) sqlUpdate).getTable()), robj);
if (changedColumns == null) {
changedColumns = new ArrayList<String>(olddata.length - i);
}
changedColumns.add(c.getName());
if (oracleServer && !usesLobs) {
int type = c.getType();
if (type == Types.BLOB && robj instanceof byte[] && ((byte[]) robj).length > 4000) {
usesLobs = true;
} else if (type == Types.CLOB && robj instanceof String && ((String) robj).length() > 4000) {
usesLobs = true;
}
}
}
}
}
if (// nothing changed after all
changedColumns == null) {
// clear the old data now else it will be kept and in a changed state.
row.flagExistInDB();
return null;
}
// add PK
Object[] pkValues = new Object[old.size()];
for (int j = 0; j < old.size(); j++) {
String dataProviderID = old.get(j);
pkValues[j] = row.getOldRequiredValue(dataProviderID);
}
// TODO: check for success
AbstractBaseQuery.setPlaceholderValue(sqlUpdate, new TablePlaceholderKey(((QueryUpdate) sqlUpdate).getTable(), SQLGenerator.PLACEHOLDER_PRIMARY_KEY), pkValues);
} else {
List<Object> argsArray = new ArrayList<Object>();
statement_action = ISQLActionTypes.INSERT_ACTION;
sqlDesc = sheet.getSQLDescription(SQLSheet.INSERT);
sqlUpdate = (ISQLUpdate) AbstractBaseQuery.deepClone(sqlDesc.getSQLQuery());
List<String> req = sqlDesc.getRequiredDataProviderIDs();
if (Debug.tracing())
Debug.trace(sqlUpdate.toString());
for (int i = 0; i < req.size(); i++) {
String dataProviderID = req.get(i);
if (sheet.isUsedByAggregate(dataProviderID)) {
aggregatesToRemove.addAll(sheet.getAggregateName(dataProviderID));
}
Column c = table.getColumn(dataProviderID);
QueryColumn queryColumn = c.queryColumn(((QueryInsert) sqlUpdate).getTable());
ColumnInfo ci = c.getColumnInfo();
if (c.isDBIdentity()) {
dbPKReturnValues.add(c);
argsArray.add(row.getDbIdentValue());
} else if (ci != null && ci.isDBManaged()) {
mustRequeryRow = true;
} else {
int columnIndex = getSQLSheet().getColumnIndex(dataProviderID);
// HACK: DIRTY way, should use some kind of identifier preferably
if (c.getDatabaseDefaultValue() != null && row.getRawValue(columnIndex, false) == null && c.getRowIdentType() == IBaseColumn.NORMAL_COLUMN) {
// The database has a default value, and the value is null, and this is an insert...
// Remove the column from the query entirely and make sure the default value is requeried from the db.
mustRequeryRow = true;
((QueryInsert) sqlUpdate).removeColumn(queryColumn);
} else {
Object robj = c.getAsRightType(row.getRawValue(columnIndex, false));
if (robj == null)
robj = ValueFactory.createNullValue(c.getType());
argsArray.add(robj);
if (oracleServer && !usesLobs) {
int type = c.getType();
if (type == Types.BLOB && robj instanceof byte[] && ((byte[]) robj).length > 4000) {
usesLobs = true;
} else if (type == Types.CLOB && robj instanceof String && ((String) robj).length() > 4000) {
usesLobs = true;
}
}
}
}
}
AbstractBaseQuery.setPlaceholderValue(sqlUpdate, new TablePlaceholderKey(((QueryInsert) sqlUpdate).getTable(), SQLGenerator.PLACEHOLDER_INSERT_KEY), argsArray.toArray());
}
Object[] pk = row.getPK();
IDataSet pks = new BufferedDataSet();
pks.addRow(pk);
String tid = null;
GlobalTransaction gt = fsm.getGlobalTransaction();
if (gt != null) {
tid = gt.getTransactionID(sheet.getServerName());
}
QuerySelect requerySelect = null;
if (mustRequeryRow) {
requerySelect = (QuerySelect) AbstractBaseQuery.deepClone(sheet.getSQL(SQLSheet.SELECT));
if (!requerySelect.setPlaceholderValue(new TablePlaceholderKey(requerySelect.getTable(), SQLGenerator.PLACEHOLDER_PRIMARY_KEY), pk)) {
Debug.error(new RuntimeException(// $NON-NLS-1$
"Could not set placeholder " + new TablePlaceholderKey(requerySelect.getTable(), SQLGenerator.PLACEHOLDER_PRIMARY_KEY) + " in query " + requerySelect + // $NON-NLS-1$//$NON-NLS-2$
"-- continuing"));
}
}
SQLStatement statement = new SQLStatement(statement_action, sheet.getServerName(), table.getName(), pks, tid, sqlUpdate, fsm.getTableFilterParams(sheet.getServerName(), sqlUpdate), requerySelect);
// check that the row is updated (skip check for insert)
if (doesExistInDB)
statement.setExpectedUpdateCount(1);
if (changedColumns != null) {
statement.setChangedColumns(changedColumns.toArray(new String[changedColumns.size()]));
}
statement.setOracleFixTrackingData(usesLobs && !tracking);
statement.setIdentityColumn(dbPKReturnValues.size() == 0 ? null : dbPKReturnValues.get(0));
if (tracking || usesLobs) {
statement.setTrackingData(sheet.getColumnNames(), row.getRawOldColumnData() != null ? new Object[][] { row.getRawOldColumnData() } : null, row.getRawColumnData() != null ? new Object[][] { row.getRawColumnData() } : null, fsm.getApplication().getUserUID(), fsm.getTrackingInfo(), fsm.getApplication().getClientID());
}
return new RowUpdateInfo(row, statement, dbPKReturnValues, aggregatesToRemove);
} catch (RemoteException e) {
throw new RepositoryException(e);
}
}
Aggregations