OOFILE  1.9
oofrec1.cpp
Go to the documentation of this file.
1 // OOFILE record-oriented abstract backend implementation
2 // COPYRIGHT 1996 A.D. Software, All rights reserved
3 
4 // this layer provides implementation classes for record-oriented
5 // backends such as c-tree Plus, dBase and RAM-based tables
6 
7 #include "oofpch_c.h" // for precompilation of core files
8 
9 #ifndef H_OOFIOS
10  #include "oofios.h"
11 #endif
12 #ifndef H_OOFRECS
13  #include "oofrecs.h"
14 #endif
15 #ifndef H_OOFWORDS
16  #include "oofwords.h"
17 #endif
18 
19 #ifdef OOF_MEM_DEBUG_LAST_INCLUDE
20  #include OOF_MEM_DEBUG_LAST_INCLUDE
21 #endif
22 
23 #ifndef OOF_NO_STDLIB
24  #ifndef std
25  using namespace std;
26  #endif
27 #endif
28 
29 
30 // -------------------------------------------------------
31 // O O F I L E _ s i m p l e R e c o r d B a c k e n d
32 // see also oofrec2.cpp & oofrec3.cpp
33 // -------------------------------------------------------
35  OOF_tableBackend(theTable),
36  mSelection(theTable->prototype()),
37  mFieldBufMap(0),
38  mFieldBufMapRefCount(0),
39  mNumFiles(0),
40  mNumIndexes(0),
41  mOverheadLeadingBytes(0),
42  mBlobFieldNums(0),
43  mDirtyRecordCache(0),
44  mIgnoreDuplicateRecords(false)
45 {};
46 
47 
49  OOF_tableBackend(rhs, theTable),
51  mSelection(theTable->prototype()),
52  mFieldBufMap(rhs.mFieldBufMap),
53  mFieldBufMapRefCount(rhs.mFieldBufMapRefCount),
54  mNumFiles(rhs.mNumFiles),
55  mNumIndexes(rhs.mNumIndexes),
56  mOverheadLeadingBytes(rhs.mOverheadLeadingBytes),
57  mDirtyRecordCache(0),
58  mIgnoreDuplicateRecords(rhs.mIgnoreDuplicateRecords)
59 {
60  if (rhs.mBlobFieldNums) {
62  assert(mBlobFieldNums);
63  }
64  else
65  mBlobFieldNums = 0;
67 
68  if (rhs.sorter())
69  setSortOrder( rhs.sorter()->clone());
70  if (selSharing == dbTable::selNotShared) { // explicitly called from cloneTableWithoutSelection
73  memset(mBuffer, 0, mRecBufLen);
74 // don't need to copy mSelection as init'ed to empty state by copy
75  }
76  else { // called from clone or just default copy ctor on user table
77  mSelection.copyFrom(rhs.mSelection, selSharing); // ref counted, copy on write or maybe shared
80  memcpy(mBuffer, rhs.mBuffer, mRecBufLen);
81  }
82 }
83 
84 
86 {
87  if (mFieldBufMapRefCount) { // in case never created database
88  if (*mFieldBufMapRefCount <= 1) {
89  delete[] mFieldBufMap;
90  delete mFieldBufMapRefCount;
91  }
92  else
94  }
95  delete mBlobFieldNums;
96  delete mDirtyRecordCache;
97 }
98 
99 
100 unsigned long
102 {
103  unsigned long len = fld->fieldStorageLen();
104  switch(fld->fieldType()) {
105 
106  case charField :
107  len += 1; // null
108  // fall through for same treatment as binary
109 
110  case fixedBinaryField :
111  if (len%2==1)
112  len += 1;
113  break;
114 
115  default:
116  ; // stop g++ complaining
117  }
118  return len;
119 }
120 
121 
122 unsigned int
124 {
125  if (fld->fieldIsBlob())
126  return 4; // uses longs
127 
128  if (fld->fieldStorageLen()==0)
129  return 0; // cope with relationships & other virtual fields
130 
131  switch(fld->nativeType()) {
132 
133  case uLongField :
134  case longField :
135  return 4;
136 
137  case realField :
138  return 8;
139 
140  case fixedBinaryField :
141  return 4; // this is just a GUESS! needs testing with 8 byte structures to see
142  // NOT YET IMPLEMENTED
143 
144  case compoundField :
145  return 1; // aligns to anything as doesn't physically exist in buffer
146 
147  default:
148  return 2;
149  }
150 }
151 
152 
153 void
155 {
156  assert( Invariant("simpleB::buildSchema-entry") );
157 
158  BuildBackendtables(rebuilding);
159  assert( Invariant("simpleB::buildSchema-after build") );
160 
161  selectAll();
162  delete[] mBuffer; // in case reallocing
163  AllocBuffer();
164  memset(mBuffer, 0, mRecBufLen);
165 
166  assert( Invariant("simpleB::buildSchema-exit") );
167 }
168 
169 void
171 {
172  assert( Invariant("OOF_simpleRecordBackend::AdoptBuffer-entry") );
173 
174  assert(buf);
175  assert(mRecBufLen==buf->mRecBufLen);
177 
178  if (!mSelection.isAllRecs()) {
179  // make sure what we adopt is in the selection, and make it the current rec!
180  unsigned long currOffsetInSelection = mSelection.current();
181  if (currOffsetInSelection != mCurrLoadedRecOffset) { // selection iter is out of whack, eg: saving cached dirty records
182  unsigned long foundAt;
183  bool selContainsCachedOID = mSelection.find(mCurrLoadedRecOffset, foundAt);
184  assert(selContainsCachedOID); // should not be adopting something not in our selection!!!!
185  mSelection.gotoRecord(foundAt); // now selection matches us!
186  }
187  }
188  mRecordState = buf->mRecordState;
189  assert(mRecordState != eUnloaded); // we couldn't have cached an unloaded record
190  delete[] mBuffer;
191  mBuffer = buf->mBuffer;
192  buf->mBuffer = 0;
193  if (mBlobFieldNums && buf->mBlobFieldBodies) { // we've blobs & there are buffers out there
194  unsigned int numBlobs = mBlobFieldNums->count();
195  for (unsigned int i=0; i<numBlobs; i++) {
196  fieldNumT fldNum = mBlobFieldNums->item(i);
197  dbBLOB* fld = (dbBLOB *) mFields[fldNum]; // safe downcast
198  char* bodyPtr = (char*) (buf->mBlobFieldBodies->item(i));
199  if (bodyPtr) {
200  fld->adoptBody(bodyPtr, BlobLenFromBuffer(fld, mBuffer));
201  buf->mBlobFieldBodies->item(i) = 0;
202  }
203  else
204  fld->reset();
205  }
206  }
207 
208  delete buf;
209  assert( Invariant("OOF_simpleRecordBackend::AdoptBuffer-exit") );
210 }
211 
212 
213 void
215 {
216  if (mBlobFieldNums) {
217  #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
219  #endif
220  delete rhs->mBlobFieldBodies; // usually 0
221  mBlobFieldBodies = 0; // OOF_ctreeBackend never has bodies, it's blobs point to their own
222  unsigned int numBlobs = mBlobFieldNums->count();
223  rhs->mBlobFieldBodies = new OOF_ExpandableLongArray(0, numBlobs);
224  assert(rhs->mBlobFieldBodies);
225  for (unsigned int i=0; i<numBlobs; i++) {
226  fieldNumT fldNum = mBlobFieldNums->item(i);
227  dbBLOB* fld = (dbBLOB *) mFields[fldNum]; // safe downcast
228  if (fld->isDirty())
229  rhs->mBlobFieldBodies->item(i) = (unsigned long) (fld->orphanBody());
230  }
231  #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
233  #endif
234  }
235 }
236 
237 
238 unsigned long
239 OOF_simpleRecordBackend::BlobLenFromBuffer(fieldNumT fldNum, const char* theirBuffer) const
240 {
241  unsigned long* at = (unsigned long *) (theirBuffer + mFieldBufMap[fldNum].mOffset+sizeof(unsigned long));
242  return *at;
243 }
244 
245 
246 unsigned long
247 OOF_simpleRecordBackend::BlobPosFromBuffer(fieldNumT fldNum, const char* theirBuffer) const
248 {
249  unsigned long* at = (unsigned long *) (theirBuffer + mFieldBufMap[fldNum].mOffset);
250  return *at;
251 }
252 
253 
254 void OOF_simpleRecordBackend::SetBlobLenInBuffer(fieldNumT fldNum, unsigned long len, const char* theirBuffer) const
255 {
256  unsigned long *at = (unsigned long *)(theirBuffer + mFieldBufMap[fldNum].mOffset + sizeof(unsigned long));
257  *at = len;
258 }
259 
260 
261 void OOF_simpleRecordBackend::SetBlobPosInBuffer(fieldNumT fldNum, unsigned long pos, const char* theirBuffer) const
262 {
263  unsigned long *at = (unsigned long *)(theirBuffer + mFieldBufMap[fldNum].mOffset);
264  *at = pos;
265 }
266 
267 
268 void
270 {
272  unsigned long *at = (unsigned long *)(mBuffer + mFieldBufMap[fldNum].mOffset + sizeof(unsigned long));
273  *at = len;
274 }
275 
276 
277 void
279 {
280  if (mBlobFieldNums) {
281  unsigned int numBlobs = mBlobFieldNums->count();
282  for (unsigned int i=0; i<numBlobs; i++) {
283  fieldNumT fldNum = mBlobFieldNums->item(i);
284  dbBLOB* fld = (dbBLOB *) mFields[fldNum]; // safe downcast
285  fld->reset();
286  }
287  }
288 }
289 
290 #ifdef OOF_DebugDumpBlobState
291 void
292 OOF_simpleRecordBackend::describeBlobs() const
293 {
294  ofstream DGebugStream("blobState",ios::app);
295 
296  if (mBlobFieldNums) {
297 
298  unsigned int numBlobs = mBlobFieldNums->count();
299  for (unsigned int i=0; i<numBlobs; i++) {
300  fieldNumT fldNum = mBlobFieldNums->item(i);
301  dbBLOB* fld = (dbBLOB *) mFields[fldNum]; // safe downcast
302  fld->blobState(DGebugStream);
303  }
304 
305  }
306  DGebugStream.close();
307 
308 }
309 #endif
310 
311 void
313 {
315 }
316 
317 
318 void
320 {
321  mIgnoreDuplicateRecords = false;
322 }
323 
324 
325 bool
327 {
329 }
330 
331 
332 bool
334 {
335  return (isRecordLoaded() && (mSelection.iter()==0) );
336 }
337 
338 
339 bool
341 {
342  return (isRecordLoaded() && (mSelection.iter()==(count()-1)) );
343 }
344 
345 
346 bool
347 OOF_simpleRecordBackend::atRelative(unsigned long rel) const
348 {
349  return (isRecordLoaded() && (mSelection.iter()==rel) );
350 }
351 
352 
353 bool
355 {
356  switch (mSelection.state()) {
357 
360  return mSelection.more();
361 
363  return mSelection.iter() < countAll();
364 
365  default :
366  return false;
367  }
368 }
369 
370 
371 void
373 {
374  unsigned long currentIter = mSelection.iter();
375  switch (currentIter) {
376  case 0:
377  if (!isRecordLoaded())
378  reloadRecord();
379  break;
380  case ULONG_MAX:
381  gotoRecord(0);
382  break;
383  default:
384  gotoRecord(currentIter-1);
385  break;
386  }
387 
388 // ES
389 /* unsigned long currentIter = mSelection.iter();
390  if (currentIter==0) {
391  if (!isRecordLoaded())
392  reloadRecord();
393  }
394  else
395  gotoRecord(currentIter-1);
396 */
397 }
398 
399 
403 unsigned long
405 {
406 
407  switch (mSelection.state()) {
408 
410  return 0;
411 
413  return 1;
414 
416  {
417  unsigned long ret = mSelection.count(); // rely on new records going into cache as well
418  if (isNew() && !tableCachesDirtyRecords()) // new record won't be in Selection
419  ret++;
420  return ret;
421  }
422 
424  return countAll();
425  }
426  return 0; // default just to keep compilers happy
427 }
428 
429 oidT
431 {
432  if (mSelection.isEmpty())
433  return 0;
435  assert (isRecordLoaded());
436  return mCurrLoadedRecOffset; // NOT YET IMPLEMENTED - handle true OID depending on dbTable settings when created
437 }
438 
439 
440 oidT
442 {
443  oidT ret = 0;
444  switch (mSelection.state()) {
445 
447  assert(0);
448 
450  assert(recno==0);
451  ret = mCurrLoadedRecOffset;
452  break;
453 
455  assert(recno<=mSelection.count());
456  ret = mSelection.value(recno);
457  break;
458 
460  gotoRecord(recno);
461  ret = mCurrLoadedRecOffset;
462  break;
463 
464  default :
465  ;
466  }
467  return ret;
468 }
469 
470 
471 unsigned long
473 {
474  unsigned long dataLen;
475 
476  switch (fld->fieldType()) {
477  case charField : {
478  if (mTable->ensureRecordLoaded(false, false)) { // don't auto-create, allow failure
479  char* at = mBuffer + mFieldBufMap[fld->fieldNumber()].mOffset;
480  dataLen = strlen(at); // the string length <= fixed width
481  }
482  else
483  dataLen = 0;
484  break;
485  }
486 
487  case blobField :
488  if (mTable->ensureRecordLoaded(false, false)) { // don't auto-create, allow failure
489  dataLen = BlobLenFromBuffer(fld, mBuffer);
490  }
491  break;
492 
493  case textField :
494  if (mTable->ensureRecordLoaded(false, false)) { // don't auto-create, allow failure
495  dataLen = BlobLenFromBuffer(fld, mBuffer); // NOTE includes trailing null
496  if (dataLen)
497  dataLen -= 1; // if there IS a blob, deduct the null
498  // it is too dangerous to expect our caller to understand!!!
499  // text field stores string AND terminating null in a blob!
500  }
501  break;
502 
503  default :
504  dataLen = fld->fieldStorageLen(); // the fixed width
505  }
506  return dataLen;
507 }
508 
509 
510 bool
512 {
513  bool ret = mDirtyMap.isDirty(fldNum);
514  return ret;
515 }
516 
517 
518 void*
520 {
521  assert( Invariant("simpleB::GetFieldWriteDest-entry") );
522 
523  assert(inField);
524  void* ret;
525  if (inField->fieldIsVirtual() && !inField->storesCalculatedValues()) // NOT YET IMPLEMENTED - smarter test for this in the field itself??
526  ret = 0;
527  else {
529  fieldNumT fldNum = inField->fieldNumber();
530  mDirtyMap.markDirty(fldNum);
531  ret = mBuffer + mFieldBufMap[fldNum].mOffset;
532  }
533  assert( Invariant("simpleB::GetFieldWriteDest-exit") );
534  return ret;
535 }
536 
543 bool
545 {
546  assert(inField);
547  assert(!inField->fieldIsStandalone());
548  short ret;
549  const short* readFrom = (const short*)GetFieldReadFrom(inField->fieldNumber());
550  if (readFrom)
551  ret = *readFrom;
552  else
553  ret = false;
554  return ret;
555 }
556 
557 
562 short
564 {
565  assert(inField);
566  assert(!inField->fieldIsStandalone());
567  short ret;
568  const short* readFrom = (const short*)GetFieldReadFrom(inField->fieldNumber());
569  if (readFrom)
570  ret = *readFrom;
571  else
572  ret = 0;
573  return ret;
574 }
575 
576 
581 long
583 {
584  assert(inField);
585  assert(!inField->fieldIsStandalone());
586  long ret;
587  const long* readFrom = (const long*)GetFieldReadFrom(inField->fieldNumber());
588  if (readFrom)
589  ret = *readFrom;
590  else
591  ret = 0;
592  return ret;
593 }
594 
595 
600 double
602 {
603  assert(inField);
604  assert(!inField->fieldIsStandalone());
605  double ret;
606  const double* readFrom = (const double*)GetFieldReadFrom(inField->fieldNumber());
607  if (readFrom)
608  ret = *readFrom;
609  else
610  ret = 0.0;
611  return ret;
612 }
613 
614 
618 const char*
620 {
621  const char* ret = (const char*) GetFieldReadFrom(inField->fieldNumber());
622  return ret;
623 }
624 
625 
626 oofString
628 {
629  const char* ret = (const char*) GetFieldReadFrom(inField->fieldNumber());
630  return oofString(ret);
631 }
632 
633 
639 void
640 OOF_simpleRecordBackend::writeBool(bool inNum, const dbField* inField)
641 {
642  assert(inField);
643  short* writeTo = (short*)GetFieldWriteDest(inField);
644  assert(writeTo);
645  if (inNum)
646  *writeTo = 1;
647  else
648  *writeTo = 0;
649  mTable->markDirty();
650 }
651 
652 
657 void
658 OOF_simpleRecordBackend::writeShort(short inNum, const dbField* inField)
659 {
660  assert(inField);
661  double* writeTo = (double*)GetFieldWriteDest(inField);
662  assert(writeTo);
663  *writeTo = inNum;
664  mTable->markDirty();
665 }
666 
667 
672 void
673 OOF_simpleRecordBackend::writeLong(long inNum, const dbField* inField)
674 {
675  assert(inField);
676  long* writeTo = (long*)GetFieldWriteDest(inField);
677  assert(writeTo);
678  *writeTo = inNum;
679  mTable->markDirty();
680 }
681 
682 
687 void
688 OOF_simpleRecordBackend::writeDouble(double inNum, const dbField* inField)
689 {
690  assert(inField);
691  double* writeTo = (double*)GetFieldWriteDest(inField);
692  assert(writeTo);
693  *writeTo = inNum;
694  mTable->markDirty();
695 }
696 
697 
698 void
699 OOF_simpleRecordBackend::writeChars(const char* inStr, long numChars, long maxLen, const dbField* inField, long startIndex)
700 {
701  assert(inField);
702  char* writeTo = (char*)GetFieldWriteDest(inField);
703  if (writeTo) {
704  assert(numChars+startIndex<=maxLen);
705  assert(inField->fieldStorageLen()>=maxLen);
706  writeTo += startIndex;
707  if (inStr && numChars>0)
708  memcpy(writeTo, inStr, numChars);
709 #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
711 #endif
712 // don't just write a terminating null, but also fill the rest of the field with nulls
713 // so indexed searches work. - only case is if we just rewrote field with shorter value.
714  for(;numChars<=maxLen;numChars++) {
715  writeTo[numChars]='\0';
716  }
717  } // writeTo
718  mTable->markDirty();
719 }
720 
721 
722 void
723 OOF_simpleRecordBackend::writeBytes(const char* inBuf, long inLen, const dbField* inField)
724 {
725  assert(inField);
726  char* writeTo = (char*)GetFieldWriteDest(inField);
727  if (writeTo) {
728  assert(inField->fieldStorageLen()>=inLen);
729  if (inBuf && inLen>0)
730  memcpy(writeTo, inBuf, inLen);
731 #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
733 #endif
734  }
735  mTable->markDirty();
736 }
737 
738 
739 char*
740 OOF_simpleRecordBackend::getByteWriteAddress(unsigned long byteIndex, const dbField* inField)
741 {
742  char* writeTo = (char*)GetFieldWriteDest(inField);
743  if (writeTo)
744  writeTo = &writeTo[byteIndex];
745  return writeTo;
746 }
747 
748 
749 void*
751 {
752  void* ret = 0;
753  if (mTable->ensureRecordLoaded(false, false)) // don't auto-create, allow failure
754  ret = mBuffer + mFieldBufMap[fldNum].mOffset;
755  return ret;
756 }
757 
758 
759 
760 bool
762 {
763 // if we have just been at a rec, assume we've returned to it for a purpose,
764 // maybe to reload after someone else modifies
765  if (mCurrLoadedRecOffset && (mSelection.iter() == relativeNum)) {
767  }
768  else {
769  if ((mCurrLoadedRecOffset==0) || mSelection.iter() > relativeNum)
770  start();
771 // WEAK IMPLEMENTATION FOR NOW but the internal iterator makes it OK if successive calls
772  while (mSelection.iter() < relativeNum)
773  next();
774  }
775  return true;
776 }
777 
778 
787 void
789 {
790 // Note: this saves all items in the cache but leaves them there
791 // for explicit removal with unloadCache
792  if (isDirty() || isNew()) {
793  assert(isRecordLoaded());
794  const bool savingDefaultCalculators = (isNew() && mHasDefaultCalculators);
795  const bool savingStoredCalculators = mHasStoredCalculators; // copy to local const for speed in loop
796  if (savingDefaultCalculators || savingStoredCalculators) {
797  unsigned long kNumFields = mFields.count();
798  for (unsigned long i=0; i<kNumFields; i++) {
799  dbField* theField = (dbField*) mFields.value(i); // safe downcast
800  if (savingDefaultCalculators)
801  theField->saveDefaultCalculatedValue();
802  if (savingStoredCalculators)
803  theField->saveStoredCalculatedValue();
804  }
805  }
806  SaveContext();
807  mDirty = false;
808  mDirtyMap.reset(); // reset even if ignore dups because behave as if we saved a record
809  }
810  if (mDirtyRecordCache) {
811 // save our current context
813  assert(buf);
814  DonateBlobBodiesTo(buf);
815 
816 // Note: the following will delete itself when it is finished
818  mDirtyRecordCache = 0;
819  }
820 // maybe trigger resort etc.
821  dbSorter* mySorter = sorter();
822  if (mySorter)
823  mySorter->backendSavedRecord(this);
824 }
825 
826 
827 void
829 {
830 /* if (isNew()) // hasn't been saved or cached - it's just being dumped
831  mSelection.deleteCurrent(); // otherwise selection keeps fake pointer
832 */
833  assert( Invariant("simpleB::unloadRecord-entry") );
834 
835  const bool recordIsNew = isNew();
836 
837  // Andy puzzled 10 Mar 2000 - why not test tableCachesDirtyRecords() so also happens
838  // for other buffering modes?
839  if ( (mTable->tableSaveOption() == dbTable::bufferForever) && (recordIsNew || isDirty()) )
841 
842  if (recordIsNew)
843  mCurrLoadedRecOffset=0; // can't reload!
845  mDirty = false;
846  ResetBlobs();
848  assert( Invariant("simpleB::unloadRecord-exit") );
849 }
850 
851 
852 void
854 {
855  assert( Invariant("simpleB::unloadCache-entry") );
856 
857  if (mDirtyRecordCache &&
860  }
861 
862  assert( Invariant("simpleB::unloadCache-exit") );
863 }
864 
865 
866 bool
868 {
869  assert( Invariant("simpleB::reloadRecord-entry") );
870 
871  bool ret = false;
872  if (mCurrLoadedRecOffset) {
874  ResetBlobs();
875  ret = true;
876  }
877  else {
878  start();
879  ret = isRecordLoaded();
880  }
881  assert( Invariant("simpleB::reloadRecord-exit") );
882  return ret;
883 }
884 
885 
886 void
888 {
889  assert( Invariant("simpleB::revertRecord-entry") );
890  if (!isRecordLoaded()) {
891  dbConnect::raise(stringstream() << flush
892  << "Attempt to revert a record which is not loaded, in table "
893  << mTable->tableName()
894  , false
895  );
896  }
897  else {
899  ResetBlobs();
900  }
901  assert( Invariant("simpleB::revertRecord-exit") );
902 }
903 
904 
905 void
907 {
908  assert( Invariant("simpleB::ContextChange-entry") );
909 
910  dbSorter* mySorter = sorter();
911  if (mySorter)
912  mySorter->backendChangedContext(this);
913 
914  assert( Invariant("simpleB::ContextChange-exit") );
915 }
916 
917 
918 void
920 {
921  assert( Invariant("simpleB::CachingContextChange-entry") );
922 
923  if (isDirty() || isNewRecord()) {
925  mDirty = false;
926  }
927  ResetBlobs();
928  ContextChange(); // triggers sorts so must occur AFTER we've stashed a dirty record
929 
930  assert( Invariant("simpleB::CachingContextChange-exit") );
931 }
932 
933 
934 void
936 {
937  assert( Invariant("simpleB::CacheDirtyCurrentRecord-entry") );
939  assert(ctx);
940  DonateBlobBodiesTo(ctx);
941  // at this point ctx contains all the persistent fields from the record
942  if (!mDirtyRecordCache)
944  else
946  assert( Invariant("simpleB::CacheDirtyCurrentRecord-exit") );
947 }
948 
949 
950 
951 
952 
953 
964 void
966 {
967  assert( Invariant("simpleB::newRecord-entry") );
968 
970  mRecordState = eNew;
971  mDirty = false;
972  memset(mBuffer, 0, mRecBufLen);
974 
975  assert( Invariant("simpleB::newRecord-exit") );
976 }
977 
978 
979 bool
981 {
982  assert( Invariant("simpleB::CommonSimpleDelete-entry") );
983 
985  assert( Invariant("simpleB::CommonSimpleDelete-exit empty") );
986  return true;
987  }
988  if (mDirtyRecordCache)
990 
992 
993  if (isNewRecord()) {
994  // selection MAY contain this pointer under certain conditions, like related cached records
995  if (mSelection.current()==mCurrLoadedRecOffset) // most likely
997  else {
998  unsigned long foundAt;
999  if (mSelection.find(mCurrLoadedRecOffset, foundAt))
1000  mSelection.deleteItem(foundAt);
1001  }
1002  unloadRecord();
1003  start(); // leaves in reasonably consistent state
1004  assert( Invariant("simpleB::CommonSimpleDelete-exit complete") );
1005  return true; // simple case we know how to handle
1006  }
1007 
1008  assert( Invariant("simpleB::CommonSimpleDelete-exit") );
1009  return false; // didn't wholly process delete!
1010 }
1011 
1012 
1013 bool
1015 {
1016  assert( Invariant("simpleB::MaybeLoadRecordFromCache-entry") );
1017 
1018  if (mDirtyRecordCache) {
1019 // maybe this record is cached and we should reload from the cache rather than the file.
1020  unsigned long cachedIndex = mDirtyRecordCache->containsOffset(offset);
1021  if (cachedIndex!=OOF_recordCache::kNotFound) {
1023  assert(buf);
1024  AdoptBuffer(buf);
1025  mDirty = true;
1026  assert( Invariant("simpleB::MaybeLoadRecordFromCache-exit-true") );
1027  return true; //**** SUCCESSFUL EXIT *****
1028  }
1029  }
1030  assert( Invariant("simpleB::MaybeLoadRecordFromCache-exit-false") );
1031  return false;
1032 }
1033 
1034 
1035 unsigned long
1037 {
1038  if (isNewRecord())
1039  return 0;
1040  unsigned long ret = mSelection.iter();
1041  if (ret == ULONG_MAX)
1042  ret = 0; // HACK FOR NOW
1043  return ret;
1044 }
1045 
1046 
1052 unsigned long
1054 {
1055  const unsigned long kNotFound = ULONG_MAX;
1056 
1057  oidT ret;
1058  switch (mSelection.state()) {
1059 
1061  ret = kNotFound;
1062 
1064  if (mCurrLoadedRecOffset==inOID)
1065  ret = 0;
1066  else
1067  ret = kNotFound;
1068  break;
1069 
1071  if (!mSelection.find(inOID, ret))
1072  ret = kNotFound;
1073  break;
1074 
1076  { // nest for Visual C++
1077  unsigned long numRecs = countAll();
1078  start();
1079  ret = kNotFound;
1080  for (unsigned long i=0; i<numRecs; i++) {
1081  if (mCurrLoadedRecOffset==inOID) {
1082  ret = i;
1083  break;
1084  }
1085  next();
1086  }
1087  }
1088  break;
1089 
1090  default :
1091  ;
1092  }
1093  return ret;
1094 }
1095 
1096 
1097 unsigned long
1098 OOF_simpleRecordBackend::recordNumberMatching(const dbQueryClause* inClause, bool* outFoundIt) const
1099 {
1100  assert( Invariant("simpleB::recordNumberMatching-entry") );
1101 
1102 // UGGH!
1103 // have to clone the database as we are const!!!!
1104 
1105 // NOT YET IMPLEMENTED
1106  if (outFoundIt)
1107  *outFoundIt = false;
1108 
1109  unsigned long ret = 0;
1110 // LATER TO BE HEAVILY REWRITTEN - ONLY SUPPORTS A VERY MINOR CASE OF STRING SEARCHING
1111 // FOR >= MATCH
1112 
1114  dbQueryBinary* qClause = (dbQueryBinary*) inClause; // safe downcast
1115  dbQueryLiteralStr* strRHS = qClause->literalStrClause();
1116  dbQueryClause::BinaryQueryOps theOp = qClause->binaryOperator();
1117  #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
1119  #endif
1120 
1121  const dbField* originalSchField = qClause->lhsField();
1122  assert(originalSchField);
1123  dbTable* schTable = originalSchField->fieldTable()->cloneTableSharingSelection();
1124  assert(schTable);
1125  dbField* schField = schTable->field(originalSchField->fieldNumber());
1126  if (strRHS) {
1127  const char* schStr = strRHS->str();
1128  assert(schStr);
1129  switch(theOp) {
1130  case (dbQueryClause::startsWith) :
1131  assert(!"OOF_simpleRecordBackend::recordNumberMatching doesn't yet support startsWith"); //lint !e506 constant Boolean
1132  break;
1133 
1134  case (dbQueryClause::hasWord) :
1135  assert(!"OOF_simpleRecordBackend::recordNumberMatching doesn't yet support hasWord"); //lint !e506 constant Boolean
1136  break;
1137 
1139  assert(!"OOF_simpleRecordBackend::recordNumberMatching doesn't yet support hasWordStartsWith"); //lint !e506 constant Boolean
1140  break;
1141 
1142  case (dbQueryClause::equals) :
1143  assert(!"OOF_simpleRecordBackend::recordNumberMatching doesn't yet support equals"); //lint !e506 constant Boolean
1144  break;
1145 
1146  case (dbQueryClause::notEquals) :
1147  assert(!"OOF_simpleRecordBackend::recordNumberMatching doesn't yet support notEquals"); //lint !e506 constant Boolean
1148  break;
1149 
1150  case (dbQueryClause::lessThan) :
1151  assert(!"OOF_simpleRecordBackend::recordNumberMatching doesn't yet support lessThan"); //lint !e506 constant Boolean
1152  break;
1153 
1155  assert(!"OOF_simpleRecordBackend::recordNumberMatching doesn't yet support lessThanOrEqual"); //lint !e506 constant Boolean
1156  break;
1157 
1159  assert(!"OOF_simpleRecordBackend::recordNumberMatching doesn't yet support greaterThan"); //lint !e506 constant Boolean
1160  break;
1161 
1163  if (schField->fieldType()==charField || schField->fieldType()==textField) {
1164  for(schTable->start();schTable->more();schTable->next()){
1165  if(OOF_stricmp(schField->asChars(), schStr)>=0) {
1166  if (outFoundIt)
1167  *outFoundIt = true;
1168  ret = schTable->recordNumber();
1169  break;
1170  } // found match
1171  } // loop looking for match
1172  }
1173  else { // use less efficient copyString
1174  for(schTable->start();schTable->more();schTable->next()){
1175  if(OOF_stricmp(schField->copyString(), schStr)>=0) {
1176  if (outFoundIt)
1177  *outFoundIt = true;
1178  ret = schTable->recordNumber();
1179  break;
1180  } // found match
1181  } // loop looking for match
1182  }
1183  break;
1184 
1185  default:
1186  ; // nothing - already set false return value up top
1187  }
1188  delete schTable;
1189  }
1190  else {
1191  assert(!"OOF_simpleRecordBackend::recordNumberMatching only supports string searches"); //lint !e506 constant Boolean
1192  } // not string rhs
1193  }
1194  else {
1195  assert(!"OOF_simpleRecordBackend::recordNumberMatching only supports binary queries"); //lint !e506 constant Boolean
1196  } // not binary query
1197 
1198  assert( Invariant("simpleB::recordNumberMatching-exit") );
1199  return ret;
1200 }
1201 
1202 
1203 bool
1205 {
1206  assert( Invariant("simpleB::addOIDtoSelection-entry") );
1207 
1208  bool ret = false;
1209  if (!contains(inOID)) {
1210  ret = true;
1211  mSelection.append(inOID);
1212  }
1213  assert( Invariant("simpleB::addOIDtoSelection-exit") );
1214  return ret;
1215 }
1216 
1217 
1218 bool
1220 {
1221  bool ret = mSelection.contains(inOID);
1222  return ret;
1223 }
1224 
1225 
1226 void
1228 {
1229  assert( Invariant("simpleB::dropRecordFromSelection-entry") );
1230 
1231  mSelection.deleteItem(inRecNum);
1232 
1233  assert( Invariant("simpleB::dropRecordFromSelection-exit") );
1234 }
1235 
1236 
1237 
1238 
1239 
1245 bool
1247 {
1248  assert( Invariant("simpleB::selectJustOID-entry") );
1249 
1250  bool ret = true;
1251  if (inOID) {
1252  mSelection.selectOneRec(inOID);
1253  start();
1254  }
1255  else {
1256  #ifdef OOF_DEBUG
1257  dbConnect::raise("selectJustOID() called with 0 recordAddress", true /* continue */);
1258  #endif
1259  selectNone();
1260  ret = false;
1261  }
1262  assert( Invariant("simpleB::selectJustOID-exit") );
1263 
1264  return ret;
1265 }
1266 
1267 
1268 void
1270 {
1271  assert( Invariant("simpleB::selectJustCurrent-entry") );
1272 
1274 
1275  assert( Invariant("simpleB::selectJustCurrent-exit") );
1276 }
1277 
1278 bool
1280 {
1281  return (mRecordState!=eUnloaded);
1282 }
1283 
1284 
1285 bool
1287 {
1288  return isNew();
1289 }
1290 
1291 
1292 void
1294 {
1295  assert( Invariant("simpleB::setSortOrder-entry") );
1296 
1297  mSelection.setSortOrder(adoptSorter);
1298 
1299  assert( Invariant("simpleB::setSortOrder-exit") );
1300 }
1301 
1302 
1303 dbSorter*
1305 {
1306  return mSelection.sorter();
1307 }
1308 
1309 
1310 dbSelection
1312 {
1313  assert( Invariant("OOF_simpleRecordBackend::currentSelection") );
1314  return dbSelection(&mSelection);
1315 }
1316 
1317 
1320 {
1322 }
1323 
1324 
1325 void
1327 {
1329 }
1330 
1331 
1332 void
1334 {
1335  assert( Invariant("simpleB::setSelection-oofsel-entry") );
1336 
1337 // dangerous downcast if user is stupid enough to mix selections but highly unlikely
1338  const OOF_recordSelection* rhsSel = (const OOF_recordSelection*) rhs;
1339  mSelection = *rhsSel;
1340  const unsigned long recsInSelection = mSelection.count();
1341  const unsigned long currentRec = mSelection.iter();
1342  if (recsInSelection)
1343  if (currentRec < recsInSelection) // haven't iterated off end
1344  gotoRecord(currentRec); // goto current record in selection
1345  else
1346  start();
1347 
1348  assert( Invariant("simpleB::setSelection-oofsel-exit") );
1349 }
1350 
1351 
1352 void
1354 {
1355  assert( Invariant("simpleB::selectAll-entry") );
1356 
1358  unloadRecord();
1360  mSelection.gotoRecord(0); // reset iterator to reasonable value
1361 
1362  assert( Invariant("simpleB::selectAll-exit") );
1363 }
1364 
1365 
1366 void
1368 {
1369  assert( Invariant("simpleB::selectNone-entry") );
1370 
1371  unloadRecord();
1374 
1375  assert( Invariant("simpleB::selectNone-exit") );
1376 }
1377 
1378 
1379 void
1381 {
1382 // null method - most backends ignore
1383 }
1384 
1385 
1386 unsigned int
1388 {
1389  return mNumIndexes;
1390 }
1391 
1392 
1393 unsigned int
1395 {
1396  return mNumFiles;
1397 }
1398 
1399 
1400 bool
1402 {
1403  return false;
1404 }
1405 
1406 
1407 unsigned long
1409 {
1410 // NOT YET IMPLEMENTED handle inline blobs
1411  return sizeof(long)+sizeof(long);
1412 }
1413 
1414 
1415 void
1417 {
1418  os << "RecState: " << mRecordState << "\t"
1419  << "Offset: " << mCurrLoadedRecOffset << "\t" ;
1420  if (mDirty)
1421  os << "Dirty\t";
1422  else
1423  os << "Clean\t";
1425  os << endl;
1426 }
1427 // -------------------------------------------------------
1428 // O O F _ r e c o r d C a c h e C o p i e r
1429 // -------------------------------------------------------
1431  oofSingleListener(listensTo),
1432  mCache(adoptsCache),
1433  mBackend(inBackend),
1434  mSavedContext(savedContext)
1435 {
1436 }
1437 
1438 
1440 {
1441  delete mCache;
1442 }
1443 
1444 
1445 #ifdef NDEBUG
1446 bool
1447 OOF_recordCacheCopier::receiveMsg(OOFmsgT msg, unsigned long /*senderDefined*/)
1448 #else
1449 bool
1450 OOF_recordCacheCopier::receiveMsg(OOFmsgT msg, unsigned long /*senderDefined*/)
1451 #endif
1452 {
1453  if (msg==OOFmsg_BroadcasterClosing) // rare but possible in some exception handling
1454  return true;
1455 
1456 // while we have cached records, make each one current and dirty
1457 // so the save loop will continue
1458  assert(msg==OOFmsg_SaveRecord); // we are only called from a tight loop
1459  unsigned int numCached = mCache->count();
1460  if (numCached) {
1461  mBackend->AdoptBuffer(mCache->orphanBuffer(numCached-1));
1462  mBackend->markDirty();
1463  }
1464  else { // all finished!
1465  mBackend->AdoptBuffer(mSavedContext);
1466  delete this;
1467  }
1468  return true;
1469 }
1470 
1471 
1472 // -------------------------------------------------------
1473 // O O F _ d i r t y F i e l d M a p
1474 // -------------------------------------------------------
1476  mNumFields(0),
1477  mDirtyMap(0)
1478 {
1479 }
1480 
1481 
1483  mNumFields(rhs.mNumFields),
1484  mDirtyMap(0)
1485 {
1486  finishMap(mNumFields);
1487 }
1488 
1489 
1491 {
1492  delete[] mDirtyMap;
1493 }
1494 
1495 
1496 
1497 void
1498 OOF_dirtyFieldMap::finishMap(unsigned short numFields)
1499 {
1500  mNumFields = numFields;
1501  delete[] mDirtyMap;
1502  mDirtyMap = new bool[numFields];
1503  reset();
1504 }
1505 
1506 
1507 bool
1509 {
1510  for (unsigned short i=0; i<mNumFields; i++) {
1511  if (mDirtyMap[i])
1512  return true;
1513  }
1514  return false;
1515 }
1516 
1517 
1518 void
1520 {
1521  for (unsigned short i=0; i<mNumFields; i++) {
1522  mDirtyMap[i] = false;
1523  }
1524 }
1525 
1526 
1527 
1528 // -------------------------------------------------------
1529 // E s e l e c t i o n S t a t e
1530 // -------------------------------------------------------
1531 ostream&
1533 {
1534  switch (st) {
1536  os << "empty";
1537  break;
1538 
1540  os << "oneRec";
1541  break;
1542 
1544  os << "someRecs";
1545  break;
1546 
1547  default :
1548  os << "allRecs";
1549  }
1550  return os;
1551 }
1552 
1553 
1554 // -------------------------------------------------------
1555 // E R e c o r d S t a t e
1556 // -------------------------------------------------------
1557 ostream&
1559 {
1560  switch (st) {
1562  os << "eNew";
1563  break;
1564 
1566  os << "eLoaded";
1567  break;
1568 
1569  default :
1570  os << "eUnloaded";
1571  }
1572  return os;
1573 }
1574 
1575 
virtual void next()=0
unsigned int * mFieldBufMapRefCount
Definition: oofrecs.h:562
void describeState(std::ostream &os) const
Definition: oofrec4.cpp:943
virtual dbSelection currentSelection() const
Definition: oofrec1.cpp:1311
virtual bool readBool(const dbField *) const
Assumes bools stored as unsigned short, 0==false.
Definition: oofrec1.cpp:544
virtual void setSortOrder(dbSorter *adoptSorter)
Definition: oofrec4.cpp:822
virtual void selectAll()
Definition: oofrec1.cpp:1353
OOF_ExpandableLongArray * mBlobFieldNums
Definition: oofrecs.h:566
void finishMap(unsigned short numFields)
Definition: oofrec1.cpp:1498
const dbField * lhsField() const
Definition: oofquery.h:620
virtual unsigned long blobPointerReferenceSize() const
Definition: oofrec1.cpp:1408
void deleteItem(unsigned long index)
Definition: oofrec4.cpp:870
Definition: oof3.h:26
unsigned short mNumFiles
Definition: oofrecs.h:563
virtual unsigned long countAll() const =0
virtual dbSorter * sorter() const
Definition: oofrec4.cpp:829
OOF_ExpandableLongArray * mBlobFieldBodies
Definition: oofrecs.h:157
static void raise(std::ostream &, bool terminateAfterMsg=true)
virtual bool isAllRecs() const
Definition: oofrecs.h:917
void resetFakeNewRecordOffSet()
Definition: oofrecs.h:1064
virtual void unloadCache()
Definition: oofrec1.cpp:853
virtual unsigned int numIndexes() const
Definition: oofrec1.cpp:1387
virtual void prev()
Definition: oofrec1.cpp:372
fieldNumT fieldNumber() const
Definition: oof3.h:754
precompilation header.
void * GetFieldReadFrom(fieldNumT) const
Definition: oofrec1.cpp:750
virtual unsigned long recordNumberOfOID(oidT inOID)
Implement dbTable::recordNumberOfOID.
Definition: oofrec1.cpp:1053
virtual void setSelection(const dbSelection &)
Definition: oofrec1.cpp:1326
virtual oofString readString(const dbField *) const
Copy field data into a string.
Definition: oofrec1.cpp:627
unsigned long recordNumber() const
Ordinal record number of current record in selection.
Definition: oof1.h:2041
virtual bool contains(oidT) const
Definition: oofrecs.h:860
Tries to hide the different platforms and version issues with standard IO.
virtual unsigned long count() const
Definition: oofrec1.cpp:404
void append(OOF_recordBufferedContext *adoptingContext)
Definition: oofrec4.cpp:135
Simplest internal representation of a record's contents and context in dbTable.
Definition: oofrecs.h:130
Highest level used to assemble queries.
Definition: oofquery.h:46
unsigned long mOffset
Definition: oofrecs.h:42
bool isDirty() const
Definition: oof1.h:1719
OOF_dirtyFieldMap mDirtyMap
Definition: oofrecs.h:158
bool isDirty(unsigned short) const
Definition: oofrecs.h:782
bool isDirty() const
Definition: oof3.h:857
bool GotoRecordForAllUnindexed(unsigned long relativeNum)
Definition: oofrec1.cpp:761
virtual void pack()
Definition: oofrec1.cpp:1380
Envelope class to contain an abstract selection apart from its dbTable.
Definition: oof1.h:316
bool fieldIsStandalone() const
Definition: oof3.h:733
virtual bool isRecordLoaded() const
Definition: oofrec1.cpp:1279
virtual void SaveContext()=0
bool more() const
Definition: oofrecs.h:887
abstract base for public interface to selections.
Definition: oof2.h:107
void deleteRecord(unsigned long recOffset)
Definition: oofrec4.cpp:159
void start()
Definition: oof1.cpp:2057
virtual bool atLast() const
Definition: oofrec1.cpp:340
dbQueryClause::BinaryQueryOps binaryOperator() const
Definition: oofquery.h:610
virtual void writeChars(const char *, long numChars, long maxLen, const dbField *, long startIndex=0)
Definition: oofrec1.cpp:699
virtual unsigned long fieldStorageLen() const =0
Definition: oof3.h:26
unsigned long BlobPosFromBuffer(const dbField *fld, const char *theirBuffer) const
Definition: oofrecs.h:749
OOF_recordSelection mSelection
Definition: oofrecs.h:560
unsigned long count() const
Definition: oofarray.h:126
Special limited oofReceiver which will only ever listen to one oofBroadcaster at a time...
Definition: oofmsg.h:133
void CacheDirtyCurrentRecord()
Definition: oofrec1.cpp:935
void append(oidT)
Definition: oofrecs.h:1020
int OOF_stricmp(const char *, const char *)
Compare strings ignoring case.
Definition: oofstr.cpp:59
void reset() const
Definition: oof3.h:878
virtual bool CanUseIndex(const dbField *, dbQueryClause::BinaryQueryOps=dbQueryClause::equals) const
Definition: oofrec1.cpp:1401
unsigned short mNumIndexes
Definition: oofrecs.h:563
dbTable * prototype() const
Definition: oof1.h:2477
bool MaybeLoadRecordFromCache(unsigned long offset)
Definition: oofrec1.cpp:1014
virtual bool allSelected() const
Definition: oofrec1.cpp:326
virtual unsigned int numFiles() const
Definition: oofrec1.cpp:1394
unsigned long PadFieldWidthForAlignment(const dbField *fld) const
Definition: oofrec1.cpp:101
OOF_bitPointer value(unsigned int index) const
Definition: oof1.h:1594
const OOFmsgT OOFmsg_BroadcasterClosing
Definition: oofmsg.h:40
virtual void noticeDuplicateRecords()
Definition: oofrec1.cpp:319
void DonateBlobBodiesTo(OOF_recordBufferedContext *)
Definition: oofrec1.cpp:214
virtual OOF_fieldTypes nativeType() const
Definition: oof3.cpp:301
virtual bool isNewRecord() const
Definition: oofrec1.cpp:1286
virtual bool receiveMsg(OOFmsgT msg, unsigned long senderDefined)
The default receiveMsg behaviour is to delete yourself when the broadcaster closes.
Definition: oofrec1.cpp:1450
void copyFrom(const OOF_recordSelection &, dbTable::selSharingT)
Definition: oofrec4.cpp:744
bool more() const
When iterating a selection, are there any more records beyond current.
Definition: oof1.h:1896
const OOF_Selection * internalSelection() const
Definition: oof2.h:317
void adoptBody(void *body, unsigned long bodyLen) const
Definition: oof3.cpp:2190
virtual void setBlobLength(fieldNumT, unsigned long len)
Definition: oofrec1.cpp:269
unsigned int FieldAlignsTo(const dbField *) const
Definition: oofrec1.cpp:123
void backendSavedRecord(OOF_tableBackend *)
Definition: oof1.cpp:3015
virtual void saveRecord()
Save current main record and any cached dirty records.
Definition: oofrec1.cpp:788
Main implementation parent for backends following the record-oriented model.
Definition: oofrecs.h:295
void saveStoredCalculatedValue()
Definition: oof3.cpp:282
Common binary query for field, eg: People.Salary > 90000.
Definition: oofquery.h:165
virtual bool addOIDtoSelection(oidT)
Definition: oofrec1.cpp:1204
virtual void LoadRecordAtOffset(unsigned long offset)=0
virtual long readLong(const dbField *) const
Definition: oofrec1.cpp:582
void saveDefaultCalculatedValue()
Definition: oof3.cpp:272
unsigned long & item(unsigned long index)
Definition: oofarray.h:168
void aboutToDirtySelection()
Definition: oofrecs.h:1042
virtual void CachingContextChange()
Definition: oofrec1.cpp:919
Definition: oof3.h:26
unsigned long iter() const
current position in selection
Definition: oofrecs.h:975
virtual unsigned long count() const
Definition: oofrecs.h:853
dbQueryLiteralStr * literalStrClause() const
Definition: oofquery.cpp:276
virtual dbSorter * sorter() const
Definition: oofrec1.cpp:1304
Selection of records in context of a single dbTable instance.
Definition: oofrecs.h:173
virtual short readShort(const dbField *) const
Definition: oofrec1.cpp:563
unsigned long oidT
type we pass around pretending we have a real OID.
Definition: oof1.h:229
virtual void writeLong(long, const dbField *)
Definition: oofrec1.cpp:673
unsigned long containsOffset(unsigned long recOffset) const
Definition: oofrec4.cpp:225
Abstract interface to database backend.
Definition: oof1.h:1047
virtual bool isEmpty() const
Definition: oofrecs.h:910
OOF_recordBufferedContext * orphanBuffer(unsigned long)
Definition: oofrec4.cpp:254
Store RAM-resident cache of records, eg: OOF_simpleRecordBackend::mDirtyRecordCache.
Definition: oofrecs.h:76
virtual void writeBool(bool, const dbField *)
Encode bool as short to be decoded by readBool.
Definition: oofrec1.cpp:640
virtual bool contains(oidT) const
Definition: oofrec1.cpp:1219
void SetBlobLenInBuffer(fieldNumT, unsigned long len, const char *theirBuffer) const
Definition: oofrec1.cpp:254
virtual void writeDouble(double, const dbField *)
Definition: oofrec1.cpp:688
OOF_recordFieldEntry * mFieldBufMap
Definition: oofrecs.h:561
void deleteAll()
Definition: oofrec4.cpp:190
unsigned long BlobLenFromBuffer(const dbField *, const char *theirBuffer) const
Definition: oofrecs.h:742
const oofString & tableName() const
Definition: oof1.h:2369
virtual oidT currentOID()
Definition: oofrec1.cpp:430
Specify sort order by one more fields.
Definition: oof1.h:1277
virtual bool gotoRecord(unsigned long relativeNum)=0
virtual ~OOF_recordCacheCopier()
Definition: oofrec1.cpp:1439
virtual dbTable * cloneTableSharingSelection() const
Definition: oof1.cpp:1433
void selectOneRec(unsigned long)
Definition: oofrecs.h:997
OOF_recordCacheCopier(oofBroadcaster *listensTo, OOF_recordCache *adoptsCache, OOF_simpleRecordBackend *inBackend, OOF_recordBufferedContext *)
Definition: oofrec1.cpp:1430
virtual bool reloadRecord()
Definition: oofrec1.cpp:867
virtual void setSortOrder(dbSorter *adoptSorter)
Definition: oofrec1.cpp:1293
virtual unsigned long fieldDataLen(const dbField *) const
Definition: oofrec1.cpp:472
bool tableCachesDirtyRecords() const
Definition: oof1.h:2518
virtual bool atRelative(unsigned long) const
Definition: oofrec1.cpp:347
virtual void buildSchema(bool rebuilding=false)
Definition: oofrec1.cpp:154
virtual char * getByteWriteAddress(unsigned long, const dbField *)
Definition: oofrec1.cpp:740
virtual void BuildBackendtables(bool rebuilding)=0
backend construction
Array of longs which expands automatically as you write to cells.
Definition: oofarray.h:21
virtual void revertRecord()
Definition: oofrec1.cpp:887
virtual void ignoreDuplicateRecords()
Definition: oofrec1.cpp:312
dbField * field(fieldNumT) const
Definition: oof1.h:2355
ERecordState mRecordState
Definition: oofrecs.h:153
void AdoptBuffer(OOF_recordBufferedContext *)
Definition: oofrec1.cpp:170
unsigned int count() const
Definition: oof1.h:1498
unsigned short fieldNumT
Definition: oof1.h:276
Base class for persistent tables.
Definition: oof1.h:452
virtual void start()=0
OOF_recordCache * mDirtyRecordCache
Definition: oofrecs.h:567
void next()
Next record in the selection becomes current.
Definition: oof1.h:1970
Definition: oof3.h:26
Portable highly capable string class.
Definition: oofstr.h:101
Definition: oof3.h:26
virtual dbSorter * clone() const
Definition: oof1.cpp:2918
Describe a subset of fields in a table which are dirty.
Definition: oofrecs.h:51
OOF_recordCache * mCache
Definition: oofrecs.h:686
unsigned long mRecBufLen
Definition: oofrecs.h:155
virtual void unloadRecord()
Definition: oofrec1.cpp:828
bool mHasStoredCalculators
Definition: oof1.h:1236
virtual void describeState(std::ostream &) const
Definition: oofrec1.cpp:1416
virtual bool find(oidT item, unsigned long &foundAt) const
Definition: oofrecs.h:870
saveOptionsT tableSaveOption() const
Definition: oof1.h:2394
virtual void writeShort(short, const dbField *)
Definition: oofrec1.cpp:658
virtual bool fieldIsVirtual() const
Definition: oof3.cpp:400
unsigned long appendNewRecord(bool appendIt)
returns new synthetic record number
Definition: oofrec4.cpp:914
#define OOF_MEM_DEBUG_FORCE_POOL_CHECK
Definition: doxyoof.h:408
virtual bool atFirst() const
Definition: oofrec1.cpp:333
unsigned long mCurrLoadedRecOffset
Definition: oofrecs.h:154
Generic broadcaster for messaging.
Definition: oofmsg.h:76
virtual void newRecord()
Sets up a new record ready to enter data On exit the state is: Selection state is aboutToDirty Select...
Definition: oofrec1.cpp:965
void backendChangedContext(OOF_tableBackend *)
Definition: oof1.cpp:2999
virtual void ContextChange()
Definition: oofrec1.cpp:906
virtual bool selectJustOID(oidT)
Definition: oofrec1.cpp:1246
RHS String argument to queries on fields like dbChar.
Definition: oofquery.h:324
void * GetFieldWriteDest(const dbField *)
Definition: oofrec1.cpp:519
virtual void selectJustCurrent()
Definition: oofrec1.cpp:1269
virtual unsigned long recordNumberMatching(const dbQueryClause *qClause, bool *outFoundIt=0) const
Definition: oofrec1.cpp:1098
virtual void dropRecordFromSelection(unsigned long)
Definition: oofrec1.cpp:1227
virtual oofString copyString() const
Definition: oof3.cpp:472
const char * str() const
Definition: oofquery.h:666
std::ostream & operator<<(std::ostream &, const oofE_Base &)
OOF_simpleRecordBackend(dbTable *)
Definition: oofrec1.cpp:34
virtual unsigned long recordNumber() const
Definition: oofrec1.cpp:1036
virtual void writeBytes(const char *inBuf, long inLen, const dbField *inField)
Definition: oofrec1.cpp:723
virtual bool fieldIsDirty(fieldNumT) const
Definition: oofrec1.cpp:511
virtual OOF_fieldTypes fieldType() const =0
unsigned long OOFmsgT
Definition: oofmsg.h:31
unsigned long current() const
value of current item
Definition: oofrecs.h:931
unsigned long value(unsigned long) const
Definition: oofrecs.h:967
Persistent field used to store an arbitrary binary object.
Definition: oof3.h:387
virtual ~OOF_simpleRecordBackend()
Definition: oofrec1.cpp:85
bool isNew() const
Definition: oofrecs.h:697
selSharingT
Definition: oof1.h:463
void gotoRecord(unsigned long)
Definition: oofrecs.h:982
dbTable * mTable
Definition: oof1.h:1234
bool Invariant(const char *optionalComment=0) const
Check combination of member variables defining Invariant state.
Definition: oofrec3.cpp:1837
EselectionState state() const
Definition: oofrecs.h:846
virtual oidT oidOfRecord(unsigned long)
Definition: oofrec1.cpp:441
const OOFmsgT OOFmsg_SaveRecord
Definition: oofmsg.h:38
OOF_Dictionary mFields
Definition: oof1.h:1233
bool anyDirty() const
Definition: oofrec1.cpp:1508
friend class OOF_recordCacheCopier
Definition: oofrecs.h:583
bool mHasDefaultCalculators
Definition: oof1.h:1236
void markDirty(unsigned short)
Definition: oofrecs.h:774
bool storesCalculatedValues() const
Definition: oof3.h:806
virtual bool more() const
Definition: oofrec1.cpp:354
virtual const char * readChars(const dbField *) const
Definition: oofrec1.cpp:619
void markDirty()
Definition: oof1.cpp:1358
char * orphanBody() const
Definition: oof3.h:893
Base class for persistent fields in dbTable's.
Definition: oof3.h:63
void SetBlobPosInBuffer(fieldNumT, unsigned long pos, const char *theirBuffer) const
Definition: oofrec1.cpp:261
virtual dbSelection makeEmptySelection() const
Definition: oofrec1.cpp:1319
virtual void selectNone()
Definition: oofrec1.cpp:1367
bool ensureRecordLoaded(bool autoCreateRelated=false, bool failureAborts=true)
Definition: oof1.cpp:1228
virtual const char * asChars() const
Definition: oof3.cpp:243
virtual double readDouble(const dbField *) const
Definition: oofrec1.cpp:601
virtual dbQueryClause::QueryClauseTypes queryClauseType() const =0
virtual bool fieldIsBlob() const
Definition: oof3.cpp:386