diff options
Diffstat (limited to 'storage/ndb/src/old_files/newtonapi/dba_binding.cpp')
-rw-r--r-- | storage/ndb/src/old_files/newtonapi/dba_binding.cpp | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/storage/ndb/src/old_files/newtonapi/dba_binding.cpp b/storage/ndb/src/old_files/newtonapi/dba_binding.cpp new file mode 100644 index 00000000000..63e48110b1d --- /dev/null +++ b/storage/ndb/src/old_files/newtonapi/dba_binding.cpp @@ -0,0 +1,439 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "dba_internal.hpp" + +static bool matchType(NdbDictionary::Column::Type, DBA_DataTypes_t); +static bool matchSize(NdbDictionary::Column::Type, unsigned, Size_t); +static int computeChecksum(const DBA_Binding_t * bindings); + +struct DBA__Array { + int count; + int data[1]; + + bool exists(int value) const { + for(int i = 0; i<count; i++) + if(data[i] == value) + return true; + return false; + } + + void insert(int value){ + data[count] = value; + count++; + } +}; + +/** + * createBindings + */ +static +DBA_Binding_t * +createBinding(const char* TableName, + int NbCol, + const DBA_ColumnBinding_t ColsBindings[], + Size_t StructSz, + const NdbDictionary::Table * theTable, + struct DBA__Array * keys, + struct DBA__Array * columns); + +extern "C" +DBA_Binding_t * +DBA_CreateBinding( const char* TableName, + int NbCol, + const DBA_ColumnBinding_t ColsBindings[], + Size_t StructSz ){ + + NdbDictionary::Dictionary * dict = DBA__TheNdb->getDictionary(); + if(dict == 0){ + DBA__SetLatestError(DBA_NDB_ERROR, 0, + "Internal NDB error: No dictionary"); + return 0; + } + + const NdbDictionary::Table * table = dict->getTable(TableName); + if(table == 0){ + DBA__SetLatestError(DBA_APPLICATION_ERROR, 0, + "No such table: %s", TableName); + return 0; + } + + /** + * Keys/Columns in table + */ + const int tabColumns = table->getNoOfColumns(); + const int tabKeys = table->getNoOfPrimaryKeys(); + + /** + * Ok, ok... I alloc four bytes extra so what... + */ + struct DBA__Array * keys = (struct DBA__Array *)malloc + (sizeof(struct DBA__Array)+tabKeys*sizeof(int)); + + if(keys == 0){ + DBA__SetLatestError(DBA_ERROR, 0, + "malloc(%d) failed", + sizeof(struct DBA__Array)+tabKeys*sizeof(int)); + return 0; + } + + struct DBA__Array * columns = (struct DBA__Array *)malloc + (sizeof(struct DBA__Array)+tabColumns*sizeof(int)); + + if(columns == 0){ + DBA__SetLatestError(DBA_ERROR, 0, + "malloc(%d) failed", + sizeof(struct DBA__Array)+tabColumns*sizeof(int)); + free(keys); + return 0; + } + + columns->count = 0; + keys->count = 0; + + DBA_Binding_t * bindings = createBinding(TableName, + NbCol, + ColsBindings, + StructSz, + table, + keys, + columns); + + for(int i = 0; i<tabColumns; i++){ + const NdbDictionary::Column * col = table->getColumn(i); + if(col->getPrimaryKey()){ + if(!keys->exists(i)){ + DBA__SetLatestError(DBA_APPLICATION_ERROR, 0, + "Key column: %s not specified in binding", + col->getName()); + + free(keys); free(columns); + DBA_DestroyBinding(bindings); + return 0; + } + } + } + + free(keys); free(columns); + + DBA__ValidBinding(bindings); + + return bindings; +} + +DBA_Binding_t * +createBinding(const char* TableName, + int NbCol, + const DBA_ColumnBinding_t ColsBindings[], + Size_t StructSz, + const NdbDictionary::Table * table, + struct DBA__Array * keys, + struct DBA__Array * columns){ + /** + * Counters for this part of binding + */ + int noOfKeys = 0; + int noOfColumns = 0; + int noOfSubBindings = 0; + + /** + * Check names and types and sizes + */ + for(int i = 0; i<NbCol; i++){ + if(ColsBindings[i].Ptr){ + /** + * Pointer binding + */ + noOfSubBindings ++; + + DBA_Binding_t * tmp = createBinding(TableName, + ColsBindings[i].Size, + ColsBindings[i].SubBinding, + StructSz, + table, + keys, + columns); + DBA__ValidBinding(tmp); + + if(tmp == 0){ + // createBindings have already set latestError + return 0; + } + + DBA_DestroyBinding(tmp); + } else { + const NdbDictionary::Column * col = + table->getColumn(ColsBindings[i].Name); + const Uint32 attrId = col->getColumnNo(); + + if(col == 0){ + DBA__SetLatestError(DBA_APPLICATION_ERROR, 0, + "Unknown column: %s", ColsBindings[i].Name); + return 0; + } + const NdbDictionary::Column::Type type = col->getType(); + if(!matchType(type, ColsBindings[i].DataType)){ + DBA_DEBUG("Incorrect type for: " << ColsBindings[i].Name); + DBA_DEBUG("type: " << type); + DBA_DEBUG("ColsBindings[i].DataType: " << ColsBindings[i].DataType); + + DBA__SetLatestError(DBA_APPLICATION_ERROR, 0, + "Incorrect type for column: %s", + ColsBindings[i].Name); + + return 0; + } + + if(!matchSize(type, col->getLength(), ColsBindings[i].Size)){ + DBA_DEBUG("Incorrect size for: " << ColsBindings[i].Name); + DBA_DEBUG("type: " << type); + DBA_DEBUG("length: " << col->getLength()); + DBA_DEBUG("ColsBindings[i].Size" << (Uint64)ColsBindings[i].Size); + + DBA__SetLatestError(DBA_APPLICATION_ERROR, 0, + "Incorrect size for column: %s", + ColsBindings[i].Name); + return 0; + } + + if(col->getPrimaryKey()){ + noOfKeys++; + } else { + noOfColumns++; + } + + /** + * Check only in "validate" phase + */ + if(columns != 0 && keys != 0){ + if(columns->exists(attrId) || keys->exists(attrId)){ + DBA_DEBUG("Column bound multiple times: " << ColsBindings[i].Name); + + DBA__SetLatestError(DBA_APPLICATION_ERROR, 0, + "Column bound multiple times: %s", + ColsBindings[i].Name); + return 0; + } + + if(col->getPrimaryKey()){ + keys->insert(attrId); + } else { + columns->insert(attrId); + } + } + } + } + + /** + * Validation is all set + */ + + /** + * Allocate memory + */ + const int szOfStruct = + sizeof(DBA_Binding_t) + + strlen(TableName) + 4 + + (2 * sizeof(int) * noOfKeys) + + (2 * sizeof(int) * noOfColumns) + + ((sizeof(struct DBA_Binding *) + sizeof(int)) * noOfSubBindings) + - 4; + + DBA_Binding * ret = (DBA_Binding *)malloc(szOfStruct); + if(ret == 0){ + DBA__SetLatestError(DBA_ERROR, 0, + "malloc(%d) failed", szOfStruct); + return 0; + } + + for(int i = 0; i<DBA__MagicLength; i++) + ret->magic[i] = DBA__TheMagic[i]; + + ret->noOfKeys = noOfKeys; + ret->noOfColumns = noOfColumns; + ret->noOfSubBindings = noOfSubBindings; + + ret->keyIds = (int *)&(ret->data[0]); + ret->keyOffsets = ret->keyIds + noOfKeys; + + ret->columnIds = ret->keyOffsets + noOfKeys; + ret->columnOffsets = ret->columnIds + noOfColumns; + + ret->subBindingOffsets = ret->columnOffsets + noOfColumns; + ret->subBindings = (DBA_Binding **) + (ret->subBindingOffsets + noOfSubBindings); + + ret->tableName = (char *)(ret->subBindings + noOfSubBindings); + ret->structSz = StructSz; + ret->checkSum = computeChecksum(ret); + + /** + * Populate arrays + */ + strcpy(ret->tableName, TableName); + + int k = 0; + int c = 0; + int p = 0; + + for(int i = 0; i<NbCol; i++){ + if(ColsBindings[i].Ptr){ + ret->subBindings[p] = createBinding(TableName, + ColsBindings[i].Size, + ColsBindings[i].SubBinding, + StructSz, + table, + 0, + 0); + + DBA__ValidBinding(ret->subBindings[p]); + + ret->subBindingOffsets[p] = ColsBindings[i].Offset; + p++; + } else { + const NdbDictionary::Column * col = + table->getColumn(ColsBindings[i].Name); + + if(col->getPrimaryKey()){ + ret->keyIds[k] = col->getColumnNo(); + ret->keyOffsets[k] = ColsBindings[i].Offset; + k++; + } else { + ret->columnIds[c] = col->getColumnNo(); + ret->columnOffsets[c] = ColsBindings[i].Offset; + c++; + } + } + } + + return ret; +} + + +extern "C" +DBA_Error_t +DBA_DestroyBinding( DBA_Binding_t* Binding ){ + + for(int i = 0; i<Binding->noOfSubBindings; i++) + DBA_DestroyBinding(Binding->subBindings[i]); + + free(Binding); + + return DBA_NO_ERROR; +} + +static +bool +matchType(NdbDictionary::Column::Type t1, DBA_DataTypes_t t2){ + for(int i = 0; i<DBA__NoOfMappings; i++) + if(DBA__DataTypesMappings[i].newtonType == t2 && + DBA__DataTypesMappings[i].ndbType == t1) + return true; + return false; +} + +static +bool +matchSize(NdbDictionary::Column::Type t, unsigned b, Size_t s) { + switch(t){ + case NdbDictionary::Column::Int: + case NdbDictionary::Column::Unsigned: + case NdbDictionary::Column::Float: + return (4 * b) == s; + case NdbDictionary::Column::Bigint: + case NdbDictionary::Column::Bigunsigned: + case NdbDictionary::Column::Double: + return (8 * b) == s; + case NdbDictionary::Column::Decimal: + case NdbDictionary::Column::Char: + case NdbDictionary::Column::Binary: + return (1 * b) == s; + case NdbDictionary::Column::Varchar: + case NdbDictionary::Column::Varbinary: + case NdbDictionary::Column::Datetime: + case NdbDictionary::Column::Timespec: + case NdbDictionary::Column::Blob: + case NdbDictionary::Column::Tinyint: + case NdbDictionary::Column::Tinyunsigned: + case NdbDictionary::Column::Smallint: + case NdbDictionary::Column::Smallunsigned: + case NdbDictionary::Column::Mediumint: + case NdbDictionary::Column::Mediumunsigned: + case NdbDictionary::Column::Undefined: + return false; + } + return false; +} + +bool +DBA__ValidBinding(const DBA_Binding_t * bindings){ + if(bindings == 0){ + DBA_DEBUG("Null pointer passed to validBinding"); + return false; + } + + for(int i = 0; i<DBA__MagicLength; i++) + if(bindings->magic[i] != DBA__TheMagic[i]){ + DBA_DEBUG("Invalid magic in validBinding"); + return false; + } + + const int cs = computeChecksum(bindings); + if(cs != bindings->checkSum){ + DBA_DEBUG("Invalid checksum in validBinding"); + DBA_DEBUG("cs = " << cs << " b->cs= " << bindings->checkSum); + return false; + } + + return true; +} + +bool +DBA__ValidBindings(const DBA_Binding_t * const * pBindings, int n){ + for(int i = 0; i<n; i++) + if(!DBA__ValidBinding(pBindings[i])) + return false; + return true; +} + +/** + * Note: currently only checksum "static" part of struct + */ +static +int +computeChecksum(const DBA_Binding_t * bindings){ + int sum = 0; + int pos = 0; + const char * ptr = ((const char *)bindings)+DBA__MagicLength+sizeof(int); + const int sz = sizeof(DBA_Binding_t) - DBA__MagicLength - sizeof(int) - 4; + + for(int i = 0; i<sz; i++){ + sum += ((int)ptr[i]) << pos; + pos += 8; + if(pos == 32) + pos = 0; + } + + return sum; +} + +int +DBA__GetStructSize(const DBA_Binding_t * bind){ + if(!DBA__ValidBinding(bind)) + return 0; + return bind->structSz; +} |