use of com.servoy.j2db.persistence.Column in project servoy-client by Servoy.
the class JSDatabaseManager method js_getSQL.
/**
* Returns the internal SQL which defines the specified (related)foundset.
* Optionally, the foundset and table filter params can be excluded in the sql (includeFilters=false).
* Make sure to set the applicable filters when the sql is used in a loadRecords() call.
* When the founset is in find mode, the find conditions are included in the resulting query.
*
* @sample var sql = databaseManager.getSQL(foundset)
*
* @param foundsetOrQBSelect The JSFoundset or QBSelect to get the sql for.
* @param includeFilters include the foundset and table filters.
*
* @return String representing the sql of the JSFoundset.
*/
public String js_getSQL(Object foundsetOrQBSelect, boolean includeFilters) throws ServoyException {
checkAuthorized();
if (foundsetOrQBSelect instanceof IFoundSetInternal && ((IFoundSetInternal) foundsetOrQBSelect).getTable() != null) {
try {
QuerySet querySet = getQuerySet(((IFoundSetInternal) foundsetOrQBSelect).getCurrentStateQuery(true, false), includeFilters);
StringBuilder sql = new StringBuilder();
QueryString[] prepares = querySet.getPrepares();
for (int i = 0; prepares != null && i < prepares.length; i++) {
// TODO parameters from updates and cleanups
// sql.append(updates[i].getSql());
// sql.append("\n"); //$NON-NLS-1$
}
sql.append(querySet.getSelect().getSql());
QueryString[] cleanups = querySet.getCleanups();
for (int i = 0; cleanups != null && i < cleanups.length; i++) {
// TODO parameters from updates and cleanups
// sql.append("\n"); //$NON-NLS-1$
// sql.append(cleanups[i].getSql());
}
return sql.toString();
} catch (Exception e) {
Debug.error(e);
}
} else if (foundsetOrQBSelect instanceof QBSelect) {
try {
QuerySelect select = ((QBSelect) foundsetOrQBSelect).build();
if (select.getColumns() == null) {
// no columns, add pk
// note that QBSelect.build() already returns a clone
ITable table = application.getFoundSetManager().getTable(select.getTable().getDataSource());
Iterator<Column> pkIt = ((Table) table).getRowIdentColumns().iterator();
if (!pkIt.hasNext()) {
throw new RepositoryException(ServoyException.InternalCodes.PRIMARY_KEY_NOT_FOUND, new Object[] { table.getName() });
}
while (pkIt.hasNext()) {
Column c = pkIt.next();
select.addColumn(c.queryColumn(select.getTable()));
}
}
QuerySet querySet = getQuerySet(select, includeFilters);
return querySet.getSelect().getSql();
} catch (RemoteException e) {
Debug.error(e);
}
}
return null;
}
use of com.servoy.j2db.persistence.Column in project servoy-client by Servoy.
the class JSDatabaseManager method js_convertToDataSet.
/**
* @clonedesc js_convertToDataSet(IFoundSetInternal)
*
* @sampleas js_convertToDataSet(IFoundSetInternal)
*
* @param foundset The foundset to be converted.
* @param dataproviderNames Array with column names.
*
* @return JSDataSet with the data.
*/
public JSDataSet js_convertToDataSet(IFoundSetInternal foundset, String[] dataproviderNames) throws RepositoryException {
if (foundset == null) {
return null;
}
// $NON-NLS-1$
String[] dpnames = { "id" };
ColumnType[] dptypes = { ColumnType.getInstance(IColumnTypes.INTEGER, Integer.MAX_VALUE, 0) };
List<Object[]> lst = new ArrayList<Object[]>();
FoundSet fs = (FoundSet) foundset;
if (fs.getTable() != null) {
if (dataproviderNames != null) {
dpnames = dataproviderNames;
} else {
dpnames = fs.getSQLSheet().getPKColumnDataProvidersAsArray();
}
FoundSetManager fsm = (FoundSetManager) application.getFoundSetManager();
boolean getInOneQuery = !fs.isInFindMode() && (fs.hadMoreRows() || fs.getSize() > fsm.config.pkChunkSize()) && !fsm.getEditRecordList().hasEditedRecords(fs);
dptypes = new ColumnType[dpnames.length];
Table table = fs.getSQLSheet().getTable();
Map<String, Column> columnMap = new HashMap<String, Column>();
for (int i = 0; i < dpnames.length; i++) {
IDataProvider dp = application.getFlattenedSolution().getDataProviderForTable(table, dpnames[i]);
dptypes[i] = dp == null ? ColumnType.getInstance(0, 0, 0) : ColumnType.getInstance(dp instanceof Column ? ((Column) dp).getType() : dp.getDataProviderType(), dp.getLength(), dp instanceof Column ? ((Column) dp).getScale() : 0);
if (getInOneQuery) {
// only columns and data we can get from the foundset (calculations only when stored)
if (dp instanceof Column) {
columnMap.put(dpnames[i], (Column) dp);
// Blobs require special resultset handling
getInOneQuery = !SQLGenerator.isBlobColumn((Column) dp);
} else {
// aggregates, globals
getInOneQuery = fs.containsDataProvider(dpnames[i]);
}
}
}
if (getInOneQuery && columnMap.size() > 0) {
// large foundset, query the columns in 1 go
QuerySelect sqlSelect = AbstractBaseQuery.deepClone(fs.getQuerySelectForReading());
ArrayList<IQuerySelectValue> cols = new ArrayList<IQuerySelectValue>(columnMap.size());
ArrayList<String> distinctColumns = new ArrayList<String>(columnMap.size());
for (String dpname : dpnames) {
Column column = columnMap.get(dpname);
if (column != null && !distinctColumns.contains(dpname)) {
distinctColumns.add(dpname);
cols.add(column.queryColumn(sqlSelect.getTable()));
}
}
boolean hasJoins = sqlSelect.getJoins() != null;
if (hasJoins) {
// add pk columns so distinct-in-memory can be used
List<Column> rowIdentColumns = ((Table) fs.getTable()).getRowIdentColumns();
for (Column column : rowIdentColumns) {
if (!columnMap.containsKey(column.getDataProviderID())) {
cols.add(column.queryColumn(sqlSelect.getTable()));
}
}
}
sqlSelect.setColumns(cols);
try {
SQLSheet sheet = fs.getSQLSheet();
IConverterManager<IColumnConverter> columnConverterManager = ((FoundSetManager) fs.getFoundSetManager()).getColumnConverterManager();
SQLStatement trackingInfo = null;
if (fsm.getEditRecordList().hasAccess(sheet.getTable(), IRepository.TRACKING_VIEWS)) {
trackingInfo = new SQLStatement(ISQLActionTypes.SELECT_ACTION, sheet.getServerName(), sheet.getTable().getName(), null, null);
trackingInfo.setTrackingData(sqlSelect.getColumnNames(), new Object[][] {}, new Object[][] {}, fsm.getApplication().getUserUID(), fsm.getTrackingInfo(), fsm.getApplication().getClientID());
}
IDataSet dataSet = fsm.getDataServer().performQuery(fsm.getApplication().getClientID(), sheet.getServerName(), fsm.getTransactionID(sheet), sqlSelect, null, fsm.getTableFilterParams(sheet.getServerName(), sqlSelect), hasJoins, 0, -1, IDataServer.FOUNDSET_LOAD_QUERY, trackingInfo);
lst = new ArrayList<Object[]>(dataSet.getRowCount());
for (int i = 0; i < dataSet.getRowCount(); i++) {
Object[] row = new Object[dpnames.length];
// may contain more data: pk columns for distinct-in-memory
Object[] dataseRow = dataSet.getRow(i);
for (int j = 0; j < dpnames.length; j++) {
Column column = columnMap.get(dpnames[j]);
if (column == null) {
// fs.containsDataProvider returned true for this dpname
row[j] = fs.getDataProviderValue(dpnames[j]);
} else {
row[j] = sheet.convertValueToObject(dataseRow[distinctColumns.indexOf(dpnames[j])], sheet.getColumnIndex(dpnames[j]), columnConverterManager);
}
}
lst.add(row);
}
} catch (RepositoryException e) {
throw e;
} catch (Exception e) {
Debug.error(e);
throw new RepositoryException(e.getMessage());
}
} else {
// loop over the records
for (int i = 0; i < fs.getSize(); i++) {
IRecordInternal record = fs.getRecord(i);
Object[] pk = new Object[dpnames.length];
for (int j = 0; j < dpnames.length; j++) {
pk[j] = record.getValue(dpnames[j]);
}
lst.add(pk);
}
}
}
return new JSDataSet(application, BufferedDataSetInternal.createBufferedDataSet(dpnames, dptypes, lst, false));
}
use of com.servoy.j2db.persistence.Column in project servoy-client by Servoy.
the class EditRecordList method stopEditingImpl.
/**
* This method should only be called through stopEditing(boolean,List<Record>) so that that can call onAutoSaveFailed.
*/
private int stopEditingImpl(final boolean javascriptStop, List<IRecord> recordsToSave, int recursionDepth) {
if (recursionDepth > 50) {
fsm.getApplication().reportJSError("stopEditing max recursion exceeded, look if on (or after) record update or inserts are constantly changing records", new RuntimeException());
return ISaveConstants.SAVE_FAILED;
}
if (ignoreSave) {
return ISaveConstants.AUTO_SAVE_BLOCKED;
}
if (isSavingAll) {
// we are saving all, no need to save anything more
return ISaveConstants.STOPPED;
}
if (recordsToSave == null && savingRecords.size() > 0) {
// we are saving some records, cannot call save all now, not supported
return ISaveConstants.STOPPED;
}
if (recordsToSave != null && savingRecords.size() > 0) {
// make a copy to be sure that removeAll is supported
recordsToSave = new ArrayList<IRecord>(recordsToSave);
recordsToSave.removeAll(savingRecords);
}
if (recordsToSave != null) {
boolean hasEditedRecords = false;
editRecordsLock.lock();
try {
for (IRecord record : recordsToSave) {
if (editedRecords.contains(record)) {
hasEditedRecords = true;
break;
}
}
} finally {
editRecordsLock.unlock();
}
if (!hasEditedRecords)
return ISaveConstants.STOPPED;
}
// here we can't have a test if editedRecords is empty (and return stop)
// because for just globals or findstates (or deleted records)
// we need to pass prepareForSave.
final List<IRecord> recordsToSaveFinal = recordsToSave;
if (!fsm.getApplication().isEventDispatchThread()) {
// only the event dispatch thread can stop an current edit.
// this is a fix for innerworkings because background aggregate queries seems to also trigger saves
// $NON-NLS-1$
Debug.trace("Stop edit postponend because it is not in the event dispatch thread: " + Thread.currentThread().getName());
// calculations running from lazy table view loading threads may trigger stopEditing
fsm.getApplication().invokeLater(new Runnable() {
public void run() {
// do not stop if the user is editing something else.
boolean stop;
editRecordsLock.lock();
try {
stop = editedRecords.size() == 1 && recordsToSaveFinal != null && recordsToSaveFinal.size() == 1 && editedRecords.get(0) == recordsToSaveFinal.get(0);
} finally {
editRecordsLock.unlock();
}
if (stop) {
stopEditing(javascriptStop, recordsToSaveFinal);
} else {
// $NON-NLS-1$
Debug.trace("Stop edit skipped because other records are being edited");
}
}
});
return ISaveConstants.AUTO_SAVE_BLOCKED;
}
int editedRecordsSize;
try {
int p = prepareForSave(true);
if (p != ISaveConstants.STOPPED) {
return p;
}
if (recordsToSave == null) {
isSavingAll = true;
} else {
savingRecords.addAll(recordsToSave);
}
// remove any non referenced failed records
boolean fireChange = false;
editRecordsLock.lock();
try {
if (failedRecords.size() != 0) {
Iterator<IRecordInternal> it = failedRecords.iterator();
while (it.hasNext()) {
IRecordInternal rec = it.next();
if (rec != null) {
if (rec.getParentFoundSet() == null) {
it.remove();
} else if (rec.getParentFoundSet().getRecordIndex(rec) == -1) {
it.remove();
}
}
}
if (failedRecords.size() == 0) {
fireChange = true;
}
}
} finally {
editRecordsLock.unlock();
}
if (fireChange)
fireEditChange();
// remove the unchanged, really calculate when it is a real stop (autosave = true or it is a javascript stop)
removeUnChangedRecords(autoSave || javascriptStop, true);
// check if anything left
int editRecordListSize;
editRecordsLock.lock();
try {
editRecordListSize = editedRecords.size();
if (editRecordListSize == 0)
return ISaveConstants.STOPPED;
} finally {
editRecordsLock.unlock();
}
// cannot stop, its blocked
if (!autoSave && !javascriptStop) {
return ISaveConstants.AUTO_SAVE_BLOCKED;
}
int failedCount = 0;
boolean justValidationErrors = false;
lastStopEditingException = null;
List<RowUpdateInfo> rowUpdates = new ArrayList<RowUpdateInfo>(editRecordListSize);
editRecordsLock.lock();
try {
if (recordsToSave == null) {
// if it is a save all, then first filter out all the duplicate rows.
for (int i = 0; i < editedRecords.size(); i++) {
Row toTest = editedRecords.get(i).getRawData();
for (int j = editedRecords.size(); --j > i; ) {
if (editedRecords.get(j).getRawData() == toTest) {
removeEditedRecord(editedRecords.get(j));
}
}
}
}
Map<IRecordInternal, Integer> processed = new HashMap<IRecordInternal, Integer>();
for (IRecordInternal tmp = getFirstElement(editedRecords, recordsToSave); tmp != null; tmp = getFirstElement(editedRecords, recordsToSave)) {
// check if we do not have an infinite recursive loop
Integer count = processed.get(tmp);
if (count != null && count.intValue() > 50) {
fsm.getApplication().reportJSError("stopEditing max loop counter exceeded on " + tmp.getParentFoundSet().getDataSource() + "/" + tmp.getPKHashKey(), new RuntimeException());
return ISaveConstants.SAVE_FAILED;
}
processed.put(tmp, Integer.valueOf(count == null ? 1 : (count.intValue() + 1)));
if (tmp instanceof Record) {
Record record = (Record) tmp;
// prevent multiple update for the same row (from multiple records)
for (int j = 0; j < rowUpdates.size(); j++) {
if (rowUpdates.get(j).getRow() == record.getRawData()) {
// create a new rowUpdate that contains both updates
RowUpdateInfo removed = rowUpdates.remove(j);
recordTested.remove(record);
// do use the first record, that one must always be leading. (for fire of events)
record = removed.getRecord();
break;
}
}
try {
// test for table events; this may execute table events if the user attached JS methods to them;
// the user might add/delete/edit records in the JS - thus invalidating a normal iterator (it)
// - edited record list changes; this is why an AllowListModificationIterator is used
// Note that the behaviour is different when trigger returns false or when it throws an exception.
// when the trigger returns false, record must stay in editedRecords.
// this is needed because the trigger may be used as validation to keep the user in the record when autosave=true.
// when the trigger throws an exception, the record must move from editedRecords to failedRecords so that in
// scripting the failed records can be examined (the thrown value is retrieved via record.exception.getValue())
editRecordsLock.unlock();
boolean validationErrors = false;
try {
JSRecordMarkers validateObject = fsm.validateRecord(record, null);
if (// throws ServoyException when trigger method throws exception
validateObject != null && validateObject.isHasErrors()) {
Object[] genericExceptions = validateObject.getGenericExceptions();
if (genericExceptions.length > 0) {
// compartible with old code, then those exceptions are catched below.
throw (Exception) genericExceptions[0];
}
// we always want to process all records, but mark this as a validation error so below the failed records are updated.
validationErrors = true;
// update the just failed boolean to true, if that is true and there is not really an exception then handleException of application is not called.
justValidationErrors = true;
failedCount++;
if (!failedRecords.contains(record)) {
failedRecords.add(record);
}
recordTested.remove(record);
}
} finally {
editRecordsLock.lock();
}
if (!validationErrors) {
RowUpdateInfo rowUpdateInfo = getRecordUpdateInfo(record);
if (rowUpdateInfo != null) {
rowUpdateInfo.setRecord(record);
rowUpdates.add(rowUpdateInfo);
} else {
recordTested.remove(record);
}
}
} catch (ServoyException e) {
// $NON-NLS-1$//$NON-NLS-2$
log.debug(// $NON-NLS-1$//$NON-NLS-2$
"stopEditing(" + javascriptStop + ") encountered an exception - could be expected and treated by solution code or not", e);
// trigger method threw exception
lastStopEditingException = e;
failedCount++;
// set latest
record.getRawData().setLastException(e);
if (!failedRecords.contains(record)) {
failedRecords.add(record);
}
recordTested.remove(record);
} catch (Exception e) {
// $NON-NLS-1$ //$NON-NLS-2$
Debug.error("Not a normal Servoy/Db Exception generated in saving record: " + record + " removing the record", e);
recordTested.remove(record);
}
} else {
// find state
recordTested.remove(tmp);
}
editedRecords.remove(tmp);
}
} finally {
editRecordsLock.unlock();
}
if (failedCount > 0) {
placeBackAlreadyProcessedRecords(rowUpdates);
if (lastStopEditingException == null && justValidationErrors) {
return ISaveConstants.VALIDATION_FAILED;
} else {
if (!(lastStopEditingException instanceof ServoyException)) {
lastStopEditingException = new ApplicationException(ServoyException.SAVE_FAILED, lastStopEditingException);
}
if (!javascriptStop)
// $NON-NLS-1$
fsm.getApplication().handleException(// $NON-NLS-1$
fsm.getApplication().getI18NMessage("servoy.formPanel.error.saveFormData"), lastStopEditingException);
return ISaveConstants.SAVE_FAILED;
}
}
if (rowUpdates.size() == 0) {
fireEditChange();
if (Debug.tracing()) {
// $NON-NLS-1$
Debug.trace("no records to update anymore, failed: " + failedRecords.size());
}
return ISaveConstants.STOPPED;
}
if (Debug.tracing()) {
// $NON-NLS-1$ //$NON-NLS-2$
Debug.trace("Updating/Inserting " + rowUpdates.size() + " records: " + rowUpdates.toString());
}
RowUpdateInfo[] infos = rowUpdates.toArray(new RowUpdateInfo[rowUpdates.size()]);
if (infos.length > 1 && !fsm.config.disableInsertsReorder()) {
// search if there are new row pks used that are
// used in records before this record and sort it based on that.
boolean changed = false;
List<RowUpdateInfo> al = new ArrayList<RowUpdateInfo>(Arrays.asList(infos));
int prevI = -1;
outer: for (int i = al.size(); --i > 0; ) {
Row row = al.get(i).getRow();
// only test for new rows and its pks.
if (row.existInDB())
continue;
String[] pkColumns = row.getRowManager().getSQLSheet().getPKColumnDataProvidersAsArray();
Object[] pk = row.getPK();
for (int j = 0; j < pk.length; j++) {
Object pkObject = pk[j];
// special case if pk was db ident and that value was copied from another row.
if (pkObject instanceof DbIdentValue && ((DbIdentValue) pkObject).getRow() != row)
continue;
for (int k = 0; k < i; k++) {
RowUpdateInfo updateInfo = al.get(k);
Object[] values = updateInfo.getRow().getRawColumnData();
int[] pkIndexes = updateInfo.getFoundSet().getSQLSheet().getPKIndexes();
IntHashMap<String> pks = new IntHashMap<String>(pkIndexes.length, 1);
for (int pkIndex : pkIndexes) {
// $NON-NLS-1$
pks.put(pkIndex, "");
}
for (int l = 0; l < values.length; l++) {
// skip all pk column indexes (except from dbidents from other rows, this may need resort). Those shouldn't be resorted
if (!(values[l] instanceof DbIdentValue && ((DbIdentValue) values[l]).getRow() != updateInfo.getRow()) && pks.containsKey(l))
continue;
boolean same = values[l] == pkObject;
if (!same && values[l] != null) {
Column pkColumn = row.getRowManager().getSQLSheet().getTable().getColumn(pkColumns[j]);
if (pkColumn.hasFlag(IBaseColumn.UUID_COLUMN)) {
// same uuids are the same even if not the same object
same = equalObjects(pkObject, values[l], 0, true);
}
}
if (same) {
al.add(k, al.remove(i));
// watch out for endless loops when 2 records both with pk's point to each other...
if (prevI != i) {
prevI = i;
i++;
}
changed = true;
continue outer;
}
}
}
}
}
if (changed) {
infos = al.toArray(infos);
}
}
ISQLStatement[] statements;
if (fsm.config.statementBatching() && infos.length > 1) {
// Merge insert statements insert statements from all info's: multiple info's can share the same statement of the records are batched together on the statement level
List<ISQLStatement> mergedStatements = new ArrayList<ISQLStatement>(infos.length);
ISQLStatement prevStatement = null;
for (RowUpdateInfo rowUpdateInfo : infos) {
ISQLStatement statement = rowUpdateInfo.getISQLStatement();
if (statement.getAction() == ISQLActionTypes.INSERT_ACTION && prevStatement != null && prevStatement.getAction() == ISQLActionTypes.INSERT_ACTION && insertStatementsCanBeMerged(prevStatement, statement)) {
mergeInsertStatements(prevStatement, statement);
} else {
prevStatement = statement;
mergedStatements.add(statement);
}
}
statements = mergedStatements.toArray(new ISQLStatement[mergedStatements.size()]);
} else {
statements = stream(infos).map(RowUpdateInfo::getISQLStatement).toArray(ISQLStatement[]::new);
}
// TODO if one statement fails in a transaction how do we know which one? and should we rollback all rows in these statements?
Object[] idents = null;
try {
idents = fsm.getDataServer().performUpdates(fsm.getApplication().getClientID(), statements);
} catch (Exception e) {
// $NON-NLS-1$//$NON-NLS-2$
log.debug("stopEditing(" + javascriptStop + ") encountered an exception - could be expected and treated by solution code or not", e);
lastStopEditingException = e;
if (!javascriptStop)
// $NON-NLS-1$
fsm.getApplication().handleException(// $NON-NLS-1$
fsm.getApplication().getI18NMessage("servoy.formPanel.error.saveFormData"), new ApplicationException(ServoyException.SAVE_FAILED, lastStopEditingException));
return ISaveConstants.SAVE_FAILED;
}
if (idents.length != infos.length) {
// $NON-NLS-1$
Debug.error("Should be of same size!!");
}
List<RowUpdateInfo> infosToBePostProcessed = new ArrayList<RowUpdateInfo>();
Map<FoundSet, List<Record>> foundsetToRecords = new HashMap<FoundSet, List<Record>>();
Map<FoundSet, List<String>> foundsetToAggregateDeletes = new HashMap<FoundSet, List<String>>();
List<Runnable> fires = new ArrayList<Runnable>(infos.length);
// Walk in reverse over it, so that related rows are update in there row manger before they are required by there parents.
for (int i = infos.length; --i >= 0; ) {
RowUpdateInfo rowUpdateInfo = infos[i];
FoundSet foundSet = rowUpdateInfo.getFoundSet();
Row row = rowUpdateInfo.getRow();
String oldKey = row.getPKHashKey();
Record record = rowUpdateInfo.getRecord();
if (idents != null && idents.length != 0 && idents[i] != null) {
Object retValue = idents[i];
if (retValue instanceof Exception) {
// $NON-NLS-1$//$NON-NLS-2$
log.debug(// $NON-NLS-1$//$NON-NLS-2$
"stopEditing(" + javascriptStop + ") encountered an exception - could be expected and treated by solution code or not", (Exception) retValue);
lastStopEditingException = (Exception) retValue;
failedCount++;
if (retValue instanceof ServoyException) {
((ServoyException) retValue).fillScriptStack();
}
row.setLastException((Exception) retValue);
markRecordAsFailed(record);
JSRecordMarkers vo = record.getRecordMarkers() != null ? record.getRecordMarkers() : new JSRecordMarkers(record, fsm.getApplication());
vo.addGenericException((Exception) retValue);
record.setRecordMarkers(vo);
continue;
} else if (retValue instanceof Object[]) {
Object[] rowData = (Object[]) retValue;
Object[] oldRowData = row.getRawColumnData();
if (oldRowData != null) {
if (oldRowData.length == rowData.length) {
for (int j = 0; j < rowData.length; j++) {
if (rowData[j] instanceof BlobMarkerValue) {
rowData[j] = oldRowData[j];
}
if (oldRowData[j] instanceof DbIdentValue) {
row.setDbIdentValue(rowData[j]);
}
}
} else {
Debug.error("Requery data has different length from row data.");
}
}
row.setRollbackData(rowData, Row.ROLLBACK_MODE.UPDATE_CHANGES);
} else if (!Boolean.TRUE.equals(retValue)) {
// is db ident, can only be one column
row.setDbIdentValue(retValue);
}
}
editRecordsLock.lock();
try {
recordTested.remove(record);
} finally {
editRecordsLock.unlock();
}
if (!row.existInDB()) {
// when row was not saved yet row pkhash will be with new value, pksAndRecordsHolder will have initial value
foundSet.updatePk(record);
}
try {
ISQLStatement statement = rowUpdateInfo.getISQLStatement();
row.getRowManager().rowUpdated(row, oldKey, foundSet, fires, statement instanceof ITrackingSQLStatement ? ((ITrackingSQLStatement) statement).getChangedColumns() : null);
} catch (Exception e) {
// $NON-NLS-1$//$NON-NLS-2$
log.debug("stopEditing(" + javascriptStop + ") encountered an exception - could be expected and treated by solution code or not", e);
lastStopEditingException = e;
failedCount++;
row.setLastException(e);
JSRecordMarkers vo = record.getRecordMarkers() != null ? record.getRecordMarkers() : new JSRecordMarkers(record, fsm.getApplication());
vo.addGenericException(e);
record.setRecordMarkers(vo);
editRecordsLock.lock();
try {
if (!failedRecords.contains(record)) {
failedRecords.add(record);
}
} finally {
editRecordsLock.unlock();
}
}
infosToBePostProcessed.add(infos[i]);
List<Record> lst = foundsetToRecords.get(foundSet);
if (lst == null) {
lst = new ArrayList<Record>(3);
foundsetToRecords.put(foundSet, lst);
}
lst.add(record);
List<String> aggregates = foundsetToAggregateDeletes.get(foundSet);
if (aggregates == null) {
foundsetToAggregateDeletes.put(foundSet, rowUpdateInfo.getAggregatesToRemove());
} else {
List<String> toMerge = rowUpdateInfo.getAggregatesToRemove();
for (int j = 0; j < toMerge.size(); j++) {
String aggregate = toMerge.get(j);
if (!aggregates.contains(aggregate)) {
aggregates.add(aggregate);
}
}
}
}
// run rowmanager fires in reverse order (original order because info's were processed in reverse order) -> first inserted record is fired first
for (int i = fires.size(); --i >= 0; ) {
fires.get(i).run();
}
// get the size of the edited records before the table events, so that we can look if those events did change records again.
editedRecordsSize = editedRecords.size();
Record rowUpdateInfoRecord = null;
for (RowUpdateInfo rowUpdateInfo : infosToBePostProcessed) {
try {
rowUpdateInfoRecord = rowUpdateInfo.getRecord();
((FoundSet) rowUpdateInfoRecord.getParentFoundSet()).executeFoundsetTrigger(new Object[] { rowUpdateInfoRecord }, rowUpdateInfo.getISQLStatement().getAction() == ISQLActionTypes.INSERT_ACTION ? StaticContentSpecLoader.PROPERTY_ONAFTERINSERTMETHODID : StaticContentSpecLoader.PROPERTY_ONAFTERUPDATEMETHODID, true);
} catch (ServoyException e) {
if (e instanceof DataException && e.getCause() instanceof JavaScriptException) {
// trigger method threw exception
// $NON-NLS-1$//$NON-NLS-2$
log.debug("stopEditing(" + javascriptStop + ") encountered an exception - could be expected and treated by solution code or not", e);
lastStopEditingException = e;
failedCount++;
rowUpdateInfoRecord.getRawData().setLastException(e);
JSRecordMarkers vo = rowUpdateInfoRecord.getRecordMarkers() != null ? rowUpdateInfoRecord.getRecordMarkers() : new JSRecordMarkers(rowUpdateInfoRecord, fsm.getApplication());
vo.addGenericException(e);
rowUpdateInfoRecord.setRecordMarkers(vo);
editRecordsLock.lock();
try {
if (!failedRecords.contains(rowUpdateInfoRecord)) {
failedRecords.add(rowUpdateInfoRecord);
}
} finally {
editRecordsLock.unlock();
}
} else {
// $NON-NLS-1$
fsm.getApplication().handleException("Failed to execute after update/insert trigger.", e);
}
}
}
for (Map.Entry<FoundSet, List<Record>> entry : foundsetToRecords.entrySet()) {
FoundSet fs = entry.getKey();
fs.recordsUpdated(entry.getValue(), foundsetToAggregateDeletes.get(fs));
}
boolean shouldFireEditChange;
editRecordsLock.lock();
try {
shouldFireEditChange = editedRecords.size() == 0;
} finally {
editRecordsLock.unlock();
}
if (shouldFireEditChange) {
fireEditChange();
}
if (failedCount > 0) {
if (!javascriptStop) {
lastStopEditingException = new ApplicationException(ServoyException.SAVE_FAILED, lastStopEditingException);
// $NON-NLS-1$
fsm.getApplication().handleException(// $NON-NLS-1$
fsm.getApplication().getI18NMessage("servoy.formPanel.error.saveFormData"), lastStopEditingException);
}
return ISaveConstants.SAVE_FAILED;
}
} catch (RuntimeException e) {
if (e instanceof IllegalArgumentException) {
fsm.getApplication().handleException(null, new ApplicationException(ServoyException.INVALID_INPUT, e));
return ISaveConstants.SAVE_FAILED;
} else if (e instanceof IllegalStateException) {
// $NON-NLS-1$
fsm.getApplication().handleException(fsm.getApplication().getI18NMessage("servoy.formPanel.error.saveFormData"), e);
return ISaveConstants.SAVE_FAILED;
} else {
Debug.error(e);
throw e;
}
} finally {
if (recordsToSave == null) {
isSavingAll = false;
} else {
savingRecords.removeAll(recordsToSave);
}
fireEvents();
}
if (editedRecords.size() != editedRecordsSize && recordsToSave == null) {
// records where changed by the after insert/update table events, call stop edit again if this was not a specific record save.
return stopEditingImpl(javascriptStop, null, recursionDepth + 1);
}
return ISaveConstants.STOPPED;
}
use of com.servoy.j2db.persistence.Column in project servoy-client by Servoy.
the class DBValueList method getDisplayFormat.
private String[] getDisplayFormat() {
if (table != null && hasRealValues()) {
String[] displayFormats = new String[3];
boolean hasDisplayFormats = false;
Column col1 = table.getColumn(valueList.getDataProviderID1());
if (col1 != null && col1.getColumnInfo() != null) {
displayFormats[0] = col1.getColumnInfo().getDefaultFormat();
hasDisplayFormats = displayFormats[0] != null;
}
Column col2 = table.getColumn(valueList.getDataProviderID2());
if (col2 != null && col2.getColumnInfo() != null) {
displayFormats[1] = col2.getColumnInfo().getDefaultFormat();
hasDisplayFormats = displayFormats[1] != null;
}
Column col3 = table.getColumn(valueList.getDataProviderID3());
if (col3 != null && col3.getColumnInfo() != null) {
displayFormats[2] = col3.getColumnInfo().getDefaultFormat();
hasDisplayFormats = displayFormats[2] != null;
}
return hasDisplayFormats ? displayFormats : null;
}
return null;
}
use of com.servoy.j2db.persistence.Column in project servoy-client by Servoy.
the class JSDatabaseManager method convertFoundSet.
public FoundSet convertFoundSet(Object foundset, Object related) throws ServoyException {
checkAuthorized();
if (foundset instanceof FoundSet && ((FoundSet) foundset).getTable() != null) {
FoundSet fs_old = (FoundSet) foundset;
try {
String relationName;
if (related instanceof RelatedFoundSet) {
relationName = ((RelatedFoundSet) related).getRelationName();
} else if (related instanceof String) {
relationName = (String) related;
} else {
// $NON-NLS-1$
Debug.warn("convertFoundSet: invalid argument " + related);
return null;
}
Relation relation = application.getFlattenedSolution().getRelation(relationName);
if (relation == null || relation.isMultiServer() || fs_old.getTable() == null || !fs_old.getTable().equals(application.getFlattenedSolution().getTable(relation.getPrimaryDataSource()))) {
// $NON-NLS-1$
Debug.warn("convertFoundSet: cannot use relation " + relationName);
return null;
}
ITable ft = application.getFlattenedSolution().getTable(relation.getForeignDataSource());
FoundSet fs_new = (FoundSet) application.getFoundSetManager().getNewFoundSet(ft, null, application.getFoundSetManager().getDefaultPKSortColumns(ft.getDataSource()));
QuerySelect sql = fs_old.getPksAndRecords().getQuerySelectForModification();
SQLSheet sheet_new = fs_old.getSQLSheet().getRelatedSheet(relation, ((FoundSetManager) application.getFoundSetManager()).getSQLGenerator());
if (sheet_new != null) {
BaseQueryTable oldTable = sql.getTable();
ISQLTableJoin join = (ISQLTableJoin) sql.getJoin(oldTable, relation.getName());
if (join == null) {
join = SQLGenerator.createJoin(application.getFlattenedSolution(), relation, oldTable, new QueryTable(ft.getSQLName(), ft.getDataSource(), ft.getCatalog(), ft.getSchema()), true, fs_old);
sql.addJoin(join);
}
BaseQueryTable mainTable = join.getForeignTable();
// invert the join
sql.setTable(mainTable);
// $NON-NLS-1$
join.invert("INVERTED." + join.getName());
// set the columns to be the PKs from the related table
ArrayList<IQuerySelectValue> pkColumns = new ArrayList<IQuerySelectValue>();
Iterator<Column> pks = sheet_new.getTable().getRowIdentColumns().iterator();
while (pks.hasNext()) {
Column column = pks.next();
pkColumns.add(column.queryColumn(mainTable));
}
sql.setColumns(pkColumns);
// sorting will be on the original columns, when distinct is set, this will conflict with the related pk columns
sql.setDistinct(false);
fs_new.setSQLSelect(sql);
return fs_new;
}
} catch (Exception e) {
Debug.error(e);
}
}
return null;
}
Aggregations