1 /*
2    Copyright (C) 2003-2006 MySQL AB
3     All rights reserved. Use is subject to license terms.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License, version 2.0,
7    as published by the Free Software Foundation.
8 
9    This program is also distributed with certain software (including
10    but not limited to OpenSSL) that is licensed under separate terms,
11    as designated in a particular file or component or in included license
12    documentation.  The authors of MySQL hereby grant you an additional
13    permission to link the program and your derivative works with the
14    separately licensed software that they have included with MySQL.
15 
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License, version 2.0, for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 */
25 
26 #include <NDBT.hpp>
27 #include <NDBT_Test.hpp>
28 #include <HugoTransactions.hpp>
29 #include <UtilTransactions.hpp>
30 #include <NdbRestarter.hpp>
31 #include <Vector.hpp>
32 #include <ndbapi_limits.h>
33 
34 const unsigned MaxTableAttrs = NDB_MAX_ATTRIBUTES_IN_TABLE;
35 const unsigned MaxIndexAttrs = NDB_MAX_ATTRIBUTES_IN_INDEX;
36 const unsigned MaxIndexes = 20;
37 
38 static unsigned
urandom(unsigned n)39 urandom(unsigned n)
40 {
41   unsigned i = random();
42   return i % n;
43 }
44 
45 static int
runDropIndex(NDBT_Context * ctx,NDBT_Step * step)46 runDropIndex(NDBT_Context* ctx, NDBT_Step* step)
47 {
48   const NdbDictionary::Table* pTab = ctx->getTab();
49   Ndb* pNdb = GETNDB(step);
50   NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
51   NdbDictionary::Dictionary::List list;
52   if (pDic->listIndexes(list, pTab->getName()) != 0) {
53     g_err << pTab->getName() << ": listIndexes failed" << endl;
54     ERR(pDic->getNdbError());
55     return NDBT_FAILED;
56   }
57   for (unsigned i = 0; i < list.count; i++) {
58     NDBT_Index* pInd = new NDBT_Index(list.elements[i].name);
59     pInd->setTable(pTab->getName());
60     g_info << "Drop index:" << endl << *pInd;
61     if (pInd->dropIndexInDb(pNdb) != 0) {
62       return NDBT_FAILED;
63     }
64   }
65   return NDBT_OK;
66 }
67 
68 static Uint32 workaround[1000];
69 
70 static void
setTableProperty(NDBT_Context * ctx,NDBT_Table * pTab,const char * name,Uint32 num)71 setTableProperty(NDBT_Context* ctx, NDBT_Table* pTab, const char* name, Uint32 num)
72 {
73   char key[200];
74   sprintf(key, "%s-%s", name, pTab->getName());
75   //ctx->setProperty(key, num);
76   workaround[pTab->getTableId()] = num;
77 }
78 
79 static Uint32
getTableProperty(NDBT_Context * ctx,NDBT_Table * pTab,const char * name)80 getTableProperty(NDBT_Context* ctx, NDBT_Table* pTab, const char* name)
81 {
82   char key[200];
83   sprintf(key, "%s-%s", name, pTab->getName());
84   //Uint32 num = ctx->getProperty(key, (Uint32)-1);
85   Uint32 num = workaround[pTab->getTableId()];
86   require(num != (Uint32)-1);
87   return num;
88 }
89 
90 static int
runCreateIndex(NDBT_Context * ctx,NDBT_Step * step)91 runCreateIndex(NDBT_Context* ctx, NDBT_Step* step)
92 {
93   srandom(1);
94   NDBT_Table* pTab = ctx->getTab();
95   Ndb* pNdb = GETNDB(step);
96   unsigned numTabAttrs = pTab->getNumAttributes();
97   unsigned numIndex = 0;
98   while (numIndex < MaxIndexes) {
99     if (numIndex != 0 && urandom(10) == 0)
100       break;
101     char buf[200];
102     sprintf(buf, "%s_X%03d", pTab->getName(), numIndex);
103     NDBT_Index* pInd = new NDBT_Index(buf);
104     pInd->setTable(pTab->getName());
105     pInd->setType(NdbDictionary::Index::OrderedIndex);
106     pInd->setLogging(false);
107     unsigned numAttrs = 0;
108     while (numAttrs < MaxIndexAttrs) {
109       if (numAttrs != 0 && urandom(5) == 0)
110 	break;
111       unsigned i = urandom(numTabAttrs);
112       const NDBT_Attribute* pAttr = pTab->getAttribute(i);
113       bool found = false;
114       for (unsigned j = 0; j < numAttrs; j++) {
115 	if (strcmp(pAttr->getName(), pInd->getAttribute(j)->getName()) == 0) {
116 	  found = true;
117 	  break;
118 	}
119       }
120       if (found)
121 	continue;
122       pInd->addAttribute(*pAttr);
123       numAttrs++;
124     }
125     g_info << "Create index:" << endl << *pInd;
126     if (pInd->createIndexInDb(pNdb, false) != 0)
127       continue;
128     numIndex++;
129   }
130   setTableProperty(ctx, pTab, "numIndex", numIndex);
131   g_info << "Created " << numIndex << " indexes on " << pTab->getName() << endl;
132   return NDBT_OK;
133 }
134 
135 static int
runInsertUpdate(NDBT_Context * ctx,NDBT_Step * step)136 runInsertUpdate(NDBT_Context* ctx, NDBT_Step* step)
137 {
138   NDBT_Table* pTab = ctx->getTab();
139   Ndb* pNdb = GETNDB(step);
140   int ret;
141   g_info << "Insert: " << pTab->getName() << endl;
142   HugoTransactions hugoTrans(*pTab);
143   ret = hugoTrans.loadTable(pNdb, ctx->getNumRecords(), 100);
144   if (ret != 0) {
145     g_err << "ERR: " << step->getName() << "failed" << endl;
146     return NDBT_FAILED;
147   }
148   return NDBT_OK;
149 }
150 
151 static int
runFullScan(NDBT_Context * ctx,NDBT_Step * step)152 runFullScan(NDBT_Context* ctx, NDBT_Step* step)
153 {
154   NDBT_Table* pTab = ctx->getTab();
155   Ndb* pNdb = GETNDB(step);
156   unsigned cntIndex = getTableProperty(ctx, pTab, "numIndex");
157   for (unsigned numIndex = 0; numIndex < cntIndex; numIndex++) {
158     char buf[200];
159     sprintf(buf, "%s_X%03d", pTab->getName(), numIndex);
160     NDBT_Index* pInd = NDBT_Index::discoverIndexFromDb(pNdb, buf, pTab->getName());
161     require(pInd != 0);
162     g_info << "Scan index:" << pInd->getName() << endl << *pInd;
163     NdbConnection* pCon = pNdb->startTransaction();
164     if (pCon == 0) {
165       ERR(pNdb->getNdbError());
166       return NDBT_FAILED;
167     }
168     NdbOperation* pOp = pCon->getNdbOperation(pInd->getName(),
169 					      pTab->getName());
170     if (pOp == 0) {
171       ERR(pCon->getNdbError());
172       pNdb->closeTransaction(pCon);
173       return NDBT_FAILED;
174     }
175     if (pOp->openScanRead() != 0) {
176       ERR(pCon->getNdbError());
177       pNdb->closeTransaction(pCon);
178       return NDBT_FAILED;
179     }
180     if (pCon->executeScan() != 0) {
181       ERR(pCon->getNdbError());
182       pNdb->closeTransaction(pCon);
183       return NDBT_FAILED;
184     }
185     unsigned rows = 0;
186     while (1) {
187       int ret = pCon->nextScanResult();
188       if (ret == 0) {
189         rows++;
190       } else if (ret == 1) {
191         break;
192       } else {
193         ERR(pCon->getNdbError());
194         pNdb->closeTransaction(pCon);
195         return NDBT_FAILED;
196       }
197     }
198     pNdb->closeTransaction(pCon);
199     g_info << "Scanned " << rows << " rows" << endl;
200   }
201   return NDBT_OK;
202 }
203 
204 NDBT_TESTSUITE(testOrderedIndex);
205 TESTCASE(
206     "DropIndex",
207     "Drop any old indexes") {
208   INITIALIZER(runDropIndex);
209 }
210 TESTCASE(
211     "CreateIndex",
212     "Create ordered indexes") {
213   INITIALIZER(runCreateIndex);
214 }
215 TESTCASE(
216     "InsertUpdate",
217     "Run inserts and updates") {
218   INITIALIZER(runInsertUpdate);
219 }
220 TESTCASE(
221     "FullScan",
222     "Full scan on each ordered index") {
223   INITIALIZER(runFullScan);
224 }
225 NDBT_TESTSUITE_END(testOrderedIndex);
226 
227 int
main(int argc,const char ** argv)228 main(int argc, const char** argv)
229 {
230   ndb_init();
231   return testOrderedIndex.execute(argc, argv);
232 }
233 
234 // vim: set sw=2:
235