testscanfilter.cpp
来自「这个文件是windows mysql源码」· C++ 代码 · 共 861 行 · 第 1/2 页
CPP
861 行
/* Copyright (C) 2007 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; version 2 of the License. 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 <NDBT.hpp>#include <NDBT_Test.hpp>#define ERR_EXIT(obj, msg) \do \{ \fprintf(stderr, "%s: %s (%d) in %s:%d\n", \msg, obj->getNdbError().message, obj->getNdbError().code, __FILE__, __LINE__); \exit(-1); \} \while (0);#define PRINT_ERROR(code,msg) \do \{ \fprintf(stderr, "Error in %s, line: %d, code: %d, msg: %s.\n", __FILE__, __LINE__, code, msg); \} \while (0);#define MYSQLERROR(mysql) { \ PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \ exit(-1); }#define APIERROR(error) { \ PRINT_ERROR(error.code,error.message); \ exit(-1); }#define TEST_NAME "TestScanFilter" #define TABLE_NAME "TABLE_SCAN"const char *COL_NAME[] = {"id", "i", "j", "k", "l", "m", "n"}; const char COL_LEN = 7;/** Not to change TUPLE_NUM, because the column in TABLE_NAME is fixed,* there are six columns, 'i', 'j', 'k', 'l', 'm', 'n', and each on is equal to 1 or 1,* Since each tuple should be unique in this case, then TUPLE_NUM = 2 power 6 = 64 */#ifdef _AIX/* IBM xlC_r breaks on the initialization with pow(): "The expression must be an integral constant expression."*/const int TUPLE_NUM = 64;#elseconst int TUPLE_NUM = (int)pow(2, COL_LEN-1);#endif/** the recursive level of random scan filter, can * modify this parameter more or less, range from * 1 to 100, larger num consumes more scan time*/const int RECURSIVE_LEVEL = 10;const int MAX_STR_LEN = (RECURSIVE_LEVEL * (COL_LEN+1) * 4);/** Each time stands for one test, it will produce a random * filter string, and scan through ndb api and through * calculation with tuples' data, then compare the result, * if they are equal, this test passed, or failed.* Only all TEST_NUM times tests passed, we can believe * the suite of test cases are okay.* Change TEST_NUM to larger will need more time to test*/const int TEST_NUM = 5000;/* Table definition*/staticconstNDBT_Attribute MYTAB1Attribs[] = { NDBT_Attribute("id", NdbDictionary::Column::Unsigned, 1, true), NDBT_Attribute("i", NdbDictionary::Column::Unsigned), NDBT_Attribute("j", NdbDictionary::Column::Unsigned), NDBT_Attribute("k", NdbDictionary::Column::Unsigned), NDBT_Attribute("l", NdbDictionary::Column::Unsigned), NDBT_Attribute("m", NdbDictionary::Column::Unsigned), NDBT_Attribute("n", NdbDictionary::Column::Unsigned),};staticconstNDBT_Table MYTAB1(TABLE_NAME, sizeof(MYTAB1Attribs)/sizeof(NDBT_Attribute), MYTAB1Attribs);int createTable(Ndb* pNdb, const NdbDictionary::Table* tab, bool _temp, bool existsOk, NDBT_CreateTableHook f){ int r = 0; do{ NdbDictionary::Table tmpTab(* tab); tmpTab.setStoredTable(_temp ? 0 : 1); if(f != 0 && f(pNdb, tmpTab, 0)) { ndbout << "Failed to create table" << endl; return NDBT_FAILED; } r = pNdb->getDictionary()->createTable(tmpTab); if(r == -1){ if(!existsOk){ ndbout << "Error: " << pNdb->getDictionary()->getNdbError() << endl; break; } if(pNdb->getDictionary()->getNdbError().code != 721){ ndbout << "Error: " << pNdb->getDictionary()->getNdbError() << endl; break; } r = 0; } }while(false); return r;}/** Function to produce the tuples' data*/int runPopulate(NDBT_Context* ctx, NDBT_Step* step){ Ndb *myNdb = GETNDB(step); const NdbDictionary::Dictionary* myDict= myNdb->getDictionary(); const NdbDictionary::Table *myTable= myDict->getTable(TABLE_NAME); if(myTable == NULL) APIERROR(myDict->getNdbError()); NdbTransaction* myTrans = myNdb->startTransaction(); if (myTrans == NULL) APIERROR(myNdb->getNdbError()); for(int num = 0; num < TUPLE_NUM; num++) { NdbOperation* myNdbOperation = myTrans->getNdbOperation(myTable); if(myNdbOperation == NULL) { APIERROR(myTrans->getNdbError()); }/* the tuples' data in TABLE_NAME+----+---+---+---+---+---+---+| id | i | j | k | l | m | n |+----+---+---+---+---+---+---+| 0 | 0 | 0 | 0 | 0 | 0 | 0 || 1 | 0 | 0 | 0 | 0 | 0 | 1 || 2 | 0 | 0 | 0 | 0 | 1 | 0 || 3 | 0 | 0 | 0 | 0 | 1 | 1 || 4 | 0 | 0 | 0 | 1 | 0 | 0 || 5 | 0 | 0 | 0 | 1 | 0 | 1 || 6 | 0 | 0 | 0 | 1 | 1 | 0 || 7 | 0 | 0 | 0 | 1 | 1 | 1 || 8 | 0 | 0 | 1 | 0 | 0 | 0 || 9 | 0 | 0 | 1 | 0 | 0 | 1 || 10 | 0 | 0 | 1 | 0 | 1 | 0 || 11 | 0 | 0 | 1 | 0 | 1 | 1 || 12 | 0 | 0 | 1 | 1 | 0 | 0 || 13 | 0 | 0 | 1 | 1 | 0 | 1 || 14 | 0 | 0 | 1 | 1 | 1 | 0 || 15 | 0 | 0 | 1 | 1 | 1 | 1 || 16 | 0 | 1 | 0 | 0 | 0 | 0 || 17 | 0 | 1 | 0 | 0 | 0 | 1 || 18 | 0 | 1 | 0 | 0 | 1 | 0 || 19 | 0 | 1 | 0 | 0 | 1 | 1 || 20 | 0 | 1 | 0 | 1 | 0 | 0 || 21 | 0 | 1 | 0 | 1 | 0 | 1 || 22 | 0 | 1 | 0 | 1 | 1 | 0 || 23 | 0 | 1 | 0 | 1 | 1 | 1 || 24 | 0 | 1 | 1 | 0 | 0 | 0 || 25 | 0 | 1 | 1 | 0 | 0 | 1 || 26 | 0 | 1 | 1 | 0 | 1 | 0 || 27 | 0 | 1 | 1 | 0 | 1 | 1 || 28 | 0 | 1 | 1 | 1 | 0 | 0 || 29 | 0 | 1 | 1 | 1 | 0 | 1 || 30 | 0 | 1 | 1 | 1 | 1 | 0 || 31 | 0 | 1 | 1 | 1 | 1 | 1 || 32 | 1 | 0 | 0 | 0 | 0 | 0 || 33 | 1 | 0 | 0 | 0 | 0 | 1 || 34 | 1 | 0 | 0 | 0 | 1 | 0 || 35 | 1 | 0 | 0 | 0 | 1 | 1 || 36 | 1 | 0 | 0 | 1 | 0 | 0 || 37 | 1 | 0 | 0 | 1 | 0 | 1 || 38 | 1 | 0 | 0 | 1 | 1 | 0 || 39 | 1 | 0 | 0 | 1 | 1 | 1 || 40 | 1 | 0 | 1 | 0 | 0 | 0 || 41 | 1 | 0 | 1 | 0 | 0 | 1 || 42 | 1 | 0 | 1 | 0 | 1 | 0 || 43 | 1 | 0 | 1 | 0 | 1 | 1 || 44 | 1 | 0 | 1 | 1 | 0 | 0 || 45 | 1 | 0 | 1 | 1 | 0 | 1 || 46 | 1 | 0 | 1 | 1 | 1 | 0 || 47 | 1 | 0 | 1 | 1 | 1 | 1 || 48 | 1 | 1 | 0 | 0 | 0 | 0 || 49 | 1 | 1 | 0 | 0 | 0 | 1 || 50 | 1 | 1 | 0 | 0 | 1 | 0 || 51 | 1 | 1 | 0 | 0 | 1 | 1 || 52 | 1 | 1 | 0 | 1 | 0 | 0 || 53 | 1 | 1 | 0 | 1 | 0 | 1 || 54 | 1 | 1 | 0 | 1 | 1 | 0 || 55 | 1 | 1 | 0 | 1 | 1 | 1 || 56 | 1 | 1 | 1 | 0 | 0 | 0 || 57 | 1 | 1 | 1 | 0 | 0 | 1 || 58 | 1 | 1 | 1 | 0 | 1 | 0 || 59 | 1 | 1 | 1 | 0 | 1 | 1 || 60 | 1 | 1 | 1 | 1 | 0 | 0 || 61 | 1 | 1 | 1 | 1 | 0 | 1 || 62 | 1 | 1 | 1 | 1 | 1 | 0 || 63 | 1 | 1 | 1 | 1 | 1 | 1 |+----+---+---+---+---+---+---+*/ myNdbOperation->insertTuple(); myNdbOperation->equal(COL_NAME[0], num); for(int col = 1; col < COL_LEN; col++) { myNdbOperation->setValue(COL_NAME[col], (num>>(COL_LEN-1-col))&1); } } int check = myTrans->execute(NdbTransaction::Commit); myTrans->close(); if (check == -1) return NDBT_FAILED; else return NDBT_OK;}/** a=AND, o=OR, A=NAND, O=NOR*/char op_string[] = "aoAO";/** the six columns' name of test table*/char col_string[] = "ijklmn";const int op_len = strlen(op_string);const int col_len = strlen(col_string);/** get a random op from "aoAO"*/int get_rand_op_ch(char *ch){ static unsigned int num = 0; if(++num == 0) num = 1; srand(num*time(NULL)); *ch = op_string[rand() % op_len]; return 1;}/** get a random order form of "ijklmn" trough exchanging letter*/void change_col_order(){ int pos1,pos2; char temp; for (int i = 0; i < 10; i++) //exchange for 10 times { srand(time(NULL)/(i+1)); pos1 = rand() % col_len; srand((i+1)*time(NULL)); pos2 = rand() % col_len; if (pos1 == pos2) continue; temp = col_string[pos1]; col_string[pos1] = col_string[pos2]; col_string[pos2] = temp; }}/** get a random sub string of "ijklmn" */int get_rand_col_str(char *str){ int len; static unsigned int num = 0; if(++num == 0) num = 1; srand(num*time(NULL)); len = rand() % col_len + 1; change_col_order(); snprintf(str, len+1, "%s", col_string); //len+1, including '\0' return len;}/** get a random string including operation and column * eg, Alnikx*/int get_rand_op_str(char *str){ char temp[256]; int len1, len2, len; len1 = get_rand_op_ch(temp); len2 = get_rand_col_str(temp+len1); len = len1 + len2; temp[len] = 'x'; snprintf(str, len+1+1, "%s", temp); //len+1, including '\0' return len+1;}/** replace a letter of source string with a new string * e.g., source string: 'Aijkx', replace i with new string 'olmx'* then source string is changed to 'Aolmxjkx'* source: its format should be produced from get_rand_op_str() * pos: range from 1 to strlen(source)-2*/int replace_a_to_str(char *source, int pos, char *newstr){ char temp[MAX_STR_LEN]; snprintf(temp, pos+1, "%s", source); snprintf(temp+pos, strlen(newstr)+1, "%s", newstr); snprintf(temp+pos+strlen(newstr), strlen(source)-pos, "%s", source+pos+1); snprintf(source, strlen(temp)+1, "%s", temp); return strlen(source);}/** check whether the inputed char is an operation */bool check_op(char ch){ if( ch == 'a' || ch == 'A' || ch == 'o' || ch == 'O') return true; else return false;}/** check whether the inputed char is end flag */bool check_end(char ch){ return (ch == 'x');}/** check whether the inputed char is end flag */bool check_col(char ch){ if( ch == 'i' || ch == 'j' || ch == 'k' || ch == 'l' || ch == 'm' || ch == 'n' ) return true; else return false;}/** To ensure we can get a random string with RECURSIVE_LEVEL,* we need a position where can replace a letter with a new string. */int get_rand_replace_pos(char *str, int len){ int pos_op = 0; int pos_x = 0; int pos_col = 0; int span = 0; static int num = 0; char temp; for(int i = 0; i < len; i++) { temp = str[i]; if(! check_end(temp)) { if(check_op(temp)) pos_op = i; } else { pos_x = i; break; } } if(++num == 0) num = 1; span = pos_x - pos_op - 1; if(span <= 1) { pos_col = pos_op + 1; } else { srand(num*time(NULL)); pos_col = pos_op + rand() % span + 1; } return pos_col;}/** Check whether the given random string is valid* and applicable for this test case*/bool check_random_str(char *str){ char *p; int op_num = 0; int end_num = 0; for(p = str; *p; p++) { bool tmp1 = false, tmp2 = false; if(tmp1 = check_op(*p)) op_num++; if(tmp2 = check_end(*p)) end_num++; if(!(tmp1 || tmp2 || check_col(*p))) //there are illegal letters return false; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?