OOFILE  1.9
oof3.cpp
Go to the documentation of this file.
1 // COPYRIGHT 1994 A.D. Software, All rights reserved
2 
3 // OOFILE database field-related classes
4 // see also oof4.cpp
5 
6 #include "oofpch_c.h" // for precompilation of core files
7 
8 #ifndef H_OOFIOS
9  #include "oofios.h"
10 #endif
11 #ifndef H_OOF2
12  #include "oof2.h"
13 #endif
14 #ifndef H_OOF3
15  #include "oof3.h"
16 #endif
17 #ifndef OOF_EXCEP
18  #include "oofexcep.h"
19 #endif
20 #ifndef H_OOFQUERY
21  #include "oofquery.h"
22 #endif
23 #ifndef H_OOFREL
24  #include "oofrel.h"
25 #endif
26 #ifndef H_OOFWORDS
27  #include "oofwords.h"
28 #endif
29 #ifndef H_OOFRELX
30  #include "oofrelx.h"
31 #endif
32 #ifdef OOF_MEM_DEBUG_LAST_INCLUDE
33  #include OOF_MEM_DEBUG_LAST_INCLUDE
34 #endif
35 
36 #ifndef OOF_NO_STDLIB
37  #ifndef std
38  using namespace std;
39  #endif
40 #endif
41 
42 #ifdef _MSC_VER
43 // suppress warning 'this' used in base member init list
44  #pragma warning( disable : 4355 )
45 #endif
46 
48 
49 // -------------------------------------------------------
50 // d b F i e l d
51 // -------------------------------------------------------
52 
53 dbField::dbField(const OOF_IndexOptions indexOptions) :
54  mBackend(0),
55  mTable(0),
56  mFieldNumber(0),
57  mCalculator(0),
58  mIndexOptions(indexOptions),
59  mPartialKeyLength(kKeyLengthAutoCalculated),
60  mCalculateOnlyDefaults(false),
61  mStoreCalculatedValues(false)
62 {
63 #ifdef OOF_DEBUG
65  dbConnect::raise(stringstream() << flush << "un-named field type"
66  << " is defined AFTER the call to newConnection or openConnection, probably by accident, and is not part of a table", false);
67  } else
68 #endif
70 }
71 
72 
73 dbField::dbField(const char* fieldName) :
74  mBackend(0),
75  mTable(0),
76  mFieldNumber(0),
77  mCalculator(0),
78  mIndexOptions(kNotIndexed),
79  mPartialKeyLength(kKeyLengthAutoCalculated),
80  mFieldName(fieldName),
81  mCalculateOnlyDefaults(false),
82  mStoreCalculatedValues(false)
83 {
84 #ifdef OOF_DEBUG
86  dbConnect::raise(stringstream() << flush << "field '" << fieldName << "' of unknown type"
87  << " is defined AFTER the call to newConnection or openConnection, probably by accident, and is not part of a table", false);
88  } else
89 #endif
91 }
92 
93 
94 dbField::dbField(const char *fieldName, const OOF_IndexOptions indexOptions) :
95  mBackend(0),
96  mTable(0),
97  mFieldNumber(0),
98  mCalculator(0),
99  mIndexOptions(indexOptions),
100  mPartialKeyLength(kKeyLengthAutoCalculated),
101  mFieldName(fieldName),
102  mCalculateOnlyDefaults(false),
103  mStoreCalculatedValues(false)
104 {
105 #ifdef OOF_DEBUG
107  dbConnect::raise(stringstream() << flush << "field: '" << fieldName
108  << "' is defined AFTER the call to newConnection or openConnection, probably by accident, and is not part of a table", false);
109  } else
110 #endif
112 }
113 
114 
116  OOF_PublicBase(rhs),
117  mBackend(rhs.mBackend),
118  mTable(0),
119  mFieldNumber(rhs.mFieldNumber),
120  mCalculator(0),
121  mIndexOptions(rhs.mIndexOptions),
122  mPartialKeyLength(rhs.mPartialKeyLength),
123  mFieldName(rhs.mFieldName),
124  mCalculateOnlyDefaults(rhs.mCalculateOnlyDefaults),
125  mStoreCalculatedValues(rhs.mStoreCalculatedValues)
126 {
127  if (!rhs.fieldIsStandalone()) {
129  theTable->attachfield(this);
130  }
131  if (rhs.mCalculator)
132  mCalculator = rhs.mCalculator->cloneOwned(this);
133 }
134 
135 
137  mBackend(0),
138  mTable(0),
139  mFieldNumber(0),
140  mCalculator(0),
141  mIndexOptions(kNotIndexed),
142  mPartialKeyLength(kKeyLengthAutoCalculated),
143  mCalculateOnlyDefaults(false),
144  mStoreCalculatedValues(false)
145 {
146 }
147 
148 
150 {
151  delete mCalculator;
152 }
153 
154 
155 oofString
157 {
158  return fieldName();
159 }
160 
161 
162 void
164 {
165  assert(0); // dummy base method for virtual fields and BLOB
166 }
167 
168 
169 bool
171 {
172  return false; // overriden for dbBLOB and dbChar
173 }
174 
175 
176 bool
178 {
179  return true;
180 }
181 
182 
185 {
186 #ifdef OOF_DEBUG
187  dbConnect::raise("You must override dbField::valueAsQueryLiteral() for field types that may be uniquely indexed");
188 #endif
189  assert(0); // must override for searchable fields
190  return 0;
191 }
192 
193 
194 void
195 dbField::setName(const char* name)
196 {
197  mFieldName = name;
198 }
199 
200 
201 const char*
203 {
204  if (fieldIsStandalone())
205  return "";
206  else
207  return mTable->tableName();
208 }
209 
210 
211 void
213 {
214 // allowed to turn off existing index
215 // assert((indexOpt==kNotIndexed) || (mIndexOptions==kNotIndexed) || (mIndexOptions==indexOpt)); // NOT ALREADY SPECIFIED as different index
216  mIndexOptions=indexOpt;
217 }
218 
219 
220 
221 unsigned long
223 {
224  const unsigned long kArbitraryWrapThreshold = 12;
225  unsigned long ret = fieldStorageLen();
226  if (ret==0) // may happen with empty standalone oofChar
227  ret = 1;
228  else if (ret > kArbitraryWrapThreshold)
229  ret = kArbitraryWrapThreshold;
230  return ret;
231 }
232 
233 
234 unsigned long
236 {
237  unsigned long ret = fieldMinWrapWidth();
238  return ret;
239 }
240 
241 
242 const char*
244 {
245  assert(!"dbField::asChars is never meant to be called, use copyString instead as a virtual method"); //lint !e506 constant Boolean
246  return"";
247 }
248 
249 
252 {
253  return 0;
254 }
255 
256 
257 bool
259 {
260  bool ret = false;
261  if (mCalculator) {
262  if (mCalculateOnlyDefaults)
263  ret = mTable->isNewRecord() && !isDirty(); // ie: new, untouched, unsaved
264  else
265  ret = true;
266  }
267  return ret;
268 }
269 
270 
271 void
273 {
274  assert(mTable->isNewRecord());
275  if (mCalculateOnlyDefaults && !isDirty()) {
277  }
278 }
279 
280 
281 void
283 {
284  if (mStoreCalculatedValues) {
286  }
287 }
288 
289 
290 bool
292 {
293  dbQueryClause* rhsLiteral = valueAsQueryLiteral();
294  dbQueryBinary dupQuery(new dbQueryField(this), dbQueryClause::equals, rhsLiteral);
295  bool ret = mBackend->checkDuplicate(&dupQuery);
296  return ret;
297 }
298 
299 
302 {
303  return fieldType(); // only override for things like dbDate which can be treated as a different native type (ulong)
304 }
305 
306 
307 dbTable*
309 {
310  return mTable;
311 }
312 
313 
314 
326 bool
328 {
329  if (fieldIsStandalone())
330  return false;
331 
332  // couple of local const cached members for faster lookup
333  const dbTable* ourTable = mTable;
334  const fieldNumT thisFieldNumber = mFieldNumber;
335 
336  const fieldNumT fieldsInTable = ourTable->numFields();
337  for (fieldNumT i=0; i<fieldsInTable; i++) {
338  if (i!=thisFieldNumber) {
339  const dbField* anotherField = ourTable->field(i);
340  if (anotherField->fieldType()==relationshipField) {
341  const dbRelRefBase* asRel = (const dbRelRefBase*) anotherField; // safe downcast
342  if (asRel->joinField()==this)
343  return true;
344  } // is rel
345  } // skip current field
346  } // loop fields
347  return false;
348 }
349 
350 
351 dbField*
353 {
354 //get the equivalent field in the baseTable, or related table to baseTable
355 // NOT YET IMPLEMENTED - cope with circular relationships!
356  dbField* ret = 0;
357 
358  if (fieldIsStandalone())
359  ret = clone();
360  else {
361  const tableNumT baseTableNum = baseTable->tableNumber();
362  const tableNumT currentTableNum = mTable->tableNumber();
363  if (baseTableNum == currentTableNum)
364  ret = baseTable->field(mFieldNumber); // common, trivial case
365  else { // assume baseTable somewhere to our left, need to trace exact relationship chain
367  if (relToLHS) {
368  dbTable* lhsTable = relToLHS->relatedTable();
369  dbRelRefBase* pointerToOurTable = relToLHS->inverse();
370  dbField* equivField = pointerToOurTable->equivalentFieldFromTable(baseTable); // RECURSE
371  assert(equivField->fieldType()==relationshipField);
372  dbRelRefBase* pointerToEquivTable = (dbRelRefBase*) equivField; // safe downcast
373  dbTable* wantedTable = pointerToEquivTable->relatedTable();
374  assert(currentTableNum == wantedTable->tableNumber());
375  ret = wantedTable->field(mFieldNumber);
376  }
377  else
378  dbConnect::raise("dbField::equivalentFieldFromTable failed for unrelated fields",false);
379  }
380  }
381  return ret;
382 }
383 
384 
385 bool
387 {
388  return false;
389 }
390 
391 
392 bool
394 {
395  return true;
396 }
397 
398 
399 bool
401 {
402  bool ret = (mCalculator && !mCalculateOnlyDefaults); // a calculator replaces our need for storage
403  return ret;
404 }
405 
406 
407 bool
409 {
410  return mIndexOptions!=kNotIndexed;
411 }
412 
413 
414 bool
416 {
417  return false;
418 }
419 
420 
421 bool
423 {
424  bool ret = ((mIndexOptions & kIndexNoDups)!=0);
425  return ret;
426 }
427 
428 
429 unsigned short
431 {
432  unsigned short ret = 0;
433  if (fieldIsIndexed()) {
435  ret = mPartialKeyLength;
436  else
437  ret = fieldStorageLen();
438  }
439  return ret;
440 }
441 
442 
443 void
444 dbField::CalculateWith(dbCalculator* adoptedCalculator, bool useOnlyForDefaults)
445 {
446 // NOTE we can't check indexed status here as the index() method can be called
447 // later, so we don't set mStoreCalculatedValues
448  if (mCalculator) {
449  if (!adoptedCalculator) {
450  if (!mCalculateOnlyDefaults) {
451  oofE_FieldError excp(fieldTable(), this,
452  "You can't remove a calculator by passing in a nil parameter unless the calculator is used only for defaults");
453  RAISE_EXCEPTION(excp);
454  }
455  }
456  delete mCalculator;
457  }
458  else {
459 // only set mCalculateOnlyDefaults if we don't have a calculator
460 // as can't change this behaviour once set - eg: too dangerous to try to convert
461 // a calc field into a calcDefaultsOnly field
462  if (useOnlyForDefaults) {
465  }
466  }
467  mCalculator = adoptedCalculator;
468 }
469 
470 
471 oofString
473 {
474  stringstream oss;
475  extract(oss);
476  return oofString(oss);
477 }
478 
479 
480 void
481 dbField::getChars(char* ioBuff, unsigned long& ioLen) const
482 {
483 #if OOF_USE_ANSI_STREAMS
484  ostringstream oss;
485  extract(oss);
486  string ossStr = oss.str(); // copied
487 
488  const unsigned long ossLen = ossStr.size();
489  if (ossLen<ioLen) // less data than user buffer
490  ioLen = ossLen; // so return accurate length
491  // else just fill the buffer they gave us
492  memcpy(ioBuff, ossStr.c_str(), ioLen); // NOT assuming null terminated strings
493 // the stream is not constructed using our buffer that we pass in,
494 // so we need to copy the output
495 
496 #else
497 // old streams directly use our buffer
498  ostringstream oss(ioBuff, ioLen);
499  extract(oss);
500  ioLen = oss.pcount(); // now that we've appended our null on the end
501 #endif
502 }
503 
504 
505 void
506 dbField::extract(ostream& os) const
507 {
508  os << "";
509 }
510 
511 
512 bool
513 dbField::insert(istream& is, char fieldSep, char recSep)
514 {
515  char c = is.peek();
516  while (is.good()) {
517  if ((c==fieldSep) || (c==recSep)) {
518  return true; // OK - hit a separator
519  }
520  is >> c; // just swallowing this character
521  c = is.peek();
522  }
523  return false; // fell through without hitting separator
524 }
525 
526 
527 istream&
528 operator>>(istream& is, dbField* fld)
529 {
530  fld->insert(is, '\t', '\n');
531  return is;
532 }
533 
534 
535 istream&
536 operator>>(istream& is, dbField& fld)
537 {
538  fld.insert(is, '\t', '\n');
539  return is;
540 }
541 
542 
543 void
544 dbField::describe(ostream& os) const
545 {
546  if (mFieldName.isEmpty())
547  os << "Un-named field";
548  else
549  os << "field: " << mFieldName;
550  os << "\t type: " << fieldType() << endl;
551  if (fieldIsIndexed())
552  os << "\tindex: " << fieldIndexOptions() << endl;
553 }
554 
555 
556 bool
558 {
559  return (fieldType()==rhs->fieldType());
560 }
561 
562 
563 bool
565 {
566  if (fieldIsStandalone())
567  return true;
569 }
570 
571 
572 // -------------------------------------------------------
573 // d b F i x e d B i n a r y
574 // -------------------------------------------------------
575 
576 dbFixedBinary::dbFixedBinary(long fieldWidth, const OOF_IndexOptions indexOptions) :
577  dbField(indexOptions),
578  mBodyLength(fieldWidth)
579 {}
580 
581 
582 dbFixedBinary::dbFixedBinary(long fieldWidth, const char *fieldName) :
583  dbField(fieldName),
584  mBodyLength(fieldWidth)
585 {}
586 
587 
588 dbFixedBinary::dbFixedBinary(long fieldWidth, const char *fieldName,
589  const OOF_IndexOptions indexOptions) :
590  dbField(fieldName, indexOptions),
591  mBodyLength(fieldWidth)
592 {}
593 
594 
595 dbField*
597 {
598  return new dbFixedBinary(*this);
599 }
600 
601 
604 {
605  return fixedBinaryField;
606 }
607 
608 
609 unsigned long
611 {
612  return mBodyLength;
613 }
614 
615 
621 {
622  if (this == &rhs) // MUST use this form to avoid invoking the operator== used for searches
623  return *this;
624  assert(!"not yet implemented since removing binaryContents()");
625 // BUG REPLACE THIS setValue(rhs.binaryContents());
626  return *this;
627 }
628 
629 
636 void
638 {
639  assert(!fieldIsStandalone());
640  const unsigned long lenToClear = mBodyLength;
641  for (unsigned long i=0; i<lenToClear; i++)
642  setByte(0, i);
643 #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
645 #endif
646  mTable->markDirty();
647 }
648 
649 
650 void
651 dbFixedBinary::setString(const char* str)
652 {
654 }
655 
656 
658 dbFixedBinary::operator=(const char* str)
659 {
660  if (!str)
661  clear();
662  else {
663  assert(strlen(str) <= mBodyLength);
664  setValue(str);
665  }
666  return *this;
667 }
668 
669 
673 void
674 dbFixedBinary::setValue(const void* inBuf)
675 {
676  assert(!fieldIsStandalone());
677  assert(mBackend);
678  mBackend->writeBytes((const char*)inBuf, mBodyLength, this);
679  mTable->markDirty();
680 }
681 
682 
683 void
684 dbFixedBinary::setByte(char c, unsigned long offset)
685 {
686  assert(!fieldIsStandalone());
687  assert(mBackend);
688  char* writeTo = mBackend->getByteWriteAddress(offset, this);
689  if (writeTo) {
690  *writeTo = c;
691 #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
693 #endif
694  }
695  else
696  ; // error NOT YET IMPLEMENTED
697  mTable->markDirty();
698 }
699 
700 
704 void
705 dbFixedBinary::extract(ostream& os) const
706 {
707  os << "yet to be implemented";
708 #if 0
709  const char *asChars = (char*)binaryContents();
710  os << hex;
711  for (unsigned int i=0; i<mBodyLength; i++)
712  os << asChars[i] << ' ';
713 #endif
714 }
715 
716 
717 
718 void
719 dbFixedBinary::generateTestData(bool generateRandom, unsigned long seedOrCount)
720 {
721  if (generateRandom) {
722  OOF_String theStr;
723  const unsigned long randLen = rand()%mBodyLength;
724  theStr.makeRandomChars(randLen);
725  dbFixedBinary::setString(theStr);
726  }
727  else {
728  OOF_CheckString theStr(seedOrCount, '-');
729  dbFixedBinary::setString(theStr);
730  }
731 }
732 
733 
734 void
735 dbFixedBinary::describe(ostream& os) const
736 {
737  dbField::describe(os);
738  os << " and a length of : " << mBodyLength << endl;
739 }
740 
741 
742 bool
744 {
746  return (mBodyLength == ((const dbFixedBinary*)rhs)->mBodyLength); // safe downcast
747  else
748  return false;
749 }
750 
751 
752 
753 // -------------------------------------------------------
754 // d b C h a r
755 // -------------------------------------------------------
756 dbChar::dbChar(unsigned long fieldWidth, const char* fieldName):
757  dbField(fieldName),
759  mMaxLength(fieldWidth)
760 {
761  CompleteInit();
762 }
763 
764 
765 dbChar::dbChar(unsigned long fieldWidth, const OOF_IndexOptions indexOptions) :
766  dbField(indexOptions),
768  mMaxLength(fieldWidth)
769 {
770  CompleteInit();
771 }
772 
773 
774 
775 dbChar::dbChar(unsigned long fieldWidth, const char* fieldName, const OOF_IndexOptions indexOptions) :
776  dbField(fieldName, indexOptions),
778  mMaxLength(fieldWidth)
779 {
780  CompleteInit();
781 }
782 
783 
784 dbChar::dbChar(const dbChar& rhs) :
785  dbField(rhs),
786  OOF_mixKeywordableField(rhs, this),
787  mMaxLength(rhs.mMaxLength)
788 {
789  CompleteInit();
790  if (fieldIsStandalone()) {
791  strcpy((char*) mBackend, (const char*) rhs.mBackend);
792  }
793 }
794 
795 
796 dbChar::dbChar(dbField::FieldIsStandaloneT k, unsigned long fieldWidth) :
797  dbField(k),
799  mMaxLength(fieldWidth)
800 {
801  CompleteInit();
802 }
803 
804 
805 void
806 dbChar::CompleteInit()
807 {
808  if (fieldIsStandalone()) {
809  mBackend = (OOF_tableBackend*) (new char[mMaxLength+1]);
810  ((char*)mBackend)[0] = '\0';
811  }
812 }
813 
814 
816 {
817  if (fieldIsStandalone())
818  delete[] (char*) mBackend;
819 }
820 
821 
822 dbField*
824 {
825  return new dbChar(*this);
826 }
827 
828 
829 dbChar&
830 dbChar::calculateWith(dbCharCalculator* adoptedCalculator, bool useOnlyForDefaults)
831 {
832  CalculateWith(adoptedCalculator, useOnlyForDefaults);
833  return *this;
834 }
835 
836 
837 void
838 dbChar::getChars(char* ioBuff, unsigned long& ioLen) const
839 {
840  const char* from = (const char*) *this;
841  unsigned long outLen = strlen(from);
842  if (ioLen < outLen)
843  outLen = ioLen;
844  else
845  ioLen = outLen;
846  memcpy(ioBuff, from, outLen);
847 }
848 
849 
850 oofString
852 {
853  return oofString( (const char*) *this);
854 }
855 
856 
857 void
859 {
860  if (srcField->fieldType()==charField)
861  *this = *(const dbChar*)srcField; // safe downcast
862 #ifdef OOF_DEBUG
863  else
864  dbConnect::raise(stringstream() << flush << "wrong field type passed in to dbChar::copyValueFrom, copying to " << fieldName() << " from " << srcField->fieldName());
865 #endif
866 }
867 
868 
869 void
871 {
872  if (srcField->fieldType()==charField) {
873  const char* rhs = *(const dbChar*)srcField; // safe downcast
874  if (strcmp(*this, rhs))
875  *this = rhs;
876  }
877 #ifdef OOF_DEBUG
878  else
879  dbConnect::raise(stringstream() << flush << "wrong field type passed in to dbChar::copyValueFrom, copying to " << fieldName() << " from " << srcField->fieldName());
880 #endif
881 }
882 
883 
886 {
887  return charField;
888 }
889 
890 
891 bool
893 {
894  return (mParser!=0);
895 }
896 
897 
898 bool
900 {
901  return false;
902 }
903 
904 
912 unsigned long
914 {
915  unsigned long ret = mMaxLength;
916  if (ret==0) // may happen with empty standalone oofChar
917  ret = 1;
918  return ret;
919 }
920 
921 
922 unsigned long
924 {
925  return mMaxLength;
926 }
927 
928 
929 unsigned short
931 {
932  return strlen(*this);
933 }
934 
935 
936 bool
938 {
939  return (length()==0);
940 }
941 
942 
943 const char*
945 {
946  return (const char*) *this;
947 }
948 
949 
952 {
953  return wordParser();
954 }
955 
956 
957 dbChar::operator const char*() const
958 {
959  const char* ret;
960  if (usingCalculator())
961  ret = calculator()->calc(this);
962  else {
963  if (fieldIsStandalone()) {
964  ret = (const char*) mBackend;
965  }
966  else {
967  assert(mBackend);
968  ret = mBackend->readChars(this);
969  if (!ret)
970  ret = "";
971  }
972  }
973  return ret;
974 }
975 
976 
977 #ifdef _Macintosh
978 void
979 dbChar::getStr255(Str255 s) const
980 {
981  const char* from = (const char*) *this;
982  s[0] = strlen(from);
983  memcpy(s+1, from, s[0]);
984 #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
986 #endif
987 }
988 
989 void
990 dbChar::setStr255(const Str255 s)
991 {
992  long charLen = s[0];
993  const char* strStart = (const char*) s+1;
994  setChars(strStart, charLen);
995 }
996 
997 
998 
999 // end of Mac-specific extra conversions
1000 #endif
1001 
1002 
1003 void
1005 {
1006  OOF_CheckString numberAsWords(n);
1007  dbChar::setString(numberAsWords);
1008 }
1009 
1010 
1014 dbChar&
1016 {
1017  if (this == &rhs) // MUST use this form to avoid invoking the operator== used for searches
1018  return *this;
1019 
1020  *this = (const char*)rhs;
1021  return *this;
1022 }
1023 
1024 
1025 dbChar&
1026 dbChar::operator=(const char* str)
1027 {
1028  if (!str)
1029  clear();
1030  else
1031  setChars(str, strlen(str));
1032  return *this;
1033 }
1034 
1035 
1036 dbChar&
1038 {
1039  char toStr[2];
1040  toStr[0] = ch;
1041  toStr[1] = '\0';
1042  setChars(toStr, 1);
1043  return *this;
1044 }
1045 
1046 
1047 void
1049 {
1050  char toStr[2];
1051  toStr[0] = ch;
1052  toStr[1] = '\0';
1053  dbChar::operator+=(toStr);
1054 }
1055 
1056 
1060 void
1061 dbChar::operator+=(const char* inStr)
1062 {
1063  unsigned long appendLen = (inStr==0) ? 0 : strlen(inStr);
1064  if (appendLen==0)
1065  return;
1066 
1067  if (usingCalculator()) // unlikely but worth checking
1068  return;
1069 
1070  const unsigned long currLen = length();
1071  assert(currLen <= mMaxLength);
1072 
1073  if (currLen == 0) {
1074  *this = inStr; // becomes assignment
1075  return;
1076  }
1077 
1078  unsigned long totalLen = currLen + appendLen;
1079  if (totalLen > mMaxLength) {
1080  dbConnect::raise((stringstream() << flush
1081  << "attempt to append string of " << totalLen << " to dbChar of only " << mMaxLength << " chars:\n"
1082  << inStr)
1083  , false
1084  );
1085  totalLen = mMaxLength; // bloody-minded truncation
1086  appendLen = totalLen - currLen;
1087  }
1088  // assignment was previously an else condition! now assigns truncated portion
1089  {
1090  if (fieldIsStandalone()) {
1091  char* oldStore = (char*) mBackend;;
1092  char* writeTo = new char[totalLen+1]; // include extra char for terminating null
1093  memcpy(writeTo, oldStore, currLen);
1094  delete[] oldStore;
1095  mBackend = (OOF_tableBackend*) writeTo;
1096  // append to local store
1097  memcpy(writeTo+currLen, inStr, appendLen);
1098  #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
1100  #endif
1101  writeTo[totalLen]='\0';
1102  }
1103  else { // not standalone
1104  assert(mBackend);
1105  const long appendAtIndex = currLen-1;
1106  assert(appendAtIndex>0); // check above for currLen==0 should prevent this case
1107  mBackend->writeChars(inStr, appendLen, mMaxLength, this, appendAtIndex);
1108  }
1109  }
1110 }
1111 
1112 
1113 void
1114 dbChar::setString(const char* str)
1115 {
1116  dbChar::operator=(str);
1117 }
1118 
1119 
1120 void
1122 {
1123  setChars(0,0);
1124 }
1125 
1126 
1135 void
1136 dbChar::setChars(const char* str , unsigned long charLen)
1137 {
1138  if (charLen > mMaxLength) {
1139 #ifdef OOF_DEBUG
1140  dbConnect::raise((stringstream() << flush
1141  << "attempt to assign string of " << charLen << " to dbChar of only " << mMaxLength << " chars:\n"
1142  << str)
1143  , false
1144  );
1145 #endif
1146  charLen = mMaxLength; // bloody-minded truncation
1147  }
1148  // assignment was previously an else condition! now assigns truncated portion
1149  {
1150  char *writeTo = 0;
1151  if (fieldIsStandalone()) {
1152  delete[] (char*) mBackend;
1153  writeTo = new char[charLen+1];
1154  mBackend = (OOF_tableBackend*) writeTo;
1155  if (writeTo) {
1156  if (str && charLen>0)
1157  memcpy(writeTo, str, charLen);
1158  #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
1160  #endif
1161  writeTo[charLen]='\0';
1162  }
1163  }
1164  else {
1165  assert(mBackend);
1166  mBackend->writeChars(str, charLen, mMaxLength, this);
1167  }
1168  }
1169 }
1170 
1171 
1172 /*
1173 Andy quick hack to see if can live without this.
1174 char&
1175 dbChar::operator[](unsigned short charIndex)
1176 {
1177  char *writeTo = 0;
1178  if (fieldIsStandalone()) {
1179  writeTo = (char*) mBackend;
1180  }
1181  else {
1182  writeTo = (char*)mBackend->getFieldWriteDest(this);
1183  }
1184  return writeTo[charIndex];
1185 }
1186 */
1187 
1188 void
1189 dbChar::extract(ostream& os) const
1190 {
1191  os << (const char*)*this;
1192 }
1193 
1194 
1198 bool
1199 dbChar::insert(istream& is, char fieldSep, char recSep)
1200 {
1201 // this is NOT very efficient, but it *is* safe
1202  if (!is.good())
1203  return false;
1204 
1205  const unsigned long maxLen = fieldStorageLen();
1206  assert(maxLen); // brief flash of paranoia in case they get this far with a field of 0 len
1207  char* buildBuf = new char[maxLen+1];
1208  assert(buildBuf);
1209  unsigned int charsRead = 0;
1210  bool hitEndOfField = false;
1211  while (is.good() && (charsRead<=maxLen)) { // allow read one char past, in case it's terminator
1212  char c = is.peek();
1213  if ((c==fieldSep) || (c==recSep)) {
1214  hitEndOfField = true;
1215  break; // OK - hit a separator
1216  }
1217  is >> c;
1218  if ( (c>=' ') && (charsRead<maxLen)) { // printable & in field length
1219  buildBuf[charsRead] = c;
1220  charsRead++;
1221  }
1222  } // loop reading char at a time
1223 
1224  bool gotDataOK = false;
1225  if (hitEndOfField) // everybody happy
1226  gotDataOK = true;
1227  else { // some form of problems along the way
1228  if (charsRead>maxLen) {// too wide for DB field, store as short anyway
1229  gotDataOK = true;
1230  dbField::insert(is, fieldSep, recSep); // consume the remainder
1231 #ifdef OOF_DEBUG
1232  dbConnect::raise(stringstream() << flush << "dbChar::insert() of field "
1233  << tableName() << "." << fieldName()
1234  << " has filled its length of " << maxLen
1235  << " before reaching the end of the field"
1236  );
1237 #endif
1238  }
1239  }
1240 
1241  if (gotDataOK) {
1243  while ((charsRead > 0) && (buildBuf[charsRead-1] ==' '))
1244  --charsRead;
1245  }
1246  buildBuf[charsRead] = '\0'; // now make it into a C string!
1247  *this = buildBuf; // finally, assign to the record
1248  }
1249  delete[] buildBuf;
1250  return gotDataOK; // if general stream problem, let caller report it
1251 }
1252 
1253 
1254 void
1255 dbChar::generateTestData(bool generateRandom, unsigned long seedOrCount)
1256 {
1257 // nearly identical to dbText and dbFixedBinary
1258  if (generateRandom) {
1259  OOF_String theStr;
1260  const unsigned long randLen = rand()%mMaxLength;
1261  theStr.makeRandomChars(randLen);
1262  dbChar::setString(theStr);
1263  }
1264  else {
1265  OOF_CheckString theStr(seedOrCount, '-');
1266  dbChar::setString(theStr);
1267  }
1268 }
1269 
1270 
1272 dbChar::operator==(const char* str) const
1273 {
1275 }
1276 
1277 
1278 dbQueryClause*
1280 {
1281  dbQueryClause* ret = new dbQueryLiteralStr(value());
1282  return ret;
1283 }
1284 
1285 
1287 dbChar::startsWith(const char* str) const
1288 {
1290 }
1291 
1292 
1293 /*
1294 
1295 // DOESN'T WORK JUST CREATING STRING IN HERE WITH WILDCARDS
1296 // WILL NEED MORE COMPLEX OPTION
1297 
1298 dbQueryBinary
1299 dbChar::contains(const char* str) const
1300 {
1301  bool ret;
1302  char* strPlus;
1303  unsigned short len = strlen(str);
1304  if (len==0) {
1305  strPlus = new char[2];
1306  strPlus[0] = '*';
1307  strPlus[1] = '\0';
1308  }
1309  else {
1310  strPlus = new char[len+3];
1311  assert(strPlus);
1312  strPlus[0] = '*';
1313  memcpy(&strPlus[1], str, len);
1314  strPlus[len+1] = '*';
1315  strPlus[len+2] = '\0';
1316  }
1317  ret = dbQueryBinary(new dbQueryField(this), dbQueryClause::equals, new dbQueryLiteralStr(strPlus));
1318  delete[] strPlus;
1319  return ret;
1320 
1321 }
1322 */
1323 
1324 
1326 dbChar::between(const char* fromStr, const char* toStr) const
1327 {
1329  new dbQueryLiteralStr(fromStr), new dbQueryLiteralStr(toStr));
1330 }
1331 
1332 
1334 dbChar::outside(const char* fromStr, const char* toStr) const
1335 {
1337  new dbQueryLiteralStr(fromStr), new dbQueryLiteralStr(toStr));
1338 }
1339 
1340 
1342 dbChar::operator!=(const char* str) const
1343 {
1345 }
1346 
1347 
1348  dbQueryBinary
1349  dbChar::operator<(const char* str) const
1350 {
1352 }
1353 
1354 
1355  dbQueryBinary
1356  dbChar::operator<=(const char* str) const
1357 {
1359 }
1360 
1361 
1362  dbQueryBinary
1363  dbChar::operator>(const char* str) const
1364 {
1366 }
1367 
1368 
1369  dbQueryBinary
1370  dbChar::operator>=(const char* str) const
1371 {
1373 }
1374 
1375 
1376 void
1377 dbChar::describe(ostream& os) const
1378 {
1379  dbField::describe(os);
1380  os << " and a maximum length of : " << mMaxLength << endl;
1381 }
1382 
1383 
1384 bool
1386 {
1387  if (dbField::fieldIsSameTypeAs(rhs))
1388  return (mMaxLength == ((const dbChar*)rhs)->mMaxLength); // safe downcast
1389  else
1390  return false;
1391 }
1392 
1393 
1394 void
1396 {
1397  assert(mCalculator);
1398  *this = calculator()->calc(this);
1399 }
1400 
1401 
1402 // -------------------------------------------------------
1403 // d b C a l c u l a t o r
1404 // -------------------------------------------------------
1405 dbCalculator*
1406 dbCalculator::cloneOwned(dbField*) const // has default implementation as not necessary to override
1407 {
1408  return clone(); // calls the pure virtual
1409 }
1410 
1411 
1412 // -------------------------------------------------------
1413 // d b C h a r S t r i p p e r C a l c u l a t o r
1414 // -------------------------------------------------------
1416  mStripsField(&stripsField),
1417  mStripChar(toStrip)
1418 {}
1419 
1420 
1421 const char*
1423 {
1424  mStrippedStr = mStripsField->asChars();
1425  mStrippedStr.stripChar(mStripChar);
1426  return mStrippedStr;
1427 }
1428 
1429 
1430 dbCalculator*
1432 {
1433  return new dbCharStripperCalculator(*this);
1434 }
1435 
1436 
1437 dbCalculator*
1439 {
1440  dbTable* newOwnerTable = newOwner->fieldTable();
1441  dbField* newStripsField = newOwnerTable->field(mStripsField->fieldNumber());
1442  return new dbCharStripperCalculator(*(dbChar*)newStripsField, mStripChar);
1443 }
1444 
1445 
1446 
1447 // -------------------------------------------------------
1448 // d b T e x t
1449 // -------------------------------------------------------
1451  dbBLOB(opt),
1453 {
1454 // assert( opt == kNotIndexed); // more later
1455  mIsTextField = true; // override dbBLOB init
1456 }
1457 
1458 
1460  dbBLOB(k),
1462 {
1463  mIsTextField = true; // override dbBLOB init
1464 }
1465 
1466 
1467 dbText::dbText(const char* fieldName) :
1468  dbBLOB(fieldName),
1470 {
1471  mIsTextField = true; // override dbBLOB init
1472 }
1473 
1474 
1475 dbText::dbText(const char* fieldName, const OOF_IndexOptions opt) :
1476  dbBLOB(fieldName, opt),
1478 {
1479 //assert(opt == kNotIndexed);
1480  mIsTextField = true; // override dbBLOB init
1481 }
1482 
1483 
1484 dbText::dbText(const dbText& rhs) :
1485  dbBLOB(rhs),
1486  OOF_mixKeywordableField(rhs, this)
1487 {
1488  mIsTextField = true; // override dbBLOB init
1489 }
1490 
1491 
1492 dbField*
1494 {
1495  return new dbText(*this);
1496 }
1497 
1498 
1499 dbText&
1500 dbText::calculateWith(dbTextCalculator* adoptedCalculator, bool useOnlyForDefaults)
1501 {
1502  CalculateWith(adoptedCalculator, useOnlyForDefaults);
1503  return *this;
1504 }
1505 
1506 
1507 dbText::operator const char*() const
1508 {
1509  const char* ret;
1510  if (usingCalculator())
1511  ret = calculator()->calc(this);
1512  else {
1513  if (length())
1514  ret = (const char *)bodyAddress();
1515  else
1516  ret = "";
1517  }
1518  return ret;
1519 }
1520 
1521 
1522 const char*
1524 {
1525  return (const char*) *this;
1526 }
1527 
1528 
1529 oofWordParser*
1531 {
1532  return wordParser();
1533 }
1534 
1535 
1536 unsigned long
1538 {
1539  if (fieldIsStandalone()) {
1540  unsigned long ret = *((long*) mBackend);
1541  if (ret)
1542  ret -= 1; // deduct trailing null
1543  return ret;
1544  }
1545  else
1546  return fieldDataLen();
1547 }
1548 
1549 
1550 void
1551 dbText::getChars(char* ioBuff, unsigned long& outLen) const
1552 {
1553  const char* from = (const char*) *this;
1554  outLen = strlen(from);
1555  memcpy(ioBuff, from, outLen);
1556 }
1557 
1558 
1559 oofString
1561 {
1562  return oofString((const char*) *this);
1563 }
1564 
1565 
1566 void
1568 {
1569  if (srcField->fieldType()==textField)
1570  *this = *(dbText*)srcField; // safe downcast
1571 #ifdef OOF_DEBUG
1572  else
1573  dbConnect::raise(stringstream() << flush << "wrong field type passed in to dbText::copyValueFrom, copying to " << fieldName() << " from " << srcField->fieldName());
1574 #endif
1575 }
1576 
1577 
1578 void
1580 {
1581  if (srcField->fieldType()==textField) {
1582  const char* rhs = *(const dbText*)srcField; // safe downcast
1583  if (strcmp(*this, rhs))
1584  *this = rhs;
1585  }
1586 #ifdef OOF_DEBUG
1587  else
1588  dbConnect::raise(stringstream() << flush << "wrong field type passed in to dbText::copyValueFrom, copying to " << fieldName() << " from " << srcField->fieldName());
1589 #endif
1590 }
1591 
1592 
1595 {
1596  return textField;
1597 }
1598 
1599 
1602 {
1603  return charField;
1604 }
1605 
1606 
1607 bool
1609 {
1610  return (mParser!=0);
1611 }
1612 
1613 
1614 bool
1616 {
1617  return false;
1618 }
1619 
1620 
1621 unsigned long
1623 {
1624  unsigned long ret = 60; // NOT YET IMPLEMENTED - settable default
1625  return ret;
1626 }
1627 
1628 
1629 
1630 
1631 
1632 dbText&
1634 {
1635  if (this == &rhs) // MUST use this form to avoid invoking the operator== used for searches
1636  return *this;
1637 
1638  *this = (const char*)rhs;
1639  return *this;
1640 }
1641 
1642 
1643 dbText&
1645 {
1646  char toStr[2];
1647  toStr[0] = ch;
1648  toStr[1] = '\0';
1649  dbText::operator=(toStr);
1650  return *this;
1651 }
1652 
1653 
1654 dbText&
1655 dbText::operator=(const char* str)
1656 {
1657  unsigned long charLen;
1658  if (str)
1659  charLen = strlen(str);
1660  else
1661  charLen = 0;
1662  setChars(str, charLen);
1663  return *this;
1664 }
1665 
1666 
1667 void
1669 {
1670  OOF_CheckString numberAsWords(n);
1671  dbText::setString(numberAsWords);
1672 }
1673 
1674 
1675 void
1676 dbText::setString(const char* str)
1677 {
1678  dbText::operator=(str);
1679 }
1680 
1681 
1682 void
1683 dbText::setChars(const char* str , unsigned long charLen)
1684 {
1685  if (!fieldIsStandalone()) {
1687  mTable->markDirty();
1688  }
1689  mStorage->setChars(str, charLen);
1690 }
1691 
1692 
1693 void
1695 {
1696  setChars(0, 0);
1697 }
1698 
1699 
1700 void
1702 {
1703  char toStr[2];
1704  toStr[0] = ch;
1705  toStr[1] = '\0';
1706  dbText::operator+=(toStr);
1707 }
1708 
1709 
1710 void
1711 dbText::operator+=(const char* str)
1712 {
1713  unsigned long charLen = strlen(str);
1714  if (charLen==0)
1715  return;
1716 
1717  dbBLOB::append(str, charLen+1); // copy the null as well!
1718 } // operator+=
1719 
1720 
1721 void
1722 dbText::adoptString(oofString& adoptedString) const
1723 {
1724  const unsigned long inLen = adoptedString.length(); // BEFORE the orphan
1725  adoptBody(adoptedString.orphan(), inLen, inLen);
1726 }
1727 
1728 
1729 void
1730 dbText::append(const void* appendBody, unsigned long bodyLen, unsigned long usedLen)
1731 {
1732  if (usedLen==0 || bodyLen==0)
1733  return;
1734 
1735  if (usedLen>bodyLen)
1736  usedLen=bodyLen; // probably optional param
1737  else
1738  if (bodyLen==ULONG_MAX)
1739  usedLen = strlen((const char*)appendBody);
1740 
1741  dbBLOB::append(appendBody, usedLen+1); // copy the null as well!
1742 } // appendChars
1743 
1744 
1745 void
1746 dbText::generateTestData(bool generateRandom, unsigned long seedOrCount)
1747 {
1748  if (generateRandom) {
1749  OOF_String theStr;
1750  const unsigned long randLen = rand()%10240; // max of 10kb test data
1751  theStr.makeRandomChars(randLen);
1752  dbText::setString(theStr);
1753  }
1754  else {
1755  OOF_CheckString theStr(seedOrCount, '-');
1756  dbText::setString(theStr);
1757  }
1758 }
1759 
1760 
1761 void
1762 dbText::extract(ostream& os) const
1763 {
1764  os << (const char*)*this;
1765 }
1766 
1767 
1768 bool
1769 dbText::insert(istream& is, char fieldSep, char recSep)
1770 {
1771 // nearly straight copy of dbChar - we really need to do something to combine these fields!
1772 
1773 // this is NOT very efficient, but it *is* safe
1774  if (!is.good())
1775  return false;
1776 
1777 // this is not yet complete - it needs a cleaner way to handle large imports
1778  const unsigned long maxLen = 16000; // KEEP UNDER 64k to avoid Win3.1 bugs
1779  char* buildBuf = new char[maxLen+1];
1780  assert(buildBuf);
1781  unsigned int charsRead = 0;
1782  bool hitEndOfField = false;
1783  while (is.good() && (charsRead<=maxLen)) { // allow read one char past, in case it's terminator
1784  char c = is.peek();
1785  if ((c==fieldSep) || (c==recSep)) {
1786  hitEndOfField = true;
1787  break; // OK - hit a separator
1788  }
1789  is >> c;
1790  if ( (c>=' ') && (charsRead<maxLen)) { // printable & in field length
1791  buildBuf[charsRead] = c;
1792  charsRead++;
1793  }
1794  } // loop reading char at a time
1795 
1796  bool gotDataOK = false;
1797  if (hitEndOfField) // everybody happy
1798  gotDataOK = true;
1799  else { // some form of problems along the way
1800  if (charsRead>maxLen) {// too wide for DB field, store as short anyway
1801  gotDataOK = true;
1802  dbField::insert(is, fieldSep, recSep); // consume the remainder
1803 #ifdef OOF_DEBUG
1804  dbConnect::raise(stringstream() << flush << "dbText::insert() of field "
1805  << tableName() << "." << fieldName()
1806  << " has filled its length of " << maxLen
1807  << " before reaching the end of the field"
1808  );
1809 #endif
1810  }
1811  }
1812 
1813  if (gotDataOK) {
1815  while ((charsRead > 0) && (buildBuf[charsRead-1] ==' '))
1816  --charsRead;
1817  }
1818  buildBuf[charsRead] = '\0'; // now make it into a C string!
1819  *this = buildBuf; // finally, assign to the record
1820  }
1821  else
1822  *this = "";
1823  delete[] buildBuf;
1824  return gotDataOK; // if general stream problem, let caller report it
1825 }
1826 
1827 
1828 
1829 
1830 
1831 dbQueryClause*
1833 {
1834  dbQueryClause* ret = new dbQueryLiteralStr(value());
1835  return ret;
1836 }
1837 
1838 
1840 dbText::operator==(const char* str) const
1841 {
1843 }
1844 
1845 
1847 dbText::operator!=(const char* str) const
1848 {
1850 }
1851 
1852 
1854 dbText::operator<(const char* str) const
1855 {
1857 }
1858 
1859 
1861 dbText::operator<=(const char* str) const
1862 {
1864 }
1865 
1866 
1868 dbText::operator>(const char* str) const
1869 {
1871 }
1872 
1873 
1875 dbText::operator>=(const char* str) const
1876 {
1878 }
1879 
1880 
1881 void
1883 {
1884  assert(mCalculator);
1885  *this = calculator()->calc(this);
1886 }
1887 
1888 
1889 // -------------------------------------------------------
1890 // d b B L O B s t o r a g e
1891 // -------------------------------------------------------
1892 dbBLOBstorage::dbBLOBstorage(dbBLOB* owner) :
1893  mBody(0),
1894  mBodyLength(0),
1895  mDirty(false),
1896  mLoaded(false),
1897  mOwner(owner)
1898  {};
1899 
1900 dbBLOBstorage::~dbBLOBstorage()
1901 {
1902  delete[] mBody;
1903 };
1904 
1905 
1906 char*
1907 dbBLOBstorage::bodyAddress() const
1908 {
1909  return mBody;
1910 }
1911 
1912 
1913 bool
1914 dbBLOBstorage::isDirty() const
1915 {
1916  return mDirty;
1917 }
1918 
1919 void
1920 dbBLOBstorage::markDirty()
1921 {
1922  mDirty = true;
1923  mLoaded = true;
1924 }
1925 
1926 #ifdef OOF_DebugDumpBlobState
1927 void
1928  dbBLOBstorage::blobState(ostream& os) const
1929  {
1930 
1931  os << "dbBLOBstorage: "<< this << endl
1932  << " mBody: " << (char*) mBody << endl
1933  << "mDirty: ";
1934 
1935  if(mDirty)
1936  os << "True ";
1937  else
1938  os << "false ";
1939  os << endl
1940  << "mLoaded: ";
1941  if(mLoaded)
1942 
1943  os << "True ";
1944  else
1945  os << "false ";
1946  os << endl << endl;
1947 
1948 }
1949 #endif
1950 
1951 void
1952 dbBLOBstorage::reset()
1953 {
1954  mDirty = false;
1955  mLoaded = false;
1956 }
1957 
1958 
1959 char*
1960 dbBLOBstorage::orphanBody()
1961 {
1962 
1963  char* ret = mBody;
1964  reset();
1965  mBody = 0;
1966  mBodyLength = 0;
1967  return ret;
1968 }
1969 
1970 
1971 void
1972 dbBLOBstorage::adoptBody(char* body, unsigned long bodyLen)
1973 {
1974  delete[] mBody;
1975  mBody = body;
1976  mBodyLength = bodyLen;
1977  mLoaded = mDirty = true;
1978 }
1979 
1980 
1981 char*
1982 dbBLOBstorage::allocRoomFor(unsigned long len)
1983 {
1984  if (len > mBodyLength) {
1985  if (mLoaded) { // assume we must preserve the buffer
1986  char *newBody = new char[len];
1987  assert(newBody);
1988  if (mBody) {
1989  memcpy(newBody, mBody, mBodyLength);
1990  delete[] mBody;
1991  }
1992  mBody = newBody;
1993  }
1994  else {
1995  delete[] mBody;
1996  mBody = new char[len];
1997  assert(mBody);
1998  }
1999  mBodyLength = len;
2000  }
2001 #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
2003 #endif
2004  return mBody;
2005 }
2006 
2007 
2008 void
2009 dbBLOBstorage::setBytes(const char* buf , unsigned long bufLen)
2010 {
2011  if (buf && bufLen) {
2012  allocRoomFor(bufLen);
2013  memcpy(mBody, buf, bufLen);
2014 #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
2016 #endif
2017  }
2018  else
2019  bufLen = 0; // cope with obscure zero buf & non-zero length
2020  mOwner->SetLength(bufLen);
2021  mOwner->markDirty();
2022 }
2023 
2024 
2025 void
2026 dbBLOBstorage::setChars(const char* str, unsigned long charLen)
2027 {
2028  if (str && charLen) {
2029  allocRoomFor(charLen+1);
2030  memcpy(mBody, str, charLen);
2031 #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
2033 #endif
2034  ((char*)mBody)[charLen]='\0';
2035  mOwner->SetLength(charLen+1);
2036  }
2037  else {
2038  mOwner->SetLength(0); // allowed to have empty body without null terminator
2039  }
2040  mOwner->markDirty();
2041 }
2042 
2043 
2044 void
2045 dbBLOBstorage::convertLineEndings()
2046 {
2047  if (mBody && mBodyLength>0) {
2048  // knock 1 off our mBodyLength as that includes the null, assuming storing text
2049  unsigned long strLen = mBodyLength-1;
2050  assert(mBody[strLen]=='\0');
2051 
2052  char* newBody = oofString::lineEndingsCurrentPlatform(mBody, strLen);
2053  if (newBody && newBody!=mBody) { // conversion reallocated buffers
2054  delete[] mBody;
2055  mBody = newBody;
2056  }
2057  mBodyLength = strLen+1; // may get non-zero result without realloc, if shortened so reset based on returned strLen
2058  assert(mBody[strLen]=='\0');
2059  }
2060 }
2061 
2062 
2063 // -------------------------------------------------------
2064 // d b B L O B
2065 // -------------------------------------------------------
2066 dbBLOB::dbBLOB(const OOF_IndexOptions indexOptions) :
2067  dbField(indexOptions),
2068  mIsTextField(false)
2069 {
2070  mStorage = new dbBLOBstorage(this);
2071 }
2072 
2073 
2074 dbBLOB::dbBLOB(const char* fieldName) :
2075  dbField(fieldName),
2076  mIsTextField(false)
2077 {
2078  mStorage = new dbBLOBstorage(this);
2079 }
2080 
2081 
2082 dbBLOB::dbBLOB(const char* fieldName, const OOF_IndexOptions indexOptions) :
2083  dbField(fieldName, indexOptions),
2084  mIsTextField(false)
2085 {
2086  mStorage = new dbBLOBstorage(this);
2087 }
2088 
2089 
2090 dbBLOB::dbBLOB(const dbBLOB& rhs) :
2091  dbField(rhs),
2092  mIsTextField(rhs.mIsTextField)
2093 {
2094  mStorage = new dbBLOBstorage(this);
2095  if (fieldIsStandalone())
2096  mBackend = (OOF_tableBackend*) (new long(0));
2097 }
2098 
2099 
2101  dbField(k),
2102  mIsTextField(false)
2103 {
2104  mStorage = new dbBLOBstorage(this);
2105  mBackend = (OOF_tableBackend*) (new long(0));
2106 }
2107 
2108 
2110 {
2111  delete mStorage;
2112  if (fieldIsStandalone())
2113  delete (long*) mBackend;
2114 };
2115 
2116 
2117 dbField*
2119 {
2120  return new dbBLOB(*this);
2121 }
2122 
2123 
2126 {
2127  return blobField;
2128 }
2129 
2130 
2131 unsigned long
2133 {
2134  if (fieldIsStandalone())
2135  if (mStorage)
2136  return mStorage->mBodyLength;
2137  else
2138  return 0;
2139  else
2141 }
2142 
2143 
2144 unsigned long
2146 {
2147  if (fieldIsStandalone())
2148  return *((long*) mBackend);
2149  else
2150  return fieldDataLen();
2151 }
2152 
2153 
2154 bool
2156 {
2157  return (length()==0);
2158 }
2159 
2160 
2161 bool
2163 {
2164  return true;
2165 }
2166 
2167 
2168 void
2169 dbBLOB::SetLength(unsigned long len) const
2170 {
2171  if (fieldIsStandalone()) {
2172  long* lenP = (long*)mBackend;
2173  *lenP = len; // store long in mBackend
2174  }
2175  else{
2177  }
2178 }
2179 
2180 
2181 void
2182 dbBLOB::adoptBody(void* body, unsigned long bodyLen, unsigned long usedLen) const
2183 {
2184  mStorage->adoptBody((char*)body, bodyLen);
2185  SetLength(usedLen);
2186 }
2187 
2188 
2189 void
2190 dbBLOB::adoptBody(void* body, unsigned long bodyLen) const
2191 {
2192  adoptBody(body, bodyLen, bodyLen);
2193 }
2194 
2195 
2196 char*
2198 {
2199  if (!fieldIsStandalone()) {
2201  if (!loaded())
2202  LoadField();
2203  }
2204  return mStorage->bodyAddress();
2205 }
2206 
2207 
2208 void
2210 {
2211  append(rhs.bodyAddress(), rhs.length());
2212 }
2213 
2214 
2215 void
2216 dbBLOB::append(const void* appendBody, unsigned long bodyLen, unsigned long usedLen)
2217 {
2218  if (usedLen==0)
2219  return;
2220 
2221  if (usedLen>bodyLen)
2222  usedLen=bodyLen; // probably optional param
2223 
2224  if (!fieldIsStandalone()) {
2226  if (!loaded())
2227  LoadField();
2228  mTable->markDirty();
2229  }
2230  const unsigned long currentFldLen = length(); // virtual call, will skip null if dbText field
2231  const unsigned long newLen = currentFldLen+bodyLen;
2232  allocRoomFor(newLen); // content-preserving
2233  const unsigned long newUsedLen = currentFldLen+usedLen;
2234  SetLength(newUsedLen); // may be shorter than that set in allocRoomFor, if have slop already
2235  markDirty();
2236  char* const body = (char*)bodyAddress();
2237  char* const appendTo = body+currentFldLen;
2238  memcpy(appendTo, appendBody, bodyLen);
2239  #ifdef OOF_MEM_DEBUG_FORCE_POOL_CHECK
2241  #endif
2242 }
2243 
2244 
2245 void
2247 {
2248  assert(this != &rhs); // can't append ourself
2249  append(rhs);
2250 }
2251 
2252 
2253 dbBLOB&
2255 {
2256  if (this == &rhs) // MUST use this form to avoid invoking the operator== used for searches
2257  return *this;
2258 
2259  setBytes(rhs.bodyAddress(), rhs.length());
2260  return *this;
2261 }
2262 
2263 
2264 void
2266 {
2267  assert(!fieldIsStandalone());
2268  mBackend->loadBlob(this);
2269  mStorage->mLoaded = true;
2271  mStorage->convertLineEndings();
2272 }
2273 
2274 
2279 void
2280 dbBLOB::setBytes(const void* buf , unsigned long bufLen)
2281 {
2282  if (!fieldIsStandalone()) {
2284  mTable->markDirty();
2285  }
2286  mStorage->setBytes((const char*)buf, bufLen);
2287 }
2288 
2289 
2290 void
2291 dbBLOB::generateTestData(bool generateRandom, unsigned long seedOrCount)
2292 {
2293  if (generateRandom) {
2294  OOF_String theStr;
2295  const unsigned long randLen = rand()%10240; // max of 10kb test data
2296  theStr.makeRandomChars(randLen);
2297  setBytes(theStr, theStr.length());
2298  }
2299  else {
2300  OOF_CheckString theStr(seedOrCount, '-');
2301  setBytes(theStr, theStr.length());
2302  }
2303 }
2304 
2305 
2306 void
2307 dbBLOB::extract(ostream& os) const
2308 {
2309 // extract as hex dump
2310  unsigned long lenToDump = length();
2311 #if defined __MWERKS__ & __MWERKS__ >= 0x2301
2312  std::ios_base::fmtflags savedFlags = os.flags(ios::right | ios::hex);
2313 #else
2314  long savedFlags = os.flags(ios::right | ios::hex);
2315 #endif
2316 
2317  int savedFill = os.fill('0');
2318 // int savedWidth = os.width(2); not needed as widths not sticky
2319  char* body = (char*) bodyAddress();
2320  unsigned short numInRow=0;
2321  for (unsigned long i=0; i<lenToDump; i++) {
2322  if (numInRow==16) {
2323  os << endl;
2324  numInRow = 0;
2325  }
2326  else
2327  numInRow++;
2328  os.width(2); // for some stupid reason CW lacks stickywidth (is this dropped from Standard?)
2329  unsigned short asNum = (unsigned char)body[i];
2330  os << asNum << ' ';
2331  }
2332  os.flags(savedFlags);
2333  os.fill(savedFill);
2334 // os.width(savedWidth); not needed as widths not sticky
2335  os << endl;
2336 }
2337 
2338 #ifdef OOF_DebugDumpBlobState
2339 void
2340 dbBLOB::blobState(ostream &os)
2341  {
2342  mStorage->blobState(os);
2343  }
2344 #endif
2345 
2346 // -------------------------------------------------------
2347 // d b C o m p o u n d F i e l d
2348 // -------------------------------------------------------
2349 
2351  dbField(indexOptions),
2352  mTotalLength(0)
2353 {}
2354 
2355 
2356 dbCompoundField::dbCompoundField(const char* fieldName) :
2357  dbField(fieldName),
2358  mTotalLength(0)
2359 {}
2360 
2361 
2362 dbCompoundField::dbCompoundField(const char* fieldName, const OOF_IndexOptions indexOptions) :
2363  dbField(fieldName, indexOptions),
2364  mTotalLength(0)
2365 {}
2366 
2367 
2369  dbField(rhs),
2370  OOF_FieldSegOwner(rhs),
2371  mTotalLength(rhs.mTotalLength)
2372 {}
2373 
2374 
2375 dbField*
2377 {
2378  return new dbCompoundField(*this);
2379 }
2380 
2381 
2384 {
2385  return compoundField;
2386 }
2387 
2388 
2389 unsigned long
2391 {
2392  return mTotalLength;
2393 }
2394 
2395 
2396 bool
2398 {
2399  return true;
2400 }
2401 
2402 
2403 void
2405 {
2406  assert(segField.fieldType() != textField);
2408  mTotalLength += segField.fieldStorageLen();
2409 }
2410 
2411 
2412 const dbField*
2413 dbCompoundField::field(unsigned int n) const
2414 {
2416  return theField;
2417 }
2418 
2419 
2421 dbCompoundField::operator==(const char* str) const
2422 {
2424 }
2425 
2426 
2428 dbCompoundField::operator!=(const char* str) const
2429 {
2431 }
2432 
2433 
2435 dbCompoundField::operator<(const char* str) const
2436 {
2438 }
2439 
2440 
2442 dbCompoundField::operator<=(const char* str) const
2443 {
2445 }
2446 
2447 
2449 dbCompoundField::operator>(const char* str) const
2450 {
2452 }
2453 
2454 
2456 dbCompoundField::operator>=(const char* str) const
2457 {
2459 }
2460 
2461 
2463 dbCompoundField::startsWith(const char* str) const
2464 {
2466 }
2467 
2468 
2469 void
2470 dbCompoundField::extract(ostream& os) const
2471 {
2472  const unsigned int numSegments = countSegments();
2473  for (unsigned int i=0; i<numSegments; i++) {
2474  const dbField* fld = field(i);
2475  fld->extract(os);
2476  }
2477 }
2478 
2479 
2480 bool
2482 {
2483  if (dbField::fieldIsSameTypeAs(rhs))
2484  return (mTotalLength == ((const dbCompoundField*)rhs)->mTotalLength); // safe downcast
2485  else
2486  return false;
2487 }
2488 
2489 
2490 // -------------------------------------------------------
2491 // O O F I L E _ f i e l d T y p e s
2492 // -------------------------------------------------------
2493 ostream&
2494 operator<<(ostream& os, OOF_fieldTypes ft)
2495 {
2496  switch (ft) {
2497  case (charField) :
2498  os << "fixed-length chars";
2499  break;
2500 
2501  case (textField) :
2502  os << "variable-length text";
2503  break;
2504 
2505  case (dateField) :
2506  os << "date";
2507  break;
2508 
2509  case (dateTimeField) :
2510  os << "date time";
2511  break;
2512 
2513  case (timeField) :
2514  os << "time";
2515  break;
2516 
2517  case (shortField) :
2518  os << "short integer";
2519  break;
2520 
2521  case (uShortField) :
2522  os << "unsigned short integer";
2523  break;
2524 
2525  case (longField) :
2526  os << "long integer";
2527  break;
2528 
2529  case (uLongField) :
2530  os << "unsigned long integer";
2531  break;
2532 
2533  case (realField) :
2534  os << "real";
2535  break;
2536 
2537  case (blobField) :
2538  os << "binary blob";
2539  break;
2540 
2541  case (compoundField) :
2542  os << "compound";
2543  break;
2544 
2545  case (fixedBinaryField) :
2546  os << "fixedBinary";
2547  break;
2548 
2549  case (boolField) :
2550  os << "bool";
2551  break;
2552 
2553  case (relationshipField) :
2554  os << "relationship traversal pointer";
2555  break;
2556 
2557  }
2558  return os;
2559 }
2560 
2561 
2562 
2563 // -------------------------------------------------------
2564 // d b F i e l d C o p i e r
2565 // -------------------------------------------------------
2566 dbFieldCopier::dbFieldCopier(oofBroadcaster* listensTo, unsigned short copyOnMessage, dbField* copyFrom, dbField* copyTo) :
2567  oofSingleListener(listensTo),
2568  mCopyFrom(copyFrom),
2569  mCopyTo(copyTo),
2570  mCopyOnMessage(copyOnMessage)
2571 {}
2572 
2573 
2575 {
2576  mCopyFrom=0; // for Lint
2577  mCopyTo=0;
2578 }
2579 
2580 bool
2581 dbFieldCopier::receiveMsg(OOFmsgT msg, unsigned long senderDefined)
2582 {
2583  if (msg==mCopyOnMessage)
2585  else
2586  oofSingleListener::receiveMsg(msg, senderDefined);
2587  return true;
2588 }
2589 
2590 
2591 // -------------------------------------------------------
2592 // dbCloneCleanup
2593 // -------------------------------------------------------
2595  oofSingleListener(listensTo),
2596  mTable(listensTo)
2597 {}
2598 
2599 
2601 {
2602  // clear ref pointers for lint
2603  mTable = 0;
2604 }
2605 
2606 
2607 bool
2608 dbCloneCleanup::receiveMsg(OOFmsgT msg, unsigned long /* senderDefined */)
2609 {
2610  if (msg!=OOFmsg_BroadcasterClosing)
2611  mTable->postCloneTableCleanup();
2612  delete this;
2613  return true;
2614 }
2615 
2616 
2617 // -------------------------------------------------------
2618 // O O F _ S e g m e n t
2619 // -------------------------------------------------------
2620 
2621 OOF_Segment::OOF_Segment(const dbField& fld) :
2622  mFieldNo(fld.fieldNumber()),
2623  mReversed(false)
2624 {}
2625 
2626 
2627 OOF_Segment::OOF_Segment(const dbField* fld) :
2628  mFieldNo(fld->fieldNumber()),
2629  mReversed(false)
2630 {}
2631 
2632 
dbQueryBinary startsWith(const char *str) const
Definition: oof3.cpp:2463
dbQueryBinary operator>=(const char *) const
Definition: oof3.cpp:1370
virtual unsigned long fieldStorageLen() const
Definition: oof3.cpp:610
dbCompoundField(const OOF_IndexOptions)
Definition: oof3.cpp:2350
bool mIsTextField
Definition: oof3.h:432
Mixin for classes allowing you to declare segments based on fields.
Definition: oof1.h:1247
static bool convertsLineEndingsOnLoad()
Definition: oof3.h:918
virtual OOF_fieldTypes fieldType() const
Definition: oof3.cpp:2125
virtual void copyValueFrom(const dbField *)
Definition: oof3.cpp:858
virtual unsigned long fieldUsualWrapWidth() const
Definition: oof3.cpp:1622
virtual unsigned long fieldStorageLen() const
Definition: oof3.cpp:2132
virtual bool receiveMsg(OOFmsgT msg, unsigned long senderDefined)
The default receiveMsg behaviour is to delete yourself when the broadcaster closes.
Definition: oof3.cpp:2608
Definition: oof3.h:26
unsigned long mBodyLength
Definition: oof3.h:562
virtual dbCalculator * clone() const =0
dbText(const OOF_IndexOptions)
Definition: oof3.cpp:1450
virtual void clear()
Definition: oof3.cpp:1694
dbText & calculateWith(dbTextCalculator *adoptedCalculator, bool useOnlyForDefaults=false)
Definition: oof3.cpp:1500
bool valueIsDuplicate() const
Definition: oof3.cpp:291
static void raise(std::ostream &, bool terminateAfterMsg=true)
const char * tableName() const
Definition: oof3.cpp:202
bool usingCalculator() const
Definition: oof3.cpp:258
Persistent field used to store a fixed-length binary object.
Definition: oof3.h:532
virtual char * getByteWriteAddress(unsigned long, const dbField *)=0
fieldNumT fieldNumber() const
Definition: oof3.h:754
virtual const oofString & fieldName() const
Definition: oof3.h:769
precompilation header.
tableNumT tableNumber() const
Definition: oof1.h:2376
dbCharCalculator * calculator() const
Definition: oof3.h:846
dbBLOB * mOwner
Definition: oof3.h:376
virtual void copyValueFrom(const dbField *)
Definition: oof3.h:140
Definition: oof3.h:26
dbField * equivalentFieldFromTable(dbTable *) const
Definition: oof3.cpp:352
Tries to hide the different platforms and version issues with standard IO.
Base class for user-replaceable word parser.
Definition: oofwords.h:40
virtual void generateTestData(bool generateRandom, unsigned long seedOrCount)
Definition: oof3.cpp:719
virtual bool fieldIsUniqueIndexed() const
Definition: oof3.cpp:422
void setChars(const char *str, unsigned long charLen)
Definition: oof3.cpp:1683
void operator+=(const dbBLOB &)
Definition: oof3.cpp:2246
Calculator attached to a dbChar.
Definition: oof3.h:222
virtual void generateTestData(bool generateRandom, unsigned long seedOrCount)
Definition: oof3.cpp:1255
virtual void setString(const char *)
Definition: oof3.cpp:651
static bool willTruncateTrailingSpaces()
Definition: oof1.h:1667
virtual unsigned short countSegments() const
Definition: oof1.h:2577
unsigned long fieldDataLen() const
Definition: oof3.h:761
Highest level used to assemble queries.
Definition: oofquery.h:46
dbQueryBinary operator<(const char *) const
Definition: oof3.cpp:1349
virtual void copyValueIfDifferent(const dbField *)
Definition: oof3.cpp:870
const char * value() const
Definition: oof3.h:839
const char * value() const
Definition: oof3.h:932
unsigned short length() const
Definition: oof3.cpp:930
virtual void generateTestData(bool generateRandom, unsigned long seedOrCount)
Definition: oof3.cpp:1746
dbRelRefBase * inverse() const
Definition: oofrel.h:242
fieldNumT fieldNumberOfSegment(unsigned int) const
Definition: oof1.cpp:2854
virtual unsigned long fieldUsualWrapWidth() const
Returns fixed width of the field.
Definition: oof3.cpp:913
char * mBody
Definition: oof3.h:373
const dbField * field(unsigned int) const
Definition: oof3.cpp:2413
virtual bool fieldIsIndexed() const
Definition: oof3.cpp:408
bool fieldIsStandalone() const
Definition: oof3.h:733
virtual const char * calc(const dbText *)=0
virtual bool isEmpty() const
Definition: oof3.cpp:170
virtual void extract(std::ostream &os) const
Definition: oof3.cpp:1762
unsigned long stripChar(char, unsigned long startAt=0)
Definition: oofstr.cpp:1892
virtual unsigned long fieldStorageLen() const
Definition: oof3.cpp:2390
virtual bool insert(std::istream &, char fieldSep, char recSep)
Implement operator>> reading from stream into dbChar.
Definition: oof3.cpp:1199
dbTable * relatedTable()
Definition: oofrel.cpp:1074
unsigned short fieldKeyLen() const
Definition: oof3.cpp:430
dbQueryBinary operator==(const char *) const
Definition: oof3.cpp:2421
virtual void generateTestData(bool generateRandom, unsigned long seedOrCount)
Definition: oof3.cpp:2291
OOF_tableBackend * mBackend
Definition: oof3.h:155
virtual void extract(std::ostream &os) const
Definition: oof3.cpp:2307
virtual OOF_fieldTypes nativeType() const
Definition: oof3.cpp:1601
void append(const dbBLOB &)
Definition: oof3.cpp:2209
char * orphan(bool neverReturnNil=true)
Give away our internal buffer, clearing our length and pointer.
Definition: oofstr.cpp:2339
bool loaded() const
Definition: oof3.h:871
virtual bool receiveMsg(OOFmsgT msg, unsigned long senderDefined)
The default receiveMsg behaviour is to delete yourself when the broadcaster closes.
Definition: oof3.cpp:2581
char * allocRoomFor(unsigned long) const
Definition: oof3.h:885
virtual unsigned long fieldStorageLen() const =0
Definition: oof3.h:26
virtual dbField * clone() const
Definition: oof3.cpp:1493
virtual void copyValueIfDifferent(const dbField *)
Definition: oof3.cpp:1579
virtual OOF_fieldTypes fieldType() const
Definition: oof3.cpp:885
virtual void addSegment(dbField &)
Definition: oof3.cpp:2404
Special limited oofReceiver which will only ever listen to one oofBroadcaster at a time...
Definition: oofmsg.h:133
virtual bool receiveMsg(OOFmsgT msg, unsigned long senderDefined)
The default receiveMsg behaviour is to delete yourself when the broadcaster closes.
Definition: oofmsg.cpp:275
virtual void clear()
Definition: oof3.cpp:1121
void index(const OOF_IndexOptions=kIndexed)
Definition: oof3.cpp:212
dbQueryBinary operator==(const char *) const
Definition: oof3.cpp:1272
virtual dbField * clone() const
Definition: oof3.cpp:596
virtual dbField * clone() const
Definition: oof3.cpp:823
dbQueryBinary operator<(const char *) const
Definition: oof3.cpp:2435
Common trinary query for field, eg: People.Salary.between(50000, 90000); Very similar to dbQueryBinar...
Definition: oofquery.h:263
static dbTable * sCurrentlyConstructing
Definition: oof1.h:816
dbQueryBinary operator>=(const char *) const
Definition: oof3.cpp:1875
void setName(const char *name)
Definition: oof3.cpp:195
virtual oofWordParser * words() const
Definition: oof3.cpp:951
bool mDirty
Definition: oof3.h:375
virtual bool fieldIsSameTypeAs(const dbField *) const
Definition: oof3.cpp:743
dbQueryTrinary outside(const char *, const char *) const
Definition: oof3.cpp:1334
fieldNumT mFieldNumber
Definition: oof3.h:157
void setChars(const char *str, unsigned long charLen)
Copy string up to the specified length or maximum size of this fixed length string.
Definition: oof3.cpp:1136
void postCloneTableCleanup()
Definition: oof1.cpp:1454
dbQueryBinary operator!=(const char *) const
Definition: oof3.cpp:2428
oofWordParser * wordParser() const
Definition: oofwords.cpp:595
const OOFmsgT OOFmsg_BroadcasterClosing
Definition: oofmsg.h:40
virtual OOF_fieldTypes nativeType() const
Definition: oof3.cpp:301
Mixin class for fields that are keyword-indexed.
Definition: oof3.h:186
dbQueryBinary operator<=(const char *) const
Definition: oof3.cpp:2442
virtual OOF_fieldTypes fieldType() const
Definition: oof3.cpp:2383
virtual void getChars(char *ioBuff, unsigned long &ioLen) const
Definition: oof3.cpp:838
virtual const char * calc(const dbChar *)=0
virtual dbCalculator * cloneOwned(dbField *) const
Definition: oof3.cpp:1438
void adoptBody(void *body, unsigned long bodyLen) const
Definition: oof3.cpp:2190
virtual void setNumber(long)
Definition: oof3.cpp:1004
dbQueryBinary operator>(const char *) const
Definition: oof3.cpp:1363
Exception for database field operations with descriptive error numbers.
Definition: oofexcep.h:218
void saveStoredCalculatedValue()
Definition: oof3.cpp:282
virtual oofString copyString() const
Definition: oof3.cpp:1560
Common binary query for field, eg: People.Salary > 90000.
Definition: oofquery.h:165
void saveDefaultCalculatedValue()
Definition: oof3.cpp:272
virtual bool isEmpty() const
Definition: oof3.cpp:2155
virtual bool fieldIsKeywordIndexed() const
Definition: oof3.cpp:415
virtual bool fieldIsSameTypeAs(const dbField *) const
Definition: oof3.cpp:1385
dbCalculator * mCalculator
Definition: oof3.h:158
Calculator attached to a dbText field.
Definition: oof3.h:443
virtual dbField * clone() const
Definition: oof3.cpp:2376
virtual void writeChars(const char *, long numChars, long maxLen, const dbField *, long startIndex=0)=0
void fieldHasDefaultCalculator(dbField *)
Definition: oof1.h:1740
void setBytes(const void *buf, unsigned long bufLen)
Copy the incoming buffer into our local buffer in mStorage.
Definition: oof3.cpp:2280
Parent for any field that is a relationship to another table.
Definition: oofrel.h:19
Definition: oof3.h:26
strings for named numbers eg check (cheque) printing, eg: "one two zero"
Definition: oofstr.h:310
LHS argument to queries on fields.
Definition: oofquery.h:572
void makeRandomChars(unsigned long numChars)
Generate string of len numChars with random content, replacing existing contents. ...
Definition: oofstr.cpp:1922
virtual unsigned long blobPointerReferenceSize() const =0
virtual void CopyCalculatedValueToBuffer()
Definition: oof3.cpp:1882
virtual void describe(std::ostream &) const
Provide human-readable information about object.
Definition: oof3.cpp:1377
dbCharStripperCalculator(dbChar &stripsField, char toStrip= ' ')
Definition: oof3.cpp:1415
void SetLength(unsigned long len) const
Definition: oof3.cpp:2169
virtual bool fieldIsBinary() const
Definition: oof3.cpp:899
void adoptString(oofString &adoptedString) const
Definition: oof3.cpp:1722
virtual ~dbField()
Definition: oof3.cpp:149
unsigned short tableNumT
Definition: oof1.h:275
virtual const char * asChars() const
Definition: oof3.cpp:944
virtual void setBlobLength(fieldNumT, unsigned long len)=0
virtual void writeBytes(const char *inBuf, long inLen, const dbField *inField)=0
virtual void addSegment(dbField &)
Definition: oof1.cpp:2861
virtual unsigned long length() const
Definition: oof3.cpp:1537
Definition: oof3.h:26
virtual OOF_fieldTypes fieldType() const
Definition: oof3.cpp:1594
dbRelRefBase * controllingRelationship() const
Definition: oof1.h:1816
dbChar(unsigned long fieldWidth=80, const char *fieldName=0)
Definition: oof3.cpp:756
void joinField(dbField &)
Definition: oofrel.cpp:415
bool isEmpty() const
Test based on either length or null pointer.
Definition: oofstr.h:413
void operator+=(char)
Definition: oof3.cpp:1701
unsigned long length() const
Primary test: oofStringTest::emptyStringByNullInitIsLenZero()
Definition: oofstr.h:447
virtual unsigned long length() const
Definition: oof3.cpp:2145
virtual ~dbChar()
Definition: oof3.cpp:815
Abstract interface to database backend.
Definition: oof1.h:1047
dbTable * mTable
Definition: oof3.h:156
Base class for a calculator attached to a dbField.
Definition: oof3.h:46
virtual void setNumber(long)
Definition: oof3.cpp:1668
virtual bool fieldIsSameTypeAs(const dbField *) const
Definition: oof3.cpp:557
bool mLoaded
Definition: oof3.h:375
void setStr255(const Str255 s)
Definition: oof3.cpp:990
virtual bool validateContents()
Definition: oof3.cpp:177
virtual bool fieldIsKeywordIndexed() const
Definition: oof3.cpp:1608
dbBLOBstorage * mStorage
Definition: oof3.h:431
virtual void getChars(char *ioBuff, unsigned long &outLen) const
Definition: oof3.cpp:481
virtual dbQueryClause * valueAsQueryLiteral() const
Definition: oof3.cpp:184
istream & operator>>(istream &is, dbField *fld)
Definition: oof3.cpp:528
virtual unsigned long fieldStorageLen() const
Definition: oof3.cpp:923
Temporary cache field used to store dbBlob contents.
Definition: oof3.h:347
virtual bool fieldIsBinary() const
Definition: oof3.cpp:393
void operator+=(char)
Definition: oof3.cpp:1048
oofWordParser * mParser
Definition: oof3.h:214
dbBLOB & operator=(const dbBLOB &)
Definition: oof3.cpp:2254
virtual void copyValueFrom(const dbField *)
Definition: oof3.cpp:1567
const oofString & tableName() const
Definition: oof1.h:2369
Persistent field used to store a fixed-length string.
Definition: oof3.h:255
virtual void CopyCalculatedValueToBuffer()
Definition: oof3.cpp:163
virtual oofString copyString() const
Definition: oof3.cpp:851
virtual void extract(std::ostream &os) const
Definition: oof3.cpp:2470
dbBLOB(const OOF_IndexOptions indexOptions)
Definition: oof3.cpp:2066
Base class used to refer to main OOFILE classes and provide base reflective API.
Definition: oof1.h:49
OOF_fieldTypes
Definition: oof3.h:26
virtual const char * asChars() const
Definition: oof3.cpp:1523
virtual void describe(std::ostream &) const
Provide human-readable information about object.
Definition: oof3.cpp:544
virtual bool fieldIsBinary() const
Definition: oof3.cpp:1615
virtual bool fieldIsKeywordIndexed() const
Definition: oof3.cpp:892
dbText & operator=(char)
Definition: oof3.cpp:1644
dbField(const OOF_IndexOptions)
Definition: oof3.cpp:53
virtual oofString name() const
Definition: oof3.cpp:156
#define RAISE_EXCEPTION(E)
Macro to allow us to either throw an exception or call dbConnect::raise.
Definition: oofexcep.h:31
dbField * field(fieldNumT) const
Definition: oof1.h:2355
Persistent field used to store a set of segments referring to other fields.
Definition: oof3.h:575
Declare query classes.
unsigned short fieldNumT
Definition: oof1.h:276
virtual void extract(std::ostream &os) const
Definition: oof3.cpp:1189
Base class for persistent tables.
Definition: oof1.h:452
virtual void extract(std::ostream &) const
Definition: oof3.cpp:506
dbFixedBinary & operator=(const dbFixedBinary &rhs)
Definition: oof3.cpp:620
Definition: oof3.h:26
virtual void append(const void *appendBody, unsigned long bodyLen=ULONG_MAX, unsigned long usedLen=ULONG_MAX)
Definition: oof3.cpp:1730
dbTable * fieldTable() const
Definition: oof3.cpp:308
virtual bool insert(std::istream &, char fieldSep, char recSep)
Definition: oof3.cpp:513
Definition: oof3.h:26
Portable highly capable string class.
Definition: oofstr.h:101
dbQueryBinary operator==(const char *) const
Definition: oof3.cpp:1840
Definition: oof3.h:26
virtual void loadBlob(const dbBLOB *)=0
virtual bool isEmpty() const
Definition: oof3.cpp:937
virtual unsigned long fieldUsualWrapWidth() const
Definition: oof3.cpp:235
bool lineEndingsCurrentPlatform()
Definition: oofstr.h:482
void markDirty() const
Definition: oof3.h:864
dbQueryBinary operator>(const char *) const
Definition: oof3.cpp:2449
virtual bool fieldIsVirtual() const
Definition: oof3.cpp:2397
bool isDirty() const
Definition: oof3.cpp:564
virtual bool fieldIsDirty(fieldNumT) const =0
virtual void setString(const char *)
Definition: oof3.cpp:1114
virtual dbField * clone() const =0
dbQueryBinary operator<=(const char *) const
Definition: oof3.cpp:1356
void useCalculatorOnlyForDefaults()
Definition: oof3.h:799
virtual bool fieldIsVirtual() const
Definition: oof3.cpp:400
virtual void describe(std::ostream &os) const
Provide human-readable information about object.
Definition: oof3.cpp:735
virtual oofWordParser * words() const
Definition: oof3.cpp:1530
#define OOF_MEM_DEBUG_FORCE_POOL_CHECK
Definition: doxyoof.h:408
bool fieldIsJoinKey() const
Checks if any relationships in field's table use field as join key.
Definition: oof3.cpp:327
dbTextCalculator * calculator() const
Definition: oof3.h:939
virtual void CopyCalculatedValueToBuffer()
Definition: oof3.cpp:1395
Generic broadcaster for messaging.
Definition: oofmsg.h:76
virtual bool insert(std::istream &, char fieldSep, char recSep)
Definition: oof3.cpp:1769
void CalculateWith(dbCalculator *adoptedCalculator, bool useOnlyForDefaults)
Definition: oof3.cpp:444
Persistent field used to store a variable length string.
Definition: oof3.h:459
OOF_IndexOptions
type used to specify index options for dbField's.
Definition: oof1.h:236
virtual dbCalculator * clone() const
Definition: oof3.cpp:1431
static bool sConvertsLineEndingsOnLoad
Definition: oof3.h:524
virtual bool fieldIsSameTypeAs(const dbField *) const
Definition: oof3.cpp:2481
RHS String argument to queries on fields like dbChar.
Definition: oofquery.h:324
dbQueryBinary operator>=(const char *) const
Definition: oof3.cpp:2456
dbChar & operator=(const char *)
Definition: oof3.cpp:1026
virtual oofString copyString() const
Definition: oof3.cpp:472
std::ostream & operator<<(std::ostream &, const oofE_Base &)
virtual void setString(const char *)
Definition: oof3.cpp:1676
FieldIsStandaloneT
Definition: oof3.h:65
dbField * mCopyTo
Definition: oof3.h:628
unsigned long mMaxLength
Maximum length that can be stored in the field.
Definition: oof3.h:333
virtual OOF_fieldTypes fieldType() const =0
void getStr255(Str255 s) const
Definition: oof3.cpp:979
unsigned long OOFmsgT
Definition: oofmsg.h:31
fieldNumT numFields() const
Definition: oof1.h:1864
virtual dbQueryClause * valueAsQueryLiteral() const
Definition: oof3.cpp:1832
dbFixedBinary(long fieldWidth=4, const char *fieldName=0)
Definition: oof3.cpp:582
dbField * mCopyFrom
Definition: oof3.h:628
Persistent field used to store an arbitrary binary object.
Definition: oof3.h:387
OOFmsgT mCopyOnMessage
Definition: oof3.h:629
dbQueryBinary operator>(const char *) const
Definition: oof3.cpp:1868
bool isNewRecord() const
Definition: oof1.h:2341
virtual oofWordParser * words() const
Definition: oof3.cpp:251
void attachfield(dbField *)
Definition: oof1.cpp:1468
virtual ~dbCloneCleanup()
Definition: oof3.cpp:2600
virtual const char * calc(const dbChar *)
Definition: oof3.cpp:1422
void LoadField() const
Definition: oof3.cpp:2265
bool fieldIsPartiallyIndexed() const
Definition: oof3.h:692
dbQueryBinary operator<(const char *) const
Definition: oof3.cpp:1854
dbQueryBinary operator!=(const char *) const
Definition: oof3.cpp:1847
dbQueryTrinary between(const char *, const char *) const
Definition: oof3.cpp:1326
virtual unsigned long fieldMinWrapWidth() const
Definition: oof3.cpp:222
virtual void extract(std::ostream &os) const
Definition: oof3.cpp:705
dbQueryBinary startsWith(const char *) const
Definition: oof3.cpp:1287
void setValue(const void *str)
Copies buffer for length fieldStorageLen().
Definition: oof3.cpp:674
dbFieldCopier(oofBroadcaster *listensTo, unsigned short copyOnMessage, dbField *copyFrom, dbField *copyTo)
Definition: oof3.cpp:2566
virtual ~dbBLOB()
Definition: oof3.cpp:2109
char * bodyAddress() const
Definition: oof3.cpp:2197
dbQueryBinary operator<=(const char *) const
Definition: oof3.cpp:1861
dbQueryBinary operator!=(const char *) const
Definition: oof3.cpp:1342
dbCloneCleanup(dbTable *listensTo)
Definition: oof3.cpp:2594
virtual dbField * clone() const
Definition: oof3.cpp:2118
void markDirty()
Definition: oof1.cpp:1358
void clear()
Implemented in fairly simple-minded approach until need shown for better.
Definition: oof3.cpp:637
virtual bool fieldIsBlob() const
Definition: oof3.cpp:2162
Base class for persistent fields in dbTable's.
Definition: oof3.h:63
virtual ~dbFieldCopier()
Definition: oof3.cpp:2574
bool ensureRecordLoaded(bool autoCreateRelated=false, bool failureAborts=true)
Definition: oof1.cpp:1228
virtual bool checkDuplicate(const dbQueryClause *)=0
virtual OOF_fieldTypes fieldType() const
Definition: oof3.cpp:603
virtual dbCalculator * cloneOwned(dbField *newOwner) const
Definition: oof3.cpp:1406
virtual const char * asChars() const
Definition: oof3.cpp:243
void setByte(char c, unsigned long offset)
Definition: oof3.cpp:684
virtual dbQueryClause * valueAsQueryLiteral() const
Definition: oof3.cpp:1279
unsigned long mBodyLength
Definition: oof3.h:374
dbChar & calculateWith(dbCharCalculator *adoptedCalculator, bool useOnlyForDefaults=false)
Definition: oof3.cpp:830
OOF_IndexOptions fieldIndexOptions() const
Definition: oof3.h:678
virtual void getChars(char *ioBuff, unsigned long &outLen) const
Definition: oof3.cpp:1551
virtual bool fieldIsBlob() const
Definition: oof3.cpp:386