/** * Checks the list of updates for violations. Updates must be ordered strictly from the highest to * the lowest PRE value. * * <p>A single node must not be affected by more than one {@link Rename}, {@link UpdateValue} * operation. * * <p>A single node must not be affected by more than one destructive operation. These operations * include {@link Replace}, {@link Delete}. */ public void check() { if (ok || updStructural.size() < 2 && updValue.size() < 2) return; int i = 0; while (i + 1 < updStructural.size()) { final BasicUpdate current = updStructural.get(i); final BasicUpdate next = updStructural.get(++i); // check order of location PRE if (current.location < next.location) Util.notexpected("Invalid order at location " + current.location); if (current.location == next.location) { // check multiple {@link Delete}, {@link Replace} if (current.destructive() && next.destructive()) Util.notexpected("Multiple deletes/replaces on node " + current.location); } } i = 0; while (i + 1 < updValue.size()) { final BasicUpdate current = updValue.get(i++); final BasicUpdate next = updValue.get(i); // check order of location PRE if (current.location < next.location) Util.notexpected("Invalid order at location " + current.location); if (current.location == next.location) { // check multiple {@link Rename} if (current instanceof Rename && next instanceof Rename) Util.notexpected("Multiple renames on node " + current.location); // check multiple {@link UpdateValue} if (current instanceof UpdateValue && next instanceof UpdateValue) Util.notexpected("Multiple updates on node " + current.location); } } ok = true; }
/** * Removes superfluous update operations. If a node T is deleted or replaced, all updates on the * descendant axis of T can be left out as they won't affect the database after all. * * <p>Superfluous updates can have a minimum PRE value of pre(T)+1 and a maximum PRE value of * pre(T)+size(T). * * <p>An update with location pre(T)+size(T) can only be removed if the update is an atomic insert * and the inserted node is then part of the subtree of T. */ public void optimize() { if (opt) return; check(); // traverse from lowest to highest PRE value int i = updStructural.size() - 1; while (i >= 0) { final BasicUpdate u = updStructural.get(i); // If this update can lead to superfluous updates ... if (u.destructive()) { // we determine the lowest and highest PRE values of a superfluous update final int pre = u.location; final int fol = pre + data.size(pre, data.kind(pre)); i--; // and have a look at the next candidate while (i >= 0) { final BasicUpdate desc = updStructural.get(i); final int descpre = desc.location; // if the candidate operates on the subtree of T and inserts a node ... if (descpre <= fol && (desc instanceof Insert || desc instanceof InsertAttr) && desc.parent() >= pre && desc.parent() < fol) { // it is removed. updStructural.remove(i--); // Other updates (not inserting a node) that operate on the subtree of T can // only have a PRE value that is smaller than the following PRE of T } else if (descpre < fol) { // these we delete. updStructural.remove(i--); // Else there's nothing to delete } else break; } } else i--; } opt = true; }