Search in sources :

Example 11 with RowIterator

use of org.hsqldb_voltpatches.navigator.RowIterator in project voltdb by VoltDB.

the class IndexAVL method size.

/**
     * Returns the node count.
     */
@Override
public int size(PersistentStore store) {
    int count = 0;
    readLock.lock();
    try {
        RowIterator it = firstRow(null, store);
        while (it.hasNext()) {
            it.getNextRow();
            count++;
        }
        return count;
    } finally {
        readLock.unlock();
    }
}
Also used : RowIterator(org.hsqldb_voltpatches.navigator.RowIterator)

Example 12 with RowIterator

use of org.hsqldb_voltpatches.navigator.RowIterator in project voltdb by VoltDB.

the class StatementDML method checkCascadeUpdate.

/**
     * Check or perform an update cascade operation on a single row. Check or
     * cascade an update (delete/insert) operation. The method takes a pair of
     * rows (new data,old data) and checks if Constraints permit the update
     * operation. A boolean arguement determines if the operation should realy
     * take place or if we just have to check for constraint violation. fredt -
     * cyclic conditions are now avoided by checking for second visit to each
     * constraint. The set of list of updates for all tables is passed and
     * filled in recursive calls.
     *
     * @param session current database session
     * @param table table to check
     * @param tableUpdateLists lists of updates
     * @param orow old row data to be deleted.
     * @param nrow new row data to be inserted.
     * @param cols indices of the columns actually changed.
     * @param ref This should be initialized to null when the method is called
     *   from the 'outside'. During recursion this will be the current table
     *   (i.e. this) to indicate from where we came. Foreign keys to this table
     *   do not have to be checked since they have triggered the update and are
     *   valid by definition.
     * @param path HashSet
     */
static void checkCascadeUpdate(Session session, Table table, HashMappedList tableUpdateLists, Row orow, Object[] nrow, int[] cols, Table ref, HashSet path) {
    // --
    for (int i = 0, size = table.fkConstraints.length; i < size; i++) {
        // -- (1) If it is a foreign key constraint we have to check if the
        // --     main table still holds a record which allows the new values
        // --     to be set in the updated columns. This test however will be
        // --     skipped if the reference table is the main table since changes
        // --     in the reference table triggered the update and therefor
        // --     the referential integrity is guaranteed to be valid.
        // --
        Constraint c = table.fkConstraints[i];
        if (ref == null || c.getMain() != ref) {
            // -- common indexes of the changed columns and the main/ref constraint
            if (ArrayUtil.countCommonElements(cols, c.getRefColumns()) == 0) {
                // -- Table::checkCascadeUpdate -- NO common cols; reiterating
                continue;
            }
            c.checkHasMainRef(session, nrow);
        }
    }
    for (int i = 0, size = table.fkMainConstraints.length; i < size; i++) {
        Constraint c = table.fkMainConstraints[i];
        // -- (2) If it happens to be a main constraint we check if the slave
        // --     table holds any records refering to the old contents. If so,
        // --     the constraint has to support an 'on update' action or we
        // --     throw an exception (all via a call to Constraint.findFkRef).
        // --
        // -- If there are no common columns between the reference constraint
        // -- and the changed columns, we reiterate.
        int[] common = ArrayUtil.commonElements(cols, c.getMainColumns());
        if (common == null) {
            // -- NO common cols between; reiterating
            continue;
        }
        int[] m_columns = c.getMainColumns();
        int[] r_columns = c.getRefColumns();
        // fredt - find out if the FK columns have actually changed
        boolean nochange = true;
        for (int j = 0; j < m_columns.length; j++) {
            // identity test is enough
            if (orow.getData()[m_columns[j]] != nrow[m_columns[j]]) {
                nochange = false;
                break;
            }
        }
        if (nochange) {
            continue;
        }
        // there must be no record in the 'slave' table
        // sebastian@scienion -- dependent on forDelete | forUpdate
        RowIterator refiterator = c.findFkRef(session, orow.getData(), false);
        if (refiterator.hasNext()) {
            if (c.core.updateAction == Constraint.NO_ACTION || c.core.updateAction == Constraint.RESTRICT) {
                int errorCode = c.core.deleteAction == Constraint.NO_ACTION ? ErrorCode.X_23501 : ErrorCode.X_23001;
                String[] info = new String[] { c.core.refName.name, c.core.refTable.getName().name };
                throw Error.error(errorCode, ErrorCode.CONSTRAINT, info);
            }
        } else {
            // no referencing row found
            continue;
        }
        Table reftable = c.getRef();
        // -- unused shortcut when update table has no imported constraint
        boolean hasref = reftable.getNextConstraintIndex(0, Constraint.MAIN) != -1;
        Index refindex = c.getRefIndex();
        // -- walk the index for all the nodes that reference update node
        HashMappedList rowSet = (HashMappedList) tableUpdateLists.get(reftable);
        if (rowSet == null) {
            rowSet = new HashMappedList();
            tableUpdateLists.add(reftable, rowSet);
        }
        for (Row refrow = refiterator.getNextRow(); ; refrow = refiterator.getNextRow()) {
            if (refrow == null || refindex.compareRowNonUnique(orow.getData(), m_columns, refrow.getData()) != 0) {
                break;
            }
            Object[] rnd = reftable.getEmptyRowData();
            System.arraycopy(refrow.getData(), 0, rnd, 0, rnd.length);
            // -- And handle the insertion procedure differently.
            if (c.getUpdateAction() == Constraint.SET_NULL) {
                // -- since we are setting <code>null</code> values
                for (int j = 0; j < r_columns.length; j++) {
                    rnd[r_columns[j]] = null;
                }
            } else if (c.getUpdateAction() == Constraint.SET_DEFAULT) {
                // -- the values and referential integrity is no longer guaranteed to be valid
                for (int j = 0; j < r_columns.length; j++) {
                    ColumnSchema col = reftable.getColumn(r_columns[j]);
                    rnd[r_columns[j]] = col.getDefaultValue(session);
                }
                if (path.add(c)) {
                    checkCascadeUpdate(session, reftable, tableUpdateLists, refrow, rnd, r_columns, null, path);
                    path.remove(c);
                }
            } else {
                // -- table therefor we set ref==this.
                for (int j = 0; j < m_columns.length; j++) {
                    rnd[r_columns[j]] = nrow[m_columns[j]];
                }
                if (path.add(c)) {
                    checkCascadeUpdate(session, reftable, tableUpdateLists, refrow, rnd, common, table, path);
                    path.remove(c);
                }
            }
            mergeUpdate(rowSet, refrow, rnd, r_columns);
        }
    }
}
Also used : HashMappedList(org.hsqldb_voltpatches.lib.HashMappedList) Index(org.hsqldb_voltpatches.index.Index) RowIterator(org.hsqldb_voltpatches.navigator.RowIterator)

Example 13 with RowIterator

use of org.hsqldb_voltpatches.navigator.RowIterator in project voltdb by VoltDB.

the class StatementDML method checkCascadeDelete.

// fredt@users 20020225 - patch 1.7.0 - CASCADING DELETES
/**
     *  Method is called recursively on a tree of tables from the current one
     *  until no referring foreign-key table is left. In the process, if a
     *  non-cascading foreign-key referring table contains data, an exception
     *  is thrown. Parameter delete indicates whether to delete refering rows.
     *  The method is called first to check if the row can be deleted, then to
     *  delete the row and all the refering rows.<p>
     *
     *  Support added for SET NULL and SET DEFAULT by kloska@users involves
     *  switching to checkCascadeUpdate(,,,,) when these rules are encountered
     *  in the constraint.(fredt@users)
     *
     * @param session current session
     * @param  table table to delete from
     * @param  tableUpdateList list of update lists
     * @param  row row to delete
     * @param  delete action
     * @param  path constraint path
     * @throws  HsqlException
     */
static void checkCascadeDelete(Session session, Table table, HashMappedList tableUpdateList, Row row, boolean delete, HashSet path) {
    for (int i = 0, size = table.fkMainConstraints.length; i < size; i++) {
        Constraint c = table.fkMainConstraints[i];
        RowIterator refiterator = c.findFkRef(session, row.getData(), delete);
        if (!refiterator.hasNext()) {
            continue;
        }
        try {
            if (c.core.deleteAction == Constraint.NO_ACTION || c.core.deleteAction == Constraint.RESTRICT) {
                if (c.core.mainTable == c.core.refTable) {
                    Row refrow = refiterator.getNextRow();
                    // with self-referencing FK's deletes
                    if (row.equals(refrow)) {
                        continue;
                    }
                }
                int errorCode = c.core.deleteAction == Constraint.NO_ACTION ? ErrorCode.X_23501 : ErrorCode.X_23001;
                String[] info = new String[] { c.core.refName.name, c.core.refTable.getName().name };
                throw Error.error(errorCode, ErrorCode.CONSTRAINT, info);
            }
            Table reftable = c.getRef();
            // shortcut when deltable has no imported constraint
            boolean hasref = reftable.fkMainConstraints.length > 0;
            // if (reftable == this) we don't need to go further and can return ??
            if (!delete && !hasref) {
                continue;
            }
            Index refindex = c.getRefIndex();
            int[] m_columns = c.getMainColumns();
            int[] r_columns = c.getRefColumns();
            Object[] mdata = row.getData();
            boolean isUpdate = c.getDeleteAction() == Constraint.SET_NULL || c.getDeleteAction() == Constraint.SET_DEFAULT;
            // -- list for records to be inserted if this is
            // -- a 'ON DELETE SET [NULL|DEFAULT]' constraint
            HashMappedList rowSet = null;
            if (isUpdate) {
                rowSet = (HashMappedList) tableUpdateList.get(reftable);
                if (rowSet == null) {
                    rowSet = new HashMappedList();
                    tableUpdateList.add(reftable, rowSet);
                }
            }
            // walk the index for all the nodes that reference delnode
            for (; ; ) {
                Row refrow = refiterator.getNextRow();
                if (refrow == null || refrow.isDeleted(session) || refindex.compareRowNonUnique(mdata, m_columns, refrow.getData()) != 0) {
                    break;
                }
                // -- switch over to the 'checkCascadeUpdate' method below this level
                if (isUpdate) {
                    Object[] rnd = reftable.getEmptyRowData();
                    System.arraycopy(refrow.getData(), 0, rnd, 0, rnd.length);
                    if (c.getDeleteAction() == Constraint.SET_NULL) {
                        for (int j = 0; j < r_columns.length; j++) {
                            rnd[r_columns[j]] = null;
                        }
                    } else {
                        for (int j = 0; j < r_columns.length; j++) {
                            ColumnSchema col = reftable.getColumn(r_columns[j]);
                            rnd[r_columns[j]] = col.getDefaultValue(session);
                        }
                    }
                    if (hasref && path.add(c)) {
                        // fredt - avoid infinite recursion on circular references
                        // these can be rings of two or more mutually dependent tables
                        // so only one visit per constraint is allowed
                        checkCascadeUpdate(session, reftable, null, refrow, rnd, r_columns, null, path);
                        path.remove(c);
                    }
                    if (delete) {
                        //  foreign key referencing own table - do not update the row to be deleted
                        if (reftable != table || !refrow.equals(row)) {
                            mergeUpdate(rowSet, refrow, rnd, r_columns);
                        }
                    }
                } else if (hasref) {
                    if (reftable != table) {
                        if (path.add(c)) {
                            checkCascadeDelete(session, reftable, tableUpdateList, refrow, delete, path);
                            path.remove(c);
                        }
                    } else {
                        // but chained rows can result in very deep recursion and StackOverflowError
                        if (refrow != row) {
                            checkCascadeDelete(session, reftable, tableUpdateList, refrow, delete, path);
                        }
                    }
                }
                if (delete && !isUpdate && !refrow.isDeleted(session)) {
                    reftable.deleteRowAsTriggeredAction(session, refrow);
                }
            }
        } finally {
            refiterator.release();
        }
    }
}
Also used : HashMappedList(org.hsqldb_voltpatches.lib.HashMappedList) Index(org.hsqldb_voltpatches.index.Index) RowIterator(org.hsqldb_voltpatches.navigator.RowIterator)

Example 14 with RowIterator

use of org.hsqldb_voltpatches.navigator.RowIterator in project voltdb by VoltDB.

the class Table method moveData.

/**
     * Moves the data from table to table.
     * The colindex argument is the index of the column that was
     * added or removed. The adjust argument is {-1 | 0 | +1}
     */
void moveData(Session session, Table from, int colindex, int adjust) {
    Object colvalue = null;
    ColumnSchema column = null;
    if (adjust >= 0 && colindex != -1) {
        column = getColumn(colindex);
        colvalue = column.getDefaultValue(session);
    }
    PersistentStore store = session.sessionData.getRowStore(this);
    try {
        RowIterator it = from.rowIterator(session);
        while (it.hasNext()) {
            Row row = it.getNextRow();
            Object[] o = row.getData();
            Object[] data = getEmptyRowData();
            if (adjust == 0 && colindex != -1) {
                colvalue = column.getDataType().convertToType(session, o[colindex], from.getColumn(colindex).getDataType());
            }
            ArrayUtil.copyAdjustArray(o, data, colvalue, colindex, adjust);
            systemSetIdentityColumn(session, data);
            enforceRowConstraints(session, data);
            // get object without RowAction
            Row newrow = (Row) store.getNewCachedObject(null, data);
            if (row.rowAction != null) {
                newrow.rowAction = row.rowAction.duplicate(newrow.getPos());
            }
            store.indexRow(null, newrow);
        }
    } catch (Throwable t) {
        store.release();
        if (t instanceof HsqlException) {
            throw (HsqlException) t;
        }
        throw new HsqlException(t, "", 0);
    }
}
Also used : RowIterator(org.hsqldb_voltpatches.navigator.RowIterator) PersistentStore(org.hsqldb_voltpatches.persist.PersistentStore) CachedObject(org.hsqldb_voltpatches.persist.CachedObject)

Aggregations

RowIterator (org.hsqldb_voltpatches.navigator.RowIterator)14 Row (org.hsqldb_voltpatches.Row)4 Index (org.hsqldb_voltpatches.index.Index)4 PersistentStore (org.hsqldb_voltpatches.persist.PersistentStore)4 RowAVL (org.hsqldb_voltpatches.RowAVL)2 NodeAVL (org.hsqldb_voltpatches.index.NodeAVL)2 HashMappedList (org.hsqldb_voltpatches.lib.HashMappedList)2 IOException (java.io.IOException)1 HsqlException (org.hsqldb_voltpatches.HsqlException)1 Session (org.hsqldb_voltpatches.Session)1 Table (org.hsqldb_voltpatches.Table)1 DoubleIntIndex (org.hsqldb_voltpatches.lib.DoubleIntIndex)1 Iterator (org.hsqldb_voltpatches.lib.Iterator)1 CachedObject (org.hsqldb_voltpatches.persist.CachedObject)1 RowOutputBinary (org.hsqldb_voltpatches.rowio.RowOutputBinary)1 RowOutputInterface (org.hsqldb_voltpatches.rowio.RowOutputInterface)1