Back to index

lightning-sunbird  0.9+nobinonly
mdb.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Blake Ross (blake@blakeross.com)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #ifndef _MDB_
00040 #define _MDB_ 1
00041 
00042 #include "nscore.h"
00043 #include "nsISupports.h"
00044 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00045 
00046 // { %%%%% begin scalar typedefs %%%%%
00047 typedef unsigned char  mdb_u1;  // make sure this is one byte
00048 typedef unsigned short mdb_u2;  // make sure this is two bytes
00049 typedef short          mdb_i2;  // make sure this is two bytes
00050 typedef PRUint32       mdb_u4;  // make sure this is four bytes
00051 typedef PRInt32        mdb_i4;  // make sure this is four bytes
00052 typedef PRWord         mdb_ip;  // make sure sizeof(mdb_ip) == sizeof(void*)
00053 
00054 typedef mdb_u1 mdb_bool;  // unsigned byte with zero=false, nonzero=true
00055 
00056 /* canonical boolean constants provided only for code clarity: */
00057 #define mdbBool_kTrue  ((mdb_bool) 1) /* actually any nonzero means true */
00058 #define mdbBool_kFalse ((mdb_bool) 0) /* only zero means false */
00059 
00060 typedef mdb_u4 mdb_id;    // unsigned object identity in a scope
00061 typedef mdb_id mdb_rid;          // unsigned row identity inside scope
00062 typedef mdb_id mdb_tid;          // unsigned table identity inside scope
00063 typedef mdb_u4 mdb_token; // unsigned token for atomized string
00064 typedef mdb_token mdb_scope;     // token used to id scope for rows
00065 typedef mdb_token mdb_kind;      // token used to id kind for tables
00066 typedef mdb_token mdb_column;    // token used to id columns for rows
00067 typedef mdb_token mdb_cscode;    // token used to id charset names
00068 typedef mdb_u4 mdb_seed;  // unsigned collection change counter
00069 typedef mdb_u4 mdb_count; // unsigned collection member count
00070 typedef mdb_u4 mdb_size;  // unsigned physical media size
00071 typedef mdb_u4 mdb_fill;  // unsigned logical content size
00072 typedef mdb_u4 mdb_more;  // more available bytes for larger buffer
00073 
00074 #define mdbId_kNone ((mdb_id) -1) /* never a valid Mork object ID */
00075 
00076 typedef mdb_u4 mdb_percent; // 0..100, with values >100 same as 100
00077 
00078 typedef mdb_u1 mdb_priority; // 0..9, for a total of ten different values
00079 
00080 // temporary substitute for NS_RESULT, for mdb.h standalone compilation:
00081 typedef nsresult mdb_err;   // equivalent to NS_RESULT
00082 
00083 // sequence position is signed; negative is useful to mean "before first":
00084 typedef mdb_i4 mdb_pos; // signed zero-based ordinal collection position
00085 
00086 #define mdbPos_kBeforeFirst ((mdb_pos) -1) /* any negative is before zero */
00087 
00088 // order is also signed, so we can use three states for comparison order:
00089 typedef mdb_i4 mdb_order; // neg:lessthan, zero:equalto, pos:greaterthan 
00090 
00091 typedef mdb_order (* mdbAny_Order)(const void* inA, const void* inB, 
00092   const void* inClosure);
00093 
00094 // } %%%%% end scalar typedefs %%%%%
00095 
00096 // { %%%%% begin C structs %%%%%
00097 
00098 #ifndef mdbScopeStringSet_typedef
00099 typedef struct mdbScopeStringSet mdbScopeStringSet;
00100 #define mdbScopeStringSet_typedef 1
00101 #endif
00102 
00103 /*| mdbScopeStringSet: a set of null-terminated C strings that enumerate some
00104 **| names of row scopes, so that row scopes intended for use by an application
00105 **| can be declared by an app when trying to open or create a database file.
00106 **| (We use strings and not tokens because we cannot know the tokens for any
00107 **| particular db without having first opened the db.)  The goal is to inform
00108 **| a db runtime that scopes not appearing in this list can be given relatively
00109 **| short shrift in runtime representation, with the expectation that other
00110 **| scopes will not actually be used.  However, a db should still be prepared
00111 **| to handle accessing row scopes not in this list, rather than raising errors.
00112 **| But it could be quite expensive to access a row scope not on the list.
00113 **| Note a zero count for the string set means no such string set is being
00114 **| specified, and that a db should handle all row scopes efficiently. 
00115 **| (It does NOT mean an app plans to use no content whatsoever.)
00116 |*/
00117 #ifndef mdbScopeStringSet_struct
00118 #define mdbScopeStringSet_struct 1
00119 struct mdbScopeStringSet { // vector of scopes for use in db opening policy
00120   // when mScopeStringSet_Count is zero, this means no scope constraints 
00121   mdb_count     mScopeStringSet_Count;    // number of strings in vector below
00122   const char**  mScopeStringSet_Strings;  // null-ended ascii scope strings
00123 };
00124 #endif /*mdbScopeStringSet_struct*/
00125 
00126 #ifndef mdbOpenPolicy_typedef
00127 typedef struct mdbOpenPolicy mdbOpenPolicy;
00128 #define mdbOpenPolicy_typedef 1
00129 #endif
00130 
00131 #ifndef mdbOpenPolicy_struct
00132 #define mdbOpenPolicy_struct 1
00133 struct mdbOpenPolicy { // policies affecting db usage for ports and stores
00134   mdbScopeStringSet  mOpenPolicy_ScopePlan; // predeclare scope usage plan
00135   mdb_bool           mOpenPolicy_MaxLazy;   // nonzero: do least work
00136   mdb_bool           mOpenPolicy_MinMemory; // nonzero: use least memory
00137 };
00138 #endif /*mdbOpenPolicy_struct*/
00139 
00140 #ifndef mdbTokenSet_typedef
00141 typedef struct mdbTokenSet mdbTokenSet;
00142 #define mdbTokenSet_typedef 1
00143 #endif
00144 
00145 #ifndef mdbTokenSet_struct
00146 #define mdbTokenSet_struct 1
00147 struct mdbTokenSet { // array for a set of tokens, and actual slots used
00148   mdb_count   mTokenSet_Count;   // number of token slots in the array
00149   mdb_fill    mTokenSet_Fill;    // the subset of count slots actually used
00150   mdb_more    mTokenSet_More;    // more tokens available for bigger array
00151   mdb_token*  mTokenSet_Tokens;  // array of count mdb_token instances
00152 };
00153 #endif /*mdbTokenSet_struct*/
00154 
00155 #ifndef mdbUsagePolicy_typedef
00156 typedef struct mdbUsagePolicy mdbUsagePolicy;
00157 #define mdbUsagePolicy_typedef 1
00158 #endif
00159 
00160 /*| mdbUsagePolicy: another version of mdbOpenPolicy which uses tokens instead
00161 **| of scope strings, because usage policies can be constructed for use with a
00162 **| db that is already open, while an open policy must be constructed before a
00163 **| db has yet been opened.
00164 |*/
00165 #ifndef mdbUsagePolicy_struct
00166 #define mdbUsagePolicy_struct 1
00167 struct mdbUsagePolicy { // policies affecting db usage for ports and stores
00168   mdbTokenSet  mUsagePolicy_ScopePlan; // current scope usage plan
00169   mdb_bool     mUsagePolicy_MaxLazy;   // nonzero: do least work
00170   mdb_bool     mUsagePolicy_MinMemory; // nonzero: use least memory
00171 };
00172 #endif /*mdbUsagePolicy_struct*/
00173 
00174 #ifndef mdbOid_typedef
00175 typedef struct mdbOid mdbOid;
00176 #define mdbOid_typedef 1
00177 #endif
00178 
00179 #ifndef mdbOid_struct
00180 #define mdbOid_struct 1
00181 struct mdbOid { // identity of some row or table inside a database
00182   mdb_scope   mOid_Scope;  // scope token for an id's namespace
00183   mdb_id      mOid_Id;     // identity of object inside scope namespace
00184 };
00185 #endif /*mdbOid_struct*/
00186 
00187 #ifndef mdbRange_typedef
00188 typedef struct mdbRange mdbRange;
00189 #define mdbRange_typedef 1
00190 #endif
00191 
00192 #ifndef mdbRange_struct
00193 #define mdbRange_struct 1
00194 struct mdbRange { // range of row positions in a table
00195   mdb_pos   mRange_FirstPos;  // position of first row
00196   mdb_pos   mRange_LastPos;   // position of last row
00197 };
00198 #endif /*mdbRange_struct*/
00199 
00200 #ifndef mdbColumnSet_typedef
00201 typedef struct mdbColumnSet mdbColumnSet;
00202 #define mdbColumnSet_typedef 1
00203 #endif
00204 
00205 #ifndef mdbColumnSet_struct
00206 #define mdbColumnSet_struct 1
00207 struct mdbColumnSet { // array of column tokens (just the same as mdbTokenSet)
00208   mdb_count    mColumnSet_Count;    // number of columns
00209   mdb_column*  mColumnSet_Columns;  // count mdb_column instances
00210 };
00211 #endif /*mdbColumnSet_struct*/
00212 
00213 #ifndef mdbYarn_typedef
00214 typedef struct mdbYarn mdbYarn;
00215 #define mdbYarn_typedef 1
00216 #endif
00217 
00218 #ifdef MDB_BEGIN_C_LINKAGE_define
00219 #define MDB_BEGIN_C_LINKAGE_define 1
00220 #define MDB_BEGIN_C_LINKAGE extern "C" {
00221 #define MDB_END_C_LINKAGE }
00222 #endif /*MDB_BEGIN_C_LINKAGE_define*/
00223 
00224 /*| mdbYarn_mGrow: an abstract API for growing the size of a mdbYarn
00225 **| instance.  With respect to a specific API that requires a caller
00226 **| to supply a string (mdbYarn) that a callee fills with content
00227 **| that might exceed the specified size, mdbYarn_mGrow is a caller-
00228 **| supplied means of letting a callee attempt to increase the string
00229 **| size to become large enough to receive all content available.
00230 **|
00231 **|| Grow(): a method for requesting that a yarn instance be made
00232 **| larger in size.  Note that such requests need not be honored, and
00233 **| need not be honored in full if only partial size growth is desired.
00234 **| (Note that no nsIMdbEnv instance is passed as argument, although one
00235 **| might be needed in some circumstances.  So if an nsIMdbEnv is needed,
00236 **| a reference to one might be held inside a mdbYarn member slot.)
00237 **|
00238 **|| self: a yarn instance to be grown.  Presumably this yarn is
00239 **| the instance which holds the mYarn_Grow method pointer.  Yarn
00240 **| instancesshould only be passed to grow methods which they were
00241 **| specifically designed to fit, as indicated by the mYarn_Grow slot.
00242 **|
00243 **|| inNewSize: the new desired value for slot mYarn_Size in self.
00244 **| If mYarn_Size is already this big, then nothing should be done.
00245 **| If inNewSize is larger than seems feasible or desirable to honor,
00246 **| then any size restriction policy can be used to grow to some size
00247 **| greater than mYarn_Size.  (Grow() might even grow to a size
00248 **| greater than inNewSize in order to make the increase in size seem
00249 **| worthwhile, rather than growing in many smaller steps over time.)
00250 |*/
00251 typedef void (* mdbYarn_mGrow)(mdbYarn* self, mdb_size inNewSize);
00252 // mdbYarn_mGrow methods must be declared with C linkage in C++
00253 
00254 /*| mdbYarn: a variable length "string" of arbitrary binary bytes,
00255 **| whose length is mYarn_Fill, inside a buffer mYarn_Buf that has
00256 **| at most mYarn_Size byte of physical space.
00257 **|
00258 **|| mYarn_Buf: a pointer to space containing content.  This slot
00259 **| might never be nil when mYarn_Size is nonzero, but checks for nil
00260 **| are recommended anyway.
00261 **| (Implementations of mdbYarn_mGrow methods should take care to
00262 **| ensure the existence of a replacement before dropping old Bufs.)
00263 **| Content in Buf can be anything in any format, but the mYarn_Form
00264 **| implies the actual format by some caller-to-callee convention.
00265 **| mYarn_Form==0 implies US-ASCII iso-8859-1 Latin1 string content.
00266 **|
00267 **|| mYarn_Size: the physical size of Buf in bytes.  Note that if one
00268 **| intends to terminate a string with a null byte, that it must not
00269 **| be written at or after mYarn_Buf[mYarn_Size] because this is after
00270 **| the last byte in the physical buffer space.  Size can be zero,
00271 **| which means the string has no content whatsoever; note that when
00272 **| Size is zero, this is a suitable reason for Buf==nil as well.
00273 **|
00274 **|| mYarn_Fill: the logical content in Buf in bytes, where Fill must
00275 **| never exceed mYarn_Size.  Note that yarn strings might not have a
00276 **| terminating null byte (since they might not even be C strings), but
00277 **| when they do, such terminating nulls are considered part of content
00278 **| and therefore Fill will count such null bytes.  So an "empty" C
00279 **| string will have Fill==1, because content includes one null byte.
00280 **| Fill does not mean "length" when applied to C strings for this
00281 **| reason.  However, clients using yarns to hold C strings can infer
00282 **| that length is equal to Fill-1 (but should take care to handle the
00283 **| case where Fill==0).  To be paranoid, one can always copy to a
00284 **| destination with size exceeding Fill, and place a redundant null
00285 **| byte in the Fill position when this simplifies matters.
00286 **|
00287 **|| mYarn_Form: a designation of content format within mYarn_Buf.
00288 **| The semantics of this slot are the least well defined, since the
00289 **| actual meaning is context dependent, to the extent that callers
00290 **| and callees must agree on format encoding conventions when such
00291 **| are not standardized in many computing contexts.  However, in the
00292 **| context of a specific mdb database, mYarn_Form is a token for an
00293 **| atomized string in that database that typically names a preferred
00294 **| mime type charset designation.  If and when mdbYarn is used for
00295 **| other purposes away from the mdb interface, folks can use another
00296 **| convention system for encoding content formats.  However, in all
00297 **| contexts is it useful to maintain the convention that Form==0
00298 **| implies Buf contains US-ASCII iso-8859-1 Latin1 string content.
00299 **|
00300 **|| mYarn_Grow: either a mdbYarn_mGrow method, or else nil.  When
00301 **| a mdbYarn_mGrow method is provided, this method can be used to
00302 **| request a yarn buf size increase.  A caller who constructs the 
00303 **| original mdbYarn instance decides whether a grow method is necessary
00304 **| or desirable, and uses only grow methods suitable for the buffering
00305 **| nature of a specific mdbYarn instance.  (For example, Buf might be a
00306 **| staticly allocated string space which switches to something heap-based
00307 **| when grown, and subsequent calls to grow the yarn must distinguish the
00308 **| original static string from heap allocated space, etc.) Note that the
00309 **| method stored in mYarn_Grow can change, and this might be a common way
00310 **| to track memory managent changes in policy for mYarn_Buf.
00311 |*/
00312 #ifndef mdbYarn_struct
00313 #define mdbYarn_struct 1
00314 struct mdbYarn { // buffer with caller space allocation semantics
00315   void*         mYarn_Buf;   // space for holding any binary content
00316   mdb_fill      mYarn_Fill;  // logical content in Buf in bytes
00317   mdb_size      mYarn_Size;  // physical size of Buf in bytes
00318   mdb_more      mYarn_More;  // more available bytes if Buf is bigger
00319   mdb_cscode    mYarn_Form;  // charset format encoding
00320   mdbYarn_mGrow mYarn_Grow;  // optional method to grow mYarn_Buf
00321   
00322   // Subclasses might add further slots after mYarn_Grow in order to
00323   // maintain bookkeeping needs, such as state info about mYarn_Buf.
00324 };
00325 #endif /*mdbYarn_struct*/
00326 
00327 // } %%%%% end C structs %%%%%
00328 
00329 // { %%%%% begin class forward defines %%%%%
00330 class nsIMdbEnv;
00331 class nsIMdbObject;
00332 class nsIMdbErrorHook;
00333 class nsIMdbCompare;
00334 class nsIMdbThumb;
00335 class nsIMdbFactory;
00336 class nsIMdbFile;
00337 class nsIMdbPort;
00338 class nsIMdbStore;
00339 class nsIMdbCursor;
00340 class nsIMdbPortTableCursor;
00341 class nsIMdbCollection;
00342 class nsIMdbTable;
00343 class nsIMdbTableRowCursor;
00344 class nsIMdbRow;
00345 class nsIMdbRowCellCursor;
00346 class nsIMdbBlob;
00347 class nsIMdbCell;
00348 class nsIMdbSorting;
00349 // } %%%%% end class forward defines %%%%%
00350 
00351 
00352 // { %%%%% begin C++ abstract class interfaces %%%%%
00353 
00354 /*| nsIMdbObject: base class for all message db class interfaces
00355 **|
00356 **|| factory: all nsIMdbObjects from the same code suite have the same factory
00357 **|
00358 **|| refcounting: both strong and weak references, to ensure strong refs are
00359 **| acyclic, while weak refs can cause cycles.  CloseMdbObject() is
00360 **| called when (strong) use counts hit zero, but clients can call this close
00361 **| method early for some reason, if absolutely necessary even though it will
00362 **| thwart the other uses of the same object.  Note that implementations must
00363 **| cope with close methods being called arbitrary numbers of times.  The COM
00364 **| calls to AddRef() and release ref map directly to strong use ref calls,
00365 **| but the total ref count for COM objects is the sum of weak & strong refs.
00366 |*/
00367 
00368 #define NS_IMDBOBJECT_IID_STR "5533ea4b-14c3-4bef-ac60-22f9e9a49084"
00369 
00370 #define NS_IMDBOBJECT_IID \
00371 {0x5533ea4b, 0x14c3, 0x4bef, \
00372 { 0xac, 0x60, 0x22, 0xf9, 0xe9, 0xa4, 0x90, 0x84}}
00373 
00374 class nsIMdbObject : public nsISupports { // msg db base class
00375 public:
00376 
00377   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBOBJECT_IID)
00378 // { ===== begin nsIMdbObject methods =====
00379 
00380   // { ----- begin attribute methods -----
00381   NS_IMETHOD IsFrozenMdbObject(nsIMdbEnv* ev, mdb_bool* outIsReadonly) = 0;
00382   // same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
00383   // } ----- end attribute methods -----
00384 
00385   // { ----- begin factory methods -----
00386   NS_IMETHOD GetMdbFactory(nsIMdbEnv* ev, nsIMdbFactory** acqFactory) = 0; 
00387   // } ----- end factory methods -----
00388 
00389   // { ----- begin ref counting for well-behaved cyclic graphs -----
00390   NS_IMETHOD GetWeakRefCount(nsIMdbEnv* ev, // weak refs
00391     mdb_count* outCount) = 0;  
00392   NS_IMETHOD GetStrongRefCount(nsIMdbEnv* ev, // strong refs
00393     mdb_count* outCount) = 0;
00394 
00395   NS_IMETHOD AddWeakRef(nsIMdbEnv* ev) = 0;
00396   NS_IMETHOD AddStrongRef(nsIMdbEnv* ev) = 0;
00397 
00398   NS_IMETHOD CutWeakRef(nsIMdbEnv* ev) = 0;
00399   NS_IMETHOD CutStrongRef(nsIMdbEnv* ev) = 0;
00400   
00401   NS_IMETHOD CloseMdbObject(nsIMdbEnv* ev) = 0; // called at strong refs zero
00402   NS_IMETHOD IsOpenMdbObject(nsIMdbEnv* ev, mdb_bool* outOpen) = 0;
00403   // } ----- end ref counting -----
00404   
00405 // } ===== end nsIMdbObject methods =====
00406 };
00407 
00408 /*| nsIMdbErrorHook: a base class for clients of this API to subclass, in order
00409 **| to provide a callback installable in nsIMdbEnv for error notifications. If
00410 **| apps that subclass nsIMdbErrorHook wish to maintain a reference to the env
00411 **| that contains the hook, then this should be a weak ref to avoid cycles.
00412 **|
00413 **|| OnError: when nsIMdbEnv has an error condition that causes the total count
00414 **| of errors to increase, then nsIMdbEnv should call OnError() to report the
00415 **| error in some fashion when an instance of nsIMdbErrorHook is installed.  The
00416 **| variety of string flavors is currently due to the uncertainty here in the
00417 **| nsIMdbBlob and nsIMdbCell interfaces.  (Note that overloading by using the
00418 **| same method name is not necessary here, and potentially less clear.)
00419 |*/
00420 class nsIMdbErrorHook : public nsISupports{ // env callback handler to report errors
00421 public:
00422 
00423 // { ===== begin error methods =====
00424   NS_IMETHOD OnErrorString(nsIMdbEnv* ev, const char* inAscii) = 0;
00425   NS_IMETHOD OnErrorYarn(nsIMdbEnv* ev, const mdbYarn* inYarn) = 0;
00426 // } ===== end error methods =====
00427 
00428 // { ===== begin warning methods =====
00429   NS_IMETHOD OnWarningString(nsIMdbEnv* ev, const char* inAscii) = 0;
00430   NS_IMETHOD OnWarningYarn(nsIMdbEnv* ev, const mdbYarn* inYarn) = 0;
00431 // } ===== end warning methods =====
00432 
00433 // { ===== begin abort hint methods =====
00434   NS_IMETHOD OnAbortHintString(nsIMdbEnv* ev, const char* inAscii) = 0;
00435   NS_IMETHOD OnAbortHintYarn(nsIMdbEnv* ev, const mdbYarn* inYarn) = 0;
00436 // } ===== end abort hint methods =====
00437 };
00438 
00439 /*| nsIMdbCompare: a caller-supplied yarn comparison interface.  When two yarns
00440 **| are compared to each other with Order(), this method should return a signed
00441 **| long integer denoting relation R between the 1st and 2nd yarn instances
00442 **| such that (First R Second), where negative is less than, zero is equal to,
00443 **| and positive is greater than.  Note that both yarns are readonly, and the
00444 **| Order() method should make no attempt to modify the yarn content.
00445 |*/
00446 class nsIMdbCompare { // caller-supplied yarn comparison
00447 public:
00448 
00449 // { ===== begin nsIMdbCompare methods =====
00450   NS_IMETHOD Order(nsIMdbEnv* ev,      // compare first to second yarn
00451     const mdbYarn* inFirst,   // first yarn in comparison
00452     const mdbYarn* inSecond,  // second yarn in comparison
00453     mdb_order* outOrder) = 0; // negative="<", zero="=", positive=">"
00454     
00455   NS_IMETHOD AddStrongRef(nsIMdbEnv* ev) = 0; // does nothing
00456   NS_IMETHOD CutStrongRef(nsIMdbEnv* ev) = 0; // does nothing
00457 // } ===== end nsIMdbCompare methods =====
00458   
00459 };
00460 
00461 /*| nsIMdbHeap: abstract memory allocation interface. 
00462 **|
00463 **|| Alloc: return a block at least inSize bytes in size with alignment
00464 **| suitable for any native type (such as long integers).  When no such
00465 **| block can be allocated, failure is indicated by a null address in
00466 **| addition to reporting an error in the environment.
00467 **|
00468 **|| Free: deallocate a block allocated or resized earlier by the same
00469 **| heap instance.  If the inBlock parameter is nil, the heap should do
00470 **| nothing (and crashing is strongly discouraged).
00471 |*/
00472 class nsIMdbHeap { // caller-supplied memory management interface
00473 public:
00474 // { ===== begin nsIMdbHeap methods =====
00475   NS_IMETHOD Alloc(nsIMdbEnv* ev, // allocate a piece of memory
00476     mdb_size inSize,        // requested byte size of new memory block 
00477     void** outBlock) = 0;   // memory block of inSize bytes, or nil
00478     
00479   NS_IMETHOD Free(nsIMdbEnv* ev, // free block from Alloc or Resize()
00480     void* ioBlock) = 0;     // block to be destroyed/deallocated
00481     
00482   NS_IMETHOD HeapAddStrongRef(nsIMdbEnv* ev) = 0;
00483   NS_IMETHOD HeapCutStrongRef(nsIMdbEnv* ev) = 0;
00484     
00485 // } ===== end nsIMdbHeap methods =====
00486 };
00487 
00488 /*| nsIMdbCPlusHeap: Alloc() with global ::new(), Free() with global ::delete(). 
00489 **| Resize() is done by ::new() followed by ::delete().
00490 |*/
00491 class nsIMdbCPlusHeap { // caller-supplied memory management interface
00492 public:
00493 // { ===== begin nsIMdbHeap methods =====
00494   NS_IMETHOD Alloc(nsIMdbEnv* ev, // allocate a piece of memory
00495     mdb_size inSize,   // requested size of new memory block 
00496     void** outBlock);  // memory block of inSize bytes, or nil
00497     
00498   NS_IMETHOD Free(nsIMdbEnv* ev, // free block allocated earlier by Alloc()
00499     void* inBlock);
00500     
00501   NS_IMETHOD HeapAddStrongRef(nsIMdbEnv* ev);
00502   NS_IMETHOD HeapCutStrongRef(nsIMdbEnv* ev);
00503 // } ===== end nsIMdbHeap methods =====
00504 };
00505 
00506 /*| nsIMdbThumb: 
00507 |*/
00508 
00509 
00510 #define NS_IMDBTHUMB_IID_STR "6d3ad7c1-a809-4e74-8577-49fa9a4562fa"
00511 
00512 #define NS_IMDBTHUMB_IID \
00513 {0x6d3ad7c1, 0xa809, 0x4e74, \
00514 { 0x85, 0x77, 0x49, 0xfa, 0x9a, 0x45, 0x62, 0xfa}}
00515 
00516 
00517 class nsIMdbThumb : public nsISupports { // closure for repeating incremental method
00518 public:
00519   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBTHUMB_IID)
00520 
00521 // { ===== begin nsIMdbThumb methods =====
00522   NS_IMETHOD GetProgress(nsIMdbEnv* ev,
00523     mdb_count* outTotal,    // total somethings to do in operation
00524     mdb_count* outCurrent,  // subportion of total completed so far
00525     mdb_bool* outDone,      // is operation finished?
00526     mdb_bool* outBroken     // is operation irreparably dead and broken?
00527   ) = 0;
00528   
00529   NS_IMETHOD DoMore(nsIMdbEnv* ev,
00530     mdb_count* outTotal,    // total somethings to do in operation
00531     mdb_count* outCurrent,  // subportion of total completed so far
00532     mdb_bool* outDone,      // is operation finished?
00533     mdb_bool* outBroken     // is operation irreparably dead and broken?
00534   ) = 0;
00535   
00536   NS_IMETHOD CancelAndBreakThumb( // cancel pending operation
00537     nsIMdbEnv* ev) = 0;
00538 // } ===== end nsIMdbThumb methods =====
00539 };
00540 
00541 /*| nsIMdbEnv: a context parameter used when calling most abstract db methods.
00542 **| The main purpose of such an object is to permit a database implementation
00543 **| to avoid the use of globals to share information between various parts of
00544 **| the implementation behind the abstract db interface.  An environment acts
00545 **| like a session object for a given calling thread, and callers should use
00546 **| at least one different nsIMdbEnv instance for each thread calling the API.
00547 **| While the database implementation might not be threaded, it is highly
00548 **| desirable that the db be thread-safe if calling threads use distinct
00549 **| instances of nsIMdbEnv.  Callers can stop at one nsIMdbEnv per thread, or they
00550 **| might decide to make on nsIMdbEnv instance for every nsIMdbPort opened, so that
00551 **| error information is segregated by database instance.  Callers create
00552 **| instances of nsIMdbEnv by calling the MakeEnv() method in nsIMdbFactory. 
00553 **|
00554 **|| tracing: an environment might support some kind of tracing, and this
00555 **| boolean attribute permits such activity to be enabled or disabled.
00556 **|
00557 **|| errors: when a call to the abstract db interface returns, a caller might
00558 **| check the number of outstanding errors to see whether the operation did
00559 **| actually succeed. Each nsIMdbEnv should have all its errors cleared by a
00560 **| call to ClearErrors() before making each call to the abstract db API,
00561 **| because outstanding errors might disable further database actions.  (This
00562 **| is not done inside the db interface, because the db cannot in general know
00563 **| when a call originates from inside or outside -- only the app knows this.)
00564 **|
00565 **|| error hook: callers can install an instance of nsIMdbErrorHook to receive
00566 **| error notifications whenever the error count increases.  The hook can
00567 **| be uninstalled by passing a null pointer.
00568 **|
00569 |*/
00570 
00571 #define NS_IMDBENV_IID_STR "a765e46b-efb6-41e6-b75b-c5d6bd710594"
00572 
00573 #define NS_IMDBENV_IID \
00574 {0xa765e46b, 0xefb6, 0x41e6, \
00575 { 0xb7, 0x5b, 0xc5, 0xd6, 0xbd, 0x71, 0x05, 0x94}}
00576 
00577 class nsIMdbEnv : public nsISupports { // db specific context parameter
00578 public:
00579 
00580   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBENV_IID)
00581 // { ===== begin nsIMdbEnv methods =====
00582 
00583   // { ----- begin attribute methods -----
00584   NS_IMETHOD GetErrorCount(mdb_count* outCount,
00585     mdb_bool* outShouldAbort) = 0;
00586   NS_IMETHOD GetWarningCount(mdb_count* outCount,
00587     mdb_bool* outShouldAbort) = 0;
00588   
00589   NS_IMETHOD GetEnvBeVerbose(mdb_bool* outBeVerbose) = 0;
00590   NS_IMETHOD SetEnvBeVerbose(mdb_bool inBeVerbose) = 0;
00591   
00592   NS_IMETHOD GetDoTrace(mdb_bool* outDoTrace) = 0;
00593   NS_IMETHOD SetDoTrace(mdb_bool inDoTrace) = 0;
00594   
00595   NS_IMETHOD GetAutoClear(mdb_bool* outAutoClear) = 0;
00596   NS_IMETHOD SetAutoClear(mdb_bool inAutoClear) = 0;
00597   
00598   NS_IMETHOD GetErrorHook(nsIMdbErrorHook** acqErrorHook) = 0;
00599   NS_IMETHOD SetErrorHook(
00600     nsIMdbErrorHook* ioErrorHook) = 0; // becomes referenced
00601   
00602   NS_IMETHOD GetHeap(nsIMdbHeap** acqHeap) = 0;
00603   NS_IMETHOD SetHeap(
00604     nsIMdbHeap* ioHeap) = 0; // becomes referenced
00605   // } ----- end attribute methods -----
00606   
00607   NS_IMETHOD ClearErrors() = 0; // clear errors beore re-entering db API
00608   NS_IMETHOD ClearWarnings() = 0; // clear warnings
00609   NS_IMETHOD ClearErrorsAndWarnings() = 0; // clear both errors & warnings
00610 // } ===== end nsIMdbEnv methods =====
00611 };
00612 
00613 /*| nsIMdbFactory: the main entry points to the abstract db interface.  A DLL
00614 **| that supports this mdb interface need only have a single exported method
00615 **| that will return an instance of nsIMdbFactory, so that further methods in
00616 **| the suite can be accessed from objects returned by nsIMdbFactory methods.
00617 **|
00618 **|| mdbYarn: note all nsIMdbFactory subclasses must guarantee null
00619 **| termination of all strings written into mdbYarn instances, as long as
00620 **| mYarn_Size and mYarn_Buf are nonzero.  Even truncated string values must
00621 **| be null terminated.  This is more strict behavior than mdbYarn requires,
00622 **| but it is part of the nsIMdbFactory interface.
00623 **|
00624 **|| envs: an environment instance is required as per-thread context for
00625 **| most of the db method calls, so nsIMdbFactory creates such instances.
00626 **|
00627 **|| rows: callers must be able to create row instances that are independent
00628 **| of storage space that is part of the db content graph.  Many interfaces
00629 **| for data exchange have strictly copy semantics, so that a row instance
00630 **| has no specific identity inside the db content model, and the text in
00631 **| cells are an independenty copy of unexposed content inside the db model.
00632 **| Callers are expected to maintain one or more row instances as a buffer
00633 **| for staging cell content copied into or out of a table inside the db.
00634 **| Callers are urged to use an instance of nsIMdbRow created by the nsIMdbFactory
00635 **| code suite, because reading and writing might be much more efficient than
00636 **| when using a hand-rolled nsIMdbRow subclass with no relation to the suite.
00637 **|
00638 **|| ports: a port is a readonly interface to a specific database file. Most
00639 **| of the methods to access a db file are suitable for a readonly interface,
00640 **| so a port is the basic minimum for accessing content.  This makes it
00641 **| possible to read other external formats for import purposes, without
00642 **| needing the code or competence necessary to write every such format.  So
00643 **| we can write generic import code just once, as long as every format can
00644 **| show a face based on nsIMdbPort. (However, same suite import can be faster.)
00645 **| Given a file name and the first 512 bytes of a file, a factory can say if
00646 **| a port can be opened by this factory.  Presumably an app maintains chains
00647 **| of factories for different suites, and asks each in turn about opening a
00648 **| a prospective file for reading (as a port) or writing (as a store).  I'm
00649 **| not ready to tackle issues of format fidelity and factory chain ordering.
00650 **|
00651 **|| stores: a store is a mutable interface to a specific database file, and
00652 **| includes the port interface plus any methods particular to writing, which
00653 **| are few in number.  Presumably the set of files that can be opened as
00654 **| stores is a subset of the set of files that can be opened as ports.  A
00655 **| new store can be created with CreateNewFileStore() by supplying a new
00656 **| file name which does not yet exist (callers are always responsible for
00657 **| destroying any existing files before calling this method). 
00658 |*/
00659 
00660 #define NS_IMDBFACTORY_IID_STR "2b80395c-b91e-4990-b1a7-023e99ab14e9"
00661 
00662 #define NS_IMDBFACTORY_IID \
00663 {0xf04aa4ab, 0x1fe, 0x4115, \
00664 { 0xa4, 0xa5, 0x68, 0x19, 0xdf, 0xf1, 0x10, 0x3d}}
00665 
00666 
00667 class nsIMdbFactory : public nsISupports { // suite entry points
00668 public:
00669 
00670   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBFACTORY_IID)
00671 // { ===== begin nsIMdbFactory methods =====
00672 
00673   // { ----- begin file methods -----
00674   NS_IMETHOD OpenOldFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
00675     const char* inFilePath,
00676     mdb_bool inFrozen, nsIMdbFile** acqFile) = 0;
00677   // Choose some subclass of nsIMdbFile to instantiate, in order to read
00678   // (and write if not frozen) the file known by inFilePath.  The file
00679   // returned should be open and ready for use, and presumably positioned
00680   // at the first byte position of the file.  The exact manner in which
00681   // files must be opened is considered a subclass specific detail, and
00682   // other portions or Mork source code don't want to know how it's done.
00683 
00684   NS_IMETHOD CreateNewFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
00685     const char* inFilePath,
00686     nsIMdbFile** acqFile) = 0;
00687   // Choose some subclass of nsIMdbFile to instantiate, in order to read
00688   // (and write if not frozen) the file known by inFilePath.  The file
00689   // returned should be created and ready for use, and presumably positioned
00690   // at the first byte position of the file.  The exact manner in which
00691   // files must be opened is considered a subclass specific detail, and
00692   // other portions or Mork source code don't want to know how it's done.
00693   // } ----- end file methods -----
00694 
00695   // { ----- begin env methods -----
00696   NS_IMETHOD MakeEnv(nsIMdbHeap* ioHeap, nsIMdbEnv** acqEnv) = 0; // acquire new env
00697   // ioHeap can be nil, causing a MakeHeap() style heap instance to be used
00698   // } ----- end env methods -----
00699 
00700   // { ----- begin heap methods -----
00701   NS_IMETHOD MakeHeap(nsIMdbEnv* ev, nsIMdbHeap** acqHeap) = 0; // acquire new heap
00702   // } ----- end heap methods -----
00703 
00704   // { ----- begin compare methods -----
00705   NS_IMETHOD MakeCompare(nsIMdbEnv* ev, nsIMdbCompare** acqCompare) = 0; // ASCII
00706   // } ----- end compare methods -----
00707 
00708   // { ----- begin row methods -----
00709   NS_IMETHOD MakeRow(nsIMdbEnv* ev, nsIMdbHeap* ioHeap, nsIMdbRow** acqRow) = 0; // new row
00710   // ioHeap can be nil, causing the heap associated with ev to be used
00711   // } ----- end row methods -----
00712   
00713   // { ----- begin port methods -----
00714   NS_IMETHOD CanOpenFilePort(
00715     nsIMdbEnv* ev, // context
00716     // const char* inFilePath, // the file to investigate
00717     // const mdbYarn* inFirst512Bytes,
00718     nsIMdbFile* ioFile, // db abstract file interface
00719     mdb_bool* outCanOpen, // whether OpenFilePort() might succeed
00720     mdbYarn* outFormatVersion) = 0; // informal file format description
00721     
00722   NS_IMETHOD OpenFilePort(
00723     nsIMdbEnv* ev, // context
00724     nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
00725     // const char* inFilePath, // the file to open for readonly import
00726     nsIMdbFile* ioFile, // db abstract file interface
00727     const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
00728     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental port open
00729   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
00730   // then call nsIMdbFactory::ThumbToOpenPort() to get the port instance.
00731 
00732   NS_IMETHOD ThumbToOpenPort( // redeeming a completed thumb from OpenFilePort()
00733     nsIMdbEnv* ev, // context
00734     nsIMdbThumb* ioThumb, // thumb from OpenFilePort() with done status
00735     nsIMdbPort** acqPort) = 0; // acquire new port object
00736   // } ----- end port methods -----
00737   
00738   // { ----- begin store methods -----
00739   NS_IMETHOD CanOpenFileStore(
00740     nsIMdbEnv* ev, // context
00741     // const char* inFilePath, // the file to investigate
00742     // const mdbYarn* inFirst512Bytes,
00743     nsIMdbFile* ioFile, // db abstract file interface
00744     mdb_bool* outCanOpenAsStore, // whether OpenFileStore() might succeed
00745     mdb_bool* outCanOpenAsPort, // whether OpenFilePort() might succeed
00746     mdbYarn* outFormatVersion) = 0; // informal file format description
00747     
00748   NS_IMETHOD OpenFileStore( // open an existing database
00749     nsIMdbEnv* ev, // context
00750     nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
00751     // const char* inFilePath, // the file to open for general db usage
00752     nsIMdbFile* ioFile, // db abstract file interface
00753     const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
00754     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental store open
00755   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
00756   // then call nsIMdbFactory::ThumbToOpenStore() to get the store instance.
00757     
00758   NS_IMETHOD
00759   ThumbToOpenStore( // redeem completed thumb from OpenFileStore()
00760     nsIMdbEnv* ev, // context
00761     nsIMdbThumb* ioThumb, // thumb from OpenFileStore() with done status
00762     nsIMdbStore** acqStore) = 0; // acquire new db store object
00763   
00764   NS_IMETHOD CreateNewFileStore( // create a new db with minimal content
00765     nsIMdbEnv* ev, // context
00766     nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
00767     // const char* inFilePath, // name of file which should not yet exist
00768     nsIMdbFile* ioFile, // db abstract file interface
00769     const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
00770     nsIMdbStore** acqStore) = 0; // acquire new db store object
00771   // } ----- end store methods -----
00772 
00773 // } ===== end nsIMdbFactory methods =====
00774 };
00775 
00776 extern "C" nsIMdbFactory* MakeMdbFactory(); 
00777 
00778 /*| nsIMdbFile: abstract file interface resembling the original morkFile
00779 **| abstract interface (which was in turn modeled on the file interface
00780 **| from public domain IronDoc).  The design of this file interface is
00781 **| complicated by the fact that some DB's will not find this interface
00782 **| adequate for all runtime requirements (even though this file API is
00783 **| enough to implement text-based DB's like Mork).  For this reason,
00784 **| more methods have been added to let a DB library force the file to
00785 **| become closed so the DB can reopen the file in some other manner.
00786 **| Folks are encouraged to suggest ways to tune this interface to suit
00787 **| DB's that cannot manage to pull their maneuvers even given this API.
00788 **|
00789 **|| Tell: get the current i/o position in file
00790 **|
00791 **|| Seek: change the current i/o position in file
00792 **|
00793 **|| Eof: return file's total length in bytes
00794 **|
00795 **|| Read: input inSize bytes into outBuf, returning actual transfer size
00796 **|
00797 **|| Get: read starting at specific file offset (e.g. Seek(); Read();)
00798 **|
00799 **|| Write: output inSize bytes from inBuf, returning actual transfer size
00800 **|
00801 **|| Put: write starting at specific file offset (e.g. Seek(); Write();)
00802 **|
00803 **|| Flush: if written bytes are buffered, push them to final destination
00804 **|
00805 **|| Path: get file path in some string representation.  This is intended
00806 **| either to support the display of file name in a user presentation, or
00807 **| to support the closing and reopening of the file when the DB needs more
00808 **| exotic file access than is presented by the nsIMdbFile interface.
00809 **|
00810 **|| Steal: tell this file to close any associated i/o stream in the file
00811 **| system, because the file ioThief intends to reopen the file in order
00812 **| to provide the MDB implementation with more exotic file access than is
00813 **| offered by the nsIMdbFile alone.  Presumably the thief knows enough
00814 **| from Path() in order to know which file to reopen.  If Steal() is
00815 **| successful, this file should probably delegate all future calls to
00816 **| the nsIMdbFile interface down to the thief files, so that even after
00817 **| the file has been stolen, it can still be read, written, or forcibly
00818 **| closed (by a call to CloseMdbObject()).
00819 **|
00820 **|| Thief: acquire and return thief passed to an earlier call to Steal().
00821 |*/
00822 
00823 #define NS_IMDBFILE_IID_STR "f04aa4ab-1fe7-4115-a4a5-6819dff1103d"
00824 
00825 #define NS_IMDBFILE_IID \
00826 {0xf04aa4ab, 0x1fe, 0x4115, \
00827 { 0xa4, 0xa5, 0x68, 0x19, 0xdf, 0xf1, 0x10, 0x3d}}
00828 
00829 class nsIMdbFile : public nsISupports { // minimal file interface
00830 public:
00831 
00832   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBFILE_IID)
00833 // { ===== begin nsIMdbFile methods =====
00834 
00835   // { ----- begin pos methods -----
00836   NS_IMETHOD Tell(nsIMdbEnv* ev, mdb_pos* outPos) const = 0;
00837   NS_IMETHOD Seek(nsIMdbEnv* ev, mdb_pos inPos, mdb_pos *outPos) = 0;
00838   NS_IMETHOD Eof(nsIMdbEnv* ev, mdb_pos* outPos) = 0;
00839   // } ----- end pos methods -----
00840 
00841   // { ----- begin read methods -----
00842   NS_IMETHOD Read(nsIMdbEnv* ev, void* outBuf, mdb_size inSize,
00843     mdb_size* outActualSize) = 0;
00844   NS_IMETHOD Get(nsIMdbEnv* ev, void* outBuf, mdb_size inSize,
00845     mdb_pos inPos, mdb_size* outActualSize) = 0;
00846   // } ----- end read methods -----
00847     
00848   // { ----- begin write methods -----
00849   NS_IMETHOD  Write(nsIMdbEnv* ev, const void* inBuf, mdb_size inSize,
00850     mdb_size* outActualSize) = 0;
00851   NS_IMETHOD  Put(nsIMdbEnv* ev, const void* inBuf, mdb_size inSize,
00852     mdb_pos inPos, mdb_size* outActualSize) = 0;
00853   NS_IMETHOD  Flush(nsIMdbEnv* ev) = 0;
00854   // } ----- end attribute methods -----
00855     
00856   // { ----- begin path methods -----
00857   NS_IMETHOD  Path(nsIMdbEnv* ev, mdbYarn* outFilePath) = 0;
00858   // } ----- end path methods -----
00859     
00860   // { ----- begin replacement methods -----
00861   NS_IMETHOD  Steal(nsIMdbEnv* ev, nsIMdbFile* ioThief) = 0;
00862   NS_IMETHOD  Thief(nsIMdbEnv* ev, nsIMdbFile** acqThief) = 0;
00863   // } ----- end replacement methods -----
00864 
00865   // { ----- begin versioning methods -----
00866   NS_IMETHOD BecomeTrunk(nsIMdbEnv* ev) = 0;
00867   // If this file is a file version branch created by calling AcquireBud(),
00868   // BecomeTrunk() causes this file's content to replace the original
00869   // file's content, typically by assuming the original file's identity.
00870   // This default implementation of BecomeTrunk() does nothing, and this
00871   // is appropriate behavior for files which are not branches, and is
00872   // also the right behavior for files returned from AcquireBud() which are
00873   // in fact the original file that has been truncated down to zero length.
00874 
00875   NS_IMETHOD AcquireBud(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
00876     nsIMdbFile** acqBud) = 0; // acquired file for new version of content
00877   // AcquireBud() starts a new "branch" version of the file, empty of content,
00878   // so that a new version of the file can be written.  This new file
00879   // can later be told to BecomeTrunk() the original file, so the branch
00880   // created by budding the file will replace the original file.  Some
00881   // file subclasses might initially take the unsafe but expedient
00882   // approach of simply truncating this file down to zero length, and
00883   // then returning the same morkFile pointer as this, with an extra
00884   // reference count increment.  Note that the caller of AcquireBud() is
00885   // expected to eventually call CutStrongRef() on the returned file
00886   // in order to release the strong reference.  High quality versions
00887   // of morkFile subclasses will create entirely new files which later
00888   // are renamed to become the old file, so that better transactional
00889   // behavior is exhibited by the file, so crashes protect old files.
00890   // Note that AcquireBud() is an illegal operation on readonly files.
00891   // } ----- end versioning methods -----
00892 
00893 // } ===== end nsIMdbFile methods =====
00894 };
00895 
00896 /*| nsIMdbPort: a readonly interface to a specific database file. The mutable
00897 **| nsIMdbStore interface is a subclass that includes writing behavior, but
00898 **| most of the needed db methods appear in the readonly nsIMdbPort interface.
00899 **|
00900 **|| mdbYarn: note all nsIMdbPort and nsIMdbStore subclasses must guarantee null
00901 **| termination of all strings written into mdbYarn instances, as long as
00902 **| mYarn_Size and mYarn_Buf are nonzero.  Even truncated string values must
00903 **| be null terminated.  This is more strict behavior than mdbYarn requires,
00904 **| but it is part of the nsIMdbPort and nsIMdbStore interface.
00905 **|
00906 **|| attributes: methods are provided to distinguish a readonly port from a
00907 **| mutable store, and whether a mutable store actually has any dirty content.
00908 **|
00909 **|| filepath: the file path used to open the port from the nsIMdbFactory can be
00910 **| queried and discovered by GetPortFilePath(), which includes format info.
00911 **|
00912 **|| export: a port can write itself in other formats, with perhaps a typical
00913 **| emphasis on text interchange formats used by other systems.  A port can be
00914 **| queried to determine its preferred export interchange format, and a port
00915 **| can be queried to see whether a specific export format is supported.  And
00916 **| actually exporting a port requires a new destination file name and format.
00917 **|
00918 **|| tokens: a port supports queries about atomized strings to map tokens to
00919 **| strings or strings to token integers.  (All atomized strings must be in
00920 **| US-ASCII iso-8859-1 Latin1 charset encoding.)  When a port is actually a
00921 **| mutable store and a string has not yet been atomized, then StringToToken()
00922 **| will actually do so and modify the store.  The QueryToken() method will not
00923 **| atomize a string if it has not already been atomized yet, even in stores.
00924 **|
00925 **|| tables: other than string tokens, all port content is presented through
00926 **| tables, which are ordered collections of rows.  Tables are identified by
00927 **| row scope and table kind, which might or might not be unique in a port,
00928 **| depending on app convention.  When tables are effectively unique, then
00929 **| queries for specific scope and kind pairs will find those tables.  To see
00930 **| all tables that match specific row scope and table kind patterns, even in
00931 **| the presence of duplicates, every port supports a GetPortTableCursor()
00932 **| method that returns an iterator over all matching tables.  Table kind is
00933 **| considered scoped inside row scope, so passing a zero for table kind will
00934 **| find all table kinds for some nonzero row scope.  Passing a zero for row
00935 **| scope will iterate over all tables in the port, in some undefined order.
00936 **| (A new table can be added to a port using nsIMdbStore::NewTable(), even when
00937 **| the requested scope and kind combination is already used by other tables.)
00938 **|
00939 **|| memory: callers can request that a database use less memory footprint in
00940 **| several flavors, from an inconsequential idle flavor to a rather drastic
00941 **| panic flavor. Callers might perform an idle purge very frequently if desired
00942 **| with very little cost, since only normally scheduled memory management will
00943 **| be conducted, such as freeing resources for objects scheduled to be dropped.
00944 **| Callers should perform session memory purges infrequently because they might
00945 **| involve costly scanning of data structures to removed cached content, and
00946 **| session purges are recommended only when a caller experiences memory crunch.
00947 **| Callers should only rarely perform a panic purge, in response to dire memory
00948 **| straits, since this is likely to make db operations much more expensive
00949 **| than they would be otherwise.  A panic purge asks a database to free as much
00950 **| memory as possible while staying effective and operational, because a caller
00951 **| thinks application failure might otherwise occur.  (Apps might better close
00952 **| an open db, so panic purges only make sense when a db is urgently needed.)
00953 |*/
00954 class nsIMdbPort : public nsISupports {
00955 public:
00956 
00957 // { ===== begin nsIMdbPort methods =====
00958 
00959   // { ----- begin attribute methods -----
00960   NS_IMETHOD GetIsPortReadonly(nsIMdbEnv* ev, mdb_bool* outBool) = 0;
00961   NS_IMETHOD GetIsStore(nsIMdbEnv* ev, mdb_bool* outBool) = 0;
00962   NS_IMETHOD GetIsStoreAndDirty(nsIMdbEnv* ev, mdb_bool* outBool) = 0;
00963 
00964   NS_IMETHOD GetUsagePolicy(nsIMdbEnv* ev, 
00965     mdbUsagePolicy* ioUsagePolicy) = 0;
00966 
00967   NS_IMETHOD SetUsagePolicy(nsIMdbEnv* ev, 
00968     const mdbUsagePolicy* inUsagePolicy) = 0;
00969   // } ----- end attribute methods -----
00970 
00971   // { ----- begin memory policy methods -----  
00972   NS_IMETHOD IdleMemoryPurge( // do memory management already scheduled
00973     nsIMdbEnv* ev, // context
00974     mdb_size* outEstimatedBytesFreed) = 0; // approximate bytes actually freed
00975 
00976   NS_IMETHOD SessionMemoryPurge( // request specific footprint decrease
00977     nsIMdbEnv* ev, // context
00978     mdb_size inDesiredBytesFreed, // approximate number of bytes wanted
00979     mdb_size* outEstimatedBytesFreed) = 0; // approximate bytes actually freed
00980 
00981   NS_IMETHOD PanicMemoryPurge( // desperately free all possible memory
00982     nsIMdbEnv* ev, // context
00983     mdb_size* outEstimatedBytesFreed) = 0; // approximate bytes actually freed
00984   // } ----- end memory policy methods -----
00985 
00986   // { ----- begin filepath methods -----
00987   NS_IMETHOD GetPortFilePath(
00988     nsIMdbEnv* ev, // context
00989     mdbYarn* outFilePath, // name of file holding port content
00990     mdbYarn* outFormatVersion) = 0; // file format description
00991     
00992   NS_IMETHOD GetPortFile(
00993     nsIMdbEnv* ev, // context
00994     nsIMdbFile** acqFile) = 0; // acquire file used by port or store
00995   // } ----- end filepath methods -----
00996 
00997   // { ----- begin export methods -----
00998   NS_IMETHOD BestExportFormat( // determine preferred export format
00999     nsIMdbEnv* ev, // context
01000     mdbYarn* outFormatVersion) = 0; // file format description
01001 
01002   // some tentative suggested import/export formats
01003   // "ns:msg:db:port:format:ldif:ns4.0:passthrough" // necessary
01004   // "ns:msg:db:port:format:ldif:ns4.5:utf8"        // necessary
01005   // "ns:msg:db:port:format:ldif:ns4.5:tabbed"
01006   // "ns:msg:db:port:format:ldif:ns4.5:binary"      // necessary
01007   // "ns:msg:db:port:format:html:ns3.0:addressbook" // necessary
01008   // "ns:msg:db:port:format:html:display:verbose"
01009   // "ns:msg:db:port:format:html:display:concise"
01010   // "ns:msg:db:port:format:mork:zany:verbose"      // necessary
01011   // "ns:msg:db:port:format:mork:zany:atomized"     // necessary
01012   // "ns:msg:db:port:format:rdf:xml"
01013   // "ns:msg:db:port:format:xml:mork"
01014   // "ns:msg:db:port:format:xml:display:verbose"
01015   // "ns:msg:db:port:format:xml:display:concise"
01016   // "ns:msg:db:port:format:xml:print:verbose"      // recommended
01017   // "ns:msg:db:port:format:xml:print:concise"
01018 
01019   NS_IMETHOD
01020   CanExportToFormat( // can export content in given specific format?
01021     nsIMdbEnv* ev, // context
01022     const char* inFormatVersion, // file format description
01023     mdb_bool* outCanExport) = 0; // whether ExportSource() might succeed
01024 
01025   NS_IMETHOD ExportToFormat( // export content in given specific format
01026     nsIMdbEnv* ev, // context
01027     // const char* inFilePath, // the file to receive exported content
01028     nsIMdbFile* ioFile, // destination abstract file interface
01029     const char* inFormatVersion, // file format description
01030     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental export
01031   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
01032   // then the export will be finished.
01033 
01034   // } ----- end export methods -----
01035 
01036   // { ----- begin token methods -----
01037   NS_IMETHOD TokenToString( // return a string name for an integer token
01038     nsIMdbEnv* ev, // context
01039     mdb_token inToken, // token for inTokenName inside this port
01040     mdbYarn* outTokenName) = 0; // the type of table to access
01041   
01042   NS_IMETHOD StringToToken( // return an integer token for scope name
01043     nsIMdbEnv* ev, // context
01044     const char* inTokenName, // Latin1 string to tokenize if possible
01045     mdb_token* outToken) = 0; // token for inTokenName inside this port
01046     
01047   // String token zero is never used and never supported. If the port
01048   // is a mutable store, then StringToToken() to create a new
01049   // association of inTokenName with a new integer token if possible.
01050   // But a readonly port will return zero for an unknown scope name.
01051 
01052   NS_IMETHOD QueryToken( // like StringToToken(), but without adding
01053     nsIMdbEnv* ev, // context
01054     const char* inTokenName, // Latin1 string to tokenize if possible
01055     mdb_token* outToken) = 0; // token for inTokenName inside this port
01056   
01057   // QueryToken() will return a string token if one already exists,
01058   // but unlike StringToToken(), will not assign a new token if not
01059   // already in use.
01060 
01061   // } ----- end token methods -----
01062 
01063   // { ----- begin row methods -----  
01064   NS_IMETHOD HasRow( // contains a row with the specified oid?
01065     nsIMdbEnv* ev, // context
01066     const mdbOid* inOid,  // hypothetical row oid
01067     mdb_bool* outHasRow) = 0; // whether GetRow() might succeed
01068 
01069   NS_IMETHOD GetRowRefCount( // get number of tables that contain a row 
01070     nsIMdbEnv* ev, // context
01071     const mdbOid* inOid,  // hypothetical row oid
01072     mdb_count* outRefCount) = 0; // number of tables containing inRowKey 
01073     
01074   NS_IMETHOD GetRow( // access one row with specific oid
01075     nsIMdbEnv* ev, // context
01076     const mdbOid* inOid,  // hypothetical row oid
01077     nsIMdbRow** acqRow) = 0; // acquire specific row (or null)
01078     
01079   // NS_IMETHOD
01080   // GetPortRowCursor( // get cursor for all rows in specific scope
01081   //   nsIMdbEnv* ev, // context
01082   //   mdb_scope inRowScope, // row scope for row ids
01083   //   nsIMdbPortRowCursor** acqCursor) = 0; // all such rows in the port
01084 
01085   NS_IMETHOD FindRow(nsIMdbEnv* ev, // search for row with matching cell
01086     mdb_scope inRowScope,   // row scope for row ids
01087     mdb_column inColumn,   // the column to search (and maintain an index)
01088     const mdbYarn* inTargetCellValue, // cell value for which to search
01089     mdbOid* outRowOid, // out row oid on match (or {0,-1} for no match)
01090     nsIMdbRow** acqRow) = 0; // acquire matching row (or nil for no match)
01091                              // can be null if you only want the oid
01092   // FindRow() searches for one row that has a cell in column inColumn with
01093   // a contained value with the same form (i.e. charset) and is byte-wise
01094   // identical to the blob described by yarn inTargetCellValue.  Both content
01095   // and form of the yarn must be an exact match to find a matching row.
01096   //
01097   // (In other words, both a yarn's blob bytes and form are significant.  The
01098   // form is not expected to vary in columns used for identity anyway.  This
01099   // is intended to make the cost of FindRow() cheaper for MDB implementors,
01100   // since any cell value atomization performed internally must necessarily
01101   // make yarn form significant in order to avoid data loss in atomization.)
01102   //
01103   // FindRow() can lazily create an index on attribute inColumn for all rows
01104   // with that attribute in row space scope inRowScope, so that subsequent
01105   // calls to FindRow() will perform faster.  Such an index might or might
01106   // not be persistent (but this seems desirable if it is cheap to do so).
01107   // Note that lazy index creation in readonly DBs is not very feasible.
01108   //
01109   // This FindRow() interface assumes that attribute inColumn is effectively
01110   // an alternative means of unique identification for a row in a rowspace,
01111   // so correct behavior is only guaranteed when no duplicates for this col
01112   // appear in the given set of rows.  (If more than one row has the same cell
01113   // value in this column, no more than one will be found; and cutting one of
01114   // two duplicate rows can cause the index to assume no other such row lives
01115   // in the row space, so future calls return nil for negative search results
01116   // even though some duplicate row might still live within the rowspace.)
01117   //
01118   // In other words, the FindRow() implementation is allowed to assume simple
01119   // hash tables mapping unqiue column keys to associated row values will be
01120   // sufficient, where any duplication is not recorded because only one copy
01121   // of a given key need be remembered.  Implementors are not required to sort
01122   // all rows by the specified column.
01123   // } ----- end row methods -----
01124 
01125   // { ----- begin table methods -----  
01126   NS_IMETHOD HasTable( // supports a table with the specified oid?
01127     nsIMdbEnv* ev, // context
01128     const mdbOid* inOid,  // hypothetical table oid
01129     mdb_bool* outHasTable) = 0; // whether GetTable() might succeed
01130     
01131   NS_IMETHOD GetTable( // access one table with specific oid
01132     nsIMdbEnv* ev, // context
01133     const mdbOid* inOid,  // hypothetical table oid
01134     nsIMdbTable** acqTable) = 0; // acquire specific table (or null)
01135   
01136   NS_IMETHOD HasTableKind( // supports a table of the specified type?
01137     nsIMdbEnv* ev, // context
01138     mdb_scope inRowScope, // rid scope for row ids
01139     mdb_kind inTableKind, // the type of table to access
01140     mdb_count* outTableCount, // current number of such tables
01141     mdb_bool* outSupportsTable) = 0; // whether GetTableKind() might succeed
01142     
01143   // row scopes to be supported include the following suggestions:
01144   // "ns:msg:db:row:scope:address:cards:all"
01145   // "ns:msg:db:row:scope:mail:messages:all"
01146   // "ns:msg:db:row:scope:news:articles:all"
01147  
01148   // table kinds to be supported include the following suggestions:
01149   // "ns:msg:db:table:kind:address:cards:main"
01150   // "ns:msg:db:table:kind:address:lists:all" 
01151   // "ns:msg:db:table:kind:address:list" 
01152   // "ns:msg:db:table:kind:news:threads:all" 
01153   // "ns:msg:db:table:kind:news:thread" 
01154   // "ns:msg:db:table:kind:mail:threads:all"
01155   // "ns:msg:db:table:kind:mail:thread"
01156     
01157   NS_IMETHOD GetTableKind( // access one (random) table of specific type
01158     nsIMdbEnv* ev, // context
01159     mdb_scope inRowScope,      // row scope for row ids
01160     mdb_kind inTableKind,      // the type of table to access
01161     mdb_count* outTableCount, // current number of such tables
01162     mdb_bool* outMustBeUnique, // whether port can hold only one of these
01163     nsIMdbTable** acqTable) = 0;       // acquire scoped collection of rows
01164     
01165   NS_IMETHOD
01166   GetPortTableCursor( // get cursor for all tables of specific type
01167     nsIMdbEnv* ev, // context
01168     mdb_scope inRowScope, // row scope for row ids
01169     mdb_kind inTableKind, // the type of table to access
01170     nsIMdbPortTableCursor** acqCursor) = 0; // all such tables in the port
01171   // } ----- end table methods -----
01172 
01173 
01174   // { ----- begin commit methods -----
01175 
01176   NS_IMETHOD ShouldCompress( // store wastes at least inPercentWaste?
01177     nsIMdbEnv* ev, // context
01178     mdb_percent inPercentWaste, // 0..100 percent file size waste threshold
01179     mdb_percent* outActualWaste, // 0..100 percent of file actually wasted
01180     mdb_bool* outShould) = 0; // true when about inPercentWaste% is wasted
01181   // ShouldCompress() returns true if the store can determine that the file
01182   // will shrink by an estimated percentage of inPercentWaste% (or more) if
01183   // CompressCommit() is called, because that percentage of the file seems
01184   // to be recoverable free space.  The granularity is only in terms of 
01185   // percentage points, and any value over 100 is considered equal to 100.
01186   //
01187   // If a store only has an approximate idea how much space might be saved
01188   // during a compress, then a best guess should be made.  For example, the
01189   // Mork implementation might keep track of how much file space began with
01190   // text content before the first updating transaction, and then consider
01191   // all content following the start of the first transaction as potentially
01192   // wasted space if it is all updates and not just new content.  (This is
01193   // a safe assumption in the sense that behavior will stabilize on a low
01194   // estimate of wastage after a commit removes all transaction updates.)
01195   //
01196   // Some db formats might attempt to keep a very accurate reckoning of free
01197   // space size, so a very accurate determination can be made.  But other db
01198   // formats might have difficulty determining size of free space, and might
01199   // require some lengthy calculation to answer.  This is the reason for
01200   // passing in the percentage threshold of interest, so that such lengthy
01201   // computations can terminate early as soon as at least inPercentWaste is
01202   // found, so that the entire file need not be groveled when unnecessary.
01203   // However, we hope implementations will always favor fast but imprecise
01204   // heuristic answers instead of extremely slow but very precise answers.
01205   //
01206   // If the outActualWaste parameter is non-nil, it will be used to return
01207   // the actual estimated space wasted as a percentage of file size.  (This
01208   // parameter is provided so callers need not call repeatedly with altered
01209   // inPercentWaste values to isolate the actual wastage figure.)  Note the
01210   // actual wastage figure returned can exactly equal inPercentWaste even
01211   // when this grossly underestimates the real figure involved, if the db
01212   // finds it very expensive to determine the extent of wastage after it is
01213   // known to at least exceed inPercentWaste.  Note we expect that whenever
01214   // outShould returns true, that outActualWaste returns >= inPercentWaste.
01215   //
01216   // The effect of different inPercentWaste values is not very uniform over
01217   // the permitted range.  For example, 50 represents 50% wastage, or a file
01218   // that is about double what it should be ideally.  But 99 represents 99%
01219   // wastage, or a file that is about ninety-nine times as big as it should
01220   // be ideally.  In the smaller direction, 25 represents 25% wastage, or
01221   // a file that is only 33% larger than it should be ideally.
01222   //
01223   // Callers can determine what policy they want to use for considering when
01224   // a file holds too much wasted space, and express this as a percentage
01225   // of total file size to pass as in the inPercentWaste parameter.  A zero
01226   // likely returns always trivially true, and 100 always trivially false.
01227   // The great majority of callers are expected to use values from 25 to 75,
01228   // since most plausible thresholds for compressing might fall between the
01229   // extremes of 133% of ideal size and 400% of ideal size.  (Presumably the
01230   // larger a file gets, the more important the percentage waste involved, so
01231   // a sliding scale for compress thresholds might use smaller numbers for
01232   // much bigger file sizes.)
01233   
01234   // } ----- end commit methods -----
01235 
01236 // } ===== end nsIMdbPort methods =====
01237 };
01238 
01239 /*| nsIMdbStore: a mutable interface to a specific database file.
01240 **|
01241 **|| tables: one can force a new table to exist in a store with NewTable()
01242 **| and nonzero values for both row scope and table kind.  (If one wishes only
01243 **| one table of a certain kind, then one might look for it first using the
01244 **| GetTableKind() method).  One can pass inMustBeUnique to force future
01245 **| users of this store to be unable to create other tables with the same pair
01246 **| of scope and kind attributes.  When inMustBeUnique is true, and the table
01247 **| with the given scope and kind pair already exists, then the existing one
01248 **| is returned instead of making a new table.  Similarly, if one passes false
01249 **| for inMustBeUnique, but the table kind has already been marked unique by a
01250 **| previous user of the store, then the existing unique table is returned.
01251 **|
01252 **|| import: all or some of another port's content can be imported by calling
01253 **| AddPortContent() with a row scope identifying the extent of content to
01254 **| be imported.  A zero row scope will import everything.  A nonzero row
01255 **| scope will only import tables with a matching row scope.  Note that one
01256 **| must somehow find a way to negotiate possible conflicts between existing
01257 **| row content and imported row content, and this involves a specific kind of
01258 **| definition for row identity involving either row IDs or unique attributes,
01259 **| or some combination of these two.  At the moment I am just going to wave
01260 **| my hands, and say the default behavior is to assign all new row identities
01261 **| to all imported content, which will result in no merging of content; this
01262 **| must change later because it is unacceptable in some contexts.
01263 **|
01264 **|| commits: to manage modifications in a mutable store, very few methods are
01265 **| really needed to indicate global policy choices that are independent of 
01266 **| the actual modifications that happen in objects at the level of tables,
01267 **| rows, and cells, etc.  The most important policy to specify is which sets
01268 **| of changes are considered associated in a manner such that they should be
01269 **| applied together atomically to a given store.  We call each such group of
01270 **| changes a transaction.  We handle three different grades of transaction,
01271 **| but they differ only in semantic significance to the application, and are
01272 **| not intended to nest.  (If small transactions were nested inside large
01273 **| transactions, that would imply that a single large transaction must be
01274 **| atomic over all the contained small transactions; but actually we intend
01275 **| smalls transaction never be undone once commited due to, say, aborting a
01276 **| transaction of greater significance.)  The small, large, and session level
01277 **| commits have equal granularity, and differ only in risk of loss from the
01278 **| perspective of an application.  Small commits characterize changes that
01279 **| can be lost with relatively small risk, so small transactions can delay
01280 **| until later if they are expensive or impractical to commit.  Large commits
01281 **| involve changes that would probably inconvenience users if lost, so the
01282 **| need to pay costs of writing is rather greater than with small commits.
01283 **| Session commits are last ditch attempts to save outstanding changes before
01284 **| stopping the use of a particular database, so there will be no later point
01285 **| in time to save changes that have been delayed due to possible high cost.
01286 **| If large commits are never delayed, then a session commit has about the
01287 **| same performance effect as another large commit; but if small and large
01288 **| commits are always delayed, then a session commit is likely to be rather
01289 **| expensive as a runtime cost compared to any earlier database usage.
01290 **|
01291 **|| aborts: the only way to abort changes to a store is by closing the store.
01292 **| So there is no specific method for causing any abort.  Stores must discard
01293 **| all changes made that are uncommited when a store is closed.  This design
01294 **| choice makes the implementations of tables, rows, and cells much less
01295 **| complex because they need not maintain a record of undobable changes.  When
01296 **| a store is closed, presumably this precipitates the closure of all tables,
01297 **| rows, and cells in the store as well.   So an application can revert the
01298 **| state of a store in the user interface by quietly closing and reopening a
01299 **| store, because this will discard uncommited changes and show old content.
01300 **| This implies an app that closes a store will need to send a "scramble"
01301 **| event notification to any views that depend on old discarded content.
01302 |*/
01303 
01304 #define NS_IMDBSTORE_IID_STR "726618d3-f15b-49b9-9f4a-efcc9db53d0d"
01305 
01306 #define NS_IMDBSTORE_IID \
01307 {0x726618d3, 0xf15b, 0x49b9, \
01308 {0x9f, 0x4a, 0xef, 0xcc, 0x9d, 0xb5, 0x3d, 0x0d}}
01309 
01310 class nsIMdbStore : public nsIMdbPort {
01311 public:
01312   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBSTORE_IID)
01313 
01314 // { ===== begin nsIMdbStore methods =====
01315 
01316   // { ----- begin table methods -----
01317   NS_IMETHOD NewTable( // make one new table of specific type
01318     nsIMdbEnv* ev, // context
01319     mdb_scope inRowScope,    // row scope for row ids
01320     mdb_kind inTableKind,    // the type of table to access
01321     mdb_bool inMustBeUnique, // whether store can hold only one of these
01322     const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
01323     nsIMdbTable** acqTable) = 0;     // acquire scoped collection of rows
01324     
01325   NS_IMETHOD NewTableWithOid( // make one new table of specific type
01326     nsIMdbEnv* ev, // context
01327     const mdbOid* inOid,   // caller assigned oid
01328     mdb_kind inTableKind,    // the type of table to access
01329     mdb_bool inMustBeUnique, // whether store can hold only one of these
01330     const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying 
01331     nsIMdbTable** acqTable) = 0;     // acquire scoped collection of rows
01332   // } ----- end table methods -----
01333 
01334   // { ----- begin row scope methods -----
01335   NS_IMETHOD RowScopeHasAssignedIds(nsIMdbEnv* ev,
01336     mdb_scope inRowScope,   // row scope for row ids
01337     mdb_bool* outCallerAssigned, // nonzero if caller assigned specified
01338     mdb_bool* outStoreAssigned) = 0; // nonzero if store db assigned specified
01339 
01340   NS_IMETHOD SetCallerAssignedIds(nsIMdbEnv* ev,
01341     mdb_scope inRowScope,   // row scope for row ids
01342     mdb_bool* outCallerAssigned, // nonzero if caller assigned specified
01343     mdb_bool* outStoreAssigned) = 0; // nonzero if store db assigned specified
01344 
01345   NS_IMETHOD SetStoreAssignedIds(nsIMdbEnv* ev,
01346     mdb_scope inRowScope,   // row scope for row ids
01347     mdb_bool* outCallerAssigned, // nonzero if caller assigned specified
01348     mdb_bool* outStoreAssigned) = 0; // nonzero if store db assigned specified
01349   // } ----- end row scope methods -----
01350 
01351   // { ----- begin row methods -----
01352   NS_IMETHOD NewRowWithOid(nsIMdbEnv* ev, // new row w/ caller assigned oid
01353     const mdbOid* inOid,   // caller assigned oid
01354     nsIMdbRow** acqRow) = 0; // create new row
01355 
01356   NS_IMETHOD NewRow(nsIMdbEnv* ev, // new row with db assigned oid
01357     mdb_scope inRowScope,   // row scope for row ids
01358     nsIMdbRow** acqRow) = 0; // create new row
01359   // Note this row must be added to some table or cell child before the
01360   // store is closed in order to make this row persist across sesssions.
01361 
01362   // } ----- end row methods -----
01363 
01364   // { ----- begin inport/export methods -----
01365   NS_IMETHOD ImportContent( // import content from port
01366     nsIMdbEnv* ev, // context
01367     mdb_scope inRowScope, // scope for rows (or zero for all?)
01368     nsIMdbPort* ioPort, // the port with content to add to store
01369     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental import
01370   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
01371   // then the import will be finished.
01372 
01373   NS_IMETHOD ImportFile( // import content from port
01374     nsIMdbEnv* ev, // context
01375     nsIMdbFile* ioFile, // the file with content to add to store
01376     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental import
01377   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
01378   // then the import will be finished.
01379   // } ----- end inport/export methods -----
01380 
01381   // { ----- begin hinting methods -----
01382   NS_IMETHOD
01383   ShareAtomColumnsHint( // advise re shared column content atomizing
01384     nsIMdbEnv* ev, // context
01385     mdb_scope inScopeHint, // zero, or suggested shared namespace
01386     const mdbColumnSet* inColumnSet) = 0; // cols desired tokenized together
01387 
01388   NS_IMETHOD
01389   AvoidAtomColumnsHint( // advise column with poor atomizing prospects
01390     nsIMdbEnv* ev, // context
01391     const mdbColumnSet* inColumnSet) = 0; // cols with poor atomizing prospects
01392   // } ----- end hinting methods -----
01393 
01394   // { ----- begin commit methods -----
01395   NS_IMETHOD SmallCommit( // save minor changes if convenient and uncostly
01396     nsIMdbEnv* ev) = 0; // context
01397   
01398   NS_IMETHOD LargeCommit( // save important changes if at all possible
01399     nsIMdbEnv* ev, // context
01400     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental commit
01401   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
01402   // then the commit will be finished.  Note the store is effectively write
01403   // locked until commit is finished or canceled through the thumb instance.
01404   // Until the commit is done, the store will report it has readonly status.
01405 
01406   NS_IMETHOD SessionCommit( // save all changes if large commits delayed
01407     nsIMdbEnv* ev, // context
01408     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental commit
01409   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
01410   // then the commit will be finished.  Note the store is effectively write
01411   // locked until commit is finished or canceled through the thumb instance.
01412   // Until the commit is done, the store will report it has readonly status.
01413 
01414   NS_IMETHOD
01415   CompressCommit( // commit and make db physically smaller if possible
01416     nsIMdbEnv* ev, // context
01417     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental commit
01418   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
01419   // then the commit will be finished.  Note the store is effectively write
01420   // locked until commit is finished or canceled through the thumb instance.
01421   // Until the commit is done, the store will report it has readonly status.
01422   
01423   // } ----- end commit methods -----
01424 
01425 // } ===== end nsIMdbStore methods =====
01426 };
01427 
01428 /*| nsIMdbCursor: base cursor class for iterating row cells and table rows
01429 **|
01430 **|| count: the number of elements in the collection (table or row)
01431 **|
01432 **|| seed: the change count in the underlying collection, which is synced
01433 **| with the collection when the iteration position is set, and henceforth
01434 **| acts to show whether the iter has lost collection synchronization, in
01435 **| case it matters to clients whether any change happens during iteration.
01436 **|
01437 **|| pos: the position of the current element in the collection.  Negative
01438 **| means a position logically before the first element.  A positive value
01439 **| equal to count (or larger) implies a position after the last element.
01440 **| To iterate over all elements, set the position to negative, so subsequent
01441 **| calls to any 'next' method will access the first collection element.
01442 **|
01443 **|| doFailOnSeedOutOfSync: whether a cursor should return an error if the
01444 **| cursor's snapshot of a table's seed becomes stale with respect the table's
01445 **| current seed value (which implies the iteration is less than total) in
01446 **| between to cursor calls that actually access collection content.  By
01447 **| default, a cursor should assume this attribute is false until specified,
01448 **| so that iterations quietly try to re-sync when they loose coherence.
01449 |*/
01450 
01451 #define NS_IMDBCURSOR_IID_STR "a0c37337-6ebc-474c-90db-e65ea0b850aa"
01452 
01453 #define NS_IMDBCURSOR_IID \
01454 {0xa0c37337, 0x6ebc, 0x474c, \
01455 {0x90, 0xdb, 0xe6, 0x5e, 0xa0, 0xb8, 0x50, 0xaa}}
01456 
01457 class nsIMdbCursor  : public nsISupports  { // collection iterator
01458 public:
01459 
01460   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBCURSOR_IID)
01461 // { ===== begin nsIMdbCursor methods =====
01462 
01463   // { ----- begin attribute methods -----
01464   NS_IMETHOD GetCount(nsIMdbEnv* ev, mdb_count* outCount) = 0; // readonly
01465   NS_IMETHOD GetSeed(nsIMdbEnv* ev, mdb_seed* outSeed) = 0;    // readonly
01466   
01467   NS_IMETHOD SetPos(nsIMdbEnv* ev, mdb_pos inPos) = 0;   // mutable
01468   NS_IMETHOD GetPos(nsIMdbEnv* ev, mdb_pos* outPos) = 0;
01469   
01470   NS_IMETHOD SetDoFailOnSeedOutOfSync(nsIMdbEnv* ev, mdb_bool inFail) = 0;
01471   NS_IMETHOD GetDoFailOnSeedOutOfSync(nsIMdbEnv* ev, mdb_bool* outFail) = 0;
01472   // } ----- end attribute methods -----
01473 
01474 // } ===== end nsIMdbCursor methods =====
01475 };
01476 
01477 #define NS_IMDBPORTTABLECURSOR_IID_STR = "f181a41e-933d-49b3-af93-20d3634b8b78"
01478 
01479 #define NS_IMDBPORTTABLECURSOR_IID \
01480 {0xf181a41e, 0x933d, 0x49b3, \
01481 {0xaf, 0x93, 0x20, 0xd3, 0x63, 0x4b, 0x8b, 0x78}}
01482 
01483 /*| nsIMdbPortTableCursor: cursor class for iterating port tables
01484 **|
01485 **|| port: the cursor is associated with a specific port, which can be
01486 **| set to a different port (which resets the position to -1 so the
01487 **| next table acquired is the first in the port.
01488 **|
01489 |*/
01490 class nsIMdbPortTableCursor : public nsISupports { // table collection iterator
01491 public:
01492 
01493   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBPORTTABLECURSOR_IID)
01494 // { ===== begin nsIMdbPortTableCursor methods =====
01495 
01496   // { ----- begin attribute methods -----
01497   NS_IMETHOD SetPort(nsIMdbEnv* ev, nsIMdbPort* ioPort) = 0; // sets pos to -1
01498   NS_IMETHOD GetPort(nsIMdbEnv* ev, nsIMdbPort** acqPort) = 0;
01499   
01500   NS_IMETHOD SetRowScope(nsIMdbEnv* ev, // sets pos to -1
01501     mdb_scope inRowScope) = 0;
01502   NS_IMETHOD GetRowScope(nsIMdbEnv* ev, mdb_scope* outRowScope) = 0; 
01503   // setting row scope to zero iterates over all row scopes in port
01504     
01505   NS_IMETHOD SetTableKind(nsIMdbEnv* ev, // sets pos to -1
01506     mdb_kind inTableKind) = 0;
01507   NS_IMETHOD GetTableKind(nsIMdbEnv* ev, mdb_kind* outTableKind) = 0;
01508   // setting table kind to zero iterates over all table kinds in row scope
01509   // } ----- end attribute methods -----
01510 
01511   // { ----- begin table iteration methods -----
01512   NS_IMETHOD NextTable( // get table at next position in the db
01513     nsIMdbEnv* ev, // context
01514     nsIMdbTable** acqTable) = 0; // the next table in the iteration
01515   // } ----- end table iteration methods -----
01516 
01517 // } ===== end nsIMdbPortTableCursor methods =====
01518 };
01519 
01520 /*| nsIMdbCollection: an object that collects a set of other objects as members.
01521 **| The main purpose of this base class is to unify the perceived semantics
01522 **| of tables and rows where their collection behavior is similar.  This helps
01523 **| isolate the mechanics of collection behavior from the other semantics that
01524 **| are more characteristic of rows and tables.
01525 **|
01526 **|| count: the number of objects in a collection is the member count. (Some
01527 **| collection interfaces call this attribute the 'size', but that can be a
01528 **| little ambiguous, and counting actual members is harder to confuse.)
01529 **|
01530 **|| seed: the seed of a collection is a counter for changes in membership in
01531 **| a specific collection.  This seed should change when members are added to
01532 **| or removed from a collection, but not when a member changes internal state.
01533 **| The seed should also change whenever the internal collection of members has
01534 **| a complex state change that reorders member positions (say by sorting) that
01535 **| would affect the nature of an iteration over that collection of members.
01536 **| The purpose of a seed is to inform any outstanding collection cursors that
01537 **| they might be stale, without incurring the cost of broadcasting an event
01538 **| notification to such cursors, which would need more data structure support.
01539 **| Presumably a cursor in a particular mdb code suite has much more direct
01540 **| access to a collection seed member slot that this abstract COM interface,
01541 **| so this information is intended more for clients outside mdb that want to
01542 **| make inferences similar to those made by the collection cursors.  The seed
01543 **| value as an integer magnitude is not very important, and callers should not
01544 **| assume meaningful information can be derived from an integer value beyond
01545 **| whether it is equal or different from a previous inspection.  A seed uses
01546 **| integers of many bits in order to make the odds of wrapping and becoming
01547 **| equal to an earlier seed value have probability that is vanishingly small.
01548 **|
01549 **|| port: every collection is associated with a specific database instance.
01550 **|
01551 **|| cursor: a subclass of nsIMdbCursor suitable for this specific collection
01552 **| subclass.  The ability to GetCursor() from the base nsIMdbCollection class
01553 **| is not really as useful as getting a more specifically typed cursor more
01554 **| directly from the base class without any casting involved.  So including
01555 **| this method here is more for conceptual illustration.
01556 **|
01557 **|| oid: every collection has an identity that persists from session to
01558 **| session. Implementations are probably able to distinguish row IDs from
01559 **| table IDs, but we don't specify anything official in this regard.  A
01560 **| collection has the same identity for the lifetime of the collection,
01561 **| unless identity is swapped with another collection by means of a call to
01562 **| BecomeContent(), which is considered a way to swap a new representation
01563 **| for an old well-known object.  (Even so, only content appears to change,
01564 **| while the identity seems to stay the same.)
01565 **|
01566 **|| become: developers can effectively cause two objects to swap identities,
01567 **| in order to effect a complete swap between what persistent content is
01568 **| represented by two oids.  The caller should consider this a content swap,
01569 **| and not identity wap, because identities will seem to stay the same while
01570 **| only content changes.  However, implementations will likely do this
01571 **| internally by swapping identities.  Callers must swap content only
01572 **| between objects of similar type, such as a row with another row, and a
01573 **| table with another table, because implementations need not support
01574 **| cross-object swapping because it might break object name spaces.
01575 **|
01576 **|| dropping: when a caller expects a row or table will no longer be used, the
01577 **| caller can tell the collection to 'drop activity', which means the runtime
01578 **| object can have it's internal representation purged to save memory or any
01579 **| other resource that is being consumed by the collection's representation.
01580 **| This has no effect on the collection's persistent content or semantics,
01581 **| and is only considered a runtime effect.  After a collection drops
01582 **| activity, the object should still be as usable as before (because it has
01583 **| NOT been closed), but further usage can be expensive to re-instate because
01584 **| it might involve reallocating space and/or re-reading disk space.  But
01585 **| since this future usage is not expected, the caller does not expect to
01586 **| pay the extra expense.  An implementation can choose to implement
01587 **| 'dropping activity' in different ways, or even not at all if this
01588 **| operation is not really feasible.  Callers cannot ask objects whether they
01589 **| are 'dropped' or not, so this should be transparent. (Note that
01590 **| implementors might fear callers do not really know whether future
01591 **| usage will occur, and therefore might delay the act of dropping until
01592 **| the near future, until seeing whether the object is used again
01593 **| immediately elsewhere. Such use soon after the drop request might cause
01594 **| the drop to be cancelled.)
01595 |*/
01596 class nsIMdbCollection : public nsISupports { // sequence of objects
01597 public:
01598 
01599 // { ===== begin nsIMdbCollection methods =====
01600 
01601   // { ----- begin attribute methods -----
01602   NS_IMETHOD GetSeed(nsIMdbEnv* ev,
01603     mdb_seed* outSeed) = 0;    // member change count
01604   NS_IMETHOD GetCount(nsIMdbEnv* ev,
01605     mdb_count* outCount) = 0; // member count
01606 
01607   NS_IMETHOD GetPort(nsIMdbEnv* ev,
01608     nsIMdbPort** acqPort) = 0; // collection container
01609   // } ----- end attribute methods -----
01610 
01611   // { ----- begin cursor methods -----
01612   NS_IMETHOD GetCursor( // make a cursor starting iter at inMemberPos
01613     nsIMdbEnv* ev, // context
01614     mdb_pos inMemberPos, // zero-based ordinal pos of member in collection
01615     nsIMdbCursor** acqCursor) = 0; // acquire new cursor instance
01616   // } ----- end cursor methods -----
01617 
01618   // { ----- begin ID methods -----
01619   NS_IMETHOD GetOid(nsIMdbEnv* ev,
01620     mdbOid* outOid) = 0; // read object identity
01621   NS_IMETHOD BecomeContent(nsIMdbEnv* ev,
01622     const mdbOid* inOid) = 0; // exchange content
01623   // } ----- end ID methods -----
01624 
01625   // { ----- begin activity dropping methods -----
01626   NS_IMETHOD DropActivity( // tell collection usage no longer expected
01627     nsIMdbEnv* ev) = 0;
01628   // } ----- end activity dropping methods -----
01629 
01630 // } ===== end nsIMdbCollection methods =====
01631 };
01632 
01633 /*| nsIMdbTable: an ordered collection of rows
01634 **|
01635 **|| row scope: an integer token for an atomized string in this database
01636 **| that names a space for row IDs.  This attribute of a table is intended
01637 **| as guidance metainformation that helps with searching a database for
01638 **| tables that operate on collections of rows of the specific type.  By
01639 **| convention, a table with a specific row scope is expected to focus on
01640 **| containing rows that belong to that scope, however exceptions are easily
01641 **| allowed because all rows in a table are known by both row ID and scope.
01642 **| (A table with zero row scope is never allowed because this would make it
01643 **| ambiguous to use a zero row scope when iterating over tables in a port to
01644 **| indicate that all row scopes should be seen by a cursor.)
01645 **|
01646 **|| table kind: an integer token for an atomized string in this database
01647 **| that names a kind of table as a subset of the associated row scope. This
01648 **| attribute is intended as guidance metainformation to clarify the role of
01649 **| this table with respect to other tables in the same row scope, and this
01650 **| also helps search for such tables in a database.  By convention, a table
01651 **| with a specific table kind has a consistent role for containing rows with
01652 **| respect to other collections of such rows in the same row scope.  Also by
01653 **| convention, at least one table in a row scope has a table kind purporting
01654 **| to contain ALL the rows that belong in that row scope, so that at least
01655 **| one table exists that allows all rows in a scope to be interated over.
01656 **| (A table with zero table kind is never allowed because this would make it
01657 **| ambiguous to use a zero table kind when iterating over tables in a port to
01658 **| indicate that all table kinds in a row scope should be seen by a cursor.)
01659 **|
01660 **|| port: every table is considered part of some port that contains the
01661 **| table, so that closing the containing port will cause the table to be
01662 **| indirectly closed as well.  We make it easy to get the containing port for
01663 **| a table, because the port supports important semantic interfaces that will
01664 **| affect how content in table is presented; the most important port context
01665 **| that affects a table is specified by the set of token to string mappings
01666 **| that affect all tokens used throughout the database, and which drive the
01667 **| meanings of row scope, table kind, cell columns, etc.
01668 **|
01669 **|| cursor: a cursor that iterates over the rows in this table, where rows
01670 **| have zero-based index positions from zero to count-1.  Making a cursor
01671 **| with negative position will next iterate over the first row in the table.
01672 **|
01673 **|| position: given any position from zero to count-1, a table will return
01674 **| the row ID and row scope for the row at that position.  (One can use the
01675 **| GetRowAllCells() method to read that row, or else use a row cursor to both
01676 **| get the row at some position and read its content at the same time.)  The
01677 **| position depends on whether a table is sorted, and upon the actual sort.
01678 **| Note that moving a row's position is only possible in unsorted tables.
01679 **|
01680 **|| row set: every table contains a collection of rows, where a member row is
01681 **| referenced by the table using the row ID and row scope for the row.  No
01682 **| single table owns a given row instance, because rows are effectively ref-
01683 **| counted and destroyed only when the last table removes a reference to that
01684 **| particular row.  (But a row can be emptied of all content no matter how
01685 **| many refs exist, and this might be the next best thing to destruction.)
01686 **| Once a row exists in a least one table (after NewRow() is called), then it
01687 **| can be added to any other table by calling AddRow(), or removed from any
01688 **| table by calling CutRow(), or queried as a member by calling HasRow().  A
01689 **| row can only be added to a table once, and further additions do nothing and
01690 **| complain not at all.  Cutting a row from a table only does something when
01691 **| the row was actually a member, and otherwise does nothing silently.
01692 **|
01693 **|| row ref count: one can query the number of tables (and/or cells)
01694 **| containing a row as a member or a child.
01695 **|
01696 **|| row content: one can access or modify the cell content in a table's row
01697 **| by moving content to or from an instance of nsIMdbRow.  Note that nsIMdbRow
01698 **| never represents the actual row inside a table, and this is the reason
01699 **| why nsIMdbRow instances do not have row IDs or row scopes.  So an instance
01700 **| of nsIMdbRow always and only contains a snapshot of some or all content in
01701 **| past, present, or future persistent row inside a table.  This means that
01702 **| reading and writing rows in tables has strictly copy semantics, and we
01703 **| currently do not plan any exceptions for specific performance reasons.
01704 **|
01705 **|| sorting: note all rows are assumed sorted by row ID as a secondary
01706 **| sort following the primary column sort, when table rows are sorted.
01707 **|
01708 **|| indexes:
01709 |*/
01710 
01711 
01712 #define NS_IMDBTABLE_IID_STR = "fe11bc98-d02b-4128-9fac-87042fdf9639"
01713 
01714 #define NS_IMDBTABLE_IID \
01715 {0xfe11bc98, 0xd02b, 0x4128, \
01716 {0x9f, 0xac, 0x87, 0x04, 0x2f, 0xdf, 0x96, 0x39}}
01717 
01718 
01719 class nsIMdbTable : public nsIMdbCollection { // a collection of rows
01720 public:
01721 
01722   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBTABLE_IID)
01723 // { ===== begin nsIMdbTable methods =====
01724 
01725   // { ----- begin meta attribute methods -----
01726   NS_IMETHOD SetTablePriority(nsIMdbEnv* ev, mdb_priority inPrio) = 0;
01727   NS_IMETHOD GetTablePriority(nsIMdbEnv* ev, mdb_priority* outPrio) = 0;
01728   
01729   NS_IMETHOD GetTableBeVerbose(nsIMdbEnv* ev, mdb_bool* outBeVerbose) = 0;
01730   NS_IMETHOD SetTableBeVerbose(nsIMdbEnv* ev, mdb_bool inBeVerbose) = 0;
01731   
01732   NS_IMETHOD GetTableIsUnique(nsIMdbEnv* ev, mdb_bool* outIsUnique) = 0;
01733   
01734   NS_IMETHOD GetTableKind(nsIMdbEnv* ev, mdb_kind* outTableKind) = 0;
01735   NS_IMETHOD GetRowScope(nsIMdbEnv* ev, mdb_scope* outRowScope) = 0;
01736   
01737   NS_IMETHOD GetMetaRow(
01738     nsIMdbEnv* ev, // context
01739     const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying 
01740     mdbOid* outOid, // output meta row oid, can be nil to suppress output
01741     nsIMdbRow** acqRow) = 0; // acquire table's unique singleton meta row
01742     // The purpose of a meta row is to support the persistent recording of
01743     // meta info about a table as cells put into the distinguished meta row.
01744     // Each table has exactly one meta row, which is not considered a member
01745     // of the collection of rows inside the table.  The only way to tell
01746     // whether a row is a meta row is by the fact that it is returned by this
01747     // GetMetaRow() method from some table. Otherwise nothing distinguishes
01748     // a meta row from any other row.  A meta row can be used anyplace that
01749     // any other row can be used, and can even be put into other tables (or
01750     // the same table) as a table member, if this is useful for some reason.
01751     // The first attempt to access a table's meta row using GetMetaRow() will
01752     // cause the meta row to be created if it did not already exist.  When the
01753     // meta row is created, it will have the row oid that was previously
01754     // requested for this table's meta row; or if no oid was ever explicitly
01755     // specified for this meta row, then a unique oid will be generated in
01756     // the row scope named "m" (so obviously MDB clients should not
01757     // manually allocate any row IDs from that special meta scope namespace).
01758     // The meta row oid can be specified either when the table is created, or
01759     // else the first time that GetMetaRow() is called, by passing a non-nil
01760     // pointer to an oid for parameter inOptionalMetaRowOid.  The meta row's
01761     // actual oid is returned in outOid (if this is a non-nil pointer), and
01762     // it will be different from inOptionalMetaRowOid when the meta row was
01763     // already given a different oid earlier.
01764   // } ----- end meta attribute methods -----
01765 
01766 
01767   // { ----- begin cursor methods -----
01768   NS_IMETHOD GetTableRowCursor( // make a cursor, starting iteration at inRowPos
01769     nsIMdbEnv* ev, // context
01770     mdb_pos inRowPos, // zero-based ordinal position of row in table
01771     nsIMdbTableRowCursor** acqCursor) = 0; // acquire new cursor instance
01772   // } ----- end row position methods -----
01773 
01774   // { ----- begin row position methods -----
01775   NS_IMETHOD PosToOid( // get row member for a table position
01776     nsIMdbEnv* ev, // context
01777     mdb_pos inRowPos, // zero-based ordinal position of row in table
01778     mdbOid* outOid) = 0; // row oid at the specified position
01779 
01780   NS_IMETHOD OidToPos( // test for the table position of a row member
01781     nsIMdbEnv* ev, // context
01782     const mdbOid* inOid, // row to find in table
01783     mdb_pos* outPos) = 0; // zero-based ordinal position of row in table
01784     
01785   NS_IMETHOD PosToRow( // test for the table position of a row member
01786     nsIMdbEnv* ev, // context
01787     mdb_pos inRowPos, // zero-based ordinal position of row in table
01788     nsIMdbRow** acqRow) = 0; // acquire row at table position inRowPos
01789     
01790   NS_IMETHOD RowToPos( // test for the table position of a row member
01791     nsIMdbEnv* ev, // context
01792     nsIMdbRow* ioRow, // row to find in table
01793     mdb_pos* outPos) = 0; // zero-based ordinal position of row in table
01794   // } ----- end row position methods -----
01795 
01796   // { ----- begin oid set methods -----
01797   NS_IMETHOD AddOid( // make sure the row with inOid is a table member 
01798     nsIMdbEnv* ev, // context
01799     const mdbOid* inOid) = 0; // row to ensure membership in table
01800 
01801   NS_IMETHOD HasOid( // test for the table position of a row member
01802     nsIMdbEnv* ev, // context
01803     const mdbOid* inOid, // row to find in table
01804     mdb_bool* outHasOid) = 0; // whether inOid is a member row
01805 
01806   NS_IMETHOD CutOid( // make sure the row with inOid is not a member 
01807     nsIMdbEnv* ev, // context
01808     const mdbOid* inOid) = 0; // row to remove from table
01809   // } ----- end oid set methods -----
01810 
01811   // { ----- begin row set methods -----
01812   NS_IMETHOD NewRow( // create a new row instance in table
01813     nsIMdbEnv* ev, // context
01814     mdbOid* ioOid, // please use minus one (unbound) rowId for db-assigned IDs
01815     nsIMdbRow** acqRow) = 0; // create new row
01816 
01817   NS_IMETHOD AddRow( // make sure the row with inOid is a table member 
01818     nsIMdbEnv* ev, // context
01819     nsIMdbRow* ioRow) = 0; // row to ensure membership in table
01820 
01821   NS_IMETHOD HasRow( // test for the table position of a row member
01822     nsIMdbEnv* ev, // context
01823     nsIMdbRow* ioRow, // row to find in table
01824     mdb_bool* outHasRow) = 0; // whether row is a table member
01825 
01826   NS_IMETHOD CutRow( // make sure the row with inOid is not a member 
01827     nsIMdbEnv* ev, // context
01828     nsIMdbRow* ioRow) = 0; // row to remove from table
01829 
01830   NS_IMETHOD CutAllRows( // remove all rows from the table
01831     nsIMdbEnv* ev) = 0; // context
01832   // } ----- end row set methods -----
01833 
01834   // { ----- begin hinting methods -----
01835   NS_IMETHOD SearchColumnsHint( // advise re future expected search cols  
01836     nsIMdbEnv* ev, // context
01837     const mdbColumnSet* inColumnSet) = 0; // columns likely to be searched
01838     
01839   NS_IMETHOD SortColumnsHint( // advise re future expected sort columns  
01840     nsIMdbEnv* ev, // context
01841     const mdbColumnSet* inColumnSet) = 0; // columns for likely sort requests
01842     
01843   NS_IMETHOD StartBatchChangeHint( // advise before many adds and cuts  
01844     nsIMdbEnv* ev, // context
01845     const void* inLabel) = 0; // intend unique address to match end call
01846     // If batch starts nest by virtue of nesting calls in the stack, then
01847     // the address of a local variable makes a good batch start label that
01848     // can be used at batch end time, and such addresses remain unique.
01849     
01850   NS_IMETHOD EndBatchChangeHint( // advise before many adds and cuts  
01851     nsIMdbEnv* ev, // context
01852     const void* inLabel) = 0; // label matching start label
01853     // Suppose a table is maintaining one or many sort orders for a table,
01854     // so that every row added to the table must be inserted in each sort,
01855     // and every row cut must be removed from each sort.  If a db client
01856     // intends to make many such changes before needing any information
01857     // about the order or positions of rows inside a table, then a client
01858     // might tell the table to start batch changes in order to disable
01859     // sorting of rows for the interim.  Presumably a table will then do
01860     // a full sort of all rows at need when the batch changes end, or when
01861     // a surprise request occurs for row position during batch changes.
01862   // } ----- end hinting methods -----
01863 
01864   // { ----- begin searching methods -----
01865   NS_IMETHOD FindRowMatches( // search variable number of sorted cols
01866     nsIMdbEnv* ev, // context
01867     const mdbYarn* inPrefix, // content to find as prefix in row's column cell
01868     nsIMdbTableRowCursor** acqCursor) = 0; // set of matching rows
01869     
01870   NS_IMETHOD GetSearchColumns( // query columns used by FindRowMatches()
01871     nsIMdbEnv* ev, // context
01872     mdb_count* outCount, // context
01873     mdbColumnSet* outColSet) = 0; // caller supplied space to put columns
01874     // GetSearchColumns() returns the columns actually searched when the
01875     // FindRowMatches() method is called.  No more than mColumnSet_Count
01876     // slots of mColumnSet_Columns will be written, since mColumnSet_Count
01877     // indicates how many slots are present in the column array.  The
01878     // actual number of search column used by the table is returned in
01879     // the outCount parameter; if this number exceeds mColumnSet_Count,
01880     // then a caller needs a bigger array to read the entire column set.
01881     // The minimum of mColumnSet_Count and outCount is the number slots
01882     // in mColumnSet_Columns that were actually written by this method.
01883     //
01884     // Callers are expected to change this set of columns by calls to
01885     // nsIMdbTable::SearchColumnsHint() or SetSearchSorting(), or both.
01886   // } ----- end searching methods -----
01887 
01888   // { ----- begin sorting methods -----
01889   // sorting: note all rows are assumed sorted by row ID as a secondary
01890   // sort following the primary column sort, when table rows are sorted.
01891 
01892   NS_IMETHOD
01893   CanSortColumn( // query which column is currently used for sorting
01894     nsIMdbEnv* ev, // context
01895     mdb_column inColumn, // column to query sorting potential
01896     mdb_bool* outCanSort) = 0; // whether the column can be sorted
01897     
01898   NS_IMETHOD GetSorting( // view same table in particular sorting
01899     nsIMdbEnv* ev, // context
01900     mdb_column inColumn, // requested new column for sorting table
01901     nsIMdbSorting** acqSorting) = 0; // acquire sorting for column
01902     
01903   NS_IMETHOD SetSearchSorting( // use this sorting in FindRowMatches()
01904     nsIMdbEnv* ev, // context
01905     mdb_column inColumn, // often same as nsIMdbSorting::GetSortColumn()
01906     nsIMdbSorting* ioSorting) = 0; // requested sorting for some column
01907     // SetSearchSorting() attempts to inform the table that ioSorting
01908     // should be used during calls to FindRowMatches() for searching
01909     // the column which is actually sorted by ioSorting.  This method
01910     // is most useful in conjunction with nsIMdbSorting::SetCompare(),
01911     // because otherwise a caller would not be able to override the
01912     // comparison ordering method used during searchs.  Note that some
01913     // database implementations might be unable to use an arbitrarily
01914     // specified sort order, either due to schema or runtime interface
01915     // constraints, in which case ioSorting might not actually be used.
01916     // Presumably ioSorting is an instance that was returned from some
01917     // earlier call to nsIMdbTable::GetSorting().  A caller can also
01918     // use nsIMdbTable::SearchColumnsHint() to specify desired change
01919     // in which columns are sorted and searched by FindRowMatches().
01920     //
01921     // A caller can pass a nil pointer for ioSorting to request that
01922     // column inColumn no longer be used at all by FindRowMatches().
01923     // But when ioSorting is non-nil, then inColumn should match the
01924     // column actually sorted by ioSorting; when these do not agree,
01925     // implementations are instructed to give precedence to the column
01926     // specified by ioSorting (so this means callers might just pass
01927     // zero for inColumn when ioSorting is also provided, since then
01928     // inColumn is both redundant and ignored).
01929   // } ----- end sorting methods -----
01930 
01931   // { ----- begin moving methods -----
01932   // moving a row does nothing unless a table is currently unsorted
01933   
01934   NS_IMETHOD MoveOid( // change position of row in unsorted table
01935     nsIMdbEnv* ev, // context
01936     const mdbOid* inOid,  // row oid to find in table
01937     mdb_pos inHintFromPos, // suggested hint regarding start position
01938     mdb_pos inToPos,       // desired new position for row inRowId
01939     mdb_pos* outActualPos) = 0; // actual new position of row in table
01940 
01941   NS_IMETHOD MoveRow( // change position of row in unsorted table
01942     nsIMdbEnv* ev, // context
01943     nsIMdbRow* ioRow,  // row oid to find in table
01944     mdb_pos inHintFromPos, // suggested hint regarding start position
01945     mdb_pos inToPos,       // desired new position for row inRowId
01946     mdb_pos* outActualPos) = 0; // actual new position of row in table
01947   // } ----- end moving methods -----
01948   
01949   // { ----- begin index methods -----
01950   NS_IMETHOD AddIndex( // create a sorting index for column if possible
01951     nsIMdbEnv* ev, // context
01952     mdb_column inColumn, // the column to sort by index
01953     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental index building
01954   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
01955   // then the index addition will be finished.
01956   
01957   NS_IMETHOD CutIndex( // stop supporting a specific column index
01958     nsIMdbEnv* ev, // context
01959     mdb_column inColumn, // the column with index to be removed
01960     nsIMdbThumb** acqThumb) = 0; // acquire thumb for incremental index destroy
01961   // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
01962   // then the index removal will be finished.
01963   
01964   NS_IMETHOD HasIndex( // query for current presence of a column index
01965     nsIMdbEnv* ev, // context
01966     mdb_column inColumn, // the column to investigate
01967     mdb_bool* outHasIndex) = 0; // whether column has index for this column
01968 
01969   
01970   NS_IMETHOD EnableIndexOnSort( // create an index for col on first sort
01971     nsIMdbEnv* ev, // context
01972     mdb_column inColumn) = 0; // the column to index if ever sorted
01973   
01974   NS_IMETHOD QueryIndexOnSort( // check whether index on sort is enabled
01975     nsIMdbEnv* ev, // context
01976     mdb_column inColumn, // the column to investigate
01977     mdb_bool* outIndexOnSort) = 0; // whether column has index-on-sort enabled
01978   
01979   NS_IMETHOD DisableIndexOnSort( // prevent future index creation on sort
01980     nsIMdbEnv* ev, // context
01981     mdb_column inColumn) = 0; // the column to index if ever sorted
01982   // } ----- end index methods -----
01983 
01984 // } ===== end nsIMdbTable methods =====
01985 };
01986 
01987 /*| nsIMdbSorting: a view of a table in some particular sort order.  This
01988 **| row order closely resembles a readonly array of rows with the same row
01989 **| membership as the underlying table, but in a different order than the
01990 **| table's explicit row order.  But the sorting's row membership changes
01991 **| whenever the table's membership changes (without any notification, so
01992 **| keep this in mind when modifying the table).
01993 **|
01994 **|| table: every sorting is associated with a particular table.  You
01995 **| cannot change which table is used by a sorting (just ask some new
01996 **| table for a suitable sorting instance instead).
01997 **|
01998 **|| compare: the ordering method used by a sorting, wrapped up in a
01999 **| abstract plug-in interface.  When this was never installed by an
02000 **| explicit call to SetNewCompare(), a compare object is still returned,
02001 **| and it might match the compare instance returned by the factory method
02002 **| nsIMdbFactory::MakeCompare(), which represents a default sort order
02003 **| (which we fervently hope is consistently ASCII byte ordering).
02004 **|
02005 **|| cursor: in case callers are more comfortable with a cursor style
02006 **| of accessing row members, each sorting will happily return a cursor
02007 **| instance with behavior very similar to a cursor returned from a call
02008 **| to nsIMdbTable::GetTableRowCursor(), but with different row order.
02009 **| A cursor should show exactly the same information as the pos methods.
02010 **|
02011 **|| pos: the PosToOid() and PosToRow() methods are just like the table
02012 **| methods of the same name, except they show rows in the sort order of 
02013 **| the sorting, rather than that of the table.  These methods are like
02014 **| readonly array position accessor's, or like a C++ operator[].
02015 |*/
02016 class nsIMdbSorting : public nsIMdbObject { // sorting of some table
02017 public:
02018 // { ===== begin nsIMdbSorting methods =====
02019 
02020   // { ----- begin attribute methods -----
02021   // sorting: note all rows are assumed sorted by row ID as a secondary
02022   // sort following the primary column sort, when table rows are sorted.
02023   
02024   NS_IMETHOD GetTable(nsIMdbEnv* ev, nsIMdbTable** acqTable) = 0;
02025   NS_IMETHOD GetSortColumn( // query which col is currently sorted
02026     nsIMdbEnv* ev, // context
02027     mdb_column* outColumn) = 0; // col the table uses for sorting (or zero)
02028 
02029   NS_IMETHOD SetNewCompare(nsIMdbEnv* ev,
02030     nsIMdbCompare* ioNewCompare) = 0;
02031     // Setting the sorting's compare object will typically cause the rows
02032     // to be resorted, presumably in a lazy fashion when the sorting is
02033     // next required to be in a valid row ordering state, such as when a
02034     // call to PosToOid() happens.  ioNewCompare can be nil, in which case
02035     // implementations should revert to the default sort order, which must
02036     // be equivalent to whatever is used by nsIMdbFactory::MakeCompare().
02037 
02038   NS_IMETHOD GetOldCompare(nsIMdbEnv* ev,
02039     nsIMdbCompare** acqOldCompare) = 0;
02040     // Get this sorting instance's compare object, which handles the
02041     // ordering of rows in the sorting, by comparing yarns from the cells
02042     // in the column being sorted.  Since nsIMdbCompare has no interface
02043     // to query the state of the compare object, it is not clear what you
02044     // would do with this object when returned, except maybe compare it
02045     // as a pointer address to some other instance, to check identities.
02046   
02047   // } ----- end attribute methods -----
02048 
02049   // { ----- begin cursor methods -----
02050   NS_IMETHOD GetSortingRowCursor( // make a cursor, starting at inRowPos
02051     nsIMdbEnv* ev, // context
02052     mdb_pos inRowPos, // zero-based ordinal position of row in table
02053     nsIMdbTableRowCursor** acqCursor) = 0; // acquire new cursor instance
02054     // A cursor interface turning same info as PosToOid() or PosToRow().
02055   // } ----- end row position methods -----
02056 
02057   // { ----- begin row position methods -----
02058   NS_IMETHOD PosToOid( // get row member for a table position
02059     nsIMdbEnv* ev, // context
02060     mdb_pos inRowPos, // zero-based ordinal position of row in table
02061     mdbOid* outOid) = 0; // row oid at the specified position
02062     
02063   NS_IMETHOD PosToRow( // test for the table position of a row member
02064     nsIMdbEnv* ev, // context
02065     mdb_pos inRowPos, // zero-based ordinal position of row in table
02066     nsIMdbRow** acqRow) = 0; // acquire row at table position inRowPos
02067   // } ----- end row position methods -----
02068 
02069 // } ===== end nsIMdbSorting methods =====
02070 };
02071 
02072 /*| nsIMdbTableRowCursor: cursor class for iterating table rows
02073 **|
02074 **|| table: the cursor is associated with a specific table, which can be
02075 **| set to a different table (which resets the position to -1 so the
02076 **| next row acquired is the first in the table.
02077 **|
02078 **|| NextRowId: the rows in the table can be iterated by identity alone,
02079 **| without actually reading the cells of any row with this method.
02080 **|
02081 **|| NextRowCells: read the next row in the table, but only read cells
02082 **| from the table which are already present in the row (so no new cells
02083 **| are added to the row, even if they are present in the table).  All the
02084 **| cells will have content specified, even it is the empty string.  No
02085 **| columns will be removed, even if missing from the row (because missing
02086 **| and empty are semantically equivalent).
02087 **|
02088 **|| NextRowAllCells: read the next row in the table, and access all the
02089 **| cells for this row in the table, adding any missing columns to the row
02090 **| as needed until all cells are represented.  All the
02091 **| cells will have content specified, even it is the empty string.  No
02092 **| columns will be removed, even if missing from the row (because missing
02093 **| and empty are semantically equivalent).
02094 **|
02095 |*/
02096 
02097 #define NS_IMDBTABLEROWCURSOR_IID_STR = "4f325dad-0385-4b62-a992-c914ab93587e"
02098 
02099 #define NS_IMDBTABLEROWCURSOR_IID \
02100 {0x4f325dad, 0x0385, 0x4b62, \
02101 {0xa9, 0x92, 0xc9, 0x14, 0xab, 0x93, 0x58, 0x7e}}
02102 
02103 
02104 
02105 class nsIMdbTableRowCursor : public nsISupports { // table row iterator
02106 public:
02107   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBTABLEROWCURSOR_IID)
02108 
02109 // { ===== begin nsIMdbTableRowCursor methods =====
02110 
02111   // { ----- begin attribute methods -----
02112   // NS_IMETHOD SetTable(nsIMdbEnv* ev, nsIMdbTable* ioTable) = 0; // sets pos to -1
02113   // Method SetTable() cut and made obsolete in keeping with new sorting methods.
02114   
02115   NS_IMETHOD GetTable(nsIMdbEnv* ev, nsIMdbTable** acqTable) = 0;
02116   // } ----- end attribute methods -----
02117 
02118   // { ----- begin duplicate row removal methods -----
02119   NS_IMETHOD CanHaveDupRowMembers(nsIMdbEnv* ev, // cursor might hold dups?
02120     mdb_bool* outCanHaveDups) = 0;
02121     
02122   NS_IMETHOD MakeUniqueCursor( // clone cursor, removing duplicate rows
02123     nsIMdbEnv* ev, // context
02124     nsIMdbTableRowCursor** acqCursor) = 0;    // acquire clone with no dups
02125     // Note that MakeUniqueCursor() is never necessary for a cursor which was
02126     // created by table method nsIMdbTable::GetTableRowCursor(), because a table
02127     // never contains the same row as a member more than once.  However, a cursor
02128     // created by table method nsIMdbTable::FindRowMatches() might contain the
02129     // same row more than once, because the same row can generate a hit by more
02130     // than one column with a matching string prefix.  Note this method can
02131     // return the very same cursor instance with just an incremented refcount,
02132     // when the original cursor could not contain any duplicate rows (calling
02133     // CanHaveDupRowMembers() shows this case on a false return).  Otherwise
02134     // this method returns a different cursor instance.  Callers should not use
02135     // this MakeUniqueCursor() method lightly, because it tends to defeat the
02136     // purpose of lazy programming techniques, since it can force creation of
02137     // an explicit row collection in a new cursor's representation, in order to
02138     // inspect the row membership and remove any duplicates; this can have big
02139     // impact if a collection holds tens of thousands of rows or more, when
02140     // the original cursor with dups simply referenced rows indirectly by row
02141     // position ranges, without using an explicit row set representation.
02142     // Callers are encouraged to use nsIMdbCursor::GetCount() to determine
02143     // whether the row collection is very large (tens of thousands), and to
02144     // delay calling MakeUniqueCursor() when possible, until a user interface
02145     // element actually demands the creation of an explicit set representation.
02146   // } ----- end duplicate row removal methods -----
02147 
02148   // { ----- begin oid iteration methods -----
02149   NS_IMETHOD NextRowOid( // get row id of next row in the table
02150     nsIMdbEnv* ev, // context
02151     mdbOid* outOid, // out row oid
02152     mdb_pos* outRowPos) = 0;    // zero-based position of the row in table
02153   // } ----- end oid iteration methods -----
02154 
02155   // { ----- begin row iteration methods -----
02156   NS_IMETHOD NextRow( // get row cells from table for cells already in row
02157     nsIMdbEnv* ev, // context
02158     nsIMdbRow** acqRow, // acquire next row in table
02159     mdb_pos* outRowPos) = 0;    // zero-based position of the row in table
02160 
02161   NS_IMETHOD PrevRowOid( // get row id of previous row in the table
02162     nsIMdbEnv* ev, // context
02163     mdbOid* outOid, // out row oid
02164     mdb_pos* outRowPos) = 0;    // zero-based position of the row in table
02165   // } ----- end oid iteration methods -----
02166 
02167   // { ----- begin row iteration methods -----
02168   NS_IMETHOD PrevRow( // get row cells from table for cells already in row
02169     nsIMdbEnv* ev, // context
02170     nsIMdbRow** acqRow, // acquire previous row in table
02171     mdb_pos* outRowPos) = 0;    // zero-based position of the row in table
02172 
02173   // } ----- end row iteration methods -----
02174 
02175   // { ----- begin copy iteration methods -----
02176   // NS_IMETHOD NextRowCopy( // put row cells into sink only when already in sink
02177   //   nsIMdbEnv* ev, // context
02178   //   nsIMdbRow* ioSinkRow, // sink for row cells read from next row
02179   //   mdbOid* outOid, // out row oid
02180   //   mdb_pos* outRowPos) = 0;    // zero-based position of the row in table
02181   // 
02182   // NS_IMETHOD NextRowCopyAll( // put all row cells into sink, adding to sink
02183   //   nsIMdbEnv* ev, // context
02184   //   nsIMdbRow* ioSinkRow, // sink for row cells read from next row
02185   //   mdbOid* outOid, // out row oid
02186   //   mdb_pos* outRowPos) = 0;    // zero-based position of the row in table
02187   // } ----- end copy iteration methods -----
02188 
02189 // } ===== end nsIMdbTableRowCursor methods =====
02190 };
02191 
02192 /*| nsIMdbRow: a collection of cells
02193 **|
02194 |*/
02195 
02196 #define NS_IMDBROW_IID_STR "271e8d6e-183a-40e3-9f18-36913b4c7853"
02197 
02198 
02199 #define NS_IMDBROW_IID \
02200 {0x271e8d6e, 0x183a, 0x40e3, \
02201 {0x9f, 0x18, 0x36, 0x91, 0x3b, 0x4c, 0x78, 0x53}}
02202 
02203 
02204 class nsIMdbRow : public nsIMdbCollection { // cell tuple
02205 public:
02206 
02207   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBROW_IID)
02208 // { ===== begin nsIMdbRow methods =====
02209 
02210   // { ----- begin cursor methods -----
02211   NS_IMETHOD GetRowCellCursor( // make a cursor starting iteration at inCellPos
02212     nsIMdbEnv* ev, // context
02213     mdb_pos inCellPos, // zero-based ordinal position of cell in row
02214     nsIMdbRowCellCursor** acqCursor) = 0; // acquire new cursor instance
02215   // } ----- end cursor methods -----
02216 
02217   // { ----- begin column methods -----
02218   NS_IMETHOD AddColumn( // make sure a particular column is inside row
02219     nsIMdbEnv* ev, // context
02220     mdb_column inColumn, // column to add
02221     const mdbYarn* inYarn) = 0; // cell value to install
02222 
02223   NS_IMETHOD CutColumn( // make sure a column is absent from the row
02224     nsIMdbEnv* ev, // context
02225     mdb_column inColumn) = 0; // column to ensure absent from row
02226 
02227   NS_IMETHOD CutAllColumns( // remove all columns from the row
02228     nsIMdbEnv* ev) = 0; // context
02229   // } ----- end column methods -----
02230 
02231   // { ----- begin cell methods -----
02232   NS_IMETHOD NewCell( // get cell for specified column, or add new one
02233     nsIMdbEnv* ev, // context
02234     mdb_column inColumn, // column to add
02235     nsIMdbCell** acqCell) = 0; // cell column and value
02236     
02237   NS_IMETHOD AddCell( // copy a cell from another row to this row
02238     nsIMdbEnv* ev, // context
02239     const nsIMdbCell* inCell) = 0; // cell column and value
02240     
02241   NS_IMETHOD GetCell( // find a cell in this row
02242     nsIMdbEnv* ev, // context
02243     mdb_column inColumn, // column to find
02244     nsIMdbCell** acqCell) = 0; // cell for specified column, or null
02245     
02246   NS_IMETHOD EmptyAllCells( // make all cells in row empty of content
02247     nsIMdbEnv* ev) = 0; // context
02248   // } ----- end cell methods -----
02249 
02250   // { ----- begin row methods -----
02251   NS_IMETHOD AddRow( // add all cells in another row to this one
02252     nsIMdbEnv* ev, // context
02253     nsIMdbRow* ioSourceRow) = 0; // row to union with
02254     
02255   NS_IMETHOD SetRow( // make exact duplicate of another row
02256     nsIMdbEnv* ev, // context
02257     nsIMdbRow* ioSourceRow) = 0; // row to duplicate
02258   // } ----- end row methods -----
02259 
02260   // { ----- begin blob methods -----  
02261   NS_IMETHOD SetCellYarn(nsIMdbEnv* ev, // synonym for AddColumn()
02262     mdb_column inColumn, // column to write
02263     const mdbYarn* inYarn) = 0;   // reads from yarn slots
02264   // make this text object contain content from the yarn's buffer
02265   
02266   NS_IMETHOD GetCellYarn(nsIMdbEnv* ev, 
02267     mdb_column inColumn, // column to read 
02268     mdbYarn* outYarn) = 0;  // writes some yarn slots 
02269   // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
02270   
02271   NS_IMETHOD AliasCellYarn(nsIMdbEnv* ev, 
02272     mdb_column inColumn, // column to alias
02273     mdbYarn* outYarn) = 0; // writes ALL yarn slots
02274   
02275   NS_IMETHOD NextCellYarn(nsIMdbEnv* ev, // iterative version of GetCellYarn()
02276     mdb_column* ioColumn, // next column to read
02277     mdbYarn* outYarn) = 0;  // writes some yarn slots 
02278   // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
02279   //
02280   // The ioColumn argument is an inout parameter which initially contains the
02281   // last column accessed and returns the next column corresponding to the
02282   // content read into the yarn.  Callers should start with a zero column
02283   // value to say 'no previous column', which causes the first column to be
02284   // read.  Then the value returned in ioColumn is perfect for the next call
02285   // to NextCellYarn(), since it will then be the previous column accessed.
02286   // Callers need only examine the column token returned to see which cell
02287   // in the row is being read into the yarn.  When no more columns remain,
02288   // and the iteration has ended, ioColumn will return a zero token again.
02289   // So iterating over cells starts and ends with a zero column token.
02290 
02291   NS_IMETHOD SeekCellYarn( // resembles nsIMdbRowCellCursor::SeekCell()
02292     nsIMdbEnv* ev, // context
02293     mdb_pos inPos, // position of cell in row sequence
02294     mdb_column* outColumn, // column for this particular cell
02295     mdbYarn* outYarn) = 0; // writes some yarn slots
02296   // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
02297   // Callers can pass nil for outYarn to indicate no interest in content, so
02298   // only the outColumn value is returned.  NOTE to subclasses: you must be
02299   // able to ignore outYarn when the pointer is nil; please do not crash.
02300 
02301   // } ----- end blob methods -----
02302 
02303 // } ===== end nsIMdbRow methods =====
02304 };
02305 
02306 /*| nsIMdbRowCellCursor: cursor class for iterating row cells
02307 **|
02308 **|| row: the cursor is associated with a specific row, which can be
02309 **| set to a different row (which resets the position to -1 so the
02310 **| next cell acquired is the first in the row.
02311 **|
02312 **|| NextCell: get the next cell in the row and return its position and
02313 **| a new instance of a nsIMdbCell to represent this next cell.
02314 |*/
02315 
02316 #define NS_IMDBROWCELLCURSOR_IID_STR "b33371a7-5d63-4d10-85a8-e44dffe75c28"
02317 
02318 
02319 #define NS_IMDBROWCELLCURSOR_IID \
02320 {0x271e8d6e, 0x5d63, 0x4d10 , \
02321 {0x85, 0xa8, 0xe4, 0x4d, 0xff, 0xe7, 0x5c, 0x28}}
02322 
02323 
02324 class nsIMdbRowCellCursor : public nsISupports{ // cell collection iterator
02325 public:
02326 
02327   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBROWCELLCURSOR_IID)
02328 // { ===== begin nsIMdbRowCellCursor methods =====
02329 
02330   // { ----- begin attribute methods -----
02331   NS_IMETHOD SetRow(nsIMdbEnv* ev, nsIMdbRow* ioRow) = 0; // sets pos to -1
02332   NS_IMETHOD GetRow(nsIMdbEnv* ev, nsIMdbRow** acqRow) = 0;
02333   // } ----- end attribute methods -----
02334 
02335   // { ----- begin cell creation methods -----
02336   NS_IMETHOD MakeCell( // get cell at current pos in the row
02337     nsIMdbEnv* ev, // context
02338     mdb_column* outColumn, // column for this particular cell
02339     mdb_pos* outPos, // position of cell in row sequence
02340     nsIMdbCell** acqCell) = 0; // the cell at inPos
02341   // } ----- end cell creation methods -----
02342 
02343   // { ----- begin cell seeking methods -----
02344   NS_IMETHOD SeekCell( // same as SetRow() followed by MakeCell()
02345     nsIMdbEnv* ev, // context
02346     mdb_pos inPos, // position of cell in row sequence
02347     mdb_column* outColumn, // column for this particular cell
02348     nsIMdbCell** acqCell) = 0; // the cell at inPos
02349   // } ----- end cell seeking methods -----
02350 
02351   // { ----- begin cell iteration methods -----
02352   NS_IMETHOD NextCell( // get next cell in the row
02353     nsIMdbEnv* ev, // context
02354     nsIMdbCell** acqCell, // changes to the next cell in the iteration
02355     mdb_column* outColumn, // column for this particular cell
02356     mdb_pos* outPos) = 0; // position of cell in row sequence
02357     
02358   NS_IMETHOD PickNextCell( // get next cell in row within filter set
02359     nsIMdbEnv* ev, // context
02360     nsIMdbCell* ioCell, // changes to the next cell in the iteration
02361     const mdbColumnSet* inFilterSet, // col set of actual caller interest
02362     mdb_column* outColumn, // column for this particular cell
02363     mdb_pos* outPos) = 0; // position of cell in row sequence
02364 
02365   // Note that inFilterSet should not have too many (many more than 10?)
02366   // cols, since this might imply a potential excessive consumption of time
02367   // over many cursor calls when looking for column and filter intersection.
02368   // } ----- end cell iteration methods -----
02369 
02370 // } ===== end nsIMdbRowCellCursor methods =====
02371 };
02372 
02373 /*| nsIMdbBlob: a base class for objects composed mainly of byte sequence state.
02374 **| (This provides a base class for nsIMdbCell, so that cells themselves can
02375 **| be used to set state in another cell, without extracting a buffer.)
02376 |*/
02377 class nsIMdbBlob : public nsISupports { // a string with associated charset
02378 public:
02379 
02380 // { ===== begin nsIMdbBlob methods =====
02381 
02382   // { ----- begin attribute methods -----
02383   NS_IMETHOD SetBlob(nsIMdbEnv* ev,
02384     nsIMdbBlob* ioBlob) = 0; // reads inBlob slots
02385   // when inBlob is in the same suite, this might be fastest cell-to-cell
02386   
02387   NS_IMETHOD ClearBlob( // make empty (so content has zero length)
02388     nsIMdbEnv* ev) = 0;
02389   // clearing a yarn is like SetYarn() with empty yarn instance content
02390   
02391   NS_IMETHOD GetBlobFill(nsIMdbEnv* ev,
02392     mdb_fill* outFill) = 0;  // size of blob 
02393   // Same value that would be put into mYarn_Fill, if one called GetYarn()
02394   // with a yarn instance that had mYarn_Buf==nil and mYarn_Size==0.
02395   
02396   NS_IMETHOD SetYarn(nsIMdbEnv* ev, 
02397     const mdbYarn* inYarn) = 0;   // reads from yarn slots
02398   // make this text object contain content from the yarn's buffer
02399   
02400   NS_IMETHOD GetYarn(nsIMdbEnv* ev, 
02401     mdbYarn* outYarn) = 0;  // writes some yarn slots 
02402   // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
02403   
02404   NS_IMETHOD AliasYarn(nsIMdbEnv* ev, 
02405     mdbYarn* outYarn) = 0; // writes ALL yarn slots
02406   // AliasYarn() reveals sensitive internal text buffer state to the caller
02407   // by setting mYarn_Buf to point into the guts of this text implementation.
02408   //
02409   // The caller must take great care to avoid writing on this space, and to
02410   // avoid calling any method that would cause the state of this text object
02411   // to change (say by directly or indirectly setting the text to hold more
02412   // content that might grow the size of the buffer and free the old buffer).
02413   // In particular, callers should scrupulously avoid making calls into the
02414   // mdb interface to write any content while using the buffer pointer found
02415   // in the returned yarn instance.  Best safe usage involves copying content
02416   // into some other kind of external content representation beyond mdb.
02417   //
02418   // (The original design of this method a week earlier included the concept
02419   // of very fast and efficient cooperative locking via a pointer to some lock
02420   // member slot.  But let's ignore that complexity in the current design.)
02421   //
02422   // AliasYarn() is specifically intended as the first step in transferring
02423   // content from nsIMdbBlob to a nsString representation, without forcing extra
02424   // allocations and/or memory copies. (A standard nsIMdbBlob_AsString() utility
02425   // will use AliasYarn() as the first step in setting a nsString instance.)
02426   //
02427   // This is an alternative to the GetYarn() method, which has copy semantics
02428   // only; AliasYarn() relaxes a robust safety principle only for performance
02429   // reasons, to accomodate the need for callers to transform text content to
02430   // some other canonical representation that would necessitate an additional
02431   // copy and transformation when such is incompatible with the mdbYarn format.
02432   //
02433   // The implementation of AliasYarn() should have extremely little overhead
02434   // besides the virtual dispatch to the method implementation, and the code
02435   // necessary to populate all the mdbYarn member slots with internal buffer
02436   // address and metainformation that describes the buffer content.  Note that
02437   // mYarn_Grow must always be set to nil to indicate no resizing is allowed.
02438   
02439   // } ----- end attribute methods -----
02440 
02441 // } ===== end nsIMdbBlob methods =====
02442 };
02443 
02444 /*| nsIMdbCell: the text in a single column of a row.  The base nsIMdbBlob
02445 **| class provides all the interface related to accessing cell text.
02446 **|
02447 **|| column: each cell in a row appears in a specific column, where this
02448 **| column is identified by the an integer mdb_scope value (generated by
02449 **| the StringToScopeToken() method in the containing nsIMdbPort instance).
02450 **| Because a row cannot have more than one cell with the same column,
02451 **| something must give if one calls SetColumn() with an existing column
02452 **| in the same row. When this happens, the other cell is replaced with
02453 **| this cell (and the old cell is closed if it has outstanding refs).
02454 **|
02455 **|| row: every cell instance is a part of some row, and every cell knows
02456 **| which row is the parent row.  (Note this should be represented by a
02457 **| weak backpointer, so that outstanding cell references cannot keep a
02458 **| row open that should be closed. Otherwise we'd have ref graph cycles.)
02459 **|
02460 **|| text: a cell can either be text, or it can have a child row or table,
02461 **| but not both at once.  If text is read from a cell with a child, the text
02462 **| content should be empty (for AliasYarn()) or a description of the type
02463 **| of child (perhaps "mdb:cell:child:row" or "mdb:cell:child:table").
02464 **|
02465 **|| child: a cell might reference another row or a table, rather than text.
02466 **| The interface for putting and getting children rows and tables was first
02467 **| defined in the nsIMdbTable interface, but then this was moved to this cell
02468 **| interface as more natural. 
02469 |*/
02470 
02471 
02472 
02473 #define NS_IMDBCELL_IID \
02474 {0xa3b62f71, 0xa181, 0x4a91, \
02475 {0xb6, 0x6b, 0x27, 0x10, 0x9b, 0x88, 0x98, 0x35}}
02476 
02477 #define NS_IMDBCELL_IID_STR = "a3b62f71-a181-4a91-b66b-27109b889835"
02478 
02479 class nsIMdbCell : public nsIMdbBlob { // text attribute in row with column scope
02480 public:
02481 
02482   NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMDBTABLEROWCURSOR_IID)
02483 // { ===== begin nsIMdbCell methods =====
02484 
02485   // { ----- begin attribute methods -----
02486   NS_IMETHOD SetColumn(nsIMdbEnv* ev, mdb_column inColumn) = 0; 
02487   NS_IMETHOD GetColumn(nsIMdbEnv* ev, mdb_column* outColumn) = 0;
02488   
02489   NS_IMETHOD GetCellInfo(  // all cell metainfo except actual content
02490     nsIMdbEnv* ev, 
02491     mdb_column* outColumn,           // the column in the containing row
02492     mdb_fill*   outBlobFill,         // the size of text content in bytes
02493     mdbOid*     outChildOid,         // oid of possible row or table child
02494     mdb_bool*   outIsRowChild) = 0;  // nonzero if child, and a row child
02495 
02496   // Checking all cell metainfo is a good way to avoid forcing a large cell
02497   // in to memory when you don't actually want to use the content.
02498   
02499   NS_IMETHOD GetRow(nsIMdbEnv* ev, // parent row for this cell
02500     nsIMdbRow** acqRow) = 0;
02501   NS_IMETHOD GetPort(nsIMdbEnv* ev, // port containing cell
02502     nsIMdbPort** acqPort) = 0;
02503   // } ----- end attribute methods -----
02504 
02505   // { ----- begin children methods -----
02506   NS_IMETHOD HasAnyChild( // does cell have a child instead of text?
02507     nsIMdbEnv* ev,
02508     mdbOid* outOid,  // out id of row or table (or unbound if no child)
02509     mdb_bool* outIsRow) = 0; // nonzero if child is a row (rather than a table)
02510 
02511   NS_IMETHOD GetAnyChild( // access table of specific attribute
02512     nsIMdbEnv* ev, // context
02513     nsIMdbRow** acqRow, // child row (or null)
02514     nsIMdbTable** acqTable) = 0; // child table (or null)
02515 
02516 
02517   NS_IMETHOD SetChildRow( // access table of specific attribute
02518     nsIMdbEnv* ev, // context
02519     nsIMdbRow* ioRow) = 0; // inRow must be bound inside this same db port
02520 
02521   NS_IMETHOD GetChildRow( // access row of specific attribute
02522     nsIMdbEnv* ev, // context
02523     nsIMdbRow** acqRow) = 0; // acquire child row (or nil if no child)
02524 
02525 
02526   NS_IMETHOD SetChildTable( // access table of specific attribute
02527     nsIMdbEnv* ev, // context
02528     nsIMdbTable* inTable) = 0; // table must be bound inside this same db port
02529 
02530   NS_IMETHOD GetChildTable( // access table of specific attribute
02531     nsIMdbEnv* ev, // context
02532     nsIMdbTable** acqTable) = 0; // acquire child table (or nil if no child)
02533   // } ----- end children methods -----
02534 
02535 // } ===== end nsIMdbCell methods =====
02536 };
02537 
02538 // } %%%%% end C++ abstract class interfaces %%%%%
02539 
02540 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
02541 
02542 #endif /* _MDB_ */
02543