use of com.servoy.j2db.persistence.Relation in project servoy-client by Servoy.
the class FoundSet method deleteRecord.
private void deleteRecord(IRecordInternal state, int row, boolean partOfBiggerDelete) throws ServoyException {
if (sheet.getTable() == null) {
return;
}
if (!hasAccess(IRepository.DELETE) && (state == null || state.existInDataSource())) {
throw new ApplicationException(ServoyException.NO_DELETE_ACCESS, new Object[] { sheet.getTable().getName() });
}
if (state != null && !(state instanceof PrototypeState) && !findMode) {
if (!fsm.getRowManager(fsm.getDataSource(sheet.getTable())).addRowToDeleteSet(state.getPKHashKey())) {
// already being deleted in recursion
return;
}
if (!partOfBiggerDelete) {
try {
// see EditRecordList.stopEditing
if (state.existInDataSource() && !executeFoundsetTriggerBreakOnFalse(new Object[] { state }, PROPERTY_ONDELETEMETHODID, true)) {
// trigger returned false
// $NON-NLS-1$
Debug.log("Delete not granted for the table " + getTable());
throw new ApplicationException(ServoyException.DELETE_NOT_GRANTED);
}
} catch (DataException e) {
// trigger threw exception
state.getRawData().setLastException(e);
getFoundSetManager().getEditRecordList().markRecordAsFailed(state);
// $NON-NLS-1$ //$NON-NLS-2$
Debug.log("Delete not granted for the table " + getTable() + ", pre-delete trigger threw exception");
throw new ApplicationException(ServoyException.DELETE_NOT_GRANTED);
}
// check for related data
FlattenedSolution flattenedSolution = fsm.getApplication().getFlattenedSolution();
Iterator<Relation> it = flattenedSolution.getRelations(sheet.getTable(), true, false);
while (it.hasNext()) {
Relation rel = it.next();
if (Relation.isValid(rel, flattenedSolution) && !rel.getAllowParentDeleteWhenHavingRelatedRecords() && !rel.isExactPKRef(fsm.getApplication().getFlattenedSolution()) && !rel.isGlobal()) {
IFoundSetInternal set = state.getRelatedFoundSet(rel.getName());
if (set != null && set.getSize() > 0) {
fsm.getApplication().reportJSError("Delete not granted due to AllowParentDeleteWhenHavingRelatedRecords size: " + set.getSize() + " from record with PK: " + state.getPKHashKey() + " index in foundset: " + row + " blocked by relation: " + rel.getName(), null);
throw new ApplicationException(ServoyException.NO_PARENT_DELETE_WITH_RELATED_RECORDS, new Object[] { rel.getName() }).setContext(this.toString());
}
}
}
// so only delete related data if the record is already in the db
if (state.existInDataSource()) {
// delete the related data
it = flattenedSolution.getRelations(sheet.getTable(), true, false);
while (it.hasNext()) {
Relation rel = it.next();
if (// if completely global never delete do cascade delete
Relation.isValid(rel, flattenedSolution) && rel.getDeleteRelatedRecords() && !rel.isGlobal()) {
IFoundSetInternal set = state.getRelatedFoundSet(rel.getName());
if (set != null) {
Debug.trace(// $NON-NLS-1$//$NON-NLS-2$
"******************************* delete related set size: " + set.getSize() + " from record with PK: " + state.getPKHashKey() + " index in foundset: " + // $NON-NLS-1$
row);
set.deleteAllInternal();
}
}
}
}
}
if (state.existInDataSource()) {
Row data = state.getRawData();
rowManager.deleteRow(this, data, hasAccess(IRepository.TRACKING), partOfBiggerDelete);
executeFoundsetTrigger(new Object[] { state }, PROPERTY_ONAFTERDELETEMETHODID, false);
GlobalTransaction gt = fsm.getGlobalTransaction();
if (gt != null) {
gt.addDeletedRecord(state);
}
// really remove the state from the edited records, can't be saved at all anymore after delete.
fsm.getEditRecordList().removeEditedRecord(state);
} else {
rowManager.clearRow(state.getRawData());
}
}
if (!(state instanceof PrototypeState)) {
removeRecordInternalEx(state, row);
// delete the row data so it won't be updated by other foundsets also having records to this rowdata.
if (state != null && state.getRawData() != null) {
state.getRawData().flagExistInDB();
}
}
}
use of com.servoy.j2db.persistence.Relation in project servoy-client by Servoy.
the class FoundSet method findColumnWrapperForColumn.
private ColumnWrapper findColumnWrapperForColumn(QuerySelect sqlSelect, QueryColumn qcolumn) throws RepositoryException {
List<Relation> relationSequence = findQueryRelationSequence(sqlSelect, qcolumn.getTable());
if (relationSequence == null) {
return null;
}
// found the relations, match the column (by sqlName)
ITable table = fsm.getTable(qcolumn.getTable().getDataSource());
if (table != null) {
IColumn column = table.getColumnBySqlname(qcolumn.getName());
if (column != null) {
return new ColumnWrapper(column, relationSequence.toArray(new Relation[relationSequence.size()]));
}
}
return null;
}
use of com.servoy.j2db.persistence.Relation in project servoy-client by Servoy.
the class FoundSet method createRecord.
private IRecordInternal createRecord(Row rowData, boolean javascriptRecord) throws ApplicationException {
if (findMode) {
// limit to 200
if (pksAndRecords.getCachedRecords().size() > fsm.config.pkChunkSize())
return null;
return new FindState(this);
}
if (javascriptRecord && !hasAccess(IRepository.INSERT)) {
throw new ApplicationException(ServoyException.NO_CREATE_ACCESS, new Object[] { getTable().getName() });
}
if (rowData == null && relationName != null) {
Relation relation = fsm.getApplication().getFlattenedSolution().getRelation(relationName);
if (relation != null) {
Placeholder ph = creationSqlSelect.getPlaceholder(SQLGenerator.createRelationKeyPlaceholderKey(creationSqlSelect.getTable(), relation.getName()));
if (ph == null || !ph.isSet() || ph.getValue() == null || ((Object[]) ph.getValue()).length == 0) {
Debug.trace(// $NON-NLS-1$
"New record failed because related foundset had no parameters, or trying to make a new findstate when it is nested more then 2 deep");
return null;
}
if (!relation.getAllowCreationRelatedRecords()) {
ApplicationException applicationException = new ApplicationException(ServoyException.NO_RELATED_CREATE_ACCESS, new Object[] { relation.getName() });
applicationException.setContext(this.toString());
throw applicationException;
}
}
}
try {
if (javascriptRecord && !executeFoundsetTriggerBreakOnFalse(null, PROPERTY_ONCREATEMETHODID, false)) {
// $NON-NLS-1$
Debug.trace("New record creation was denied by onCreateRecord method");
return null;
}
} catch (ServoyException e) {
Debug.error(e);
return null;
}
IRecordInternal newRecord = null;
if (rowData == null) {
Object[] data = sheet.getNewRowData(fsm.getApplication(), this);
newRecord = new Record(this, rowManager.createNotYetExistInDBRowObject(data, true));
sheet.processCopyValues(newRecord);
} else {
newRecord = new Record(this, rowData);
}
try {
if (javascriptRecord) {
executeFoundsetTrigger(new Object[] { newRecord }, PROPERTY_ONAFTERCREATEMETHODID, false);
}
} catch (ServoyException e) {
Debug.error(e);
}
return newRecord;
}
use of com.servoy.j2db.persistence.Relation in project servoy-client by Servoy.
the class FoundSet method getRelatedFoundSet.
/**
* Get related foundset, relationName may be multiple-levels deep
*/
public IFoundSetInternal getRelatedFoundSet(IRecordInternal record, String fullRelationName, List<SortColumn> defaultSortColumns) throws ServoyException {
if (fullRelationName == null) {
return null;
}
IFoundSetInternal retval = null;
IRecordInternal currentRecord = record;
// $NON-NLS-1$
String[] parts = fullRelationName.split("\\.");
for (int i = 0; i < parts.length; i++) {
// if this is a findstate and that is not the source record then leave the relation lookup to the findstate itself.
if (currentRecord instanceof FindState && i != 0) {
String leftPart = parts[i];
for (int k = i + 1; k < parts.length; k++) {
// $NON-NLS-1$
leftPart += "." + parts[k];
}
return currentRecord.getRelatedFoundSet(leftPart);
}
SQLSheet relatedSheet = sheet.getRelatedSheet(fsm.getApplication().getFlattenedSolution().getRelation(parts[i]), fsm.getSQLGenerator());
if (relatedSheet == null) {
retval = fsm.getGlobalRelatedFoundSet(parts[i]);
} else {
retval = fsm.getRelatedFoundSet(currentRecord, relatedSheet, parts[i], defaultSortColumns);
if (retval != null) {
if (retval.getSize() == 0 && !currentRecord.existInDataSource()) {
Relation r = fsm.getApplication().getFlattenedSolution().getRelation(parts[i]);
if (// TODO add unique column test instead of pk requirement
r != null && r.isExactPKRef(fsm.getApplication().getFlattenedSolution())) {
((FoundSet) retval).newRecord(record.getRawData(), 0, true, false);
}
}
retval.addParent(currentRecord);
}
}
if (retval == null) {
return null;
}
if (i < parts.length - 1) {
currentRecord = retval.getRecord(retval.getSelectedIndex());
if (currentRecord == null) {
return null;
}
}
}
return retval;
}
use of com.servoy.j2db.persistence.Relation in project servoy-client by Servoy.
the class FoundSet method deleteAllInternal.
public void deleteAllInternal() throws ServoyException {
Table table = sheet.getTable();
if (table == null) {
return;
}
fireSelectionAdjusting();
boolean partOfBiggerDelete = false;
// does have access, does not have join to other table and doesn't have a on delete method
QuerySelect sqlSelect;
IDataSet currentPKs;
synchronized (pksAndRecords) {
sqlSelect = pksAndRecords.getQuerySelectForReading();
currentPKs = pksAndRecords.getPks();
}
if (!hasAccess(IRepository.TRACKING) && sqlSelect.getJoins() == null && !tableHasOnDeleteMethods()) {
if (!hasAccess(IRepository.DELETE)) {
throw new ApplicationException(ServoyException.NO_DELETE_ACCESS, new Object[] { table.getName() });
}
boolean hasRelationsWithDelete = false;
Iterator<Relation> it = fsm.getApplication().getFlattenedSolution().getRelations(table, true, false);
while (it.hasNext()) {
Relation element = it.next();
if ((element.getDeleteRelatedRecords() || !element.getAllowParentDeleteWhenHavingRelatedRecords()) && !element.isGlobal()) {
// $NON-NLS-1$ //$NON-NLS-2$
Debug.trace("Foundset deleted per-record because relation '" + element.getName() + "' requires some checks");
hasRelationsWithDelete = true;
break;
}
}
if (!hasRelationsWithDelete) {
getFoundSetManager().getEditRecordList().removeEditedRecords(this);
// do sql delete all at once
QueryDelete delete_sql = new QueryDelete(sqlSelect.getTable());
delete_sql.setCondition(sqlSelect.getWhereClone());
IDataSet deletePKs;
boolean allFoundsetRecordsLoaded = currentPKs != null && pksAndRecords.getCachedRecords().size() == getSize() && !hadMoreRows();
if (allFoundsetRecordsLoaded) {
// clone because this will be used in a separate thread by performUpdates while it will be altered in this one (deletes all records at the end of the method)
deletePKs = currentPKs.clone();
} else {
deletePKs = new BufferedDataSet();
deletePKs.addRow(new Object[] { ValueFactory.createTableFlushValue() });
}
String tid = fsm.getTransactionID(table.getServerName());
SQLStatement statement = new SQLStatement(ISQLActionTypes.DELETE_ACTION, table.getServerName(), table.getName(), deletePKs, tid, delete_sql, fsm.getTableFilterParams(table.getServerName(), delete_sql));
try {
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) {
throw (ServoyException) results[i];
}
}
if (!allFoundsetRecordsLoaded) {
fsm.flushCachedDatabaseData(fsm.getDataSource(table));
}
partOfBiggerDelete = true;
} catch (ApplicationException aex) {
if (allFoundsetRecordsLoaded || aex.getErrorCode() != ServoyException.RECORD_LOCKED) {
throw aex;
}
// a record was locked by another client, try per-record
// $NON-NLS-1$
Debug.log("Could not delete all records in 1 statement (a record may be locked), trying per-record");
} catch (RemoteException e) {
throw new RepositoryException(e);
}
}
}
// Need to get all the PKs, recursive delete may not actually remove the PK from the list because it is already being deleted.
if (!partOfBiggerDelete) {
PksAndRecordsHolder pksAndRecordsCopy;
int rowCount;
synchronized (pksAndRecords) {
pksAndRecordsCopy = pksAndRecords.shallowCopy();
IDataSet pks = pksAndRecordsCopy.getPks();
rowCount = pks == null ? 0 : pks.getRowCount();
}
queryForMorePKs(pksAndRecordsCopy, rowCount, -1, false);
}
try {
for (int i = getSize() - 1; i >= 0; i--) {
deleteRecord(i, partOfBiggerDelete);
}
} finally {
int correctedSize = getCorrectedSizeForFires();
if (correctedSize > -1)
fireFoundSetEvent(0, correctedSize, FoundSetEvent.CHANGE_DELETE);
}
}
Aggregations