private Table tTable; // null: memory row; otherwise: cached table #endregion Fields #region Constructors /** * Constructor declaration * * * @param t * @param o */ public Row(Table t, object[] o) { tTable = t; int index = tTable.getIndexCount(); nFirstIndex = new Node(this, 0); Node n = nFirstIndex; for (int i = 1; i < index; i++) { n.nNext = new Node(this, i); n = n.nNext; } oData = o; if (tTable != null && tTable.cCache != null) { iLastAccess = iCurrentAccess++; // todo: 32 bytes overhead for each index + iSize, iPos iSize = 8 + Column.getSize(o, tTable) + 16 * tTable.getIndexCount(); //((iSize + 7) / 8) * 8; // align to 8 byte blocks tTable.cCache.add(this); } bChanged = true; }
/** * Method declaration * * * @return * * @throws Exception */ public bool findFirst() { if (iIndex == null) { iIndex = tTable.getPrimaryIndex(); } if (eStart == null) { nCurrent = iIndex.first(); } else { int type = eStart.getArg().getDataType(); object o = eStart.getArg2().getValue(type); nCurrent = iIndex.findFirst(o, eStart.getType()); } while (nCurrent != null) { oCurrentData = nCurrent.getData(); if (!test(eEnd)) { break; } if (test(eAnd)) { return true; } nCurrent = iIndex.next(nCurrent); } oCurrentData = oEmptyData; if (bOuterJoin) { return true; } return false; }
/** * Method declaration * * * @return * * @throws Exception */ public bool next() { if (bOuterJoin && nCurrent == null) { return false; } nCurrent = iIndex.next(nCurrent); while (nCurrent != null) { oCurrentData = nCurrent.getData(); if (!test(eEnd)) { break; } if (test(eAnd)) { return true; } nCurrent = iIndex.next(nCurrent); } oCurrentData = oEmptyData; return false; }
/** * Method declaration * * * @param n * * @throws Exception */ public void setRight(Node n) { if (Trace.ASSERT) { Trace.assert(iBalance != -2); } rData.changed(); if (n == null) { iRight = 0; nRight = null; } else if (n.rData.iPos != 0) { iRight = n.rData.iPos; } else { nRight = n; } }
/** * Method declaration * * * @param n * * @return * * @throws Exception */ public bool equals(Node n) { if (Trace.ASSERT) { Trace.assert(iBalance != -2); // rData.iLastAccess=Row.iCurrentAccess++; } if (Trace.ASSERT) { if (n != this) { Trace.assert(rData.iPos == 0 || n == null || n.rData.iPos != rData.iPos); } else { Trace.assert(n.rData.iPos == rData.iPos); } } return n == this; }
/** * Method declaration * */ public void delete() { iBalance = -2; nLeft = nRight = nParent = null; iLeft = iRight = iParent = 0; }
/** * Method declaration * * * @param row * @param datatoo * * @throws Exception */ public void delete(object[] row, bool datatoo) { Node x = search(row); if (x == null) { return; } Node n; if (x.getLeft() == null) { n = x.getRight(); } else if (x.getRight() == null) { n = x.getLeft(); } else { Node d = x; x = x.getLeft(); // todo: this can be improved while (x.getRight() != null) { if (Trace.STOP) { Trace.stop(); } x = x.getRight(); } // x will be replaced with n later n = x.getLeft(); // swap d and x int b = x.getBalance(); x.setBalance(d.getBalance()); d.setBalance(b); // set x.parent Node xp = x.getParent(); Node dp = d.getParent(); if (d == root) { root = x; } x.setParent(dp); if (dp != null) { if (dp.getRight().Equals(d)) { dp.setRight(x); } else { dp.setLeft(x); } } // for in-memory tables we could use: d.rData=x.rData; // but not for cached tables // relink d.parent, x.left, x.right if (xp == d) { d.setParent(x); if (d.getLeft().Equals(x)) { x.setLeft(d); x.setRight(d.getRight()); } else { x.setRight(d); x.setLeft(d.getLeft()); } } else { d.setParent(xp); xp.setRight(d); x.setRight(d.getRight()); x.setLeft(d.getLeft()); } x.getRight().setParent(x); x.getLeft().setParent(x); // set d.left, d.right d.setLeft(n); if (n != null) { n.setParent(d); } d.setRight(null); x = d; } bool way = from(x); replace(x, n); n = x.getParent(); x.delete(); if (datatoo) { x.rData.delete(); } while (n != null) { if (Trace.STOP) { Trace.stop(); } x = n; int sign = way ? 1 : -1; switch (x.getBalance() * sign) { case -1: x.setBalance(0); break; case 0: x.setBalance(sign); return; case 1: Node r = child(x, !way); int b = r.getBalance(); if (b * sign >= 0) { replace(x, r); set(x, !way, child(r, way)); set(r, way, x); if (b == 0) { x.setBalance(sign); r.setBalance(-sign); return; } x.setBalance(0); r.setBalance(0); x = r; } else { Node l = child(r, way); replace(x, l); b = l.getBalance(); set(r, way, child(l, !way)); set(l, !way, r); set(x, !way, child(l, way)); set(l, way, x); x.setBalance((b == sign) ? -sign : 0); r.setBalance((b == -sign) ? sign : 0); l.setBalance(0); x = l; } } way = from(x); n = x.getParent(); } }
/** * Method declaration * * * @param x * @param w * @param n * * @throws Exception */ private void set(Node x, bool w, Node n) { if (w) { x.setLeft(n); } else { x.setRight(n); } if (n != null) { n.setParent(x); } }
/** * Method declaration * * * @param x * @param n * * @throws Exception */ private void replace(Node x, Node n) { if (x.Equals(root)) { root = n; if (n != null) { n.setParent(null); } } else { set(x.getParent(), from(x), n); } }
/** * Method declaration * * * @param x * * @return * * @throws Exception */ private bool from(Node x) { if (x.Equals(root)) { return true; } if (Trace.ASSERT) { Trace.assert(x.getParent() != null); } return x.Equals(x.getParent().getLeft()); }
/** * Method declaration * * * @param x * @param w * * @return * * @throws Exception */ private Node child(Node x, bool w) { return w ? x.getLeft() : x.getRight(); }
/** * Method declaration * * * @param r */ public void setRoot(Node r) { root = r; }
/** * Method declaration * * * @param x * * @return * * @throws Exception */ public Node next(Node x) { if ((++iNeedCleanUp & 127) == 0) { x.rData.cleanUpCache(); } Node r = x.getRight(); if (r != null) { x = r; Node l = x.getLeft(); while (l != null) { if (Trace.STOP) { Trace.stop(); } x = l; l = x.getLeft(); } return x; } Node ch = x; x = x.getParent(); while (x != null && ch.Equals(x.getRight())) { if (Trace.STOP) { Trace.stop(); } ch = x; x = x.getParent(); } return x; }
/** * Method declaration * * * @param i * * @throws Exception */ public void insert(Node i) { object[] data = i.getData(); Node n = root, x = n; bool way = true; int compare = -1; while (true) { if (Trace.STOP) { Trace.stop(); } if (n == null) { if (x == null) { root = i; return; } set(x, way, i); break; } x = n; compare = compareRow(data, x.getData()); Trace.check(compare != 0, Trace.VIOLATION_OF_UNIQUE_INDEX); way = compare < 0; n = child(x, way); } while (true) { if (Trace.STOP) { Trace.stop(); } int sign = way ? 1 : -1; switch (x.getBalance() * sign) { case 1: x.setBalance(0); return; case 0: x.setBalance(-sign); break; case -1: Node l = child(x, way); if (l.getBalance() == -sign) { replace(x, l); set(x, way, child(l, !way)); set(l, !way, x); x.setBalance(0); l.setBalance(0); } else { Node r = child(l, !way); replace(x, r); set(l, !way, child(r, way)); set(r, way, l); set(x, way, child(r, !way)); set(r, !way, x); int rb = r.getBalance(); x.setBalance((rb == -sign) ? sign : 0); l.setBalance((rb == sign) ? -sign : 0); r.setBalance(0); } return; } if (x.Equals(root)) { return; } way = from(x); x = x.getParent(); } }
// if read from cache /** * Constructor declaration * * * @param t * @param in * @param pos * @param before */ public Row(Table t, BinaryReader din, int pos, Row before) { tTable = t; int index = tTable.getIndexCount(); iPos = pos; nFirstIndex = new Node(this, din, 0); Node n = nFirstIndex; for (int i = 1; i < index; i++) { n.nNext = new Node(this, din, i); n = n.nNext; } int l = tTable.getInternalColumnCount(); oData = Column.readData(din, l); int iCurrent = din.ReadInt32(); Trace.check(iCurrent == iPos, Trace.INPUTSTREAM_ERROR); insert(before); iLastAccess = iCurrentAccess++; }