home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Demos / OOFILE / Buildable, limited OOFILE / OOFILE partial source / oof3.cpp < prev    next >
Encoding:
Text File  |  1995-09-25  |  19.5 KB  |  978 lines  |  [TEXT/CWIE]

  1. // COPYRIGHT 1994 A.D. Software, All rights reserved
  2.  
  3. // OOFILE database field-related classes
  4. // see also oof4.cpp
  5.  
  6. #include "oof2.hpp"
  7. #include "oof3.hpp"
  8. #include "oofquery.hpp" 
  9. #include "oofrel.hpp"  
  10.  
  11. // -------------------------------------------------------
  12. //                      d b F i e l d 
  13. // -------------------------------------------------------
  14.  
  15.  
  16. dbField::dbField() :
  17.             mIndexOptions(kNotIndexed)
  18. {
  19.     dbTable::sCurrentlyConstructing->attachfield(this);
  20. }
  21.  
  22.  
  23. dbField::dbField(const OOF_IndexOptions indexOptions) :
  24.             mIndexOptions(indexOptions)
  25. {
  26.     dbTable::sCurrentlyConstructing->attachfield(this);
  27. }
  28.  
  29.  
  30. dbField::dbField(const char *fieldName) :
  31.                 mIndexOptions(kNotIndexed),
  32.                 mFieldName(fieldName)
  33. {
  34.     dbTable::sCurrentlyConstructing->attachfield(this);
  35. }
  36.  
  37.  
  38. dbField::dbField(const char *fieldName, const OOF_IndexOptions indexOptions) :
  39.                 mIndexOptions(indexOptions),
  40.                 mFieldName(fieldName)
  41. {
  42.     dbTable::sCurrentlyConstructing->attachfield(this);
  43. }
  44.  
  45.  
  46. dbField::dbField(const dbField& rhs) :
  47.             mBackend(0),
  48.             mTable(0),
  49.             mFieldNumber(rhs.mFieldNumber),
  50.             mIndexOptions(rhs.mIndexOptions),
  51.             mFieldName(rhs.mFieldName)
  52. {
  53. #ifdef OOF_Debug
  54.     validateDatabaseState();
  55. #endif
  56.     if(mRelationChain) { // must be copying a related field, probably a temp copy from a view
  57.         mTable = rhs.mTable;
  58.         mBackend = rhs.mBackend;
  59.     }
  60.     else // normal copy
  61.     {
  62.         dbTable* theTable = dbTable::sCurrentlyConstructing;
  63.         theTable->attachfield(this);
  64.     }
  65. }
  66.  
  67. unsigned int dbField::fieldEditLen() const
  68. {
  69.         if (fieldType()==charField)
  70.             return fieldLen();
  71.         else
  72.             if (fieldType()==textField)
  73.                 return 20;
  74.             else
  75.                 return 10;
  76. }
  77.  
  78.  
  79. const void* dbField::binaryContents()
  80. {
  81.     validateContextInCaseRelated();
  82.     return mBackend->getFieldReadFrom(mFieldNumber);
  83. }
  84.  
  85.  
  86. dbTable* dbField::fieldTable() const
  87. {
  88.     return mTable;  
  89. }
  90.  
  91.  
  92. unsigned int dbField::countSegments() const
  93. {    
  94.     if (mIndexOptions==kNotIndexed)
  95.         return 0;
  96.     else
  97.         return 1;  // overridden for compound keys
  98. }
  99.  
  100.  
  101. bool dbField::fieldIsBlob() const
  102. {
  103.     return false;  
  104. }
  105.  
  106.  
  107. bool dbField::fieldIsBinary() const
  108. {
  109.     return true;  
  110. }
  111.  
  112.  
  113. bool dbField::fieldIsVirtual() const
  114. {
  115.     return false;
  116. }
  117.     
  118.     
  119. bool dbField::fieldIsIndexed() const
  120. {
  121.     return mIndexOptions!=kNotIndexed;
  122.  
  123.  
  124. bool dbField::fieldIsUniqueIndexed() const
  125. {
  126.     return mIndexOptions==kIndexNoDups;
  127.  
  128.  
  129. char *dbField::copyAsChars()
  130. {
  131.     ostrstream oss;
  132.     extract(oss);
  133.     oss << ends;
  134. #ifdef _RTLDLL  // Borland use this to indicate runtime lib in DLL which may mean different allocator
  135.     char* s = oss.str();  // can't just return this - causes crash on delete[]
  136.     long sLen = strlen(s);
  137.     char* ret = new char[sLen+1];
  138.     assert(ret);
  139.     strncpy(ret, s, sLen);
  140.    ret[sLen]='\0';
  141.     oss.rdbuf()->freeze(0);  // leave buffer for stream to delete
  142.     return ret;
  143. #else
  144.     return oss.str();
  145. #endif
  146. }
  147.  
  148.  
  149. void dbField::extract(ostream& os)
  150. {
  151.     os << "";
  152. }
  153.  
  154.  
  155. bool dbField::insert(istream& is, char fieldSep, char recSep)
  156. {
  157.     char c;
  158.     while (is.good()) {
  159.         is >> c;
  160.         if ((c==fieldSep) || (c==recSep)) {
  161.             is.putback(c); // put the separator back so the caller knows what kind we hit
  162.             return true;  // OK - hit a separator
  163.         }
  164.     }
  165.     return false;  // fell through without hitting separator
  166. }
  167.  
  168.  
  169. void dbField::describe(ostream& os)
  170. {
  171.     if (mFieldName.isEmpty())
  172.         os << "Un-named field";
  173.     else
  174.         os << "field: " << mFieldName;
  175.     os << " is field type: " << fieldType() << endl;
  176.     if (fieldIsIndexed())
  177.         os << "    has indexing: " << fieldIndexOptions() << endl;
  178. }
  179.  
  180.  
  181. void dbField::validateContextInCaseRelated()
  182. {
  183. #ifdef OOF_Debug
  184.     validateDatabaseState();
  185. #endif
  186.     if (mRelationChain)
  187.         mRelationChain->validateContext();
  188. }
  189.  
  190.  
  191. dbField* dbField::GetRelatedFieldOrUs()
  192. {
  193.     if (ConsumePossibleRelationChain()) {
  194.         dbRelChain* tempChain = mRelationChain;
  195.         mRelationChain = 0;  // clear it, the clone field owns it
  196.         tempChain = tempChain->buildChain();
  197.         return tempChain->getFinalField(mFieldNumber);
  198.     }
  199.     else
  200.         return this;
  201. }
  202.  
  203.  
  204. // -------------------------------------------------------
  205. //                  d b F i x e d B i n a r y
  206. // -------------------------------------------------------
  207. OOF_fieldTypes dbFixedBinary::fieldType() const
  208. {
  209.     return fixedBinaryField; 
  210. }
  211.  
  212.  
  213. unsigned long dbFixedBinary::fieldLen() const
  214. {
  215.     return mBodyLength; 
  216. }
  217.  
  218.  
  219. dbFixedBinary& dbFixedBinary::operator=(dbFixedBinary& rhs)
  220. {
  221.     if (this == &rhs)  // MUST use this form to avoid invoking the operator== used for searches
  222.         return *this;
  223.     
  224.     setValue(rhs.binaryContents());
  225.     return *this;
  226. }
  227.  
  228.  
  229. dbFixedBinary&  dbFixedBinary::operator=(const char* str)
  230. {
  231.     assert(strlen(str) <= mBodyLength);
  232.     setValue(str);
  233.     return *this;
  234. }
  235.  
  236.  
  237.  
  238. void dbFixedBinary::setValue(const void* str)
  239. {
  240.     validateContextInCaseRelated();
  241.     char *writeTo = (char*)mBackend->getFieldWriteDest(mFieldNumber);
  242.     if (writeTo) {
  243.         memcpy(writeTo, str, mBodyLength);
  244. #ifdef OOF_SmartHeap
  245.     MemPoolCheck(MemDefaultPool);
  246. #endif
  247.     }    
  248.     else
  249.         ;  // error NOT YET IMPLEMENTED
  250.     mBackend->markDirty();
  251. }
  252.  
  253.  
  254. void dbFixedBinary::setByte(char c, unsigned int offset)
  255. {
  256.     validateContextInCaseRelated();
  257.     char *writeTo = (char*) mBackend->getFieldWriteDest(mFieldNumber);
  258.     if (writeTo) {
  259.         writeTo[offset] = c;
  260. #ifdef OOF_SmartHeap
  261.     MemPoolCheck(MemDefaultPool);
  262. #endif
  263.     }    
  264.     else
  265.         ;  // error NOT YET IMPLEMENTED
  266.     mBackend->markDirty();
  267. }
  268.  
  269.  
  270. void dbFixedBinary::extract(ostream& os)
  271. {
  272.     const char *asChars = (char*)binaryContents();
  273.     os << hex;
  274.     for (unsigned int i=0; i<mBodyLength; i++)
  275.         os << asChars[i] << ' ';
  276. }
  277.  
  278.  
  279.  
  280. void dbFixedBinary::generateTestData(const char *testBuf, unsigned long testBufLen)
  281. {
  282.     for (unsigned int i=0; i<mBodyLength; i++) {
  283.         char c = rand()%0xFF;
  284.         setByte(c, i);
  285.     }
  286. }
  287.  
  288.  
  289. void dbFixedBinary::describe(ostream& os)
  290. {
  291.     dbField::describe(os);
  292.     os << "    and a length of : " << mBodyLength << endl;
  293. }
  294.  
  295.  
  296. dbFixedBinary& dbFixedBinary::operator()()
  297. {
  298.     dbFixedBinary* retField = (dbFixedBinary*) GetRelatedFieldOrUs();
  299.     return *retField;
  300. }
  301.  
  302.  
  303. // -------------------------------------------------------
  304. //                      d b C h a r
  305. // -------------------------------------------------------
  306. char * dbChar::copyAsChars()
  307. {
  308.     char* ret = new char[mBackend->fieldDataLen(this)+1];
  309.     assert(ret);
  310.     strcpy(ret, (const char*)*this);
  311.     return ret;
  312. }
  313.  
  314. OOF_fieldTypes dbChar::fieldType() const
  315. {
  316.     return charField; 
  317. }
  318.  
  319.  
  320. bool dbChar::fieldIsBinary() const
  321. {
  322.     return false;  
  323. }
  324.  
  325.  
  326. unsigned long dbChar::fieldLen() const
  327. {
  328.     return mMaxLength; 
  329. }
  330.  
  331.  
  332. dbChar::operator const char*() 
  333. {
  334.     validateContextInCaseRelated();
  335.     return (char*) mBackend->getFieldReadFrom(mFieldNumber);
  336. }
  337.  
  338.  
  339. #ifdef _Macintosh
  340. void dbChar::asStr255(Str255 s) 
  341. {
  342.     validateContextInCaseRelated();
  343.     char* from = (char*) mBackend->getFieldReadFrom(mFieldNumber);
  344.     s[0] = strlen(from);
  345.     memcpy(s+1, from, s[0]);
  346. #ifdef OOF_SmartHeap
  347.     MemPoolCheck(MemDefaultPool);
  348. #endif
  349. }
  350.  
  351. void dbChar::setStr255(const Str255 s)
  352. {
  353.     long charLen = s[0];
  354.     const char* strStart = (char*) s+1;
  355.     setChars(strStart, charLen);
  356. }
  357.  
  358.  
  359.  
  360. // end of Mac-specific extra conversions
  361. #endif
  362.  
  363.  
  364. dbChar& dbChar::operator=(dbChar& rhs)
  365. {
  366.     if (this == &rhs)  // MUST use this form to avoid invoking the operator== used for searches
  367.         return *this;
  368.     
  369.     *this = (const char*)rhs;
  370.     return *this;
  371. }
  372.  
  373.  
  374. dbChar&  dbChar::operator=(const char* str)
  375. {
  376.     unsigned int charLen = strlen(str);
  377.     if (charLen > mMaxLength)
  378.         ;  // error NOT YET IMPLEMENTED
  379.     else
  380.     {
  381.         validateContextInCaseRelated();
  382.         char *writeTo = (char*)mBackend->getFieldWriteDest(mFieldNumber);
  383.         if (writeTo)
  384.             strcpy(writeTo, str);    
  385.         else
  386.             ;  // error NOT YET IMPLEMENTED
  387.     }
  388.     mBackend->markDirty();
  389.     return *this;
  390. }
  391.  
  392.  
  393.  
  394. void dbChar::setChars(const char* str , unsigned long charLen)
  395. {
  396.     assert(charLen <= mMaxLength);
  397.     validateContextInCaseRelated();
  398.     char *writeTo = (char*)mBackend->getFieldWriteDest(mFieldNumber);
  399.     if (writeTo) {
  400.         memcpy(writeTo, str, charLen);
  401.         writeTo[charLen]='\0';
  402.     }    
  403.     else
  404.         ;  // error NOT YET IMPLEMENTED
  405.     mBackend->markDirty();
  406. }
  407.  
  408.  
  409.  void dbChar::extract(ostream& os)
  410. {
  411.     os << (const char*)*this;
  412. }
  413.  
  414.  
  415.  
  416. bool dbChar::insert(istream& is, char fieldSep, char recSep)
  417. {
  418. // this is NOT very efficient, but it *is* safe
  419.     if (!is.good()) 
  420.         return false;
  421.         
  422.     const unsigned int maxLen = fieldLen();
  423.     assert(maxLen);  // brief flash of paranoia in case they get this far with a field of 0 len
  424.     char* buildBuf = new char[maxLen+1];
  425.     assert(buildBuf);
  426.     unsigned int charsRead = 0;
  427.     bool hitEndOfField = false;
  428.     while (is.good() && (charsRead<=maxLen)) {  // allow read one char past, in case it's terminator
  429.         char c;
  430.         is >> c;
  431.         if ((c==fieldSep) || (c==recSep)) {
  432.             is.putback(c); // put the separator back so the caller knows what kind we hit
  433.             hitEndOfField = true;
  434.             break;  // OK - hit a separator
  435.         }
  436.         if (charsRead<maxLen)
  437.             buildBuf[charsRead] = c;
  438.         charsRead++;
  439.     } // loop reading char at a time
  440.  
  441.     bool gotDataOK = false;
  442.     if (hitEndOfField)  // everybody happy
  443.         gotDataOK = true;
  444.     else {  // some form of problems along the way
  445.         if (charsRead>maxLen) {// too wide for DB field, store as short anyway
  446.             gotDataOK = true;
  447.             dbField::insert(is, fieldSep, recSep);  // consume the remainder
  448. #ifdef OOF_Debug
  449.             dbConnect::raise(ostrstream() << "dbChar::insert() of field " 
  450.                                                                         << mTable->tableName() << "." << fieldName()
  451.                                           << " has filled its length of " << maxLen 
  452.                                                                         << " before reaching the end of the field"
  453.                                             );   
  454. #endif
  455.         }
  456.     }
  457.     
  458.     if (gotDataOK) { 
  459.         buildBuf[charsRead] = '\0';  // now make it into a C string!
  460.         *this = buildBuf;  // finally, assign to the record
  461.     }
  462.     delete[] buildBuf;
  463.     return gotDataOK;  // if general stream problem, let caller report it
  464. }
  465.  
  466.  
  467. void dbChar::generateTestData(const char *testBuf, unsigned long testBufLen)
  468. {
  469.     unsigned long randLen = rand()%mMaxLength;
  470.     const char *readFrom = testBuf + rand()%(testBufLen-randLen);
  471.     setChars(readFrom, randLen);
  472. }
  473.  
  474.  
  475. dbQueryBinary    dbChar::operator==(const char* str) const
  476. {
  477.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::equals, new dbQueryLiteralStr(str));
  478. }  
  479.  
  480.  
  481. dbQueryBinary    dbChar::startsWith(const char* str) const
  482. {
  483.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::startsWith, new dbQueryLiteralStr(str));
  484. }  
  485.  
  486.  
  487. dbQueryTrinary    dbChar::between(const char* fromStr, const char* toStr) const
  488. {
  489.     return dbQueryTrinary(new dbQueryField(this), dbQueryClause::between,
  490.         new dbQueryLiteralStr(fromStr), new dbQueryLiteralStr(toStr));
  491. }
  492.  
  493.  
  494. dbQueryTrinary    dbChar::outside(const char* fromStr, const char* toStr) const
  495. {
  496.     return dbQueryTrinary(new dbQueryField(this), dbQueryClause::outside,
  497.         new dbQueryLiteralStr(fromStr), new dbQueryLiteralStr(toStr));
  498. }
  499.  
  500.  
  501. dbQueryBinary    dbChar::operator!=(const char* str) const
  502. {
  503.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::notEquals, new dbQueryLiteralStr(str));
  504. }  
  505.  
  506.  
  507.  dbQueryBinary    dbChar::operator<(const char* str) const
  508. {
  509.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThan, new dbQueryLiteralStr(str));
  510. }  
  511.  
  512.  
  513.  dbQueryBinary    dbChar::operator<=(const char* str) const
  514. {
  515.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThanOrEqual, new dbQueryLiteralStr(str));
  516. }  
  517.  
  518.  
  519.  dbQueryBinary    dbChar::operator>(const char* str) const
  520. {
  521.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThan, new dbQueryLiteralStr(str));
  522. }  
  523.  
  524.  
  525.  dbQueryBinary    dbChar::operator>=(const char* str) const
  526. {
  527.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThanOrEqual, new dbQueryLiteralStr(str));
  528. }  
  529.  
  530.  
  531. void dbChar::describe(ostream& os)
  532. {
  533.     dbField::describe(os);
  534.     os << "    and a maximum length of : " << mMaxLength << endl;
  535. }
  536.  
  537.  
  538. dbChar& dbChar::operator()()
  539. {
  540.     dbChar* retField = (dbChar*) GetRelatedFieldOrUs();
  541.     return *retField;
  542. }
  543.  
  544.  
  545. // -------------------------------------------------------
  546. //                      d b T e x t
  547. // -------------------------------------------------------
  548. dbText::operator const char*()
  549. {
  550.     if (!mLoaded)
  551.         LoadField();
  552.     if (fieldDataLen())
  553.         return (char *)mBody;
  554.     else
  555.         return &OOF_String::sEmptyStr;
  556. }
  557.  
  558.  
  559. char * dbText::copyAsChars()
  560. {
  561.     unsigned long len = mBackend->fieldDataLen(this);
  562.     char* ret;
  563.     if (len) {
  564.         ret = new char[len];  // len from DB includes null
  565.         memcpy(ret, (const char*)*this, len);
  566. #ifdef OOF_SmartHeap
  567.     MemPoolCheck(MemDefaultPool);
  568. #endif
  569.     }
  570.     else {
  571.         ret = new char[1];
  572.         ret[0] = '\0';
  573.     }
  574.     return ret;
  575. }
  576.  
  577.  
  578. OOF_fieldTypes dbText::fieldType() const
  579. {
  580.     return textField; 
  581. }
  582.  
  583.  
  584. bool dbText::fieldIsBinary() const
  585. {
  586.     return false;  
  587. }
  588.  
  589.  
  590. dbText& dbText::operator=(dbText& rhs)
  591. {
  592.     if (this == &rhs)  // MUST use this form to avoid invoking the operator== used for searches
  593.         return *this;
  594.     
  595.     *this = (const char*)rhs;
  596.     return *this;
  597. }
  598.  
  599.  
  600. dbText& dbText::operator=(const char* str)
  601. {
  602.     unsigned long charLen;
  603.     if (str)
  604.         charLen = strlen(str);
  605.     else
  606.         charLen = 0;
  607.     if (charLen) {
  608.         allocRoomFor(charLen+1);
  609.         memcpy((char*)mBody, str, charLen);
  610.         ((char*)mBody)[charLen] = '\0';
  611. #ifdef OOF_SmartHeap
  612.     MemPoolCheck(MemDefaultPool);
  613. #endif
  614.         SetLength(charLen+1);
  615.     }
  616.     else
  617.         SetLength(0);
  618.     mBackend->markDirty();
  619.     mDirty = true;
  620.     mLoaded = true;
  621.     return *this;
  622. }
  623.  
  624.  
  625. void dbText::setChars(const char* str , unsigned long charLen)
  626. {
  627.     if (str && charLen) {
  628.         allocRoomFor(charLen+1);
  629.         memcpy(mBody, str, charLen);
  630. #ifdef OOF_SmartHeap
  631.     MemPoolCheck(MemDefaultPool);
  632. #endif
  633.         ((char*)mBody)[charLen]='\0';
  634.         SetLength(charLen+1);
  635.     }
  636.     else
  637.         SetLength(0);
  638.     mBackend->markDirty();
  639.     mDirty = true;
  640.     mLoaded = true;
  641. }
  642.  
  643.  
  644. void dbText::operator+=(const char* str)
  645. {
  646.     unsigned long charLen = strlen(str);
  647.     unsigned long currentFldLen = mBackend->fieldDataLen(this);    // inc null
  648.     if (charLen) {
  649.         unsigned long newLen = currentFldLen+charLen;
  650.         allocRoomFor(newLen);
  651.         if (!mLoaded)
  652.             LoadField();
  653.         memcpy((char*)mBody+currentFldLen-1, str, charLen);    // we KNOW where the null is
  654.         ((char*)mBody)[newLen-1] = '\0';
  655.         #ifdef OOF_SmartHeap
  656.             MemPoolCheck(MemDefaultPool);
  657.         #endif
  658.         SetLength(newLen);
  659.         mBackend->markDirty();
  660.       mDirty = true;
  661.  
  662.     }
  663. }
  664.  
  665.  
  666. void dbText::extract(ostream& os)
  667. {
  668.     os << (const char*)*this;
  669. }
  670.  
  671.  
  672.  
  673. void dbText::generateTestData(const char *testBuf , unsigned long testBufLen)
  674. {
  675.     unsigned long randLen = rand()%testBufLen%10240;        // up to 10kb allowed in one dbText
  676.     const char *readFrom = testBuf + rand()%(testBufLen-randLen);
  677.     setChars(readFrom, randLen);
  678. }
  679.  
  680.  
  681. dbQueryBinary    dbText::operator==(const char* str) const
  682. {
  683.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::equals, new dbQueryLiteralStr(str));
  684. }  
  685.  
  686.  
  687.  dbQueryBinary    dbText::operator!=(const char* str) const
  688. {
  689.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::notEquals, new dbQueryLiteralStr(str));
  690. }  
  691.  
  692.  
  693.  dbQueryBinary    dbText::operator<(const char* str) const
  694. {
  695.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThan, new dbQueryLiteralStr(str));
  696. }  
  697.  
  698.  
  699.  dbQueryBinary    dbText::operator<=(const char* str) const
  700. {
  701.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThanOrEqual, new dbQueryLiteralStr(str));
  702. }  
  703.  
  704.  
  705.  dbQueryBinary    dbText::operator>(const char* str) const
  706. {
  707.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThan, new dbQueryLiteralStr(str));
  708. }  
  709.  
  710.  
  711.  dbQueryBinary    dbText::operator>=(const char* str) const
  712. {
  713.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThanOrEqual, new dbQueryLiteralStr(str));
  714. }  
  715.  
  716.  
  717. dbText& dbText::operator()()
  718. {
  719.     dbText* retField = (dbText*) GetRelatedFieldOrUs();
  720.     return *retField;
  721. }
  722.  
  723.  
  724. // -------------------------------------------------------
  725. //                      d b B L O B
  726. // -------------------------------------------------------
  727. dbBLOB::~dbBLOB()
  728. {
  729.     delete[] mBody;
  730. };
  731.  
  732.  
  733. OOF_fieldTypes dbBLOB::fieldType() const
  734. {
  735.     return blobField; 
  736. }
  737.  
  738.  
  739. unsigned long dbBLOB::fieldLen() const
  740. {
  741.     return mBackend->blobPointerReferenceSize();  
  742. }
  743.  
  744.  
  745. bool dbBLOB::fieldIsBlob() const
  746. {
  747.     return true;  
  748. }
  749.  
  750.  
  751. void dbBLOB::SetLength(unsigned long len)
  752. {
  753.     validateContextInCaseRelated();
  754.     mBackend->setBlobLength(mFieldNumber, len);
  755. }
  756.  
  757.  
  758. void dbBLOB::reset()
  759. {
  760.     mDirty = false;
  761.     mLoaded = false;
  762. }
  763.  
  764.  
  765.  
  766. void* dbBLOB::orphanBody()
  767. {
  768.     
  769.     void* ret = mBody;
  770.     reset();
  771.     mBody = 0;
  772.     mBodyLength = 0;
  773.     return ret;
  774. }
  775.  
  776.  
  777.  
  778. void dbBLOB::adoptBody(void* body, unsigned long bodyLen)
  779. {
  780.     delete[] mBody;
  781.     mBody = body;
  782.     mBodyLength = bodyLen;
  783.     mLoaded = mDirty = true;
  784. }
  785.  
  786.  
  787.  
  788. void* dbBLOB::allocRoomFor(unsigned long len)
  789. {
  790.     if (len > mBodyLength) {
  791.         if (mLoaded) {    // assume we must preserve the buffer
  792.             char *newBody = new char[len];
  793.             assert(newBody);
  794.             if (mBody) {
  795.                 memcpy(newBody, mBody, mBodyLength);
  796.                 delete[] mBody;
  797.             }
  798.             mBody = newBody;
  799.         }
  800.         else {            
  801.             delete[] mBody;
  802.             mBody = new char[len];
  803.             assert(mBody);
  804.         }
  805.         mBodyLength = len;
  806.     }
  807. #ifdef OOF_SmartHeap
  808.     MemPoolCheck(MemDefaultPool);
  809. #endif
  810.     return mBody;
  811. }
  812.  
  813.  
  814. void dbBLOB::LoadField()
  815. {
  816.     validateContextInCaseRelated();
  817.     mBackend->loadBlob(this);
  818.     mLoaded = true;
  819. }
  820.  
  821.  
  822. dbBLOB& dbBLOB::operator()()
  823. {
  824.     dbBLOB* retField = (dbBLOB*) GetRelatedFieldOrUs();
  825.     return *retField;
  826. }
  827.  
  828.  
  829.  
  830. // -------------------------------------------------------
  831. //               d b C o m p o u n d F i e l d 
  832. // -------------------------------------------------------
  833. OOF_fieldTypes dbCompoundField::fieldType() const
  834. {
  835.     return compoundField;
  836. }
  837.  
  838.  
  839. unsigned long dbCompoundField::fieldLen() const
  840. {
  841.     return mTotalLength;   
  842. }
  843.  
  844.  
  845. bool dbCompoundField::fieldIsVirtual() const
  846. {
  847.     return true;
  848. }
  849.  
  850.  
  851. const dbField* dbCompoundField::segment(unsigned int i) const
  852. {
  853.     assert(i<mSegments.count());
  854.     return (const dbField*) (mSegments.value(i));  // safe downcast
  855. }
  856.  
  857.  
  858. void dbCompoundField::addSegment(dbField& segfield) {
  859.     assert(segfield.fieldType() != textField);
  860.     mSegments.append(&segfield);
  861.     mTotalLength += segfield.fieldLen();
  862. }
  863.  
  864.  
  865. dbQueryBinary    dbCompoundField::operator==(const char* str) const
  866. {
  867.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::equals, new dbQueryLiteralStr(str));
  868. }  
  869.  
  870.  
  871.  dbQueryBinary    dbCompoundField::operator!=(const char* str) const
  872. {
  873.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::notEquals, new dbQueryLiteralStr(str));
  874. }  
  875.  
  876.  
  877.  dbQueryBinary    dbCompoundField::operator<(const char* str) const
  878. {
  879.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThan, new dbQueryLiteralStr(str));
  880. }  
  881.  
  882.  
  883.  dbQueryBinary    dbCompoundField::operator<=(const char* str) const
  884. {
  885.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::lessThanOrEqual, new dbQueryLiteralStr(str));
  886. }  
  887.  
  888.  
  889.  dbQueryBinary    dbCompoundField::operator>(const char* str) const
  890. {
  891.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThan, new dbQueryLiteralStr(str));
  892. }  
  893.  
  894.  
  895. dbQueryBinary    dbCompoundField::operator>=(const char* str) const
  896. {
  897.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::greaterThanOrEqual, new dbQueryLiteralStr(str));
  898. }  
  899.  
  900.  
  901. dbQueryBinary    dbCompoundField::startsWith(const char* str) const
  902. {
  903.     return dbQueryBinary(new dbQueryField(this), dbQueryClause::startsWith, new dbQueryLiteralStr(str));
  904. }  
  905.  
  906.  
  907. void dbCompoundField::extract(ostream& os)
  908. {
  909.     unsigned int numSegments = mSegments.count();
  910.     for (unsigned int i=0; i<numSegments; i++) {
  911.         dbField* fld = (dbField*) mSegments[i];  // safe downcast
  912.         fld->extract(os);
  913.     }
  914. }
  915.  
  916.  
  917. // -------------------------------------------------------
  918. //                  O O F I L E _ f i e l d T y p e s
  919. // -------------------------------------------------------
  920. ostream& operator<<(ostream& os, OOF_fieldTypes ft)
  921. {
  922.     switch (ft) {
  923.     case (charField) :
  924.         os << "fixed-length chars";
  925.         break;
  926.         
  927.     case (textField) :
  928.         os << "variable-length text";
  929.         break;
  930.         
  931.     case (dateField) :
  932.         os << "date";
  933.         break;
  934.         
  935.     case (shortField) :
  936.         os << "short integer";
  937.         break;
  938.         
  939.     case (uShortField) :
  940.         os << "unsigned short integer";
  941.         break;
  942.         
  943.     case (longField) :
  944.         os << "long integer";
  945.         break;
  946.         
  947.     case (uLongField) :
  948.         os << "unsigned long integer";
  949.         break;
  950.         
  951.     case (realField) :
  952.         os << "real";
  953.         break;
  954.         
  955.     case (blobField) :
  956.         os << "binary blob";
  957.         break;
  958.         
  959.     case (compoundField) :
  960.         os << "compound";
  961.         break;
  962.         
  963.     case (fixedBinaryField) :
  964.         os << "compound";
  965.         break;
  966.         
  967.     case (boolField) :
  968.         os << "compound";
  969.         break;
  970.         
  971.     }
  972.     return os;
  973. }
  974.  
  975.  
  976.