diff options
Diffstat (limited to 'db/mork/src/morkTable.cpp')
-rw-r--r-- | db/mork/src/morkTable.cpp | 1610 |
1 files changed, 1610 insertions, 0 deletions
diff --git a/db/mork/src/morkTable.cpp b/db/mork/src/morkTable.cpp new file mode 100644 index 0000000000..aaa4bd50e4 --- /dev/null +++ b/db/mork/src/morkTable.cpp @@ -0,0 +1,1610 @@ +/* -*- 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 _MORKMAP_ +#include "morkMap.h" +#endif + +#ifndef _MORKENV_ +#include "morkEnv.h" +#endif + +#ifndef _MORKTABLE_ +#include "morkTable.h" +#endif + +#ifndef _MORKSTORE_ +#include "morkStore.h" +#endif + +#ifndef _MORKROWSPACE_ +#include "morkRowSpace.h" +#endif + +#ifndef _MORKARRAY_ +#include "morkArray.h" +#endif + +#ifndef _MORKROW_ +#include "morkRow.h" +#endif + +#ifndef _MORKTABLEROWCURSOR_ +#include "morkTableRowCursor.h" +#endif + +#ifndef _MORKROWOBJECT_ +#include "morkRowObject.h" +#endif + +//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +// ````` ````` ````` ````` ````` +// { ===== begin morkNode interface ===== + +/*public virtual*/ void +morkTable::CloseMorkNode(morkEnv* ev) /*i*/ // CloseTable() only if open +{ + if ( this->IsOpenNode() ) + { + morkObject::CloseMorkNode(ev); // give base class a chance. + this->MarkClosing(); + this->CloseTable(ev); + this->MarkShut(); + } +} + +/*public virtual*/ +morkTable::~morkTable() /*i*/ // assert CloseTable() executed earlier +{ + CloseMorkNode(mMorkEnv); + MORK_ASSERT(this->IsShutNode()); + MORK_ASSERT(mTable_Store==0); + MORK_ASSERT(mTable_RowSpace==0); +} + +/*public non-poly*/ +morkTable::morkTable(morkEnv* ev, /*i*/ + const morkUsage& inUsage, nsIMdbHeap* ioHeap, + morkStore* ioStore, nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace, + const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying + mork_tid inTid, mork_kind inKind, mork_bool inMustBeUnique) +: morkObject(ev, inUsage, ioHeap, (mork_color) inTid, (morkHandle*) 0) +, mTable_Store( 0 ) +, mTable_RowSpace( 0 ) +, mTable_MetaRow( 0 ) + +, mTable_RowMap( 0 ) +// , mTable_RowMap(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap, +// morkTable_kStartRowMapSlotCount) +, mTable_RowArray(ev, morkUsage::kMember, (nsIMdbHeap*) 0, + morkTable_kStartRowArraySize, ioSlotHeap) + +, mTable_ChangeList() +, mTable_ChangesCount( 0 ) +, mTable_ChangesMax( 3 ) // any very small number greater than zero + +, mTable_Kind( inKind ) + +, mTable_Flags( 0 ) +, mTable_Priority( morkPriority_kLo ) // NOT high priority +, mTable_GcUses( 0 ) +, mTable_Pad( 0 ) +{ + this->mLink_Next = 0; + this->mLink_Prev = 0; + + if ( ev->Good() ) + { + if ( ioStore && ioSlotHeap && ioRowSpace ) + { + if ( inKind ) + { + if ( inMustBeUnique ) + this->SetTableUnique(); + mTable_Store = ioStore; + mTable_RowSpace = ioRowSpace; + if ( inOptionalMetaRowOid ) + mTable_MetaRowOid = *inOptionalMetaRowOid; + else + { + mTable_MetaRowOid.mOid_Scope = 0; + mTable_MetaRowOid.mOid_Id = morkRow_kMinusOneRid; + } + if ( ev->Good() ) + { + if ( this->MaybeDirtySpaceStoreAndTable() ) + this->SetTableRewrite(); // everything is dirty + + mNode_Derived = morkDerived_kTable; + } + this->MaybeDirtySpaceStoreAndTable(); // new table might dirty store + } + else + ioRowSpace->ZeroKindError(ev); + } + else + ev->NilPointerError(); + } +} + +NS_IMPL_ISUPPORTS_INHERITED(morkTable, morkObject, nsIMdbTable) + +/*public non-poly*/ void +morkTable::CloseTable(morkEnv* ev) /*i*/ // called by CloseMorkNode(); +{ + if ( this->IsNode() ) + { + morkRowMap::SlotStrongRowMap((morkRowMap*) 0, ev, &mTable_RowMap); + // mTable_RowMap.CloseMorkNode(ev); + mTable_RowArray.CloseMorkNode(ev); + mTable_Store = 0; + mTable_RowSpace = 0; + this->MarkShut(); + } + else + this->NonNodeError(ev); +} + + +// } ===== end morkNode methods ===== +// ````` ````` ````` ````` ````` + +// { ===== begin nsIMdbCollection methods ===== + +// { ----- begin attribute methods ----- +NS_IMETHODIMP +morkTable::GetSeed(nsIMdbEnv* mev, + mdb_seed* outSeed) // member change count +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + *outSeed = mTable_RowArray.mArray_Seed; + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::GetCount(nsIMdbEnv* mev, + mdb_count* outCount) // member count +{ + NS_ENSURE_ARG_POINTER(outCount); + *outCount = mTable_RowArray.mArray_Fill; + return NS_OK; +} + +NS_IMETHODIMP +morkTable::GetPort(nsIMdbEnv* mev, + nsIMdbPort** acqPort) // collection container +{ + (void) morkEnv::FromMdbEnv(mev); + NS_ENSURE_ARG_POINTER(acqPort); + *acqPort = mTable_Store; + return NS_OK; +} +// } ----- end attribute methods ----- + +// { ----- begin cursor methods ----- +NS_IMETHODIMP +morkTable::GetCursor( // make a cursor starting iter at inMemberPos + nsIMdbEnv* mev, // context + mdb_pos inMemberPos, // zero-based ordinal pos of member in collection + nsIMdbCursor** acqCursor) // acquire new cursor instance +{ + return this->GetTableRowCursor(mev, inMemberPos, + (nsIMdbTableRowCursor**) acqCursor); +} +// } ----- end cursor methods ----- + +// { ----- begin ID methods ----- +NS_IMETHODIMP +morkTable::GetOid(nsIMdbEnv* mev, + mdbOid* outOid) // read object identity +{ + morkEnv* ev = morkEnv::FromMdbEnv(mev); + GetTableOid(ev, outOid); + return NS_OK; +} + +NS_IMETHODIMP +morkTable::BecomeContent(nsIMdbEnv* mev, + const mdbOid* inOid) // exchange content +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; + // remember table->MaybeDirtySpaceStoreAndTable(); +} + +// } ----- end ID methods ----- + +// { ----- begin activity dropping methods ----- +NS_IMETHODIMP +morkTable::DropActivity( // tell collection usage no longer expected + nsIMdbEnv* mev) +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +// } ----- end activity dropping methods ----- + +// } ===== end nsIMdbCollection methods ===== + +// { ===== begin nsIMdbTable methods ===== + +// { ----- begin attribute methods ----- + +NS_IMETHODIMP +morkTable::SetTablePriority(nsIMdbEnv* mev, mdb_priority inPrio) +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + if ( inPrio > morkPriority_kMax ) + inPrio = morkPriority_kMax; + + mTable_Priority = inPrio; + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::GetTablePriority(nsIMdbEnv* mev, mdb_priority* outPrio) +{ + nsresult outErr = NS_OK; + mork_priority prio = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + prio = mTable_Priority; + if ( prio > morkPriority_kMax ) + { + prio = morkPriority_kMax; + mTable_Priority = prio; + } + outErr = ev->AsErr(); + } + if ( outPrio ) + *outPrio = prio; + return outErr; +} + + +NS_IMETHODIMP +morkTable:: GetTableBeVerbose(nsIMdbEnv* mev, mdb_bool* outBeVerbose) +{ + NS_ENSURE_ARG_POINTER(outBeVerbose); + *outBeVerbose = IsTableVerbose(); + return NS_OK; +} + +NS_IMETHODIMP +morkTable::SetTableBeVerbose(nsIMdbEnv* mev, mdb_bool inBeVerbose) +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + if ( inBeVerbose ) + SetTableVerbose(); + else + ClearTableVerbose(); + + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::GetTableIsUnique(nsIMdbEnv* mev, mdb_bool* outIsUnique) +{ + NS_ENSURE_ARG_POINTER(outIsUnique); + *outIsUnique = IsTableUnique(); + return NS_OK; +} + +NS_IMETHODIMP +morkTable::GetTableKind(nsIMdbEnv* mev, mdb_kind* outTableKind) +{ + NS_ENSURE_ARG_POINTER(outTableKind); + *outTableKind = mTable_Kind; + return NS_OK; +} + +NS_IMETHODIMP +morkTable::GetRowScope(nsIMdbEnv* mev, mdb_scope* outRowScope) +{ + nsresult outErr = NS_OK; + mdb_scope rowScope = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + if ( mTable_RowSpace ) + rowScope = mTable_RowSpace->SpaceScope(); + else + NilRowSpaceError(ev); + + outErr = ev->AsErr(); + } + if ( outRowScope ) + *outRowScope = rowScope; + return outErr; +} + +NS_IMETHODIMP +morkTable::GetMetaRow( nsIMdbEnv* mev, + const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying + mdbOid* outOid, // output meta row oid, can be nil to suppress output + nsIMdbRow** acqRow) // acquire table's unique singleton meta row + // The purpose of a meta row is to support the persistent recording of + // meta info about a table as cells put into the distinguished meta row. + // Each table has exactly one meta row, which is not considered a member + // of the collection of rows inside the table. The only way to tell + // whether a row is a meta row is by the fact that it is returned by this + // GetMetaRow() method from some table. Otherwise nothing distinguishes + // a meta row from any other row. A meta row can be used anyplace that + // any other row can be used, and can even be put into other tables (or + // the same table) as a table member, if this is useful for some reason. + // The first attempt to access a table's meta row using GetMetaRow() will + // cause the meta row to be created if it did not already exist. When the + // meta row is created, it will have the row oid that was previously + // requested for this table's meta row; or if no oid was ever explicitly + // specified for this meta row, then a unique oid will be generated in + // the row scope named "metaScope" (so obviously MDB clients should not + // manually allocate any row IDs from that special meta scope namespace). + // The meta row oid can be specified either when the table is created, or + // else the first time that GetMetaRow() is called, by passing a non-nil + // pointer to an oid for parameter inOptionalMetaRowOid. The meta row's + // actual oid is returned in outOid (if this is a non-nil pointer), and + // it will be different from inOptionalMetaRowOid when the meta row was + // already given a different oid earlier. +{ + nsresult outErr = NS_OK; + nsIMdbRow* outRow = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkRow* row = GetMetaRow(ev, inOptionalMetaRowOid); + if ( row && ev->Good() ) + { + if ( outOid ) + *outOid = row->mRow_Oid; + + outRow = row->AcquireRowHandle(ev, mTable_Store); + } + outErr = ev->AsErr(); + } + if ( acqRow ) + *acqRow = outRow; + + if ( ev->Bad() && outOid ) + { + outOid->mOid_Scope = 0; + outOid->mOid_Id = morkRow_kMinusOneRid; + } + return outErr; +} + +// } ----- end attribute methods ----- + +// { ----- begin cursor methods ----- +NS_IMETHODIMP +morkTable::GetTableRowCursor( // make a cursor, starting iteration at inRowPos + nsIMdbEnv* mev, // context + mdb_pos inRowPos, // zero-based ordinal position of row in table + nsIMdbTableRowCursor** acqCursor) // acquire new cursor instance +{ + nsresult outErr = NS_OK; + nsIMdbTableRowCursor* outCursor = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkTableRowCursor* cursor = NewTableRowCursor(ev, inRowPos); + if ( cursor ) + { + if ( ev->Good() ) + { + // cursor->mCursor_Seed = (mork_seed) inRowPos; + outCursor = cursor; + outCursor->AddRef(); + } + } + + outErr = ev->AsErr(); + } + if ( acqCursor ) + *acqCursor = outCursor; + return outErr; +} +// } ----- end row position methods ----- + +// { ----- begin row position methods ----- +NS_IMETHODIMP +morkTable::PosToOid( // get row member for a table position + nsIMdbEnv* mev, // context + mdb_pos inRowPos, // zero-based ordinal position of row in table + mdbOid* outOid) // row oid at the specified position +{ + nsresult outErr = NS_OK; + mdbOid roid; + roid.mOid_Scope = 0; + roid.mOid_Id = (mork_id) -1; + + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkRow* row = SafeRowAt(ev, inRowPos); + if ( row ) + roid = row->mRow_Oid; + + outErr = ev->AsErr(); + } + if ( outOid ) + *outOid = roid; + return outErr; +} + +NS_IMETHODIMP +morkTable::OidToPos( // test for the table position of a row member + nsIMdbEnv* mev, // context + const mdbOid* inOid, // row to find in table + mdb_pos* outPos) // zero-based ordinal position of row in table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + mork_pos pos = ArrayHasOid(ev, inOid); + if ( outPos ) + *outPos = pos; + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::PosToRow( // get row member for a table position + nsIMdbEnv* mev, // context + mdb_pos inRowPos, // zero-based ordinal position of row in table + nsIMdbRow** acqRow) // acquire row at table position inRowPos +{ + nsresult outErr = NS_OK; + nsIMdbRow* outRow = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkRow* row = SafeRowAt(ev, inRowPos); + if ( row && mTable_Store ) + outRow = row->AcquireRowHandle(ev, mTable_Store); + + outErr = ev->AsErr(); + } + if ( acqRow ) + *acqRow = outRow; + return outErr; +} + +NS_IMETHODIMP +morkTable::RowToPos( // test for the table position of a row member + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow, // row to find in table + mdb_pos* outPos) // zero-based ordinal position of row in table +{ + nsresult outErr = NS_OK; + mork_pos pos = -1; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkRowObject* row = (morkRowObject*) ioRow; + pos = ArrayHasOid(ev, &row->mRowObject_Row->mRow_Oid); + outErr = ev->AsErr(); + } + if ( outPos ) + *outPos = pos; + return outErr; +} + +// Note that HasRow() performs the inverse oid->pos mapping +// } ----- end row position methods ----- + +// { ----- begin oid set methods ----- +NS_IMETHODIMP +morkTable::AddOid( // make sure the row with inOid is a table member + nsIMdbEnv* mev, // context + const mdbOid* inOid) // row to ensure membership in table +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::HasOid( // test for the table position of a row member + nsIMdbEnv* mev, // context + const mdbOid* inOid, // row to find in table + mdb_bool* outHasOid) // whether inOid is a member row +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + if ( outHasOid ) + *outHasOid = MapHasOid(ev, inOid); + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::CutOid( // make sure the row with inOid is not a member + nsIMdbEnv* mev, // context + const mdbOid* inOid) // row to remove from table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + if ( inOid && mTable_Store ) + { + morkRow* row = mTable_Store->GetRow(ev, inOid); + if ( row ) + CutRow(ev, row); + } + else + ev->NilPointerError(); + + outErr = ev->AsErr(); + } + return outErr; +} +// } ----- end oid set methods ----- + +// { ----- begin row set methods ----- +NS_IMETHODIMP +morkTable::NewRow( // create a new row instance in table + nsIMdbEnv* mev, // context + mdbOid* ioOid, // please use zero (unbound) rowId for db-assigned IDs + nsIMdbRow** acqRow) // create new row +{ + nsresult outErr = NS_OK; + nsIMdbRow* outRow = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + if ( ioOid && mTable_Store ) + { + morkRow* row = 0; + if ( ioOid->mOid_Id == morkRow_kMinusOneRid ) + row = mTable_Store->NewRow(ev, ioOid->mOid_Scope); + else + row = mTable_Store->NewRowWithOid(ev, ioOid); + + if ( row && AddRow(ev, row) ) + outRow = row->AcquireRowHandle(ev, mTable_Store); + } + else + ev->NilPointerError(); + + outErr = ev->AsErr(); + } + if ( acqRow ) + *acqRow = outRow; + return outErr; +} + +NS_IMETHODIMP +morkTable::AddRow( // make sure the row with inOid is a table member + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow) // row to ensure membership in table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkRowObject *rowObj = (morkRowObject *) ioRow; + morkRow* row = rowObj->mRowObject_Row; + AddRow(ev, row); + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::HasRow( // test for the table position of a row member + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow, // row to find in table + mdb_bool* outBool) // zero-based ordinal position of row in table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkRowObject *rowObj = (morkRowObject *) ioRow; + morkRow* row = rowObj->mRowObject_Row; + if ( outBool ) + *outBool = MapHasOid(ev, &row->mRow_Oid); + outErr = ev->AsErr(); + } + return outErr; +} + + +NS_IMETHODIMP +morkTable::CutRow( // make sure the row with inOid is not a member + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow) // row to remove from table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkRowObject *rowObj = (morkRowObject *) ioRow; + morkRow* row = rowObj->mRowObject_Row; + CutRow(ev, row); + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::CutAllRows( // remove all rows from the table + nsIMdbEnv* mev) // context +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + CutAllRows(ev); + outErr = ev->AsErr(); + } + return outErr; +} +// } ----- end row set methods ----- + +// { ----- begin searching methods ----- +NS_IMETHODIMP +morkTable::FindRowMatches( // search variable number of sorted cols + nsIMdbEnv* mev, // context + const mdbYarn* inPrefix, // content to find as prefix in row's column cell + nsIMdbTableRowCursor** acqCursor) // set of matching rows +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::GetSearchColumns( // query columns used by FindRowMatches() + nsIMdbEnv* mev, // context + mdb_count* outCount, // context + mdbColumnSet* outColSet) // caller supplied space to put columns + // GetSearchColumns() returns the columns actually searched when the + // FindRowMatches() method is called. No more than mColumnSet_Count + // slots of mColumnSet_Columns will be written, since mColumnSet_Count + // indicates how many slots are present in the column array. The + // actual number of search column used by the table is returned in + // the outCount parameter; if this number exceeds mColumnSet_Count, + // then a caller needs a bigger array to read the entire column set. + // The minimum of mColumnSet_Count and outCount is the number slots + // in mColumnSet_Columns that were actually written by this method. + // + // Callers are expected to change this set of columns by calls to + // nsIMdbTable::SearchColumnsHint() or SetSearchSorting(), or both. +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} +// } ----- end searching methods ----- + +// { ----- begin hinting methods ----- +NS_IMETHODIMP +morkTable::SearchColumnsHint( // advise re future expected search cols + nsIMdbEnv* mev, // context + const mdbColumnSet* inColumnSet) // columns likely to be searched +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::SortColumnsHint( // advise re future expected sort columns + nsIMdbEnv* mev, // context + const mdbColumnSet* inColumnSet) // columns for likely sort requests +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::StartBatchChangeHint( // advise before many adds and cuts + nsIMdbEnv* mev, // context + const void* inLabel) // intend unique address to match end call + // If batch starts nest by virtue of nesting calls in the stack, then + // the address of a local variable makes a good batch start label that + // can be used at batch end time, and such addresses remain unique. +{ + // we don't do anything here. + return NS_OK; +} + +NS_IMETHODIMP +morkTable::EndBatchChangeHint( // advise before many adds and cuts + nsIMdbEnv* mev, // context + const void* inLabel) // label matching start label + // Suppose a table is maintaining one or many sort orders for a table, + // so that every row added to the table must be inserted in each sort, + // and every row cut must be removed from each sort. If a db client + // intends to make many such changes before needing any information + // about the order or positions of rows inside a table, then a client + // might tell the table to start batch changes in order to disable + // sorting of rows for the interim. Presumably a table will then do + // a full sort of all rows at need when the batch changes end, or when + // a surprise request occurs for row position during batch changes. +{ + // we don't do anything here. + return NS_OK; +} +// } ----- end hinting methods ----- + +// { ----- begin sorting methods ----- +// sorting: note all rows are assumed sorted by row ID as a secondary +// sort following the primary column sort, when table rows are sorted. + +NS_IMETHODIMP +morkTable::CanSortColumn( // query which column is currently used for sorting + nsIMdbEnv* mev, // context + mdb_column inColumn, // column to query sorting potential + mdb_bool* outCanSort) // whether the column can be sorted +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::GetSorting( // view same table in particular sorting + nsIMdbEnv* mev, // context + mdb_column inColumn, // requested new column for sorting table + nsIMdbSorting** acqSorting) // acquire sorting for column +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::SetSearchSorting( // use this sorting in FindRowMatches() + nsIMdbEnv* mev, // context + mdb_column inColumn, // often same as nsIMdbSorting::GetSortColumn() + nsIMdbSorting* ioSorting) // requested sorting for some column + // SetSearchSorting() attempts to inform the table that ioSorting + // should be used during calls to FindRowMatches() for searching + // the column which is actually sorted by ioSorting. This method + // is most useful in conjunction with nsIMdbSorting::SetCompare(), + // because otherwise a caller would not be able to override the + // comparison ordering method used during searchs. Note that some + // database implementations might be unable to use an arbitrarily + // specified sort order, either due to schema or runtime interface + // constraints, in which case ioSorting might not actually be used. + // Presumably ioSorting is an instance that was returned from some + // earlier call to nsIMdbTable::GetSorting(). A caller can also + // use nsIMdbTable::SearchColumnsHint() to specify desired change + // in which columns are sorted and searched by FindRowMatches(). + // + // A caller can pass a nil pointer for ioSorting to request that + // column inColumn no longer be used at all by FindRowMatches(). + // But when ioSorting is non-nil, then inColumn should match the + // column actually sorted by ioSorting; when these do not agree, + // implementations are instructed to give precedence to the column + // specified by ioSorting (so this means callers might just pass + // zero for inColumn when ioSorting is also provided, since then + // inColumn is both redundant and ignored). +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +// } ----- end sorting methods ----- + +// { ----- begin moving methods ----- +// moving a row does nothing unless a table is currently unsorted + +NS_IMETHODIMP +morkTable::MoveOid( // change position of row in unsorted table + nsIMdbEnv* mev, // context + const mdbOid* inOid, // row oid to find in table + mdb_pos inHintFromPos, // suggested hint regarding start position + mdb_pos inToPos, // desired new position for row inOid + mdb_pos* outActualPos) // actual new position of row in table +{ + nsresult outErr = NS_OK; + mdb_pos actualPos = -1; // meaning it was never found in table + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + if ( inOid && mTable_Store ) + { + morkRow* row = mTable_Store->GetRow(ev, inOid); + if ( row ) + actualPos = MoveRow(ev, row, inHintFromPos, inToPos); + } + else + ev->NilPointerError(); + + outErr = ev->AsErr(); + } + if ( outActualPos ) + *outActualPos = actualPos; + return outErr; +} + +NS_IMETHODIMP +morkTable::MoveRow( // change position of row in unsorted table + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow, // row oid to find in table + mdb_pos inHintFromPos, // suggested hint regarding start position + mdb_pos inToPos, // desired new position for row ioRow + mdb_pos* outActualPos) // actual new position of row in table +{ + mdb_pos actualPos = -1; // meaning it was never found in table + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if ( ev ) + { + morkRowObject *rowObj = (morkRowObject *) ioRow; + morkRow* row = rowObj->mRowObject_Row; + actualPos = MoveRow(ev, row, inHintFromPos, inToPos); + outErr = ev->AsErr(); + } + if ( outActualPos ) + *outActualPos = actualPos; + return outErr; +} +// } ----- end moving methods ----- + +// { ----- begin index methods ----- +NS_IMETHODIMP +morkTable::AddIndex( // create a sorting index for column if possible + nsIMdbEnv* mev, // context + mdb_column inColumn, // the column to sort by index + nsIMdbThumb** acqThumb) // acquire thumb for incremental index building +// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and +// then the index addition will be finished. +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::CutIndex( // stop supporting a specific column index + nsIMdbEnv* mev, // context + mdb_column inColumn, // the column with index to be removed + nsIMdbThumb** acqThumb) // acquire thumb for incremental index destroy +// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and +// then the index removal will be finished. +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::HasIndex( // query for current presence of a column index + nsIMdbEnv* mev, // context + mdb_column inColumn, // the column to investigate + mdb_bool* outHasIndex) // whether column has index for this column +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::EnableIndexOnSort( // create an index for col on first sort + nsIMdbEnv* mev, // context + mdb_column inColumn) // the column to index if ever sorted +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::QueryIndexOnSort( // check whether index on sort is enabled + nsIMdbEnv* mev, // context + mdb_column inColumn, // the column to investigate + mdb_bool* outIndexOnSort) // whether column has index-on-sort enabled +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::DisableIndexOnSort( // prevent future index creation on sort + nsIMdbEnv* mev, // context + mdb_column inColumn) // the column to index if ever sorted +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} +// } ----- end index methods ----- + +// } ===== end nsIMdbTable methods ===== + +// we override these so that we'll use the xpcom add and release ref. +#ifndef _MSC_VER +mork_refs +morkTable::AddStrongRef(nsIMdbEnv *ev) +{ + return (mork_refs) AddRef(); +} +#endif + +mork_refs +morkTable::AddStrongRef(morkEnv *ev) +{ + return (mork_refs) AddRef(); +} + +#ifndef _MSC_VER +nsresult +morkTable::CutStrongRef(nsIMdbEnv *ev) +{ + return (nsresult) Release(); +} +#endif + +mork_refs +morkTable::CutStrongRef(morkEnv *ev) +{ + return (mork_refs) Release(); +} + +mork_u2 +morkTable::AddTableGcUse(morkEnv* ev) +{ + MORK_USED_1(ev); + if ( mTable_GcUses < morkTable_kMaxTableGcUses ) // not already maxed out? + ++mTable_GcUses; + + return mTable_GcUses; +} + +mork_u2 +morkTable::CutTableGcUse(morkEnv* ev) +{ + if ( mTable_GcUses ) // any outstanding uses to cut? + { + if ( mTable_GcUses < morkTable_kMaxTableGcUses ) // not frozen at max? + --mTable_GcUses; + } + else + this->TableGcUsesUnderflowWarning(ev); + + return mTable_GcUses; +} + +// table dirty handling more complex thatn morkNode::SetNodeDirty() etc. + +void morkTable::SetTableClean(morkEnv* ev) +{ + if ( mTable_ChangeList.HasListMembers() ) + { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes + } + mTable_ChangesCount = 0; + + mTable_Flags = 0; + this->SetNodeClean(); +} + +// notifications regarding table changes: + +void morkTable::NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos) +{ + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + if ( this->IsTableRewrite() || this->HasChangeOverflow() ) + this->NoteTableSetAll(ev); + else + { + morkTableChange* tableChange = new(*heap, ev) + morkTableChange(ev, ioRow, inPos); + if ( tableChange ) + { + if ( ev->Good() ) + { + mTable_ChangeList.PushTail(tableChange); + ++mTable_ChangesCount; + } + else + { + tableChange->ZapOldNext(ev, heap); + this->SetTableRewrite(); // just plan to write all table rows + } + } + } +} + +void morkTable::note_row_move(morkEnv* ev, morkRow* ioRow, mork_pos inNewPos) +{ + if ( this->IsTableRewrite() || this->HasChangeOverflow() ) + this->NoteTableSetAll(ev); + else + { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + morkTableChange* tableChange = new(*heap, ev) + morkTableChange(ev, ioRow, inNewPos); + if ( tableChange ) + { + if ( ev->Good() ) + { + mTable_ChangeList.PushTail(tableChange); + ++mTable_ChangesCount; + } + else + { + tableChange->ZapOldNext(ev, heap); + this->NoteTableSetAll(ev); + } + } + } +} + +void morkTable::note_row_change(morkEnv* ev, mork_change inChange, + morkRow* ioRow) +{ + if ( this->IsTableRewrite() || this->HasChangeOverflow() ) + this->NoteTableSetAll(ev); + else + { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + morkTableChange* tableChange = new(*heap, ev) + morkTableChange(ev, inChange, ioRow); + if ( tableChange ) + { + if ( ev->Good() ) + { + mTable_ChangeList.PushTail(tableChange); + ++mTable_ChangesCount; + } + else + { + tableChange->ZapOldNext(ev, heap); + this->NoteTableSetAll(ev); + } + } + } +} + +void morkTable::NoteTableSetAll(morkEnv* ev) +{ + if ( mTable_ChangeList.HasListMembers() ) + { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes + } + mTable_ChangesCount = 0; + this->SetTableRewrite(); +} + +/*static*/ void +morkTable::TableGcUsesUnderflowWarning(morkEnv* ev) +{ + ev->NewWarning("mTable_GcUses underflow"); +} + +/*static*/ void +morkTable::NonTableTypeError(morkEnv* ev) +{ + ev->NewError("non morkTable"); +} + +/*static*/ void +morkTable::NonTableTypeWarning(morkEnv* ev) +{ + ev->NewWarning("non morkTable"); +} + +/*static*/ void +morkTable::NilRowSpaceError(morkEnv* ev) +{ + ev->NewError("nil mTable_RowSpace"); +} + +mork_bool morkTable::MaybeDirtySpaceStoreAndTable() +{ + morkRowSpace* rowSpace = mTable_RowSpace; + if ( rowSpace ) + { + morkStore* store = rowSpace->mSpace_Store; + if ( store && store->mStore_CanDirty ) + { + store->SetStoreDirty(); + rowSpace->mSpace_CanDirty = morkBool_kTrue; + } + + if ( rowSpace->mSpace_CanDirty ) // first time being dirtied? + { + if ( this->IsTableClean() ) + { + mork_count rowCount = this->GetRowCount(); + mork_count oneThird = rowCount / 4; // one third of rows + if ( oneThird > 0x07FFF ) // more than half max u2? + oneThird = 0x07FFF; + + mTable_ChangesMax = (mork_u2) oneThird; + } + this->SetTableDirty(); + rowSpace->SetRowSpaceDirty(); + + return morkBool_kTrue; + } + } + return morkBool_kFalse; +} + +morkRow* +morkTable::GetMetaRow(morkEnv* ev, const mdbOid* inOptionalMetaRowOid) +{ + morkRow* outRow = mTable_MetaRow; + if ( !outRow ) + { + morkStore* store = mTable_Store; + mdbOid* oid = &mTable_MetaRowOid; + if ( inOptionalMetaRowOid && !oid->mOid_Scope ) + *oid = *inOptionalMetaRowOid; + + if ( oid->mOid_Scope ) // oid already recorded in table? + outRow = store->OidToRow(ev, oid); + else + { + outRow = store->NewRow(ev, morkStore_kMetaScope); + if ( outRow ) // need to record new oid in table? + *oid = outRow->mRow_Oid; + } + mTable_MetaRow = outRow; + if ( outRow ) // need to note another use of this row? + { + outRow->AddRowGcUse(ev); + + this->SetTableNewMeta(); + if ( this->IsTableClean() ) // catch dirty status of meta row? + this->MaybeDirtySpaceStoreAndTable(); + } + } + + return outRow; +} + +void +morkTable::GetTableOid(morkEnv* ev, mdbOid* outOid) +{ + morkRowSpace* space = mTable_RowSpace; + if ( space ) + { + outOid->mOid_Scope = space->SpaceScope(); + outOid->mOid_Id = this->TableId(); + } + else + this->NilRowSpaceError(ev); +} + +nsIMdbTable* +morkTable::AcquireTableHandle(morkEnv* ev) +{ + AddRef(); + return this; +} + +mork_pos +morkTable::ArrayHasOid(morkEnv* ev, const mdbOid* inOid) +{ + MORK_USED_1(ev); + mork_count count = mTable_RowArray.mArray_Fill; + mork_pos pos = -1; + while ( ++pos < (mork_pos)count ) + { + morkRow* row = (morkRow*) mTable_RowArray.At(pos); + MORK_ASSERT(row); + if ( row && row->EqualOid(inOid) ) + { + return pos; + } + } + return -1; +} + +mork_bool +morkTable::MapHasOid(morkEnv* ev, const mdbOid* inOid) +{ + if ( mTable_RowMap ) + return ( mTable_RowMap->GetOid(ev, inOid) != 0 ); + else + return ( ArrayHasOid(ev, inOid) >= 0 ); +} + +void morkTable::build_row_map(morkEnv* ev) +{ + morkRowMap* map = mTable_RowMap; + if ( !map ) + { + mork_count count = mTable_RowArray.mArray_Fill + 3; + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + map = new(*heap, ev) morkRowMap(ev, morkUsage::kHeap, heap, heap, count); + if ( map ) + { + if ( ev->Good() ) + { + mTable_RowMap = map; // put strong ref here + count = mTable_RowArray.mArray_Fill; + mork_pos pos = -1; + while ( ++pos < (mork_pos)count ) + { + morkRow* row = (morkRow*) mTable_RowArray.At(pos); + if ( row && row->IsRow() ) + map->AddRow(ev, row); + else + row->NonRowTypeError(ev); + } + } + else + map->CutStrongRef(ev); + } + } +} + +morkRow* morkTable::find_member_row(morkEnv* ev, morkRow* ioRow) +{ + if ( mTable_RowMap ) + return mTable_RowMap->GetRow(ev, ioRow); + else + { + mork_count count = mTable_RowArray.mArray_Fill; + mork_pos pos = -1; + while ( ++pos < (mork_pos)count ) + { + morkRow* row = (morkRow*) mTable_RowArray.At(pos); + if ( row == ioRow ) + return row; + } + } + return (morkRow*) 0; +} + +mork_pos +morkTable::MoveRow(morkEnv* ev, morkRow* ioRow, // change row position + mork_pos inHintFromPos, // suggested hint regarding start position + mork_pos inToPos) // desired new position for row ioRow + // MoveRow() returns the actual position of ioRow afterwards; this + // position is -1 if and only if ioRow was not found as a member. +{ + mork_pos outPos = -1; // means ioRow was not a table member + mork_bool canDirty = ( this->IsTableClean() )? + this->MaybeDirtySpaceStoreAndTable() : morkBool_kTrue; + + morkRow** rows = (morkRow**) mTable_RowArray.mArray_Slots; + mork_count count = mTable_RowArray.mArray_Fill; + if ( count && rows && ev->Good() ) // any members at all? no errors? + { + mork_pos lastPos = count - 1; // index of last row slot + + if ( inToPos > lastPos ) // beyond last used array slot? + inToPos = lastPos; // put row into last available slot + else if ( inToPos < 0 ) // before first usable slot? + inToPos = 0; // put row in very first slow + + if ( inHintFromPos > lastPos ) // beyond last used array slot? + inHintFromPos = lastPos; // seek row in last available slot + else if ( inHintFromPos < 0 ) // before first usable slot? + inHintFromPos = 0; // seek row in very first slow + + morkRow** fromSlot = 0; // becomes nonzero of ioRow is ever found + morkRow** rowsEnd = rows + count; // one past last used array slot + + if ( inHintFromPos <= 0 ) // start of table? just scan for row? + { + morkRow** cursor = rows - 1; // before first array slot + while ( ++cursor < rowsEnd ) + { + if ( *cursor == ioRow ) + { + fromSlot = cursor; + break; // end while loop + } + } + } + else // search near the start position and work outwards + { + morkRow** lo = rows + inHintFromPos; // lowest search point + morkRow** hi = lo; // highest search point starts at lowest point + + // Seek ioRow in spiral widening search below and above inHintFromPos. + // This is faster when inHintFromPos is at all accurate, but is slower + // than a straightforward scan when inHintFromPos is nearly random. + + while ( lo >= rows || hi < rowsEnd ) // keep searching? + { + if ( lo >= rows ) // low direction search still feasible? + { + if ( *lo == ioRow ) // actually found the row? + { + fromSlot = lo; + break; // end while loop + } + --lo; // advance further lower + } + if ( hi < rowsEnd ) // high direction search still feasible? + { + if ( *hi == ioRow ) // actually found the row? + { + fromSlot = hi; + break; // end while loop + } + ++hi; // advance further higher + } + } + } + + if ( fromSlot ) // ioRow was found as a table member? + { + outPos = fromSlot - rows; // actual position where row was found + if ( outPos != inToPos ) // actually need to move this row? + { + morkRow** toSlot = rows + inToPos; // slot where row must go + + ++mTable_RowArray.mArray_Seed; // we modify the array now: + + if ( fromSlot < toSlot ) // row is moving upwards? + { + morkRow** up = fromSlot; // leading pointer going upward + while ( ++up <= toSlot ) // have not gone above destination? + { + *fromSlot = *up; // shift down one + fromSlot = up; // shift trailing pointer up + } + } + else // ( fromSlot > toSlot ) // row is moving downwards + { + morkRow** down = fromSlot; // leading pointer going downward + while ( --down >= toSlot ) // have not gone below destination? + { + *fromSlot = *down; // shift up one + fromSlot = down; // shift trailing pointer + } + } + *toSlot = ioRow; + outPos = inToPos; // okay, we actually moved the row here + + if ( canDirty ) + this->note_row_move(ev, ioRow, inToPos); + } + } + } + return outPos; +} + +mork_bool +morkTable::AddRow(morkEnv* ev, morkRow* ioRow) +{ + morkRow* row = this->find_member_row(ev, ioRow); + if ( !row && ev->Good() ) + { + mork_bool canDirty = ( this->IsTableClean() )? + this->MaybeDirtySpaceStoreAndTable() : morkBool_kTrue; + + mork_pos pos = mTable_RowArray.AppendSlot(ev, ioRow); + if ( ev->Good() && pos >= 0 ) + { + ioRow->AddRowGcUse(ev); + if ( mTable_RowMap ) + { + if ( mTable_RowMap->AddRow(ev, ioRow) ) + { + // okay, anything else? + } + else + mTable_RowArray.CutSlot(ev, pos); + } + else if ( mTable_RowArray.mArray_Fill >= morkTable_kMakeRowMapThreshold ) + this->build_row_map(ev); + + if ( canDirty && ev->Good() ) + this->NoteTableAddRow(ev, ioRow); + } + } + return ev->Good(); +} + +mork_bool +morkTable::CutRow(morkEnv* ev, morkRow* ioRow) +{ + morkRow* row = this->find_member_row(ev, ioRow); + if ( row ) + { + mork_bool canDirty = ( this->IsTableClean() )? + this->MaybeDirtySpaceStoreAndTable() : morkBool_kTrue; + + mork_count count = mTable_RowArray.mArray_Fill; + morkRow** rowSlots = (morkRow**) mTable_RowArray.mArray_Slots; + if ( rowSlots ) // array has vector as expected? + { + mork_pos pos = -1; + morkRow** end = rowSlots + count; + morkRow** slot = rowSlots - 1; // prepare for preincrement: + while ( ++slot < end ) // another slot to check? + { + if ( *slot == row ) // found the slot containing row? + { + pos = slot - rowSlots; // record absolute position + break; // end while loop + } + } + if ( pos >= 0 ) // need to cut if from the array? + mTable_RowArray.CutSlot(ev, pos); + else + ev->NewWarning("row not found in array"); + } + else + mTable_RowArray.NilSlotsAddressError(ev); + + if ( mTable_RowMap ) + mTable_RowMap->CutRow(ev, ioRow); + + if ( canDirty ) + this->NoteTableCutRow(ev, ioRow); + + if ( ioRow->CutRowGcUse(ev) == 0 ) + ioRow->OnZeroRowGcUse(ev); + } + return ev->Good(); +} + + +mork_bool +morkTable::CutAllRows(morkEnv* ev) +{ + if ( this->MaybeDirtySpaceStoreAndTable() ) + { + this->SetTableRewrite(); // everything is dirty + this->NoteTableSetAll(ev); + } + + if ( ev->Good() ) + { + mTable_RowArray.CutAllSlots(ev); + if ( mTable_RowMap ) + { + morkRowMapIter i(ev, mTable_RowMap); + mork_change* c = 0; + morkRow* r = 0; + + for ( c = i.FirstRow(ev, &r); c; c = i.NextRow(ev, &r) ) + { + if ( r ) + { + if ( r->CutRowGcUse(ev) == 0 ) + r->OnZeroRowGcUse(ev); + + i.CutHereRow(ev, (morkRow**) 0); + } + else + ev->NewWarning("nil row in table map"); + } + } + } + return ev->Good(); +} + +morkTableRowCursor* +morkTable::NewTableRowCursor(morkEnv* ev, mork_pos inRowPos) +{ + morkTableRowCursor* outCursor = 0; + if ( ev->Good() ) + { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + morkTableRowCursor* cursor = new(*heap, ev) + morkTableRowCursor(ev, morkUsage::kHeap, heap, this, inRowPos); + if ( cursor ) + { + if ( ev->Good() ) + outCursor = cursor; + else + cursor->CutStrongRef((nsIMdbEnv *) ev); + } + } + return outCursor; +} + +//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +morkTableChange::morkTableChange(morkEnv* ev, mork_change inChange, + morkRow* ioRow) +// use this constructor for inChange == morkChange_kAdd or morkChange_kCut +: morkNext() +, mTableChange_Row( ioRow ) +, mTableChange_Pos( morkTableChange_kNone ) +{ + if ( ioRow ) + { + if ( ioRow->IsRow() ) + { + if ( inChange == morkChange_kAdd ) + mTableChange_Pos = morkTableChange_kAdd; + else if ( inChange == morkChange_kCut ) + mTableChange_Pos = morkTableChange_kCut; + else + this->UnknownChangeError(ev); + } + else + ioRow->NonRowTypeError(ev); + } + else + ev->NilPointerError(); +} + +morkTableChange::morkTableChange(morkEnv* ev, morkRow* ioRow, mork_pos inPos) +// use this constructor when the row is moved +: morkNext() +, mTableChange_Row( ioRow ) +, mTableChange_Pos( inPos ) +{ + if ( ioRow ) + { + if ( ioRow->IsRow() ) + { + if ( inPos < 0 ) + this->NegativeMovePosError(ev); + } + else + ioRow->NonRowTypeError(ev); + } + else + ev->NilPointerError(); +} + +void morkTableChange::UnknownChangeError(morkEnv* ev) const +// morkChange_kAdd or morkChange_kCut +{ + ev->NewError("mTableChange_Pos neither kAdd nor kCut"); +} + +void morkTableChange::NegativeMovePosError(morkEnv* ev) const +// move must be non-neg position +{ + ev->NewError("negative mTableChange_Pos for row move"); +} + +//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + + +morkTableMap::~morkTableMap() +{ +} + +morkTableMap::morkTableMap(morkEnv* ev, const morkUsage& inUsage, + nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap) +#ifdef MORK_BEAD_OVER_NODE_MAPS + : morkBeadMap(ev, inUsage, ioHeap, ioSlotHeap) +#else /*MORK_BEAD_OVER_NODE_MAPS*/ + : morkNodeMap(ev, inUsage, ioHeap, ioSlotHeap) +#endif /*MORK_BEAD_OVER_NODE_MAPS*/ +{ + if ( ev->Good() ) + mNode_Derived = morkDerived_kTableMap; +} + +//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + |