summaryrefslogtreecommitdiff
path: root/db/mork/src/morkTableRowCursor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'db/mork/src/morkTableRowCursor.cpp')
-rw-r--r--db/mork/src/morkTableRowCursor.cpp493
1 files changed, 493 insertions, 0 deletions
diff --git a/db/mork/src/morkTableRowCursor.cpp b/db/mork/src/morkTableRowCursor.cpp
new file mode 100644
index 0000000000..6f36932695
--- /dev/null
+++ b/db/mork/src/morkTableRowCursor.cpp
@@ -0,0 +1,493 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _MDB_
+#include "mdb.h"
+#endif
+
+#ifndef _MORK_
+#include "mork.h"
+#endif
+
+#ifndef _MORKNODE_
+#include "morkNode.h"
+#endif
+
+#ifndef _MORKENV_
+#include "morkEnv.h"
+#endif
+
+#ifndef _MORKCURSOR_
+#include "morkCursor.h"
+#endif
+
+#ifndef _MORKTABLEROWCURSOR_
+#include "morkTableRowCursor.h"
+#endif
+
+#ifndef _MORKSTORE_
+#include "morkStore.h"
+#endif
+
+#ifndef _MORKTABLE_
+#include "morkTable.h"
+#endif
+
+#ifndef _MORKROW_
+#include "morkRow.h"
+#endif
+
+//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+
+// ````` ````` ````` ````` `````
+// { ===== begin morkNode interface =====
+
+/*public virtual*/ void
+morkTableRowCursor::CloseMorkNode(morkEnv* ev) // CloseTableRowCursor() only if open
+{
+ if ( this->IsOpenNode() )
+ {
+ this->MarkClosing();
+ this->CloseTableRowCursor(ev);
+ this->MarkShut();
+ }
+}
+
+/*public virtual*/
+morkTableRowCursor::~morkTableRowCursor() // CloseTableRowCursor() executed earlier
+{
+ CloseMorkNode(mMorkEnv);
+ MORK_ASSERT(this->IsShutNode());
+}
+
+/*public non-poly*/
+morkTableRowCursor::morkTableRowCursor(morkEnv* ev,
+ const morkUsage& inUsage,
+ nsIMdbHeap* ioHeap, morkTable* ioTable, mork_pos inRowPos)
+: morkCursor(ev, inUsage, ioHeap)
+, mTableRowCursor_Table( 0 )
+{
+ if ( ev->Good() )
+ {
+ if ( ioTable )
+ {
+ mCursor_Pos = inRowPos;
+ mCursor_Seed = ioTable->TableSeed();
+ morkTable::SlotWeakTable(ioTable, ev, &mTableRowCursor_Table);
+ if ( ev->Good() )
+ mNode_Derived = morkDerived_kTableRowCursor;
+ }
+ else
+ ev->NilPointerError();
+ }
+}
+
+NS_IMPL_ISUPPORTS_INHERITED(morkTableRowCursor, morkCursor, nsIMdbTableRowCursor)
+/*public non-poly*/ void
+morkTableRowCursor::CloseTableRowCursor(morkEnv* ev)
+{
+ if ( this->IsNode() )
+ {
+ mCursor_Pos = -1;
+ mCursor_Seed = 0;
+ morkTable::SlotWeakTable((morkTable*) 0, ev, &mTableRowCursor_Table);
+ this->CloseCursor(ev);
+ this->MarkShut();
+ }
+ else
+ this->NonNodeError(ev);
+}
+
+// } ===== end morkNode methods =====
+// ````` ````` ````` ````` `````
+// { ----- begin attribute methods -----
+/*virtual*/ nsresult
+morkTableRowCursor::GetCount(nsIMdbEnv* mev, mdb_count* outCount)
+{
+ nsresult outErr = NS_OK;
+ mdb_count count = 0;
+ morkEnv* ev = morkEnv::FromMdbEnv(mev);
+ if ( ev )
+ {
+ count = GetMemberCount(ev);
+ outErr = ev->AsErr();
+ }
+ if ( outCount )
+ *outCount = count;
+ return outErr;
+}
+
+/*virtual*/ nsresult
+morkTableRowCursor::GetSeed(nsIMdbEnv* mev, mdb_seed* outSeed)
+{
+ NS_ASSERTION(false, "not implemented");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/*virtual*/ nsresult
+morkTableRowCursor::SetPos(nsIMdbEnv* mev, mdb_pos inPos)
+{
+ mCursor_Pos = inPos;
+ return NS_OK;
+}
+
+/*virtual*/ nsresult
+morkTableRowCursor::GetPos(nsIMdbEnv* mev, mdb_pos* outPos)
+{
+ *outPos = mCursor_Pos;
+ return NS_OK;
+}
+
+/*virtual*/ nsresult
+morkTableRowCursor::SetDoFailOnSeedOutOfSync(nsIMdbEnv* mev, mdb_bool inFail)
+{
+ mCursor_DoFailOnSeedOutOfSync = inFail;
+ return NS_OK;
+}
+
+/*virtual*/ nsresult
+morkTableRowCursor::GetDoFailOnSeedOutOfSync(nsIMdbEnv* mev, mdb_bool* outFail)
+{
+ NS_ENSURE_ARG_POINTER(outFail);
+ *outFail = mCursor_DoFailOnSeedOutOfSync;
+ return NS_OK;
+}
+// } ----- end attribute methods -----
+
+
+// { ===== begin nsIMdbTableRowCursor methods =====
+
+// { ----- begin attribute methods -----
+
+NS_IMETHODIMP
+morkTableRowCursor::GetTable(nsIMdbEnv* mev, nsIMdbTable** acqTable)
+{
+ nsresult outErr = NS_OK;
+ nsIMdbTable* outTable = 0;
+ morkEnv* ev = morkEnv::FromMdbEnv(mev);
+ if ( ev )
+ {
+ if ( mTableRowCursor_Table )
+ outTable = mTableRowCursor_Table->AcquireTableHandle(ev);
+
+ outErr = ev->AsErr();
+ }
+ if ( acqTable )
+ *acqTable = outTable;
+ return outErr;
+}
+// } ----- end attribute methods -----
+
+// { ----- begin oid iteration methods -----
+NS_IMETHODIMP
+morkTableRowCursor::NextRowOid( // get row id of next row in the table
+ nsIMdbEnv* mev, // context
+ mdbOid* outOid, // out row oid
+ mdb_pos* outRowPos)
+{
+ nsresult outErr = NS_OK;
+ mork_pos pos = -1;
+ morkEnv* ev = morkEnv::FromMdbEnv(mev);
+ if ( ev )
+ {
+ if ( outOid )
+ {
+ pos = NextRowOid(ev, outOid);
+ }
+ else
+ ev->NilPointerError();
+ outErr = ev->AsErr();
+ }
+ if ( outRowPos )
+ *outRowPos = pos;
+ return outErr;
+}
+
+NS_IMETHODIMP
+morkTableRowCursor::PrevRowOid( // get row id of previous row in the table
+ nsIMdbEnv* mev, // context
+ mdbOid* outOid, // out row oid
+ mdb_pos* outRowPos)
+{
+ nsresult outErr = NS_OK;
+ mork_pos pos = -1;
+ morkEnv* ev = morkEnv::FromMdbEnv(mev);
+ if ( ev )
+ {
+ if ( outOid )
+ {
+ pos = PrevRowOid(ev, outOid);
+ }
+ else
+ ev->NilPointerError();
+ outErr = ev->AsErr();
+ }
+ if ( outRowPos )
+ *outRowPos = pos;
+ return outErr;
+}
+// } ----- end oid iteration methods -----
+
+// { ----- begin row iteration methods -----
+NS_IMETHODIMP
+morkTableRowCursor::NextRow( // get row cells from table for cells already in row
+ nsIMdbEnv* mev, // context
+ nsIMdbRow** acqRow, // acquire next row in table
+ mdb_pos* outRowPos)
+{
+ nsresult outErr = NS_OK;
+ nsIMdbRow* outRow = 0;
+ morkEnv* ev = morkEnv::FromMdbEnv(mev);
+ if ( ev )
+ {
+
+ mdbOid oid; // place to put oid we intend to ignore
+ morkRow* row = NextRow(ev, &oid, outRowPos);
+ if ( row )
+ {
+ morkStore* store = row->GetRowSpaceStore(ev);
+ if ( store )
+ outRow = row->AcquireRowHandle(ev, store);
+ }
+ outErr = ev->AsErr();
+ }
+ if ( acqRow )
+ *acqRow = outRow;
+ return outErr;
+}
+
+NS_IMETHODIMP
+morkTableRowCursor::PrevRow( // get row cells from table for cells already in row
+ nsIMdbEnv* mev, // context
+ nsIMdbRow** acqRow, // acquire previous row in table
+ mdb_pos* outRowPos)
+{
+ nsresult outErr = NS_OK;
+ nsIMdbRow* outRow = 0;
+ morkEnv* ev = morkEnv::FromMdbEnv(mev);
+ if ( ev )
+ {
+
+ mdbOid oid; // place to put oid we intend to ignore
+ morkRow* row = PrevRow(ev, &oid, outRowPos);
+ if ( row )
+ {
+ morkStore* store = row->GetRowSpaceStore(ev);
+ if ( store )
+ outRow = row->AcquireRowHandle(ev, store);
+ }
+ outErr = ev->AsErr();
+ }
+ if ( acqRow )
+ *acqRow = outRow;
+ return outErr;
+}
+
+// } ----- end row iteration methods -----
+
+
+// { ----- begin duplicate row removal methods -----
+NS_IMETHODIMP
+morkTableRowCursor::CanHaveDupRowMembers(nsIMdbEnv* mev, // cursor might hold dups?
+ mdb_bool* outCanHaveDups)
+{
+ nsresult outErr = NS_OK;
+ mdb_bool canHaveDups = mdbBool_kFalse;
+
+ morkEnv* ev = morkEnv::FromMdbEnv(mev);
+ if ( ev )
+ {
+ canHaveDups = CanHaveDupRowMembers(ev);
+ outErr = ev->AsErr();
+ }
+ if ( outCanHaveDups )
+ *outCanHaveDups = canHaveDups;
+ return outErr;
+}
+
+NS_IMETHODIMP
+morkTableRowCursor::MakeUniqueCursor( // clone cursor, removing duplicate rows
+ nsIMdbEnv* mev, // context
+ nsIMdbTableRowCursor** acqCursor) // acquire clone with no dups
+ // Note that MakeUniqueCursor() is never necessary for a cursor which was
+ // created by table method nsIMdbTable::GetTableRowCursor(), because a table
+ // never contains the same row as a member more than once. However, a cursor
+ // created by table method nsIMdbTable::FindRowMatches() might contain the
+ // same row more than once, because the same row can generate a hit by more
+ // than one column with a matching string prefix. Note this method can
+ // return the very same cursor instance with just an incremented refcount,
+ // when the original cursor could not contain any duplicate rows (calling
+ // CanHaveDupRowMembers() shows this case on a false return). Otherwise
+ // this method returns a different cursor instance. Callers should not use
+ // this MakeUniqueCursor() method lightly, because it tends to defeat the
+ // purpose of lazy programming techniques, since it can force creation of
+ // an explicit row collection in a new cursor's representation, in order to
+ // inspect the row membership and remove any duplicates; this can have big
+ // impact if a collection holds tens of thousands of rows or more, when
+ // the original cursor with dups simply referenced rows indirectly by row
+ // position ranges, without using an explicit row set representation.
+ // Callers are encouraged to use nsIMdbCursor::GetCount() to determine
+ // whether the row collection is very large (tens of thousands), and to
+ // delay calling MakeUniqueCursor() when possible, until a user interface
+ // element actually demands the creation of an explicit set representation.
+{
+ nsresult outErr = NS_OK;
+ nsIMdbTableRowCursor* outCursor = 0;
+
+ morkEnv* ev = morkEnv::FromMdbEnv(mev);
+ if ( ev )
+ {
+ AddRef();
+ outCursor = this;
+
+ outErr = ev->AsErr();
+ }
+ if ( acqCursor )
+ *acqCursor = outCursor;
+ return outErr;
+}
+// } ----- end duplicate row removal methods -----
+
+// } ===== end nsIMdbTableRowCursor methods =====
+
+
+/*static*/ void
+morkTableRowCursor::NonTableRowCursorTypeError(morkEnv* ev)
+{
+ ev->NewError("non morkTableRowCursor");
+}
+
+
+mdb_pos
+morkTableRowCursor::NextRowOid(morkEnv* ev, mdbOid* outOid)
+{
+ mdb_pos outPos = -1;
+ (void) this->NextRow(ev, outOid, &outPos);
+ return outPos;
+}
+
+mdb_pos
+morkTableRowCursor::PrevRowOid(morkEnv* ev, mdbOid* outOid)
+{
+ mdb_pos outPos = -1;
+ (void) this->PrevRow(ev, outOid, &outPos);
+ return outPos;
+}
+
+mork_bool
+morkTableRowCursor::CanHaveDupRowMembers(morkEnv* ev)
+{
+ return morkBool_kFalse; // false default is correct
+}
+
+mork_count
+morkTableRowCursor::GetMemberCount(morkEnv* ev)
+{
+ morkTable* table = mTableRowCursor_Table;
+ if ( table )
+ return table->mTable_RowArray.mArray_Fill;
+ else
+ return 0;
+}
+
+morkRow*
+morkTableRowCursor::PrevRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos)
+{
+ morkRow* outRow = 0;
+ mork_pos pos = -1;
+
+ morkTable* table = mTableRowCursor_Table;
+ if ( table )
+ {
+ if ( table->IsOpenNode() )
+ {
+ morkArray* array = &table->mTable_RowArray;
+ pos = mCursor_Pos - 1;
+
+ if ( pos >= 0 && pos < (mork_pos)(array->mArray_Fill) )
+ {
+ mCursor_Pos = pos; // update for next time
+ morkRow* row = (morkRow*) array->At(pos);
+ if ( row )
+ {
+ if ( row->IsRow() )
+ {
+ outRow = row;
+ *outOid = row->mRow_Oid;
+ }
+ else
+ row->NonRowTypeError(ev);
+ }
+ else
+ ev->NilPointerError();
+ }
+ else
+ {
+ outOid->mOid_Scope = 0;
+ outOid->mOid_Id = morkId_kMinusOne;
+ }
+ }
+ else
+ table->NonOpenNodeError(ev);
+ }
+ else
+ ev->NilPointerError();
+
+ *outPos = pos;
+ return outRow;
+}
+
+morkRow*
+morkTableRowCursor::NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos)
+{
+ morkRow* outRow = 0;
+ mork_pos pos = -1;
+
+ morkTable* table = mTableRowCursor_Table;
+ if ( table )
+ {
+ if ( table->IsOpenNode() )
+ {
+ morkArray* array = &table->mTable_RowArray;
+ pos = mCursor_Pos;
+ if ( pos < 0 )
+ pos = 0;
+ else
+ ++pos;
+
+ if ( pos < (mork_pos)(array->mArray_Fill) )
+ {
+ mCursor_Pos = pos; // update for next time
+ morkRow* row = (morkRow*) array->At(pos);
+ if ( row )
+ {
+ if ( row->IsRow() )
+ {
+ outRow = row;
+ *outOid = row->mRow_Oid;
+ }
+ else
+ row->NonRowTypeError(ev);
+ }
+ else
+ ev->NilPointerError();
+ }
+ else
+ {
+ outOid->mOid_Scope = 0;
+ outOid->mOid_Id = morkId_kMinusOne;
+ }
+ }
+ else
+ table->NonOpenNodeError(ev);
+ }
+ else
+ ev->NilPointerError();
+
+ *outPos = pos;
+ return outRow;
+}
+
+//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789