use of com.servoy.j2db.query.QueryUpdate in project servoy-client by Servoy.
the class JSFoundSetUpdater method js_performUpdate.
/**
* Do the actual update in the database, returns true if successful. It will first try to save all editing records (from all foundsets), if cannot save will return false before doing the update.
* There are 3 types of possible use with the foundset updater
* 1) update entire foundset by a single sql statement; that is not possible when the table of the foundset has tracking enabled then it will loop over the whole foundset.
* When a single sql statement is done, modification columns will not be updated and associated Table Events won't be triggered, because it does the update directly in the database, without getting the records.
* NOTE: this mode will refresh all foundsets based on same datasource
* 2) update part of foundset, for example the first 4 row (starts with selected row)
* 3) safely loop through foundset (starts with selected row)
*
* after the perform update call there are no records in edit mode, that where not already in edit mode, because all of them are saved directly to the database,
* or in mode 1 the records are not touched at all and the database is updated directly.
*
* @sample
* //1) update entire foundset
* var fsUpdater = databaseManager.getFoundSetUpdater(foundset)
* fsUpdater.setColumn('customer_type',1)
* fsUpdater.setColumn('my_flag',0)
* fsUpdater.performUpdate()
*
* //2) update part of foundset, for example the first 4 row (starts with selected row)
* var fsUpdater = databaseManager.getFoundSetUpdater(foundset)
* fsUpdater.setColumn('customer_type',new Array(1,2,3,4))
* fsUpdater.setColumn('my_flag',new Array(1,0,1,0))
* fsUpdater.performUpdate()
*
* //3) safely loop through foundset (starts with selected row)
* controller.setSelectedIndex(1)
* var count = 0
* var fsUpdater = databaseManager.getFoundSetUpdater(foundset)
* while(fsUpdater.next())
* {
* fsUpdater.setColumn('my_flag',count++)
* }
*
* @return true if succeeded, false if failed.
*/
public boolean js_performUpdate() throws ServoyException {
if (list.size() == 0 || foundset.getTable() == null) {
return false;
}
if (!foundset.hasAccess(IRepository.UPDATE)) {
throw new ApplicationException(ServoyException.NO_MODIFY_ACCESS, new Object[] { foundset.getTable().getName() });
}
// first stop all edits, 'force' stop the edit by saying that it is a javascript stop
if (application.getFoundSetManager().getEditRecordList().stopEditing(true) != ISaveConstants.STOPPED)
return false;
try {
QuerySelect sqlParts;
IDataSet currentPKs;
synchronized (foundset.getPksAndRecords()) {
sqlParts = foundset.getPksAndRecords().getQuerySelectForReading();
currentPKs = foundset.getPksAndRecords().getPks();
}
FoundSetManager fsm = (FoundSetManager) application.getFoundSetManager();
if (rowsToUpdate == -1 && !foundset.hasAccess(IRepository.TRACKING) && sqlParts.getJoins() == null && // does not have join to other table
!fsm.hasTableFiltersWithJoins(foundset.getTable().getServerName(), sqlParts)) {
// all rows at once, via sql
Table table = (Table) foundset.getTable();
SQLSheet sheet = foundset.getSQLSheet();
QueryUpdate sqlUpdate = new QueryUpdate(sqlParts.getTable());
for (Pair<String, Object> p : list) {
String name = p.getLeft();
Object val = p.getRight();
int columnIndex = sheet.getColumnIndex(name);
VariableInfo variableInfo = sheet.getCalculationOrColumnVariableInfo(name, columnIndex);
if (// do not convert null to 0 incase of numbers, this means the calcs the value whould change each time //$NON-NLS-1$
val != null && !("".equals(val) && Column.mapToDefaultType(variableInfo.type) == IColumnTypes.TEXT)) {
val = sheet.convertObjectToValue(name, val, foundset.getFoundSetManager().getColumnConverterManager(), foundset.getFoundSetManager().getColumnValidatorManager(), null);
}
Column c = table.getColumn(name);
if (val == null) {
val = ValueFactory.createNullValue(c.getType());
}
sqlUpdate.addValue(c.queryColumn(sqlParts.getTable()), val);
}
sqlUpdate.setCondition(sqlParts.getWhereClone());
IDataSet pks;
boolean allFoundsetRecordsLoaded = currentPKs != null && currentPKs.getRowCount() <= fsm.config.pkChunkSize() && !currentPKs.hadMoreRows();
if (allFoundsetRecordsLoaded) {
pks = currentPKs;
} else {
pks = new BufferedDataSet();
pks.addRow(new Object[] { ValueFactory.createTableFlushValue() });
}
String transaction_id = fsm.getTransactionID(foundset.getSQLSheet());
try {
SQLStatement statement = new SQLStatement(ISQLActionTypes.UPDATE_ACTION, table.getServerName(), table.getName(), pks, transaction_id, sqlUpdate, fsm.getTableFilterParams(table.getServerName(), sqlUpdate));
if (allFoundsetRecordsLoaded) {
statement.setExpectedUpdateCount(pks.getRowCount());
}
Object[] results = fsm.getDataServer().performUpdates(fsm.getApplication().getClientID(), new ISQLStatement[] { statement });
for (int i = 0; results != null && i < results.length; i++) {
if (results[i] instanceof ServoyException) {
if (((ServoyException) results[i]).getErrorCode() == ServoyException.UNEXPECTED_UPDATE_COUNT) {
performLoopUpdate();
clear();
return true;
}
fsm.flushCachedDatabaseData(fsm.getDataSource(table));
throw (ServoyException) results[i];
}
}
fsm.flushCachedDatabaseData(fsm.getDataSource(table));
clear();
return true;
} catch (ApplicationException aex) {
if (allFoundsetRecordsLoaded || aex.getErrorCode() != ServoyException.RECORD_LOCKED) {
throw aex;
}
// a record was locked by another client, try per-record
Debug.log("foundsetUpdater could not update all records in 1 statement (a record may be locked), trying per-record");
}
}
performLoopUpdate();
} catch (Exception ex) {
// $NON-NLS-1$
application.handleException(// $NON-NLS-1$
application.getI18NMessage("servoy.foundsetupdater.updateFailed"), new ApplicationException(ServoyException.SAVE_FAILED, ex));
return false;
}
clear();
return true;
}
use of com.servoy.j2db.query.QueryUpdate in project servoy-client by Servoy.
the class SQLGenerator method createTableSQL.
private SQLSheet createTableSQL(String dataSource, boolean cache) throws ServoyException {
if (dataSource == null) {
return createNoTableSQL(cache);
}
Table table = (Table) application.getFoundSetManager().getTable(dataSource);
if (table == null) {
// $NON-NLS-1$
throw new RepositoryException("Cannot create sql: table not found for data source '" + dataSource + '\'');
}
SQLSheet retval = new SQLSheet(application, table.getServerName(), table);
// never remove this line, due to recursive behaviour, register a state when immediately!
if (cache)
cachedDataSourceSQLSheets.put(dataSource, retval);
QueryTable queryTable = new QueryTable(table.getSQLName(), table.getDataSource(), table.getCatalog(), table.getSchema());
QuerySelect select = new QuerySelect(queryTable);
QueryDelete delete = new QueryDelete(queryTable);
QueryInsert insert = new QueryInsert(queryTable);
QueryUpdate update = new QueryUpdate(queryTable);
List<Column> columns = new ArrayList<Column>();
Iterator<Column> it1 = table.getColumns().iterator();
while (it1.hasNext()) {
Column c = it1.next();
ColumnInfo ci = c.getColumnInfo();
if (ci != null && ci.isExcluded()) {
continue;
}
columns.add(c);
}
List<String> requiredDataProviderIDs = new ArrayList<String>();
Iterator<Column> pks = table.getRowIdentColumns().iterator();
if (!pks.hasNext()) {
throw new RepositoryException(ServoyException.InternalCodes.PRIMARY_KEY_NOT_FOUND, new Object[] { table.getName() });
}
List<QueryColumn> pkQueryColumns = new ArrayList<QueryColumn>();
while (pks.hasNext()) {
Column column = pks.next();
if (!columns.contains(column))
columns.add(column);
requiredDataProviderIDs.add(column.getDataProviderID());
pkQueryColumns.add(column.queryColumn(queryTable));
}
Iterator<Column> it2 = columns.iterator();
select.setColumns(makeQueryColumns(it2, queryTable, insert));
SetCondition pkSelect = new SetCondition(IBaseSQLCondition.EQUALS_OPERATOR, pkQueryColumns.toArray(new QueryColumn[pkQueryColumns.size()]), new Placeholder(new TablePlaceholderKey(queryTable, PLACEHOLDER_PRIMARY_KEY)), true);
select.setCondition(CONDITION_SEARCH, pkSelect);
delete.setCondition(deepClone(pkSelect));
update.setCondition(deepClone(pkSelect));
// fill dataprovider map
List<String> dataProviderIDsDilivery = new ArrayList<String>();
for (Column col : columns) {
dataProviderIDsDilivery.add(col.getDataProviderID());
}
retval.addSelect(select, dataProviderIDsDilivery, requiredDataProviderIDs, null);
retval.addDelete(delete, requiredDataProviderIDs);
retval.addInsert(insert, dataProviderIDsDilivery);
retval.addUpdate(update, dataProviderIDsDilivery, requiredDataProviderIDs);
// related stuff
createAggregates(retval, queryTable);
return retval;
}
use of com.servoy.j2db.query.QueryUpdate in project servoy-client by Servoy.
the class ViewFoundSet method doSave.
int doSave(ViewRecord record) {
int retCode = ISaveConstants.STOPPED;
List<ViewRecord> toSave = new ArrayList<>();
if (record == null) {
toSave.addAll(editedRecords);
} else {
if (record.isEditing())
toSave.add(record);
}
if (toSave.size() > 0) {
ArrayList<ViewRecord> processedRecords = new ArrayList<ViewRecord>();
try {
boolean previousRefresh = refresh;
String serverName = DataSourceUtils.getDataSourceServerName(select.getTable().getDataSource());
String transaction_id = manager.getTransactionID(serverName);
HashMap<SQLStatement, ViewRecord> statementToRecord = new HashMap<>();
List<SQLStatement> statements = new ArrayList<>();
for (ViewRecord rec : toSave) {
Map<String, Object> changes = rec.getChanges();
// directly just remove it from the edited records if we try to save it.
editedRecords.remove(rec);
if (changes == null)
continue;
Map<BaseQueryTable, Map<QueryColumn, Object>> tableToChanges = new IdentityHashMap<>();
columnNames.forEach((selectValue, name) -> {
if (changes.containsKey(name)) {
QueryColumn realColumn = select.getRealColumn(selectValue).orElseThrow(() -> {
RuntimeException ex = new RuntimeException("Can't save " + rec + " for changed values " + changes + " because table for column '" + name + "' cannot be found");
rec.setLastException(ex);
if (!failedRecords.contains(rec))
failedRecords.add(rec);
return ex;
});
BaseQueryTable table = realColumn.getTable();
Map<QueryColumn, Object> map = tableToChanges.get(table);
if (map == null) {
map = new HashMap<>();
tableToChanges.put(table, map);
}
map.put(realColumn, rec.getValue(name));
}
});
tableToChanges.forEach((table, changesMap) -> {
List<IQuerySelectValue> pkColumns = pkColumnsForTable.get(table);
if (pkColumns == null) {
RuntimeException ex = new RuntimeException("Can't save " + rec + " for changed values " + changes + " because there are no pk's found for table with changes " + table.getAlias() != null ? table.getAlias() : table.getName());
rec.setLastException(ex);
if (!failedRecords.contains(rec))
failedRecords.add(rec);
throw ex;
}
int counter = 0;
Object[] pk = new Object[pkColumns.size()];
QueryUpdate update = new QueryUpdate(table);
IQuerySelectValue[] queryPks = null;
try {
RowManager rowManager = manager.getRowManager(table.getDataSource());
if (rowManager != null) {
queryPks = getOrderedPkColumns(pkColumns, rowManager.getSQLSheet().getPKColumnDataProvidersAsArray());
}
} catch (Exception ex) {
Debug.error(ex);
}
if (queryPks == null)
queryPks = pkColumns.toArray(new IQuerySelectValue[0]);
for (IQuerySelectValue pkColumn : queryPks) {
Object pkValue = rec.getValue(columnNames.get(pkColumn));
update.addCondition(new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, pkColumn, pkValue));
pk[counter++] = pkValue;
}
IDataSet pks = new BufferedDataSet();
pks.addRow(pk);
counter = 0;
String[] changedColumns = new String[changes.size()];
for (Entry<QueryColumn, Object> entry : changesMap.entrySet()) {
QueryColumn column = entry.getKey();
update.addValue(column, entry.getValue());
changedColumns[counter++] = column.getName();
}
SQLStatement statement = new SQLStatement(ISQLActionTypes.UPDATE_ACTION, serverName, table.getName(), pks, transaction_id, update, manager.getTableFilterParams(serverName, update));
statement.setChangedColumns(changedColumns);
statement.setExpectedUpdateCount(1);
statements.add(statement);
statementToRecord.put(statement, rec);
});
JSRecordMarkers validateObject = validate(rec);
if (validateObject != null && validateObject.isHasErrors()) {
Object[] genericExceptions = validateObject.getGenericExceptions();
if (genericExceptions.length > 0) {
rec.setLastException((Exception) genericExceptions[0]);
}
if (!failedRecords.contains(rec)) {
failedRecords.add(rec);
retCode = ISaveConstants.SAVE_FAILED;
}
}
if (!failedRecords.contains(rec)) {
processedRecords.add(rec);
}
}
if (// if this is a save all call we don't save if we have failed records
toSave.size() > 1 && failedRecords.isEmpty() || // if this is a single record save, we just check if it is failed or not
toSave.size() == 1 && !failedRecords.contains(record)) {
Object[] updateResult = manager.getApplication().getDataServer().performUpdates(manager.getApplication().getClientID(), statements.toArray(new SQLStatement[statements.size()]));
for (int i = 0; i < updateResult.length; i++) {
// i of the updateResults should be the same for the statements;
ViewRecord rec = statementToRecord.remove(statements.get(i));
Object o = updateResult[i];
if (o instanceof Exception) {
// something went wrong
failedRecords.add(rec);
rec.setLastException((Exception) o);
retCode = ISaveConstants.SAVE_FAILED;
} else if (!statementToRecord.values().contains(rec) && !failedRecords.contains(rec)) {
rec.clearChanges();
}
}
for (SQLStatement statement : statements) {
manager.notifyDataChange(DataSourceUtils.createDBTableDataSource(statement.getServerName(), statement.getTableName()), statement.getPKsRow(0), ISQLActionTypes.UPDATE_ACTION, statement.getChangedColumns());
}
// do a load but only if there are listeners
if (previousRefresh && shouldRefresh() && foundSetEventListeners.size() > 0) {
loadAllRecordsImpl();
}
}
} catch (ServoyException | RemoteException e) {
Debug.error(e);
} finally {
if (!failedRecords.isEmpty()) {
processedRecords.stream().forEachOrdered(editedRecords::add);
}
}
}
return retCode;
}
use of com.servoy.j2db.query.QueryUpdate in project servoy-client by Servoy.
the class I18NUtil method writeMessagesToRepository.
public static void writeMessagesToRepository(String i18NServerName, String i18NTableName, IRepository repository, IDataServer dataServer, String clientID, TreeMap<String, MessageEntry> messages, boolean noUpdates, boolean noRemoves, TreeMap<String, MessageEntry> remoteMessages, String filterName, String[] filterValue, IFoundSetManagerInternal fm) throws Exception {
// get remote messages snapshot
if (remoteMessages == null)
remoteMessages = loadSortedMessagesFromRepository(repository, dataServer, clientID, i18NServerName, i18NTableName, filterName, filterValue, fm);
if (remoteMessages != null) {
IServer i18NServer = repository.getServer(i18NServerName);
Table i18NTable = null;
if (i18NServer != null) {
i18NTable = (Table) i18NServer.getTable(i18NTableName);
}
if (i18NTable != null) {
// runtime exception when no ident columns
Column pkColumn = i18NTable.getRowIdentColumns().get(0);
QueryTable messagesTable = new QueryTable(i18NTable.getSQLName(), i18NTable.getDataSource(), i18NTable.getCatalog(), i18NTable.getSchema());
QueryColumn pkCol = pkColumn.queryColumn(messagesTable);
QueryColumn msgLang = new QueryColumn(messagesTable, -1, "message_language", Types.VARCHAR, 150, 0, null, 0);
QueryColumn msgKey = new QueryColumn(messagesTable, -1, "message_key", Types.VARCHAR, 150, 0, null, 0);
QueryColumn msgVal = new QueryColumn(messagesTable, -1, "message_value", Types.VARCHAR, 2000, 0, null, 0);
ArrayList<SQLStatement> updateStatements = new ArrayList<SQLStatement>();
// go thorough messages, update exiting, add news to remote
// in case we need to insert a record, we must know if it is database managed or servoy managed
boolean logIdIsServoyManaged = false;
ColumnInfo ci = pkColumn.getColumnInfo();
if (ci != null) {
int autoEnterType = ci.getAutoEnterType();
int autoEnterSubType = ci.getAutoEnterSubType();
logIdIsServoyManaged = (autoEnterType == ColumnInfo.SEQUENCE_AUTO_ENTER) && (autoEnterSubType != ColumnInfo.NO_SEQUENCE_SELECTED) && (autoEnterSubType != ColumnInfo.DATABASE_IDENTITY);
}
List<Column> tenantColumns = i18NTable.getTenantColumns();
Iterator<Map.Entry<String, MessageEntry>> messagesIte = messages.entrySet().iterator();
Map.Entry<String, MessageEntry> messageEntry;
while (messagesIte.hasNext()) {
messageEntry = messagesIte.next();
String key = messageEntry.getKey();
String value = messageEntry.getValue().getValue();
String lang = messageEntry.getValue().getLanguage();
if (lang.equals(""))
lang = null;
String messageKey = messageEntry.getValue().getKey();
if (// insert
!remoteMessages.containsKey(key)) {
QueryInsert insert = new QueryInsert(messagesTable);
QueryColumn[] insertColumns = null;
Object[] insertColumnValues = null;
if (logIdIsServoyManaged) {
Object messageId = dataServer.getNextSequence(i18NServerName, i18NTableName, pkColumn.getName(), -1, i18NServerName);
if (lang == null) {
insertColumns = new QueryColumn[] { pkCol, msgKey, msgVal };
insertColumnValues = new Object[] { messageId, messageKey, value };
} else {
insertColumns = new QueryColumn[] { pkCol, msgKey, msgLang, msgVal };
insertColumnValues = new Object[] { messageId, messageKey, lang, value };
}
} else {
if (lang == null) {
insertColumns = new QueryColumn[] { msgKey, msgVal };
insertColumnValues = new Object[] { messageKey, value };
} else {
insertColumns = new QueryColumn[] { msgKey, msgLang, msgVal };
insertColumnValues = new Object[] { messageKey, lang, value };
}
}
Column filterColumn = i18NTable.getColumn(filterName);
if (filterColumn != null && filterValue != null && filterValue.length > 0) {
insertColumns = Utils.arrayAdd(insertColumns, filterColumn.queryColumn(messagesTable), true);
insertColumnValues = Utils.arrayAdd(insertColumnValues, filterValue[0], true);
}
insert.setColumnValues(insertColumns, insertColumnValues);
updateStatements.add(new SQLStatement(ISQLActionTypes.INSERT_ACTION, i18NServerName, i18NTableName, null, null, insert, null));
} else if (// update
!remoteMessages.get(key).getValue().equals(value) && !noUpdates) {
QueryUpdate update = new QueryUpdate(messagesTable);
update.addValue(msgVal, value);
update.addCondition(new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, msgKey, messageKey));
update.addCondition(new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, msgLang, lang));
if (filterName != null) {
Column filterColumn = i18NTable.getColumn(filterName);
if (filterColumn != null && filterValue != null && filterValue.length > 0) {
QueryColumn columnFilter = filterColumn.queryColumn(messagesTable);
CompareCondition cc = new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, columnFilter, new QueryColumnValue(filterValue[0], null));
// $NON-NLS-1$
update.addCondition("FILTER", cc);
}
}
// Add condition to update only records having the default tenant value (null)
for (Column column : tenantColumns) {
QueryColumn tenantColumn = column.queryColumn(messagesTable);
CompareCondition cc = new CompareCondition(IBaseSQLCondition.ISNULL_OPERATOR, tenantColumn, null);
update.addCondition(cc);
}
updateStatements.add(new SQLStatement(ISQLActionTypes.UPDATE_ACTION, i18NServerName, i18NTableName, null, null, update, fm != null ? fm.getTableFilterParams(i18NServerName, update) : null));
}
}
if (!noRemoves) {
// go thorough remote, remove if not existing locally
Iterator<Map.Entry<String, MessageEntry>> remoteMessagesIte = remoteMessages.entrySet().iterator();
Map.Entry<String, MessageEntry> remoteMessageEntry;
while (remoteMessagesIte.hasNext()) {
remoteMessageEntry = remoteMessagesIte.next();
String key = remoteMessageEntry.getKey();
if (// delete
!messages.containsKey(key)) {
String lang = remoteMessageEntry.getValue().getLanguage();
if (lang.equals(""))
lang = null;
String messageKey = remoteMessageEntry.getValue().getKey();
QueryDelete delete = new QueryDelete(messagesTable);
delete.addCondition(new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, msgKey, messageKey));
delete.addCondition(new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, msgLang, lang));
if (filterName != null) {
Column filterColumn = i18NTable.getColumn(filterName);
if (filterColumn != null && filterValue != null && filterValue.length > 0) {
QueryColumn columnFilter = filterColumn.queryColumn(messagesTable);
CompareCondition cc = new CompareCondition(IBaseSQLCondition.EQUALS_OPERATOR, columnFilter, new QueryColumnValue(filterValue[0], null));
delete.addCondition(cc);
}
}
// Add condition to remove only records having the default tenant value (null)
for (Column column : tenantColumns) {
QueryColumn tenantColumn = column.queryColumn(messagesTable);
CompareCondition cc = new CompareCondition(IBaseSQLCondition.ISNULL_OPERATOR, tenantColumn, null);
delete.addCondition(cc);
}
updateStatements.add(new SQLStatement(ISQLActionTypes.DELETE_ACTION, i18NServerName, i18NTableName, null, null, delete, fm != null ? fm.getTableFilterParams(i18NServerName, delete) : null));
}
}
}
for (SQLStatement st : updateStatements) {
st.setDataType(ISQLStatement.I18N_DATA_TYPE);
}
dataServer.performUpdates(clientID, updateStatements.toArray(new ISQLStatement[updateStatements.size()]));
}
}
}
use of com.servoy.j2db.query.QueryUpdate 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