Search in sources :

Example 36 with Relation

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();
        }
    }
}
Also used : Relation(com.servoy.j2db.persistence.Relation) ApplicationException(com.servoy.j2db.ApplicationException) FlattenedSolution(com.servoy.j2db.FlattenedSolution)

Example 37 with Relation

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;
}
Also used : Relation(com.servoy.j2db.persistence.Relation) IColumn(com.servoy.j2db.persistence.IColumn) ColumnWrapper(com.servoy.j2db.persistence.ColumnWrapper) ITable(com.servoy.j2db.persistence.ITable)

Example 38 with Relation

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;
}
Also used : Placeholder(com.servoy.j2db.query.Placeholder) Relation(com.servoy.j2db.persistence.Relation) ApplicationException(com.servoy.j2db.ApplicationException) IJSRecord(com.servoy.base.scripting.api.IJSRecord) ServoyException(com.servoy.j2db.util.ServoyException)

Example 39 with Relation

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;
}
Also used : Relation(com.servoy.j2db.persistence.Relation) IJSFoundSet(com.servoy.base.scripting.api.IJSFoundSet)

Example 40 with Relation

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);
    }
}
Also used : BaseQueryTable(com.servoy.base.query.BaseQueryTable) Table(com.servoy.j2db.persistence.Table) QueryTable(com.servoy.j2db.query.QueryTable) ITable(com.servoy.j2db.persistence.ITable) QueryDelete(com.servoy.j2db.query.QueryDelete) RepositoryException(com.servoy.j2db.persistence.RepositoryException) QuerySelect(com.servoy.j2db.query.QuerySelect) ServoyException(com.servoy.j2db.util.ServoyException) Relation(com.servoy.j2db.persistence.Relation) ApplicationException(com.servoy.j2db.ApplicationException) RemoteException(java.rmi.RemoteException)

Aggregations

Relation (com.servoy.j2db.persistence.Relation)53 ServoyException (com.servoy.j2db.util.ServoyException)16 ArrayList (java.util.ArrayList)16 FlattenedSolution (com.servoy.j2db.FlattenedSolution)15 RepositoryException (com.servoy.j2db.persistence.RepositoryException)15 Column (com.servoy.j2db.persistence.Column)11 ITable (com.servoy.j2db.persistence.ITable)11 RemoteException (java.rmi.RemoteException)10 BaseQueryTable (com.servoy.base.query.BaseQueryTable)9 IDataProvider (com.servoy.j2db.persistence.IDataProvider)8 QuerySelect (com.servoy.j2db.query.QuerySelect)8 QueryTable (com.servoy.j2db.query.QueryTable)8 IColumn (com.servoy.j2db.persistence.IColumn)7 Placeholder (com.servoy.j2db.query.Placeholder)7 ApplicationException (com.servoy.j2db.ApplicationException)6 Table (com.servoy.j2db.persistence.Table)6 QueryColumn (com.servoy.j2db.query.QueryColumn)6 IQuerySelectValue (com.servoy.j2db.query.IQuerySelectValue)5 ISQLTableJoin (com.servoy.j2db.query.ISQLTableJoin)5 SafeArrayList (com.servoy.j2db.util.SafeArrayList)5