19 #include <NDBT_Test.hpp>
21 #define ERR_EXIT(obj, msg) \
24 fprintf(stderr, "%s: %s (%d) in %s:%d\n", \
25 msg, obj->getNdbError().message, obj->getNdbError().code, __FILE__, __LINE__); \
30 #define PRINT_ERROR(code,msg) \
33 fprintf(stderr, "Error in %s, line: %d, code: %d, msg: %s.\n", __FILE__, __LINE__, code, msg); \
37 #define MYSQLERROR(mysql) { \
38 PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
40 #define APIERROR(error) { \
41 PRINT_ERROR(error.code,error.message); \
44 #define TEST_NAME "TestScanFilter"
45 #define TABLE_NAME "TABLE_SCAN"
47 const char *COL_NAME[] = {
"id",
"i",
"j",
"k",
"l",
"m",
"n"};
48 const char COL_LEN = 7;
54 const int TUPLE_NUM = 1 << (COL_LEN - 1);
61 const int RECURSIVE_LEVEL = 10;
63 const int MAX_STR_LEN = (RECURSIVE_LEVEL * (COL_LEN+1) * 4);
74 const int TEST_NUM = 5000;
126 static const char* TABLE2_NAME=
"MyTab2";
132 static const int NUM_COLS=
sizeof(MYTAB2Attribs)/
sizeof(
NDBT_Attribute);
133 static const int MAX_BIT_WIDTH= 513;
135 static const int TOTAL_ROWS= MAX_BIT_WIDTH + 1;
138 bool existsOk, NDBT_CreateTableHook f)
143 tmpTab.setStoredTable(_temp ? 0 : 1);
144 if(f != 0 && f(pNdb, tmpTab, 0, NULL))
146 ndbout <<
"Failed to create table" << endl;
171 Ndb *myNdb = GETNDB(step);
181 for(
int num = 0; num < TUPLE_NUM; num++)
183 NdbOperation* myNdbOperation = myTrans->getNdbOperation(myTable);
184 if(myNdbOperation == NULL)
186 APIERROR(myTrans->getNdbError());
260 myNdbOperation->
equal(COL_NAME[0], num);
261 for(
int col = 1; col < COL_LEN; col++)
263 myNdbOperation->
setValue(COL_NAME[col], (num>>(COL_LEN-1-col))&1);
283 char op_string[] =
"aoAO";
287 char col_string[] =
"ijklmn";
288 const int op_len = strlen(op_string);
289 const int col_len = strlen(col_string);
294 int get_rand_op_ch(
char *ch)
296 static unsigned int num = 0;
299 srand(num*(
unsigned int)time(NULL));
300 *ch = op_string[rand() % op_len];
307 void change_col_order()
311 for (
int i = 0;
i < 10;
i++)
313 srand((
unsigned int)time(NULL)/(
i+1));
314 pos1 = rand() % col_len;
315 srand((
i+1)*(
unsigned int)time(NULL));
316 pos2 = rand() % col_len;
319 temp = col_string[pos1];
320 col_string[pos1] = col_string[pos2];
321 col_string[pos2] =
temp;
328 int get_rand_col_str(
char *str)
331 static unsigned int num = 0;
334 srand(num*(
unsigned int)time(NULL));
335 len = rand() % col_len + 1;
345 int get_rand_op_str(
char *str)
349 len1 = get_rand_op_ch(temp);
350 len2 = get_rand_col_str(temp+len1);
365 int replace_a_to_str(
char *source,
int pos,
char *newstr)
367 char temp[MAX_STR_LEN];
372 return strlen(source);
378 bool check_op(
char ch)
380 if( ch ==
'a' || ch ==
'A' || ch ==
'o' || ch ==
'O')
389 bool check_end(
char ch)
397 bool check_col(
char ch)
399 if( ch ==
'i' || ch ==
'j' || ch ==
'k'
400 || ch ==
'l' || ch ==
'm' || ch ==
'n' )
410 int get_rand_replace_pos(
char *str,
int len)
419 for(
int i = 0;
i < len;
i++)
422 if(! check_end(temp))
437 span = pos_x - pos_op - 1;
440 pos_col = pos_op + 1;
444 srand(num*(
unsigned int)time(NULL));
445 pos_col = pos_op + rand() % span + 1;
454 bool check_random_str(
char *str)
460 for(p = str; *p; p++)
462 bool tmp1 =
false, tmp2 =
false;
463 if ((tmp1 = check_op(*p)))
465 if ((tmp2 = check_end(*p)))
467 if (!(tmp1 || tmp2 || check_col(*p)))
471 if(op_num != end_num)
480 void get_rand_op_str_compound(
char *str)
491 srand(num*(
unsigned int)time(NULL));
492 level = 1 + rand() % RECURSIVE_LEVEL;
494 get_rand_op_str(str);
498 get_rand_op_str(small_str);
499 tmp = strlen(small_str);
500 get_rand_op_str(small_str + tmp);
501 pos = get_rand_replace_pos(str, strlen(str));
502 replace_a_to_str(str, pos, small_str);
506 if(!check_random_str(str))
508 fprintf(stderr,
"Error random string! \n");
516 int get_column_id(
char ch)
518 return (ch -
'i' + 1);
526 bool check_col_equal_one(
int tuple_no,
int col_id)
528 int i = 1 << (6 - col_id);
529 int j = tuple_no /
i;
541 bool AND_op(
bool *value,
int len)
543 for(
int i = 0; i < len; i++)
556 bool OR_op(
bool *value,
int len)
558 for(
int i = 0; i < len; i++)
571 bool NAND_op(
bool *value,
int len)
573 return (! AND_op(value, len));
581 bool NOR_op(
bool *value,
int len)
583 return (! OR_op(value, len));
589 bool calculate_one_op(
char op_type,
bool *value,
int len)
594 return AND_op(value, len);
597 return OR_op(value, len);
600 return NAND_op(value, len);
603 return NOR_op(value, len);
620 bool stack_col[RECURSIVE_LEVEL * COL_LEN * 2];
628 bool check_one_tuple(
int tuple_no,
char *str,
int len)
632 for(
int i = 0; i < len; i++)
634 char letter = *(str +
i);
637 stack_op[pop_op].type = letter;
638 stack_op[pop_op].num = 0;
641 if(check_col(letter))
643 stack_col[pop_col] = check_col_equal_one(tuple_no, get_column_id(letter));
645 stack_op[pop_op-1].num += 1;
647 if(check_end(letter))
651 return calculate_one_op(stack_op[pop_op-1].
type,
653 stack_op[pop_op-1].num);
657 bool tmp1 = calculate_one_op(stack_op[pop_op-1].
type,
658 stack_col + pop_col - stack_op[pop_op-1].num,
659 stack_op[pop_op-1].num);
660 pop_col -= stack_op[pop_op-1].num;
662 stack_col[pop_col] = tmp1;
664 stack_op[pop_op-1].num += 1;
675 void check_all_tuples(
char *str,
bool *res)
677 for (
int i = 0; i < TUPLE_NUM; i++)
679 if(check_one_tuple(i, str, strlen(str)))
695 fprintf(stderr,
"Invalid group name %c !\n", op_name);
709 for (p = str; *p; p++)
713 if(scanfilter->
begin(get_api_group(*p)))
714 ERR_EXIT(transaction,
"filter begin() failed");
719 ERR_EXIT(transaction,
"filter eq() failed");
723 if(scanfilter->
end())
726 printf(
"Problem closing ScanFilter= %d\n", err.
code);
727 ERR_EXIT(transaction,
"filter end() failed");
739 void ndbapi_tuples(
Ndb *ndb,
char *str,
bool *res)
743 ERR_EXIT(ndb,
"Can't get dict");
747 ERR_EXIT(dict,
"Can't get table"TABLE_NAME);
751 for(
int ii = 0; ii < COL_LEN; ii++)
754 col[ii] = table->
getColumn(COL_NAME[ii]);
768 ERR_EXIT(ndb,
"Can't start transaction");
772 ERR_EXIT(transaction,
"Can't get scan op");
775 ERR_EXIT(scan,
"Can't set up read");
778 for(
int ii = 0; ii < COL_LEN; ii++)
781 rec[ii] = scan->
getValue(COL_NAME[ii]);
789 filter = call_ndbapi(str, transaction, scan, col);
792 ERR_EXIT(transaction,
"Can't execute");
805 res[32*i+16*j+8*k+4*l+2*m+
n] =
true;
810 transaction->
close();
819 bool compare_cal_ndb(
char *str,
Ndb *ndb)
824 for(
int i = 0; i < TUPLE_NUM; i++)
826 res_cal.push_back(
false);
827 res_ndb.push_back(
false);
830 check_all_tuples(str, res_cal.getBase());
831 ndbapi_tuples(ndb, str, res_ndb.getBase());
833 for(
int i = 0; i < TUPLE_NUM; i++)
835 if(res_cal[i] != res_ndb[i])
844 Ndb *pNdb = GETNDB(step);
846 int ret = createTable(pNdb, &MYTAB1,
false,
true, 0);
855 int ret = GETNDB(step)->getDictionary()->dropTable(MYTAB1.
getName());
864 char random_str[MAX_STR_LEN];
865 Ndb *myNdb = GETNDB(step);
867 for(
int i = 0; i < TEST_NUM; i++)
869 get_rand_op_str_compound(random_str);
870 if( !compare_cal_ndb(random_str, myNdb))
883 const Uint32 MaxLength= NDB_MAX_SCANFILTER_SIZE_IN_WORDS;
885 const Uint32 InstructionWordsPerEq= 3;
887 const Uint32 MaxEqsInScanFilter= MaxLength/InstructionWordsPerEq;
889 Ndb *myNdb = GETNDB(step);
901 ndbout <<
"Bad rc from begin\n";
902 ndbout << sf.getNdbError() <<
"\n";
908 for (;loop < MaxEqsInScanFilter; loop++)
912 ndbout <<
"Bad rc from eq at loop " << loop <<
"\n";
913 ndbout << sf.getNdbError() <<
"\n";
918 if (! sf.eq(0u, 10u))
920 ndbout <<
"Expected ScanFilter instruction addition to fail after"
921 << MaxEqsInScanFilter <<
"iterations, but it didn't\n";
927 if (err.
code != 4294)
929 ndbout <<
"Expected to get error code 4294, but instead got " << err.
code <<
"\n";
943 Ndb *myNdb = GETNDB(step);
953 APIERROR(trans->getNdbError());
963 APIERROR(trans->getNdbError());
976 ndbout <<
"Expected error 4536, had error " <<
982 if (brokenSf.getNdbError().code != 4539)
984 ndbout <<
"Expected error 4539, had error " <<
985 brokenSf.getNdbError().code <<
" instead" << endl;
989 if (brokenSf.begin() != -1)
990 { ndbout <<
"Bad rc from begin" << endl;
return NDBT_FAILED; }
992 if (brokenSf.istrue() != -1)
993 { ndbout <<
"Bad rc from istrue" << endl;
return NDBT_FAILED; }
995 if (brokenSf.isfalse() != -1)
996 { ndbout <<
"Bad rc from isfalse" << endl;
return NDBT_FAILED; }
998 if (brokenSf.isnull(0) != -1)
999 { ndbout <<
"Bad rc from isnull" << endl;
return NDBT_FAILED; }
1001 if (brokenSf.isnotnull(0) != -1)
1002 { ndbout <<
"Bad rc from isnotnull" << endl;
return NDBT_FAILED; }
1005 { ndbout <<
"Bad rc from cmp" << endl;
return NDBT_FAILED; }
1007 if (brokenSf.end() != -1)
1008 { ndbout <<
"Bad rc from begin" << endl;
return NDBT_FAILED; }
1019 APIERROR(trans->getNdbError());
1025 trans->getNdbScanOperation(myTable);
1027 if (tabScanOp==NULL)
1029 APIERROR(trans->getNdbError());
1037 if (sf.getNdbError().code != 0)
1038 { APIERROR(sf.getNdbError());
return NDBT_FAILED; };
1046 APIERROR(trans->getNdbError());
1052 if (sf2.getNdbError().code != 4539)
1054 ndbout <<
"Error, expected 4539" << endl;
1055 APIERROR(sf2.getNdbError());
1062 bool getBit(
const Uint32* bitMap,
1065 return ((bitMap[ bitNum >> 5 ] & (1 << (bitNum & 31))) != 0);
1068 void setBit(Uint32* bitMap,
int bitMapByteSize,
1071 assert(bitNum >= 0 && bitNum < (bitMapByteSize * 8));
1072 bitMap[ bitNum >> 5 ] |= (1 << (bitNum & 31));
1075 enum TestConditions {
1084 COND_AND_EQ_MASK = 8,
1085 COND_AND_NE_MASK = 9,
1086 COND_AND_EQ_ZERO = 10,
1087 COND_AND_NE_ZERO = 11
1090 int getExpectedBitsSet(
int rowId,
1099 return (rowId % (colBitWidth + 1)) -1;
1102 bool isNullValue(
int rowId,
1106 return (((rowId + colBitWidth) % 13) == 0);
1109 void getBitfieldVariants(
int bitNum,
int&
offset,
bool& invert)
1113 if ((bitNum % 5) == 3)
1118 if ((bitNum % 7) == 6)
1121 offset= (bitNum / 2);
1126 bool isRowExpected(
int rowId,
1127 TestConditions cond,
1129 int bitsSetInScanFilter,
1131 const Uint32* maskBuff)
1133 if (isNullable && isNullValue(rowId, colBitWidth))
1152 case COND_AND_EQ_MASK:
1154 case COND_AND_NE_MASK:
1156 case COND_AND_EQ_ZERO:
1158 case COND_AND_NE_ZERO:
1161 printf(
"isRowExpected given bad condition : %u\n",
1169 int expectedBitsSet= getExpectedBitsSet(rowId, colBitWidth);
1174 getBitfieldVariants(bitsSetInScanFilter + 1, offset, invert);
1178 return expectedBitsSet <= bitsSetInScanFilter;
1180 return expectedBitsSet < bitsSetInScanFilter;
1182 return expectedBitsSet >= bitsSetInScanFilter;
1184 return expectedBitsSet > bitsSetInScanFilter;
1186 return expectedBitsSet == bitsSetInScanFilter;
1188 return expectedBitsSet != bitsSetInScanFilter;
1193 case COND_AND_EQ_MASK:
1194 case COND_AND_NE_MASK:
1198 for (
int idx=0; idx < colBitWidth; idx++)
1200 bool bitVal= (expectedBitsSet >= 0)?
1201 (expectedBitsSet >= idx):
false;
1202 bool maskVal= getBit(maskBuff, idx);
1203 if ((bitVal & maskVal) != maskVal)
1212 return (result ^ (cond == COND_AND_NE_MASK));
1214 case COND_AND_EQ_ZERO:
1215 case COND_AND_NE_ZERO:
1219 for (
int idx=0; idx < colBitWidth; idx++)
1221 bool bitVal= (expectedBitsSet >= 0)?
1222 (expectedBitsSet >= idx):
false;
1223 bool maskVal= getBit(maskBuff, idx);
1224 if ((bitVal & maskVal) != 0)
1232 return (result ^ (cond == COND_AND_NE_ZERO));
1235 printf(
"isRowExpected given bad condition : %u\n",
1242 int insertBitRows(
Ndb* pNdb)
1249 for (
int i=0; i< TOTAL_ROWS; i++)
1252 if (myTrans == NULL)
1256 if (insertOp == NULL)
1259 const int buffSize= (MAX_BIT_WIDTH + 31) / 32;
1260 Uint32 buff[ buffSize ];
1262 if (insertOp->insertTuple() != 0)
1263 APIERROR(insertOp->getNdbError());
1265 if (insertOp->equal((Uint32)0, i) != 0)
1266 APIERROR(insertOp->getNdbError());
1275 isNullValue(i, colBitWidth))
1278 if (insertOp->setValue(col, (
char*) NULL) != 0)
1279 APIERROR(insertOp->getNdbError());
1284 memset(buff, 0, (4 * buffSize));
1286 int bitsToSet= getExpectedBitsSet(i, colBitWidth);
1290 for (
int idx=0; idx <= bitsToSet; idx++)
1291 setBit(buff,
sizeof(buff), idx);
1294 if (insertOp->setValue(col, (
char *)buff) != 0)
1295 APIERROR(insertOp->getNdbError());
1306 printf(
"Inserted %u rows\n", TOTAL_ROWS);
1311 int verifyBitData(
Ndb* pNdb)
1319 if (myTrans == NULL)
1326 if (scanOp->readTuples() != 0)
1327 APIERROR(scanOp->getNdbError());
1331 for (
int col=0; col< NUM_COLS; col++)
1333 if ((results[col]= scanOp->getValue(col)) == NULL)
1334 APIERROR(scanOp->getNdbError());
1338 APIERROR(myTrans->getNdbError());
1340 for (
int row=0; row < TOTAL_ROWS; row++)
1342 if (scanOp->nextResult() != 0)
1343 APIERROR(scanOp->getNdbError());
1347 for (
int col=1; col < NUM_COLS; col++)
1354 isNullValue(rowId, colBitWidth))
1356 if (!results[ col ] ->isNULL())
1358 printf(
"Mismatch at result %d row %d, column %d, expected NULL\n",
1367 int expectedSetBits= getExpectedBitsSet(rowId, colBitWidth);
1369 const Uint32* val= (
const Uint32 *) results[ col ]->aRef();
1371 for (
int bitNum=0; bitNum < colBitWidth; bitNum++)
1373 bool expectClear= (bitNum > expectedSetBits);
1374 bool isClear= ! getBit(val, bitNum);
1375 if (expectClear != isClear)
1377 printf(
"Mismatch at result %d row %d, column %d, bit %d"
1379 row, rowId, col, bitNum, (expectClear)?0:1);
1388 if (scanOp->nextResult() != 1)
1390 printf(
"Too many rows returned\n");
1395 APIERROR(myTrans->getNdbError());
1399 printf(
"Verified data for %u rows\n",
1405 int verifyBitScanFilter(
Ndb* pNdb)
1418 for (
int col=1; col < NUM_COLS; col++)
1422 printf(
"Testing %s column %u (width=%u bits) with %u scan filter variants\n",
1424 col, bitWidth, ((bitWidth+1) * (COND_AND_NE_ZERO + 1)));
1425 for (
int comp=0; comp <= COND_AND_NE_ZERO; comp++)
1427 for (
int bitNum=0; bitNum <= bitWidth; bitNum++)
1431 if (myTrans == NULL)
1438 if (scanOp->readTuples() != 0)
1439 APIERROR(scanOp->getNdbError());
1442 if ((ra= scanOp->getValue((Uint32)0)) == NULL)
1443 APIERROR(scanOp->getNdbError());
1446 const int buffSize= (MAX_BIT_WIDTH + 31)/32;
1447 Uint32 buff[ buffSize ];
1448 memset(buff, 0, (4 * buffSize));
1455 case COND_AND_EQ_MASK:
1456 case COND_AND_NE_MASK:
1457 case COND_AND_EQ_ZERO:
1458 case COND_AND_NE_ZERO:
1459 getBitfieldVariants(bitNum, offset, invert);
1467 int bitsSetInFilter= bitNum-1;
1469 if ((bitsSetInFilter >= 0) ||
1472 for (
int idx=0; idx < (32 * buffSize); idx++)
1474 if ((idx >= offset) &&
1475 (idx <= (offset + bitsSetInFilter)))
1478 setBit(buff,
sizeof(buff), idx);
1483 setBit(buff,
sizeof(buff), idx);
1493 APIERROR(sf.getNdbError());
1495 if ((comp != COND_NULL) &&
1496 (comp != COND_NOTNULL))
1502 APIERROR(sf.getNdbError());
1508 if (sf.isnull(col) != 0)
1509 APIERROR(sf.getNdbError());
1512 if (sf.isnotnull(col) != 0)
1513 APIERROR(sf.getNdbError());
1516 printf(
"Condition %u not supported\n", comp);
1522 APIERROR(sf.getNdbError());
1530 int expectedResultCount= 0;
1531 for (
int i=0; i< TOTAL_ROWS; i++)
1533 if (isRowExpected(i,
1534 (TestConditions)comp,
1539 expectedResultCount++;
1553 while ((rc= scanOp->nextResult()) == 0)
1560 if (isRowExpected(rowId,
1561 (TestConditions)comp,
1571 printf(
"Col=%u Comp=%u BitNum=%u row=%u : "
1572 "Got row %u back which I did not expect\n",
1573 col, comp, bitNum, count, rowId);
1581 printf(
"Col=%u Comp=%u BitNum=%u :"
1582 "nextResult failure %d\n", col, comp, bitNum, rc);
1590 if (matchCount != expectedResultCount)
1592 printf(
"Col=%u Comp=%u BitNum=%u :"
1593 "Mismatch between expected(%u) and received(%u) result counts\n",
1594 col, comp, bitNum, expectedResultCount, matchCount);
1610 printf(
"Verified %u scans with bitfield ScanFilter conditions\n",
1620 Ndb *pNdb = GETNDB(step);
1622 int ret = createTable(pNdb, &MYTAB2,
false,
true, 0);
1627 if (insertBitRows(pNdb) != NDBT_OK)
1631 if (verifyBitData(pNdb) != NDBT_OK)
1635 if (verifyBitScanFilter(pNdb) != NDBT_OK)
1645 NDBT_TESTSUITE(testScanFilter);
1647 "Scan table TABLE_NAME for the records which accord with \
1648 conditions of logical scan operations: AND/OR/NAND/NOR")
1650 INITIALIZER(runCreateTables);
1651 INITIALIZER(runPopulate);
1652 INITIALIZER(runScanRandomFilterTest);
1653 INITIALIZER(runMaxScanFilterSize);
1654 INITIALIZER(runScanFilterConstructorFail);
1655 FINALIZER(runDropTables);
1658 TESTCASE(
"TestScanFilterBit",
1659 "Test ScanFilter with bitfield columns")
1661 INITIALIZER(runTestScanFilterBit);
1664 NDBT_TESTSUITE_END(testScanFilter);
1667 int main(
int argc,
const char** argv)
1674 return NDBT_ProgramExit(NDBT_FAILED);
1677 NDBT_TESTSUITE_INSTANCE(testScanFilter);
1678 return testScanFilter.execute(argc, argv);