use of com.servoy.j2db.util.ServoyException in project servoy-client by Servoy.
the class Record method manageCalcDependency.
protected void manageCalcDependency(String calc, UsedDataProviderTracker usedDataProviderTracker) {
if (usedDataProviderTracker == null) {
return;
}
Set<String> usedGlobals = usedDataProviderTracker.getGlobals();
if (usedGlobals != null) {
for (String usedGlobal : usedGlobals) {
row.getRowManager().addCalculationGlobalDependency(usedGlobal, calc);
}
}
Set<UsedDataProvider> usedColumns = usedDataProviderTracker.getColumns();
if (usedColumns != null) {
for (UsedDataProvider usedColumn : usedColumns) {
try {
RowManager rowManager = ((FoundSetManager) parent.getFoundSetManager()).getRowManager(usedColumn.dataSource);
if (rowManager != null) {
rowManager.addCalculationDependency(usedColumn.pkHashKey, usedColumn.dataProviderId, parent.getDataSource(), getPKHashKey(), calc);
}
} catch (ServoyException e) {
Debug.error(e);
}
}
}
Set<UsedRelation> uedRelations = usedDataProviderTracker.getRelations();
if (uedRelations != null) {
for (UsedRelation usedRelation : uedRelations) {
row.getRowManager().addCalculationRelationDependency(usedRelation.whereArgsHash, usedRelation.name, parent.getDataSource(), getPKHashKey(), calc);
}
}
Set<UsedAggregate> usedAggregates = usedDataProviderTracker.getAggregates();
if (usedAggregates != null) {
for (UsedAggregate usedAggregate : usedAggregates) {
row.getRowManager().addCalculationAggregateDependency(usedAggregate.foundSet, usedAggregate.name, calc);
}
}
}
use of com.servoy.j2db.util.ServoyException in project servoy-client by Servoy.
the class RelatedFoundSet method createRelatedFoundSets.
/**
* Create multiple related foundsets in one call to the data server.
*
* @param factory
* @param app
* @param parents same length as whereArsgLists
* @param relation
* @param sheet
* @param whereArsgLists
* @param defaultSortColumns
* @return
* @throws ServoyException
*/
public static IFoundSetInternal[] createRelatedFoundSets(IFoundSetFactory factory, IFoundSetManagerInternal app, IRecordInternal[] parents, Relation relation, SQLSheet sheet, Object[][] whereArsgLists, List<SortColumn> defaultSortColumns) throws ServoyException {
if (sheet == null) {
// $NON-NLS-1$
throw new IllegalArgumentException(app.getApplication().getI18NMessage("servoy.foundSet.error.sqlsheet"));
}
FoundSetManager fsm = (FoundSetManager) app;
List<SortColumn> sortColumns;
if (defaultSortColumns == null || defaultSortColumns.size() == 0) {
sortColumns = sheet.getDefaultPKSort();
} else {
sortColumns = defaultSortColumns;
}
QuerySelect cleanSelect = fsm.getSQLGenerator().getPKSelectSqlSelect(fsm.getScopesScopeProvider(), sheet.getTable(), null, null, true, null, sortColumns, false);
QuerySelect relationSelect = (QuerySelect) sheet.getRelatedSQLDescription(relation.getName()).getSQLQuery();
// don't select all columns in pk select
cleanSelect.setColumns(AbstractBaseQuery.relinkTable(relationSelect.getTable(), cleanSelect.getTable(), relationSelect.getColumnsClone()));
// copy the where (is foreign where)
cleanSelect.setCondition(SQLGenerator.CONDITION_RELATION, AbstractBaseQuery.relinkTable(relationSelect.getTable(), cleanSelect.getTable(), relationSelect.getConditionClone(SQLGenerator.CONDITION_RELATION)));
TablePlaceholderKey placeHolderKey = SQLGenerator.createRelationKeyPlaceholderKey(cleanSelect.getTable(), relation.getName());
// all queries
QuerySelect[] sqlSelects = new QuerySelect[whereArsgLists.length];
// all aggregates
QuerySelect[] aggregateSelects = new QuerySelect[whereArsgLists.length];
List<Integer> queryIndex = new ArrayList<Integer>(whereArsgLists.length);
Map<Integer, Row> cachedRows = new HashMap<Integer, Row>();
List<QueryData> queryDatas = new ArrayList<QueryData>(whereArsgLists.length);
String transactionID = fsm.getTransactionID(sheet);
String clientID = fsm.getApplication().getClientID();
ArrayList<TableFilter> sqlFilters = fsm.getTableFilterParams(sheet.getServerName(), cleanSelect);
for (int i = 0; i < whereArsgLists.length; i++) {
Object[] whereArgs = whereArsgLists[i];
if (whereArgs == null || whereArgs.length == 0) {
// $NON-NLS-1$
throw new IllegalArgumentException(app.getApplication().getI18NMessage("servoy.relatedfoundset.error.noFK") + relation.getName());
}
QuerySelect sqlSelect;
if (i == whereArsgLists.length - 1) {
// the last one, use the template, no clone needed
sqlSelect = cleanSelect;
} else {
sqlSelect = AbstractBaseQuery.deepClone(cleanSelect);
}
if (!sqlSelect.setPlaceholderValue(placeHolderKey, whereArgs)) {
// $NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
Debug.error(new RuntimeException("Could not set placeholder " + placeHolderKey + " in query " + sqlSelect + "-- continuing"));
}
sqlSelects[i] = sqlSelect;
// Check for non-empty where-arguments, joins on null-conditions are not allowed (similar to FK constraints in databases)
if (!whereArgsIsEmpty(whereArgs)) {
Row cachedRow = null;
if (relation.isFKPKRef(fsm.getApplication().getFlattenedSolution())) {
// optimize for FK->PK relation, if the data is already cached, do not query
RowManager rowManager = fsm.getRowManager(relation.getForeignDataSource());
if (rowManager != null) {
cachedRow = rowManager.getCachedRow(whereArgs).getLeft();
}
}
if (cachedRow != null) {
if (Debug.tracing()) {
// $NON-NLS-1$
Debug.trace(Thread.currentThread().getName() + ": Found cached FK record");
}
cachedRows.put(Integer.valueOf(i), cachedRow);
} else if (!parents[i].existInDataSource() && !fsm.config.loadRelatedRecordsIfParentIsNew() && relation.hasPKFKCondition(fsm.getApplication().getFlattenedSolution())) {
/*
* Optimize for init of related foundsets on a parent record that is new and where the relation includes equal conditions for all the parent
* rowIdentifier columns
*
* In this case no query has to be made to the DB to fetch existing records, as there wouldn't be any.
*/
} else {
ISQLSelect selectStatement = AbstractBaseQuery.deepClone((ISQLSelect) sqlSelect);
// Note: put a clone of sqlSelect in the queryDatas list, we will compress later over multiple queries using pack().
// Clone is needed because packed queries may not be save to manipulate.
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(sheet.getColumnNames(), new Object[][] {}, new Object[][] {}, fsm.getApplication().getUserUID(), fsm.getTrackingInfo(), fsm.getApplication().getClientID());
}
queryDatas.add(new QueryData(selectStatement, sqlFilters, !sqlSelect.isUnique(), 0, fsm.config.initialRelatedChunkSize(), IDataServer.RELATION_QUERY, trackingInfo));
queryIndex.add(Integer.valueOf(i));
QuerySelect aggregateSelect = FoundSet.getAggregateSelect(sheet, sqlSelect);
if (aggregateSelect != null) {
// Note: see note about clone above.
queryDatas.add(new QueryData(AbstractBaseQuery.deepClone((ISQLSelect) aggregateSelect), fsm.getTableFilterParams(sheet.getServerName(), aggregateSelect), false, 0, 1, IDataServer.AGGREGATE_QUERY, null));
// same index for aggregates
queryIndex.add(Integer.valueOf(i));
aggregateSelects[i] = aggregateSelect;
}
}
}
}
IDataSet[] dataSets = null;
if (queryDatas.size() > 0) {
try {
// pack is safe here because queryDatas contains only cloned ISQLSelect objects
QueryData[] qDatas = queryDatas.toArray(new QueryData[queryDatas.size()]);
AbstractBaseQuery.acceptVisitor(qDatas, new PackVisitor());
int size = 0;
if (// trace the message size
Debug.tracing()) {
try {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bs);
os.writeObject(qDatas);
os.close();
size = bs.size();
} catch (Exception e) {
Debug.trace(e);
}
}
long time = System.currentTimeMillis();
dataSets = fsm.getDataServer().performQuery(clientID, sheet.getServerName(), transactionID, qDatas);
if (Debug.tracing()) {
Debug.trace(// $NON-NLS-1$ //$NON-NLS-2$
Thread.currentThread().getName() + ": Relation query: " + relation.getName() + " with: " + qDatas.length + " queries,query size: " + size + ",time: " + (System.currentTimeMillis() - time) + // $NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
"ms");
}
} catch (RepositoryException re) {
testException(clientID, re);
throw re;
} catch (RemoteException e) {
testException(clientID, e.getCause());
throw new RepositoryException(e);
}
}
IFoundSetInternal[] foundsets = new RelatedFoundSet[whereArsgLists.length];
int d = 0;
for (int i = 0; i < whereArsgLists.length; i++) {
IDataSet data;
IDataSet aggregateData = null;
int index = (d >= queryIndex.size()) ? -1 : queryIndex.get(d).intValue();
if (index == i) {
// regular query
data = dataSets[d++];
// optionally followed by aggregate
index = (d >= queryIndex.size()) ? -1 : queryIndex.get(d).intValue();
if (index == i) {
// aggregate
aggregateData = dataSets[d++];
}
} else {
data = new BufferedDataSet();
Row row = cachedRows.get(Integer.valueOf(i));
if (row != null) {
// cached
data.addRow(row.getRawColumnData());
}
// else whereArgsIsEmpty
}
foundsets[i] = factory.createRelatedFoundSet(data, sqlSelects[i], app, parents[i], relation.getName(), sheet, sortColumns, aggregateSelects[i], aggregateData);
if (aggregateData != null && foundsets[i] instanceof FoundSet) {
((FoundSet) foundsets[i]).fillAggregates(aggregateSelects[i], aggregateData);
}
}
if (d != queryIndex.size()) {
// $NON-NLS-1$
throw new RepositoryException("Related query parameters out of sync " + d + '/' + queryIndex.size());
}
return foundsets;
}
use of com.servoy.j2db.util.ServoyException in project servoy-client by Servoy.
the class RowManager method deleteRow.
void deleteRow(IRowListener src, Row r, boolean tracking, boolean partOfBiggerDelete) throws ServoyException {
// $NON-NLS-1$
if (r.getRowManager() != this)
throw new IllegalArgumentException("I'm not the row manager from row");
// prevent it processed by any update, changed is false now
r.flagExistInDB();
if (!partOfBiggerDelete) {
QueryDelete sqlDelete = AbstractBaseQuery.deepClone((QueryDelete) sheet.getSQLDescription(SQLSheet.DELETE).getSQLQuery());
Object[] pk = r.getPK();
if (!sqlDelete.setPlaceholderValue(new TablePlaceholderKey(sqlDelete.getTable(), SQLGenerator.PLACEHOLDER_PRIMARY_KEY), pk)) {
Debug.error(new RuntimeException(// $NON-NLS-1$
"Could not set placeholder " + new TablePlaceholderKey(sqlDelete.getTable(), SQLGenerator.PLACEHOLDER_PRIMARY_KEY) + " in query " + sqlDelete + // $NON-NLS-1$ //$NON-NLS-2$
"-- continuing"));
}
IDataSet pks = new BufferedDataSet();
pks.addRow(pk);
ISQLStatement[] stats_a = new ISQLStatement[1];
String tid = null;
GlobalTransaction gt = fsm.getGlobalTransaction();
if (gt != null) {
tid = gt.getTransactionID(sheet.getServerName());
}
SQLStatement statement = new SQLStatement(ISQLActionTypes.DELETE_ACTION, sheet.getServerName(), sheet.getTable().getName(), pks, tid, sqlDelete, fsm.getTableFilterParams(sheet.getServerName(), sqlDelete));
// check that 1 record is deleted
statement.setExpectedUpdateCount(1);
stats_a[0] = statement;
if (tracking) {
statement.setTrackingData(sheet.getColumnNames(), r.getRawColumnData() != null ? new Object[][] { r.getRawColumnData() } : null, null, fsm.getApplication().getUserUID(), fsm.getTrackingInfo(), fsm.getApplication().getClientID());
}
try {
Object[] results = fsm.getDataServer().performUpdates(fsm.getApplication().getClientID(), stats_a);
for (int i = 0; results != null && i < results.length; i++) {
if (results[i] instanceof ServoyException) {
throw (ServoyException) results[i];
}
}
} catch (RemoteException e) {
throw new RepositoryException(e);
}
SoftReferenceWithData<Row, Pair<Map<String, List<CalculationDependency>>, CalculationDependencyData>> removed;
synchronized (this) {
removed = pkRowMap.remove(r.getPKHashKey());
}
fireDependingCalcs(removed, null, null);
} else {
synchronized (this) {
pkRowMap.remove(r.getPKHashKey());
}
}
fireNotifyChange(src, r, r.getPKHashKey(), null, RowEvent.DELETE);
}
use of com.servoy.j2db.util.ServoyException 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.util.ServoyException in project servoy-client by Servoy.
the class FoundSetManager method getTable.
@SuppressWarnings("nls")
public ITable getTable(String dataSource) throws RepositoryException {
if (dataSource == null) {
return null;
}
if (application.getSolution() == null) {
if (Debug.tracing()) {
Debug.trace("Trying to get a table for a datasource: " + dataSource + " on an already closed solution", new RuntimeException());
}
return null;
}
ITable table = dataSource.startsWith(DataSourceUtils.VIEW_DATASOURCE_SCHEME_COLON) ? viewDataSources.get(dataSource) : inMemDataSources.get(dataSource);
if (table == null) {
// when it is a db:/server/table data source
String[] servernameTablename = DataSourceUtilsBase.getDBServernameTablename(dataSource);
if (servernameTablename != null && servernameTablename[0] != null) {
try {
IServer server = application.getSolution().getServer(servernameTablename[0]);
if (server == null) {
// $NON-NLS-1$
throw new RepositoryException(Messages.getString("servoy.exception.serverNotFound", new Object[] { servernameTablename[0] }));
}
table = server.getTable(servernameTablename[1]);
} catch (RemoteException e) {
throw new RepositoryException(e);
}
} else if (getDataSourceServerName(dataSource) == IServer.INMEM_SERVER) {
if (!inMemDataSources.containsKey(dataSource) && dataSourceExists(dataSource)) {
try {
insertToDataSource(DataSourceUtils.getDataSourceTableName(dataSource), new BufferedDataSet(), null, null, true, false, IServer.INMEM_SERVER);
} catch (Exception e) {
Debug.error(e);
}
}
return inMemDataSources.get(dataSource);
} else if (getDataSourceServerName(dataSource) == IServer.VIEW_SERVER) {
Optional<ServoyJSONObject> columnDefintion;
if (!viewDataSources.containsKey(dataSource) && (columnDefintion = getColumnDefintion(dataSource)).isPresent()) {
Table tbl = new Table(IServer.VIEW_SERVER, DataSourceUtils.getViewDataSourceName(dataSource), true, ITable.VIEW, null, null);
tbl.setDataSource(dataSource);
DatabaseUtils.deserializeInMemoryTable(application.getFlattenedSolution().getPersistFactory(), tbl, columnDefintion.get());
tbl.setExistInDB(true);
tbl.setInitialized(true);
viewDataSources.put(dataSource, tbl);
try {
executeFoundsetTriggerReturnFirst(tbl, new Object[] { DataSourceUtils.getViewDataSourceName(dataSource) }, StaticContentSpecLoader.PROPERTY_ONFOUNDSETLOADMETHODID, false, // can't entity methods, not supported on view foundsets
null);
} catch (ServoyException e) {
Debug.error("Error executing foundset method for datasource: " + dataSource, e);
}
}
return viewDataSources.get(dataSource);
}
}
return table;
}
Aggregations