mariadb/storage/ndb/test/ndbapi/ScanInterpretTest.hpp

515 lines
13 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 */
#ifndef SCAN_INTERPRET_TEST_HPP
#define SCAN_INTERPRET_TEST_HPP
#include "ScanFilter.hpp"
class ScanInterpretTest {
public:
ScanInterpretTest(const NdbDictionary::Table& _tab,
const NdbDictionary::Table& _restab) :
tab(_tab),
restab(_restab),
row(_tab){
}
int scanRead(Ndb*,
int records,
int parallelism,
ScanFilter& filter);
int scanReadVerify(Ndb*,
int records,
int parallelism,
ScanFilter& filter);
int addRowToInsert(Ndb* pNdb,
NdbConnection* pInsTrans);
int addRowToCheckTrans(Ndb* pNdb,
NdbConnection* pCheckTrans);
private:
const NdbDictionary::Table& tab;
const NdbDictionary::Table& restab;
NDBT_ResultRow row;
};
inline
int
ScanInterpretTest::addRowToInsert(Ndb* pNdb,
NdbConnection* pInsTrans){
NdbOperation* pOp =
pInsTrans->getNdbOperation(restab.getName());
if (pOp == NULL) {
ERR(pInsTrans->getNdbError());
pNdb->closeTransaction(pInsTrans);
return NDBT_FAILED;
}
if( pOp->insertTuple() == -1 ) {
ERR(pInsTrans->getNdbError());
pNdb->closeTransaction(pInsTrans);
return NDBT_FAILED;
}
// Copy all attribute to the new operation
for (int a = 0; a<restab.getNoOfColumns(); a++){
const NdbDictionary::Column* attr = tab.getColumn(a);
NdbRecAttr* reca = row.attributeStore(a);
int check = -1;
switch (attr->getType()){
case NdbDictionary::Column::Char:
case NdbDictionary::Column::Varchar:
case NdbDictionary::Column::Binary:
case NdbDictionary::Column::Varbinary:{
check = pOp->setValue( attr->getName(),
reca->aRef());
break;
}
case NdbDictionary::Column::Int:{
check = pOp->setValue( attr->getName(),
reca->int32_value());
}
break;
case NdbDictionary::Column::Bigint:{
check = pOp->setValue( attr->getName(),
reca->int64_value());
}
break;
case NdbDictionary::Column::Unsigned:{
check = pOp->setValue( attr->getName(),
reca->u_32_value());
}
break;
case NdbDictionary::Column::Bigunsigned:{
check = pOp->setValue( attr->getName(),
reca->u_64_value());
}
break;
case NdbDictionary::Column::Float:
check = pOp->setValue( attr->getName(),
reca->float_value());
break;
default:
check = -1;
break;
}
if(check != 0){
ERR(pInsTrans->getNdbError());
pNdb->closeTransaction(pInsTrans);
return NDBT_FAILED;
}
}
return NDBT_OK;
}
inline
int
ScanInterpretTest::addRowToCheckTrans(Ndb* pNdb,
NdbConnection* pCheckTrans){
NdbOperation* pOp =
pCheckTrans->getNdbOperation(restab.getName());
if (pOp == NULL) {
ERR(pNdb->getNdbError());
return NDBT_FAILED;
}
if(pOp->readTuple() != 0) {
ERR(pNdb->getNdbError());
return NDBT_FAILED;
}
// Copy pk attribute's to the new operation
for (int a = 0; a<restab.getNoOfColumns(); a++){
const NdbDictionary::Column* attr = restab.getColumn(a);
if (attr->getPrimaryKey() == true){
NdbRecAttr* reca = row.attributeStore(a);
int check = -1;
switch (attr->getType()){
case NdbDictionary::Column::Char:
case NdbDictionary::Column::Varchar:
case NdbDictionary::Column::Binary:
case NdbDictionary::Column::Varbinary:{
check = pOp->equal( attr->getName(),
reca->aRef());
break;
}
case NdbDictionary::Column::Int:{
check = pOp->equal( attr->getName(),
reca->int32_value());
}
break;
case NdbDictionary::Column::Bigint:{
check = pOp->equal( attr->getName(),
reca->int64_value());
}
break;
case NdbDictionary::Column::Unsigned:{
check = pOp->equal( attr->getName(),
reca->u_32_value());
}
break;
case NdbDictionary::Column::Bigunsigned:{
check = pOp->equal( attr->getName(),
reca->u_64_value());
}
break;
default:
check = -1;
break;
}
if(check != 0){
ERR(pNdb->getNdbError());
return NDBT_FAILED;
}
}
}
return NDBT_OK;
}
inline
int
ScanInterpretTest::scanRead(Ndb* pNdb,
int records,
int parallelism,
ScanFilter& filter){
int retryAttempt = 0;
int retryMax = 100;
int check;
NdbConnection *pTrans;
NdbScanOperation *pOp;
while (true){
if (retryAttempt >= retryMax){
ndbout << "ERROR: has retried this operation " << retryAttempt
<< " times, failing!" << endl;
return NDBT_FAILED;
}
pTrans = pNdb->startTransaction();
if (pTrans == NULL) {
const NdbError err = pNdb->getNdbError();
if (err.status == NdbError::TemporaryError){
ERR(err);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
return NDBT_FAILED;
}
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
if (filter.filterOp(pOp) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
// Read all attributes
for(int a = 0; a<tab.getNoOfColumns(); a++){
if((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
}
check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
int eof;
int rows = 0;
NdbConnection* pInsTrans;
while((eof = pOp->nextResult(true)) == 0){
do {
rows++;
if (addRowToInsert(pNdb, pTrans) != 0){
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
} while((eof = pOp->nextResult(false)) == 0);
check = pTrans->execute(Commit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
ERR(err);
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
g_info << rows << " rows have been scanned" << endl;
return NDBT_OK;
}
return NDBT_FAILED;
}
inline
int
ScanInterpretTest::scanReadVerify(Ndb* pNdb,
int records,
int parallelism,
ScanFilter& filter){
int retryAttempt = 0;
const int retryMax = 100;
int check;
NdbConnection *pTrans;
NdbScanOperation *pOp;
while (true){
if (retryAttempt >= retryMax){
ndbout << "ERROR: has retried this operation " << retryAttempt
<< " times, failing!" << endl;
return NDBT_FAILED;
}
pTrans = pNdb->startTransaction();
if (pTrans == NULL) {
const NdbError err = pNdb->getNdbError();
if (err.status == NdbError::TemporaryError){
ERR(err);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
return NDBT_FAILED;
}
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) { if (pOp->getValue("KOL2") == 0){
ERR(pNdb->getNdbError());
return NDBT_FAILED;
}
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
check = pOp->interpret_exit_ok();
if (check == -1) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
// Read all attributes
for(int a = 0; a<tab.getNoOfColumns(); a++){
if((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
}
check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
int eof;
int rows = 0;
int rowsNoExist = 0;
int rowsExist = 0;
int existingRecordsNotFound = 0;
int nonExistingRecordsFound = 0;
NdbConnection* pExistTrans;
NdbConnection* pNoExistTrans;
while((eof = pOp->nextResult(true)) == 0){
pExistTrans = pNdb->startTransaction();
if (pExistTrans == NULL) {
const NdbError err = pNdb->getNdbError();
ERR(err);
return NDBT_FAILED;
}
pNoExistTrans = pNdb->startTransaction();
if (pNoExistTrans == NULL) {
const NdbError err = pNdb->getNdbError();
ERR(err);
return NDBT_FAILED;
}
do {
rows++;
if (filter.verifyRecord(row) == NDBT_OK){
rowsExist++;
if (addRowToCheckTrans(pNdb, pExistTrans) != 0){
pNdb->closeTransaction(pTrans);
pNdb->closeTransaction(pExistTrans);
pNdb->closeTransaction(pNoExistTrans);
return NDBT_FAILED;
}
}else{
rowsNoExist++;
if (addRowToCheckTrans(pNdb, pNoExistTrans) != 0){
pNdb->closeTransaction(pTrans);
pNdb->closeTransaction(pExistTrans);
pNdb->closeTransaction(pNoExistTrans);
return NDBT_FAILED;
}
}
} while((eof = pOp->nextResult(false)) == 0);
// Execute the transaction containing reads of
// all the records that should be in the result table
check = pExistTrans->execute(Commit);
if( check == -1 ) {
const NdbError err = pExistTrans->getNdbError();
ERR(err);
if (err.code != 626){
pNdb->closeTransaction(pExistTrans);
pNdb->closeTransaction(pNoExistTrans);
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}else{
// Some of the records expected to be found wasn't
// there
existingRecordsNotFound = 1;
}
}
pNdb->closeTransaction(pExistTrans);
// Execute the transaction containing reads of
// all the records that should NOT be in the result table
check = pNoExistTrans->execute(Commit, CommitAsMuchAsPossible);
if( check == -1 ) {
const NdbError err = pNoExistTrans->getNdbError();
// The transactions error code should be zero
if (err.code != 626){
ERR(err);
pNdb->closeTransaction(pNoExistTrans);
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
// Loop through the no existing transaction and check that no
// operations where successful
const NdbOperation* pOp2 = NULL;
while ((pOp2 = pNoExistTrans->getNextCompletedOperation(pOp2)) != NULL){
const NdbError err = pOp2->getNdbError();
if (err.code != 626){
ndbout << "err.code = " << err.code<< endl;
nonExistingRecordsFound = 1;
}
}
}
pNdb->closeTransaction(pNoExistTrans);
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
int testResult = NDBT_OK;
int rowsResult = 0;
UtilTransactions utilTrans(restab);
if (utilTrans.selectCount(pNdb,
240,
&rowsResult) != 0){
return NDBT_FAILED;
}
if (existingRecordsNotFound == 1){
ndbout << "!!! Expected records not found" << endl;
testResult = NDBT_FAILED;
}
if (nonExistingRecordsFound == 1){
ndbout << "!!! Unxpected records found" << endl;
testResult = NDBT_FAILED;
}
ndbout << rows << " rows scanned("
<< rowsExist << " found, " << rowsResult<<" expected)" << endl;
if (rowsResult != rowsExist){
ndbout << "!!! Number of rows in result table different from expected" << endl;
testResult = NDBT_FAILED;
}
return testResult;
}
return NDBT_FAILED;
}
#endif