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