dba_binding.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:11k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include "dba_internal.hpp"
  14. static bool matchType(NdbDictionary::Column::Type, DBA_DataTypes_t);
  15. static bool matchSize(NdbDictionary::Column::Type, unsigned, Size_t);
  16. static int  computeChecksum(const DBA_Binding_t * bindings);
  17. struct DBA__Array {
  18.   int count;
  19.   int data[1];
  20.   bool exists(int value) const {
  21.     for(int i = 0; i<count; i++)
  22.       if(data[i] == value)
  23. return true;
  24.     return false;
  25.   }
  26.   void insert(int value){
  27.     data[count] = value;
  28.     count++;
  29.   }
  30. };
  31. /**
  32.  * createBindings
  33.  */
  34. static 
  35. DBA_Binding_t *
  36. createBinding(const char* TableName, 
  37.       int NbCol,
  38.       const DBA_ColumnBinding_t ColsBindings[],
  39.       Size_t StructSz,
  40.       const NdbDictionary::Table * theTable, 
  41.       struct DBA__Array * keys,
  42.       struct DBA__Array * columns);
  43. extern "C"
  44. DBA_Binding_t *
  45. DBA_CreateBinding( const char* TableName, 
  46.    int NbCol, 
  47.    const DBA_ColumnBinding_t ColsBindings[], 
  48.    Size_t StructSz ){
  49.   NdbDictionary::Dictionary * dict = DBA__TheNdb->getDictionary();
  50.   if(dict == 0){
  51.     DBA__SetLatestError(DBA_NDB_ERROR, 0, 
  52. "Internal NDB error: No dictionary");
  53.     return 0;
  54.   }
  55.   
  56.   const NdbDictionary::Table * table = dict->getTable(TableName);
  57.   if(table == 0){
  58.     DBA__SetLatestError(DBA_APPLICATION_ERROR, 0, 
  59. "No such table: %s", TableName);
  60.     return 0;
  61.   }
  62.   
  63.   /**
  64.    * Keys/Columns in table
  65.    */
  66.   const int tabColumns = table->getNoOfColumns();
  67.   const int tabKeys    = table->getNoOfPrimaryKeys();
  68.   
  69.   /**
  70.    * Ok, ok... I alloc four bytes extra so what...
  71.    */
  72.   struct DBA__Array * keys    = (struct DBA__Array *)malloc
  73.     (sizeof(struct DBA__Array)+tabKeys*sizeof(int));
  74.   if(keys == 0){
  75.     DBA__SetLatestError(DBA_ERROR, 0,
  76. "malloc(%d) failed", 
  77. sizeof(struct DBA__Array)+tabKeys*sizeof(int));
  78.     return 0;
  79.   }
  80.   
  81.   struct DBA__Array * columns = (struct DBA__Array *)malloc
  82.     (sizeof(struct DBA__Array)+tabColumns*sizeof(int));
  83.   
  84.   if(columns == 0){
  85.     DBA__SetLatestError(DBA_ERROR, 0,
  86. "malloc(%d) failed", 
  87. sizeof(struct DBA__Array)+tabColumns*sizeof(int));
  88.     free(keys);
  89.     return 0;
  90.   }
  91.   
  92.   columns->count = 0;
  93.   keys->count = 0;
  94.   
  95.   DBA_Binding_t * bindings = createBinding(TableName,
  96.    NbCol,
  97.    ColsBindings,
  98.    StructSz,
  99.    table, 
  100.    keys,
  101.    columns);
  102.   
  103.   for(int i = 0; i<tabColumns; i++){
  104.     const NdbDictionary::Column * col = table->getColumn(i);
  105.     if(col->getPrimaryKey()){
  106.       if(!keys->exists(i)){
  107. DBA__SetLatestError(DBA_APPLICATION_ERROR, 0,
  108.     "Key column: %s not specified in binding",
  109.     col->getName());
  110. free(keys); free(columns);
  111. DBA_DestroyBinding(bindings);
  112. return 0;
  113.       }
  114.     }
  115.   }
  116.   
  117.   free(keys); free(columns);
  118.   
  119.   DBA__ValidBinding(bindings);
  120.   return bindings;
  121. }
  122. DBA_Binding_t *
  123. createBinding(const char* TableName, 
  124.       int NbCol,
  125.       const DBA_ColumnBinding_t ColsBindings[],
  126.       Size_t StructSz,
  127.       const NdbDictionary::Table * table, 
  128.       struct DBA__Array * keys,
  129.       struct DBA__Array * columns){
  130.   /**
  131.    * Counters for this part of binding
  132.    */
  133.   int noOfKeys        = 0;
  134.   int noOfColumns     = 0;
  135.   int noOfSubBindings = 0;
  136.   /**
  137.    * Check names and types and sizes
  138.    */
  139.   for(int i = 0; i<NbCol; i++){
  140.     if(ColsBindings[i].Ptr){
  141.       /**
  142.        * Pointer binding
  143.        */
  144.       noOfSubBindings ++;
  145.       DBA_Binding_t * tmp = createBinding(TableName,
  146.   ColsBindings[i].Size,
  147.   ColsBindings[i].SubBinding,
  148.   StructSz,
  149.   table,
  150.   keys,
  151.   columns);
  152.       DBA__ValidBinding(tmp);
  153.       
  154.       if(tmp == 0){
  155. // createBindings have already set latestError
  156. return 0;
  157.       }
  158.       
  159.       DBA_DestroyBinding(tmp);
  160.     } else {
  161.       const NdbDictionary::Column * col = 
  162. table->getColumn(ColsBindings[i].Name);
  163.       const Uint32 attrId = col->getColumnNo();
  164.       if(col == 0){
  165. DBA__SetLatestError(DBA_APPLICATION_ERROR, 0,
  166.     "Unknown column: %s", ColsBindings[i].Name);
  167. return 0;
  168.       }
  169.       const NdbDictionary::Column::Type type = col->getType();
  170.       if(!matchType(type, ColsBindings[i].DataType)){
  171. DBA_DEBUG("Incorrect type for: " << ColsBindings[i].Name);
  172. DBA_DEBUG("type: " << type);
  173. DBA_DEBUG("ColsBindings[i].DataType: " << ColsBindings[i].DataType);
  174. DBA__SetLatestError(DBA_APPLICATION_ERROR, 0,
  175.     "Incorrect type for column: %s", 
  176.     ColsBindings[i].Name);
  177. return 0;
  178.       }
  179.       if(!matchSize(type, col->getLength(), ColsBindings[i].Size)){
  180. DBA_DEBUG("Incorrect size for: " << ColsBindings[i].Name);
  181. DBA_DEBUG("type: " << type);
  182. DBA_DEBUG("length: " << col->getLength());
  183. DBA_DEBUG("ColsBindings[i].Size" << (Uint64)ColsBindings[i].Size);
  184. DBA__SetLatestError(DBA_APPLICATION_ERROR, 0,
  185.     "Incorrect size for column: %s", 
  186.     ColsBindings[i].Name);
  187. return 0;
  188.       }
  189.       
  190.       if(col->getPrimaryKey()){
  191. noOfKeys++;
  192.       } else {
  193. noOfColumns++;
  194.       }
  195.       
  196.       /**
  197.        * Check only in "validate" phase
  198.        */
  199.       if(columns != 0 && keys != 0){
  200. if(columns->exists(attrId) || keys->exists(attrId)){
  201.   DBA_DEBUG("Column bound multiple times: " << ColsBindings[i].Name);
  202.   
  203.   DBA__SetLatestError(DBA_APPLICATION_ERROR, 0,
  204.       "Column bound multiple times: %s",
  205.       ColsBindings[i].Name);
  206.   return 0;
  207. }
  208. if(col->getPrimaryKey()){
  209.   keys->insert(attrId);
  210. } else {
  211.   columns->insert(attrId);
  212. }
  213.       }
  214.     }
  215.   }
  216.   
  217.   /**
  218.    * Validation is all set
  219.    */
  220.   
  221.   /**
  222.    * Allocate memory
  223.    */
  224.   const int szOfStruct = 
  225.     sizeof(DBA_Binding_t)
  226.     + strlen(TableName) + 4
  227.     + (2 * sizeof(int) * noOfKeys)
  228.     + (2 * sizeof(int) * noOfColumns)
  229.     + ((sizeof(struct DBA_Binding *) + sizeof(int)) * noOfSubBindings)
  230.     - 4;
  231.   
  232.   DBA_Binding * ret = (DBA_Binding *)malloc(szOfStruct);
  233.   if(ret == 0){
  234.     DBA__SetLatestError(DBA_ERROR, 0,
  235. "malloc(%d) failed", szOfStruct);
  236.     return 0;
  237.   }
  238.   
  239.   for(int i = 0; i<DBA__MagicLength; i++)
  240.     ret->magic[i] = DBA__TheMagic[i];
  241.   
  242.   ret->noOfKeys          = noOfKeys;
  243.   ret->noOfColumns       = noOfColumns;
  244.   ret->noOfSubBindings   = noOfSubBindings;
  245.   ret->keyIds            = (int *)&(ret->data[0]);
  246.   ret->keyOffsets        = ret->keyIds + noOfKeys;
  247.   ret->columnIds         = ret->keyOffsets + noOfKeys;
  248.   ret->columnOffsets     = ret->columnIds + noOfColumns;
  249.   ret->subBindingOffsets = ret->columnOffsets + noOfColumns;
  250.   ret->subBindings       = (DBA_Binding **)
  251.     (ret->subBindingOffsets + noOfSubBindings);
  252.   
  253.   ret->tableName         = (char *)(ret->subBindings + noOfSubBindings);
  254.   ret->structSz          = StructSz;
  255.   ret->checkSum          = computeChecksum(ret);
  256.   /**
  257.    * Populate arrays
  258.    */
  259.   strcpy(ret->tableName, TableName);
  260.   int k = 0;
  261.   int c = 0;
  262.   int p = 0;
  263.   for(int i = 0; i<NbCol; i++){
  264.     if(ColsBindings[i].Ptr){
  265.       ret->subBindings[p] = createBinding(TableName,
  266.   ColsBindings[i].Size,
  267.   ColsBindings[i].SubBinding,
  268.   StructSz,
  269.   table, 
  270.   0, 
  271.   0);
  272.       
  273.       DBA__ValidBinding(ret->subBindings[p]);
  274.       ret->subBindingOffsets[p] = ColsBindings[i].Offset;
  275.       p++;
  276.     } else {
  277.       const NdbDictionary::Column * col = 
  278. table->getColumn(ColsBindings[i].Name);
  279.       if(col->getPrimaryKey()){
  280. ret->keyIds[k]     = col->getColumnNo();
  281. ret->keyOffsets[k] = ColsBindings[i].Offset;
  282. k++;
  283.       } else {
  284. ret->columnIds[c]     = col->getColumnNo();
  285. ret->columnOffsets[c] = ColsBindings[i].Offset;
  286. c++;
  287.       }
  288.     }  
  289.   }
  290.   
  291.   return ret;
  292. }
  293. extern "C"
  294. DBA_Error_t 
  295. DBA_DestroyBinding( DBA_Binding_t* Binding ){
  296.   for(int i = 0; i<Binding->noOfSubBindings; i++)
  297.     DBA_DestroyBinding(Binding->subBindings[i]);
  298.   
  299.   free(Binding);
  300.   
  301.   return DBA_NO_ERROR;
  302. }
  303. static
  304. bool
  305. matchType(NdbDictionary::Column::Type t1, DBA_DataTypes_t t2){
  306.   for(int i = 0; i<DBA__NoOfMappings; i++)
  307.     if(DBA__DataTypesMappings[i].newtonType == t2 &&
  308.        DBA__DataTypesMappings[i].ndbType    == t1)
  309.       return true;
  310.   return false;
  311. }
  312. static
  313. bool
  314. matchSize(NdbDictionary::Column::Type t, unsigned b, Size_t s) {
  315.   switch(t){
  316.   case NdbDictionary::Column::Int:
  317.   case NdbDictionary::Column::Unsigned:
  318.   case NdbDictionary::Column::Float:
  319.     return (4 * b) == s;
  320.   case NdbDictionary::Column::Bigint:
  321.   case NdbDictionary::Column::Bigunsigned:
  322.   case NdbDictionary::Column::Double:
  323.     return (8 * b) == s;
  324.   case NdbDictionary::Column::Decimal:
  325.   case NdbDictionary::Column::Char:
  326.   case NdbDictionary::Column::Binary:
  327.     return (1 * b) == s;
  328.   case NdbDictionary::Column::Varchar:
  329.   case NdbDictionary::Column::Varbinary:
  330.   case NdbDictionary::Column::Datetime:
  331.   case NdbDictionary::Column::Timespec:
  332.   case NdbDictionary::Column::Blob:
  333.   case NdbDictionary::Column::Tinyint:
  334.   case NdbDictionary::Column::Tinyunsigned:
  335.   case NdbDictionary::Column::Smallint:
  336.   case NdbDictionary::Column::Smallunsigned:
  337.   case NdbDictionary::Column::Mediumint:
  338.   case NdbDictionary::Column::Mediumunsigned:
  339.   case NdbDictionary::Column::Undefined:
  340.     return false;
  341.   }
  342.   return false;
  343. }
  344. bool
  345. DBA__ValidBinding(const DBA_Binding_t * bindings){
  346.   if(bindings == 0){
  347.     DBA_DEBUG("Null pointer passed to validBinding");
  348.     return false;
  349.   }
  350.   
  351.   for(int i = 0; i<DBA__MagicLength; i++)
  352.     if(bindings->magic[i] != DBA__TheMagic[i]){
  353.       DBA_DEBUG("Invalid magic in validBinding");
  354.       return false;
  355.     }
  356.   
  357.   const int cs = computeChecksum(bindings);
  358.   if(cs != bindings->checkSum){
  359.     DBA_DEBUG("Invalid checksum in validBinding");
  360.     DBA_DEBUG("cs = " << cs << " b->cs= " << bindings->checkSum);
  361.     return false;
  362.   }
  363.   return true;
  364. }
  365. bool
  366. DBA__ValidBindings(const DBA_Binding_t * const * pBindings, int n){
  367.   for(int i = 0; i<n; i++)
  368.     if(!DBA__ValidBinding(pBindings[i]))
  369.       return false;
  370.   return true;
  371. }
  372. /**
  373.  * Note: currently only checksum "static" part of struct
  374.  */
  375. static
  376. int
  377. computeChecksum(const DBA_Binding_t * bindings){
  378.   int sum = 0;
  379.   int pos = 0;
  380.   const char * ptr = ((const char *)bindings)+DBA__MagicLength+sizeof(int);
  381.   const int sz = sizeof(DBA_Binding_t) - DBA__MagicLength - sizeof(int) - 4;
  382.   for(int i = 0; i<sz; i++){
  383.     sum += ((int)ptr[i]) << pos;
  384.     pos += 8;
  385.     if(pos == 32)
  386.       pos = 0;
  387.   }
  388.   
  389.   return sum;
  390. }
  391. int
  392. DBA__GetStructSize(const DBA_Binding_t * bind){
  393.   if(!DBA__ValidBinding(bind))
  394.     return 0;
  395.   return bind->structSz;
  396. }