mariadb/ndb/test/src/HugoCalculator.cpp
unknown fced35f74a ndb - fix new decimal type mysql vs. ndb
mysql-test/r/ndb_index_ordered.result:
  fix new decimal mysql vs. ndb
mysql-test/t/ndb_index_ordered.test:
  fix new decimal mysql vs. ndb
ndb/include/kernel/signaldata/DictTabInfo.hpp:
  fix new decimal mysql vs. ndb
ndb/include/ndb_constants.h:
  fix new decimal mysql vs. ndb
ndb/include/ndbapi/NdbDictionary.hpp:
  fix new decimal mysql vs. ndb
ndb/include/util/NdbSqlUtil.hpp:
  fix new decimal mysql vs. ndb
ndb/src/common/util/NdbSqlUtil.cpp:
  fix new decimal mysql vs. ndb
ndb/src/ndbapi/NdbDictionary.cpp:
  fix new decimal mysql vs. ndb
ndb/src/ndbapi/NdbDictionaryImpl.cpp:
  fix new decimal mysql vs. ndb
ndb/src/ndbapi/NdbRecAttr.cpp:
  fix new decimal mysql vs. ndb
ndb/test/include/NdbSchemaOp.hpp:
  fix new decimal mysql vs. ndb
ndb/test/src/HugoCalculator.cpp:
  fix new decimal mysql vs. ndb
ndb/tools/restore/consumer.cpp:
  fix new decimal mysql vs. ndb
sql/ha_ndbcluster.cc:
  fix new decimal mysql vs. ndb
2005-02-16 21:19:42 +01:00

267 lines
7.6 KiB
C++

/* 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 <ndb_global.h>
#include "HugoCalculator.hpp"
#include <NDBT.hpp>
#include <Base64.hpp>
static
Uint32
myRand(Uint64 * seed)
{
const Uint64 mul= 0x5deece66dull;
const Uint64 add= 0xb;
Uint64 loc_result = *seed * mul + add;
* seed= loc_result;
return loc_result >> 1;
}
static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
/* *************************************************************
* HugoCalculator
*
* Comon class for the Hugo test suite, provides the functions
* that is used for calculating values to load in to table and
* also knows how to verify a row that's been read from db
*
* ************************************************************/
HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) {
// The "id" column of this table is found in the first integer column
int i;
for (i=0; i<m_tab.getNoOfColumns(); i++){
const NdbDictionary::Column* attr = m_tab.getColumn(i);
if (attr->getType() == NdbDictionary::Column::Unsigned){
m_idCol = i;
break;
}
}
// The "number of updates" column for this table is found in the last column
for (i=m_tab.getNoOfColumns()-1; i>=0; i--){
const NdbDictionary::Column* attr = m_tab.getColumn(i);
if (attr->getType() == NdbDictionary::Column::Unsigned &&
!attr->getPrimaryKey()){
m_updatesCol = i;
break;
}
}
#if 0
ndbout << "idCol = " << m_idCol << endl;
ndbout << "updatesCol = " << m_updatesCol << endl;
#endif
// Check that idCol is not conflicting with updatesCol
assert(m_idCol != m_updatesCol && m_idCol != -1 && m_updatesCol != -1);
}
Int32
HugoCalculator::calcValue(int record,
int attrib,
int updates) const {
Int32 i;
calcValue(record, attrib, updates, (char*)&i, sizeof(i));
return i;
}
#if 0
HugoCalculator::U_Int32 calcValue(int record, int attrib, int updates) const;
HugoCalculator::U_Int64 calcValue(int record, int attrib, int updates) const;
HugoCalculator::Int64 calcValue(int record, int attrib, int updates) const;
HugoCalculator::float calcValue(int record, int attrib, int updates) const;
HugoCalculator::double calcValue(int record, int attrib, int updates) const;
#endif
const char*
HugoCalculator::calcValue(int record,
int attrib,
int updates,
char* buf,
int len) const {
Uint64 seed;
const NdbDictionary::Column* attr = m_tab.getColumn(attrib);
Uint32 val;
do
{
if (attrib == m_idCol)
{
val= record;
memcpy(buf, &val, 4);
return buf;
}
// If this is the update column
if (attrib == m_updatesCol)
{
val= updates;
memcpy(buf, &val, 4);
return buf;
}
if (attr->getPrimaryKey())
{
seed = record + attrib;
}
else
{
seed = record + attrib + updates;
}
} while (0);
val = myRand(&seed);
if(attr->getNullable() && (((val >> 16) & 255) > 220))
return NULL;
int pos= 0;
switch(attr->getType()){
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::Int:
case NdbDictionary::Column::Unsigned:
case NdbDictionary::Column::Bigint:
case NdbDictionary::Column::Bigunsigned:
case NdbDictionary::Column::Float:
case NdbDictionary::Column::Double:
case NdbDictionary::Column::Olddecimal:
case NdbDictionary::Column::Olddecimalunsigned:
case NdbDictionary::Column::Decimal:
case NdbDictionary::Column::Decimalunsigned:
case NdbDictionary::Column::Binary:
case NdbDictionary::Column::Datetime:
case NdbDictionary::Column::Time:
case NdbDictionary::Column::Date:
case NdbDictionary::Column::Bit:
while (len > 4)
{
memcpy(buf+pos, &val, 4);
pos += 4;
len -= 4;
val= myRand(&seed);
}
memcpy(buf+pos, &val, len);
if(attr->getType() == NdbDictionary::Column::Bit)
{
Uint32 bits= attr->getLength();
Uint32 tmp = bits >> 5;
Uint32 size = bits & 31;
((Uint32*)buf)[tmp] &= ((1 << size) - 1);
}
break;
case NdbDictionary::Column::Varbinary:
case NdbDictionary::Column::Varchar:
case NdbDictionary::Column::Text:
case NdbDictionary::Column::Char:
case NdbDictionary::Column::Longvarchar:
case NdbDictionary::Column::Longvarbinary:
{
char* ptr= (char*)&val;
while(len >= 4)
{
len -= 4;
buf[pos++] = base64_table[ptr[0] & 0x3f];
buf[pos++] = base64_table[ptr[1] & 0x3f];
buf[pos++] = base64_table[ptr[2] & 0x3f];
buf[pos++] = base64_table[ptr[3] & 0x3f];
val= myRand(&seed);
}
for(; len; len--, pos++)
buf[pos] = base64_table[ptr[len] & 0x3f];
pos--;
break;
}
case NdbDictionary::Column::Blob:
case NdbDictionary::Column::Undefined:
abort();
break;
}
return buf;
}
int
HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{
int id, updates;
id = pRow->attributeStore(m_idCol)->u_32_value();
updates = pRow->attributeStore(m_updatesCol)->u_32_value();
int result = 0;
// Check the values of each column
for (int i = 0; i<m_tab.getNoOfColumns(); i++){
if (i != m_updatesCol && id != m_idCol) {
const NdbDictionary::Column* attr = m_tab.getColumn(i);
Uint32 len = attr->getSizeInBytes();
char buf[8000];
const char* res = calcValue(id, i, updates, buf, len);
if (res == NULL){
if (!pRow->attributeStore(i)->isNULL()){
g_err << "|- NULL ERROR: expected a NULL but the column was not null" << endl;
g_err << "|- The row: \"" << (*pRow) << "\"" << endl;
result = -1;
}
} else{
if (memcmp(res, pRow->attributeStore(i)->aRef(), len) != 0){
g_err << "Column: " << attr->getName() << endl;
const char* buf2 = pRow->attributeStore(i)->aRef();
for (Uint32 j = 0; j < len; j++)
{
g_err << j << ":" << hex << (Uint32)(Uint8)buf[j] << "[" << hex << (Uint32)(Uint8)buf2[j] << "]";
if (buf[j] != buf2[j])
{
g_err << "==>Match failed!";
}
g_err << endl;
}
g_err << endl;
g_err << "|- Invalid data found in attribute " << i << ": \""
<< pRow->attributeStore(i)->aRef()
<< "\" != \"" << res << "\"" << endl
<< "Length of expected=" << (unsigned)strlen(res) << endl
<< "Lenght of read="
<< (unsigned)strlen(pRow->attributeStore(i)->aRef()) << endl;
g_err << "|- The row: \"" << (* pRow) << "\"" << endl;
result = -1;
}
}
}
}
return result;
}
int
HugoCalculator::getIdValue(NDBT_ResultRow* const pRow) const {
return pRow->attributeStore(m_idCol)->u_32_value();
}
int
HugoCalculator::getUpdatesValue(NDBT_ResultRow* const pRow) const {
return pRow->attributeStore(m_updatesCol)->u_32_value();
}