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();
}
}
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);
}
}
}
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();
}
}
}
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);
}
}
Aggregations