home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / OS2 / DB02_SRC.ZIP / DIAGREL.CC < prev    next >
C/C++ Source or Header  |  1993-11-05  |  11KB  |  448 lines

  1. /**************************************************************************
  2.  * Source Id :
  3.  *
  4.  * $Id: diagrel.cc,v 1.12 1993/11/03 12:21:12 davison Exp $
  5.  *-------------------------------------------------------------------------
  6.  * Project Notes :
  7.  *
  8.  *  Diamond Base
  9.  *  ============
  10.  *      A solid database implementation, spurred on by the continuing
  11.  *  Metal (Lead) Base saga.
  12.  *
  13.  *  Project Team :
  14.  *        A. Davison
  15.  *        K. Lentin
  16.  *        D. Platt
  17.  *
  18.  *    Project Commenced : 05-02-1993
  19.  *
  20.  *-------------------------------------------------------------------------
  21.  *  Module Notes :
  22.  *
  23.  *
  24.  * The diaGRel class is used to provide generalised access to relations
  25.  * without the need for associated compiled comparison code. It effectively
  26.  * sits on top of a diaRel class and provides comparison, load and store 
  27.  * support for the object methods (must inherit an object base class too).
  28.  *
  29.  *  Original Author : Daz
  30.  *
  31.  *-------------------------------------------------------------------------
  32.  * Revision History:
  33.  *
  34.  * $Log: diagrel.cc,v $
  35. // Revision 1.12  1993/11/03  12:21:12  davison
  36. // Ahh - maybe I cant count parenthesis ?
  37. //
  38. // Revision 1.11  1993/11/03  12:17:27  davison
  39. // Made implicit boolean tests explicit in comparison functions.
  40. //
  41. // Revision 1.10  1993/11/03  11:05:19  kevinl
  42. // Missing char* cast on theData
  43. //
  44. // Revision 1.9  1993/11/03  10:04:46  kevinl
  45. // Added ichar and utils.{h,cc}
  46. //
  47. // Revision 1.8  1993/10/31  16:25:15  darrenp
  48. // uniqueOffset not set correctly when no unique present - and
  49. // has unique failed, and writing to unique gave wierd results.
  50. //
  51. // Revision 1.7  1993/10/28  07:49:01  kevinl
  52. // Added diaGRel dbString/dbData support
  53. //
  54. // Revision 1.6  1993/10/18  11:38:31  kevinl
  55. // Added 0 on end of char array fields
  56. // Added fieldNum
  57. //
  58. // Revision 1.5  1993/10/05  07:32:11  kevinl
  59. // Moved all info out and into dbObj. Made all accesses to relation data
  60. // via dbObjData pointer.
  61. //
  62. // Revision 1.4  1993/09/28  13:03:43  kevinl
  63. // Moved some includes, fixed the extern diamondBase
  64. // Added UNIQUE to some of the assignment functions
  65. // Added the result check to the strncmp in compare D_CHAR
  66. //
  67. // Revision 1.3  1993/09/27  05:22:25  darrenp
  68. // Removed test code.
  69. //
  70. // Revision 1.1  1993/09/26  16:06:20  darrenp
  71. // Initial revision
  72. //
  73.  */
  74.  
  75. #include <stdlib.h>
  76. #include <string.h>
  77. #include <assert.h>
  78. #if !defined(MALLOC_H_MISSING) && !defined(MALLOC_H_INCLUDED)
  79. extern "C" {
  80. #include <malloc.h>
  81. }
  82. #define MALLOC_H_INCLUDED
  83. #endif
  84.  
  85. #include <diagrel.h>
  86. #include <ordcomp.h>
  87.  
  88. //
  89. // Now for my first trick, I will attempt to
  90. // examine the header of a db file.
  91.  
  92. extern diamondBase theDiamondBase;
  93.  
  94. #ifdef DIAGREL_TEST
  95.  
  96. struct dnaTagRel {
  97.     long    length;
  98.     long    id;
  99.     long    experiment;
  100.     char    name[10];
  101.     char     circular;
  102.  
  103. {
  104.  
  105.     for(testGRel.first();testGRel.ok();testGRel.next()) {
  106.         dnaTagRel *d = (dnaTagRel *)testGRel.theData;            
  107.         cout << "id         =" << d->id << endl;
  108.         cout << "circular   =" << d->circular << endl;
  109.         cout << "------------------------------" << endl;
  110.     }
  111.     testGRel.end();
  112. }
  113. #endif
  114. //
  115. // Implementation of the diaGRel methods.
  116. // ---
  117.  
  118. diaGRel::diaGRel(const char *relName, void* newData) : diaRel(relName)
  119. {
  120.     if (status != db_ok)
  121.         return;
  122.  
  123.     // Allocate a transfer area or use a given one.
  124.     if (newData)
  125.         theData = newData;
  126.     else
  127.         theData = new char[objData->dataLength];
  128.  
  129.     if (objData->uniqOff != -1) {
  130.         uniqOffset = (long *)((char *)theData+objData->uniqOff);
  131.     } else {
  132.         uniqOffset = 0;
  133.     }
  134.  
  135.     if (numStrings()) 
  136.     {
  137.         theArray = new _db_strStruct[numStrings()];
  138.         for (int i=0; i<numStrings(); i++)
  139.         {
  140.             if (objData->fieldType[objData->stringField[i]] == D_STRING)
  141.                 theArray[i].theString = new dbString;
  142.             else
  143.                 theArray[i].theString = new dbData;
  144.             theArray[i].theLong = (long*)((char*)theData+objData->fieldOffset[objData->stringField[i]]);
  145.         }
  146.     }
  147.     else
  148.         theArray = 0;
  149. }    
  150.  
  151. diaGRel::operator void*()
  152. {
  153.     return theData;
  154. }
  155.  
  156. // These are just cues to the person using the
  157. // database, that they should have the data ready for fetching.
  158. // This is to make inter process transfer efficient when the engine
  159. // and the application aren't the same process. Don't worry about them
  160. // for now.
  161.  
  162. void diaGRel::getData(void)
  163. {
  164. }
  165. void diaGRel::putData(void)
  166. {
  167. }
  168. void diaGRel::startData(void)
  169. {
  170. }
  171. void diaGRel::endData(void)
  172. {
  173. }
  174. long diaGRel::getDataLength(void)
  175. {
  176.     return objData->dataLength;
  177. }
  178. pKeyType diaGRel::getKey(long keyNum)
  179. {
  180.     // Retrieve the data associated with keyNum.
  181.     char *data = new char[objData->keyLength[keyNum]];
  182.     long i,j;
  183.     j = 0;
  184.  
  185.     // Copy the
  186.     for(i=0;i<MAX_FIELDS_IN_INDEX;i++) {
  187.         long k = objData->indexedOnP[keyNum][i];
  188.         if (k==-1) break;
  189.  
  190.         // Copy each field of the record according to
  191.         // its type.
  192.         // Switch statement is probably overkill for this kind of
  193.         // situation.
  194.         switch(objData->fieldType[k]) {
  195.             case D_UNIQUE:
  196.             case D_STRING:
  197.             case D_DATA:
  198.             case D_LONG:
  199.             case D_ULONG:
  200.             case D_DOUBLE:
  201.             case D_MONEY:
  202.             case D_DATE:
  203.             case D_SHORT:
  204.             case D_USHORT:
  205.             case D_FLOAT:
  206.                 // For most things, just copy a long across.
  207.                 // It might not be correct for some of the above
  208.                 // data types, but we don't use them - I think ?
  209.                 *(long *)(data+j) = *(long *)((char *)theData + objData->fieldOffset[k]);
  210.                 break;
  211.             case D_CHAR:
  212.             case D_ICHAR:
  213.                 strncpy(data+j,((char*)theData+objData->fieldOffset[k]),objData->fieldLength[k]);
  214.                 *(data+j+objData->fieldLength[k]-1) = 0;
  215.                 break;
  216.             default:
  217.                 cerr << "Illegal field type" << endl;
  218.                 assert(0);
  219.         }
  220.         j+=objData->fieldLength[k];
  221.     }
  222.     return data;
  223. }
  224. bool diaGRel::hasUnique(void)
  225. {
  226.     return (uniqOffset!=0)?true:false;
  227. }
  228. long diaGRel::getUnique(void)
  229. {
  230.     return *uniqOffset;
  231. }
  232. void diaGRel::setUnique(long uniq)
  233. {
  234.     *uniqOffset = uniq;
  235. }
  236. long diaGRel::getKeyLength(long keyNum)
  237. {
  238.     if (keyNum==-1) return 0;
  239.     return objData->keyLength[keyNum];
  240. }
  241.  
  242. void diaGRel::setKey(pKeyType newKey, long keyNum)
  243. {
  244.     // Unpack a key that is given to us.
  245.     long i,j;
  246.     j = 0;
  247.  
  248.     for(i=0;i<MAX_FIELDS_IN_INDEX;i++) {
  249.         long k = objData->indexedOnP[keyNum][i];
  250.         if (k==-1) break;
  251.  
  252.         // Copy each field of the record according to
  253.         // its type.
  254.         // Switch statement is probably overkill for this kind of
  255.         // situation.
  256.         switch(objData->fieldType[k]) {
  257.             case D_UNIQUE:
  258.             case D_STRING:
  259.             case D_DATA:
  260.             case D_LONG:
  261.             case D_ULONG:
  262.             case D_DOUBLE:
  263.             case D_MONEY:
  264.             case D_DATE:
  265.             case D_SHORT:
  266.             case D_USHORT:
  267.             case D_FLOAT:
  268.                 // For most things, just copy a long across.
  269.                 // It might not be correct for some of the above
  270.                 // data types, but we don't use them - I think ?
  271.                 *(long *)((char *)theData + objData->fieldOffset[k]) =
  272.                     *(long *)(newKey+j);
  273.                 break;
  274.             case D_CHAR:
  275.             case D_ICHAR:
  276.                 strncpy(
  277.                     (char *)theData+objData->fieldOffset[k],
  278.                     newKey + j,objData->fieldLength[k]);
  279.                 *((char*)theData+objData->fieldOffset[k]+objData->fieldLength[k]-1) = 0;
  280.                 break;
  281.             default:
  282.                 cerr << "Illegal field type" << endl;
  283.                 assert(0);
  284.         }
  285.         j+=objData->fieldLength[k];
  286.     }
  287. }
  288.  
  289. long diaGRel::compare(pKeyType key, long keyNum)
  290. {
  291.     // This is the nasty one which does a lot of hard work.
  292.     // It performs the necessary comparisons on the necessary
  293.     // keys. The actual fields which are to be compared come from
  294.     // various arrays.
  295.  
  296.     // Retrieve the data associated with keyNum.
  297.     long i,j,k,res;
  298.  
  299.     // Compare each field in turn - as soon as they
  300.     // differ, return +1 or -1 - if they match all the
  301.     // way down, return 0.
  302.  
  303.     // j tracks the index into the packed key supplied.
  304.     j = 0;
  305.     for(i=0;i<MAX_FIELDS_IN_INDEX;i++) {
  306.         k = objData->indexedOnC[keyNum][i];
  307.         //cout << "Compare   i=" << i << "   k=" << k << endl;
  308.         if (k==-1) return 0; // Have reached end with no differences.
  309.  
  310.         // Compare each field of the record according to
  311.         // its type.
  312.  
  313.         switch(objData->fieldType[k]) {
  314.             case D_STRING:
  315.                 cerr << "String comparison unimplemented" << endl;
  316.                 abort();
  317.             case D_DATA:
  318.                 cerr << "String comparison unimplemented" << endl;
  319.                 abort();
  320.             case D_UNIQUE:
  321.                 if ((res = compare_uniqueType(
  322.                     (pKeyType)theData + objData->fieldOffset[k],
  323.                     (pKeyType)key + j))!=0) {
  324.                     return res;
  325.                 }
  326.                 break; // continue comparison.
  327.             case D_LONG:
  328.                 if ((res = compare_long(
  329.                     (pKeyType)theData + objData->fieldOffset[k],
  330.                     (pKeyType)key + j))!=0) {
  331.                     return res;
  332.                 }
  333.                 break; // continue comparison.
  334.             case D_ULONG:
  335.                 if ((res = compare_ulong(
  336.                     (pKeyType)theData + objData->fieldOffset[k],
  337.                     (pKeyType)key + j))!=0) {
  338.                     return res;
  339.                 }
  340.                 break; // continue comparison.
  341.             case D_DOUBLE:
  342.                 if ((res = compare_double(
  343.                     (pKeyType)theData + objData->fieldOffset[k],
  344.                     (pKeyType)key + j))!=0) {
  345.                     return res;
  346.                 }
  347.                 break; // continue comparison.
  348.             case D_MONEY:
  349.                 if ((res = compare_moneyType(
  350.                     (pKeyType)theData + objData->fieldOffset[k],
  351.                     (pKeyType)key + j))!=0) {
  352.                     return res;
  353.                 }
  354.                 break; // continue comparison.
  355.             case D_DATE:
  356.                 if ((res = compare_dateType(
  357.                     (pKeyType)theData + objData->fieldOffset[k],
  358.                     (pKeyType)key + j))!=0) {
  359.                     return res;
  360.                 }
  361.                 break; // continue comparison.
  362.             case D_SHORT:
  363.                 if ((res = compare_short(
  364.                     (pKeyType)theData + objData->fieldOffset[k],
  365.                     (pKeyType)key + j))!=0) {
  366.                     return res;
  367.                 }
  368.                 break; // continue comparison.
  369.             case D_USHORT:
  370.                 if ((res = compare_ushort(
  371.                     (pKeyType)theData + objData->fieldOffset[k],
  372.                     (pKeyType)key + j))!=0) {
  373.                     return res;
  374.                 }
  375.                 break; // continue comparison.
  376.             case D_FLOAT:
  377.                 if ((res = compare_float(
  378.                     (pKeyType)theData + objData->fieldOffset[k],
  379.                     (pKeyType)key + j))!=0) {
  380.                     return res;
  381.                 }
  382.                 break; // continue comparison.
  383.             case D_ICHAR:
  384.                 //cout << "Compare:" << (char *)(theData+objData->fieldOffset[k]) << ":" << (char *)(key + j) << ":" << endl;
  385.                 if ((res = strncasecmp(
  386.                     (char *)theData+objData->fieldOffset[k], key + j,
  387.                     objData->fieldLength[k]))!=0) {
  388.                     return res;
  389.                 }
  390.                 break;
  391.             case D_CHAR:
  392.                 //cout << "Compare:" << (char *)(theData+objData->fieldOffset[k]) << ":" << (char *)(key + j) << ":" << endl;
  393.                 if ((res = strncmp(
  394.                     (char *)theData+objData->fieldOffset[k], key + j,
  395.                     objData->fieldLength[k]))!=0) {
  396.                     return res;
  397.                 }
  398.                 break;
  399.             default:
  400.                 cerr << "Illegal field type" << endl;
  401.                 abort();
  402.         }
  403.         j+=objData->fieldLength[k]; // Move to next section of the packed key.
  404.     }
  405.     return 0; // All fields done up to MAX FIELDS, and no difference.
  406. }
  407.  
  408. bool diaGRel::isUnique(long keyNum)
  409. {
  410.     // Return true if the index number 'keyNum' includes
  411.     // a unique field.
  412.     if (keyNum == -1) return false; // Not sure why this is here.
  413.     return objData->containsUniq[keyNum]?true:false;
  414. }
  415.  
  416. long 
  417. diaGRel::numStrings(void)
  418. {
  419.     return objData->stringCount;
  420. }
  421.  
  422. _db_strStruct* 
  423. diaGRel::getArray(void)
  424. {
  425.     return theArray;
  426. }
  427.  
  428. dbData*
  429. diaGRel::getString(long num)
  430. {
  431.     return theArray[num].theString;
  432. }
  433.  
  434. long*
  435. diaGRel::getLong(long num)
  436. {
  437.     return theArray[num].theLong;
  438. }
  439.  
  440. long
  441. diaGRel::fieldNum(char* name)
  442. {
  443.     for (int i=0; i<objData->numFields; i++) 
  444.         if (!strcmp(objData->fieldName[i], name))
  445.             return i;
  446.     return -1;
  447. }
  448.