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 + -
显示快捷键?