1 /*
2 Copyright (C) 2003-2006, 2008 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 <NdbRestarts.hpp>
32 #include <Vector.hpp>
33 #include <random.h>
34 #include <NdbTick.h>
35
36
37 #define CHECK(b) if (!(b)) { \
38 ndbout << "ERR: "<< step->getName() \
39 << " failed on line " << __LINE__ << endl; \
40 result = NDBT_FAILED; \
41 continue; }
42
runClearTable(NDBT_Context * ctx,NDBT_Step * step)43 int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
44 int records = ctx->getNumRecords();
45 int batchSize = ctx->getProperty("BatchSize", 1);
46
47 HugoTransactions hugoTrans(*ctx->getTab());
48 if (hugoTrans.pkDelRecords(GETNDB(step), records, batchSize) != 0){
49 return NDBT_FAILED;
50 }
51 return NDBT_OK;
52 }
53
runLoadTable(NDBT_Context * ctx,NDBT_Step * step)54 int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
55
56 int records = ctx->getNumRecords();
57 HugoTransactions hugoTrans(*ctx->getTab());
58 if (hugoTrans.loadTable(GETNDB(step), records) != 0){
59 return NDBT_FAILED;
60 }
61 return NDBT_OK;
62 }
63
runTestIncValue64(NDBT_Context * ctx,NDBT_Step * step)64 int runTestIncValue64(NDBT_Context* ctx, NDBT_Step* step){
65 int records = ctx->getNumRecords();
66 // NDBT_Table* pTab = ctx->getTab();
67 //Ndb* pNdb = GETNDB(step);
68
69 HugoTransactions hugoTrans(*ctx->getTab());
70 if (hugoTrans.pkInterpretedUpdateRecords(GETNDB(step),
71 records) != 0){
72 return NDBT_FAILED;
73 }
74
75 // Verify the update
76 if (hugoTrans.pkReadRecords(GETNDB(step),
77 records) != 0){
78 return NDBT_FAILED;
79 }
80
81 return NDBT_OK;
82
83 }
84
runTestIncValue32(NDBT_Context * ctx,NDBT_Step * step)85 int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){
86 const NdbDictionary::Table * pTab = ctx->getTab();
87 Ndb* pNdb = GETNDB(step);
88
89 if (strcmp(pTab->getName(), "T1") != 0) {
90 g_err << "runTestBug19537: skip, table != T1" << endl;
91 return NDBT_OK;
92 }
93
94
95 NdbConnection* pTrans = pNdb->startTransaction();
96 if (pTrans == NULL){
97 NDB_ERR(pNdb->getNdbError());
98 return NDBT_FAILED;
99 }
100
101 NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
102 if (pOp == NULL) {
103 NDB_ERR(pTrans->getNdbError());
104 pNdb->closeTransaction(pTrans);
105 return NDBT_FAILED;
106 }
107
108 int check = pOp->interpretedUpdateTuple();
109 if( check == -1 ) {
110 NDB_ERR(pTrans->getNdbError());
111 pNdb->closeTransaction(pTrans);
112 return NDBT_FAILED;
113 }
114
115
116 // Primary keys
117 Uint32 pkVal = 1;
118 check = pOp->equal("KOL1", pkVal );
119 if( check == -1 ) {
120 NDB_ERR(pTrans->getNdbError());
121 pNdb->closeTransaction(pTrans);
122 return NDBT_FAILED;
123 }
124
125 // Attributes
126
127 // Perform initial read of column start value
128 NdbRecAttr* initialVal = pOp->getValue("KOL2");
129 if( initialVal == NULL ) {
130 NDB_ERR(pTrans->getNdbError());
131 pNdb->closeTransaction(pTrans);
132 return NDBT_FAILED;
133 }
134
135 // Update the column
136 Uint32 valToIncWith = 1;
137 check = pOp->incValue("KOL2", valToIncWith);
138 if( check == -1 ) {
139 NDB_ERR(pTrans->getNdbError());
140 pNdb->closeTransaction(pTrans);
141 return NDBT_FAILED;
142 }
143
144 // Perform final read of column after value
145 NdbRecAttr* afterVal = pOp->getValue("KOL2");
146 if( afterVal == NULL ) {
147 NDB_ERR(pTrans->getNdbError());
148 pNdb->closeTransaction(pTrans);
149 return NDBT_FAILED;
150 }
151
152 check = pTrans->execute(Commit);
153 if( check == -1 ) {
154 NDB_ERR(pTrans->getNdbError());
155 pNdb->closeTransaction(pTrans);
156 return NDBT_FAILED;
157 }
158
159 Uint32 oldValue = initialVal->u_32_value();
160 Uint32 newValue = afterVal->u_32_value();
161 Uint32 expectedValue = oldValue + valToIncWith;
162
163 if (newValue != expectedValue)
164 {
165 g_err << "Failed : Expected " << oldValue << "+" <<
166 valToIncWith << "=" << expectedValue <<
167 " but received " << newValue << endl;
168 pNdb->closeTransaction(pTrans);
169 return NDBT_FAILED;
170 }
171
172 pNdb->closeTransaction(pTrans);
173
174
175 return NDBT_OK;
176 }
177
runTestBug19537(NDBT_Context * ctx,NDBT_Step * step)178 int runTestBug19537(NDBT_Context* ctx, NDBT_Step* step){
179 const NdbDictionary::Table * pTab = ctx->getTab();
180 Ndb* pNdb = GETNDB(step);
181
182 if (strcmp(pTab->getName(), "T1") != 0) {
183 g_err << "runTestBug19537: skip, table != T1" << endl;
184 return NDBT_OK;
185 }
186
187
188 NdbConnection* pTrans = pNdb->startTransaction();
189 if (pTrans == NULL){
190 NDB_ERR(pNdb->getNdbError());
191 return NDBT_FAILED;
192 }
193
194 NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
195 if (pOp == NULL) {
196 NDB_ERR(pTrans->getNdbError());
197 pNdb->closeTransaction(pTrans);
198 return NDBT_FAILED;
199 }
200
201 if (pOp->interpretedUpdateTuple() == -1) {
202 NDB_ERR(pOp->getNdbError());
203 pNdb->closeTransaction(pTrans);
204 return NDBT_FAILED;
205 }
206
207
208 // Primary keys
209 const Uint32 pkVal = 1;
210 if (pOp->equal("KOL1", pkVal) == -1) {
211 NDB_ERR(pTrans->getNdbError());
212 pNdb->closeTransaction(pTrans);
213 return NDBT_FAILED;
214 }
215
216 // Load 64-bit constant into register 1 and
217 // write from register 1 to 32-bit column KOL2
218 const Uint64 reg_val = 0x0102030405060708ULL;
219 #if 0
220 Uint32 reg_ptr32[2];
221 memcpy(&(reg_ptr32[0]), (Uint8*)®_val, sizeof(Uint32));
222 memcpy(&(reg_ptr32[1]), ((Uint8*)®_val)+4, sizeof(Uint32));
223 if (reg_ptr32[0] == 0x05060708 && reg_ptr32[1] == 0x01020304) {
224 g_err << "runTestBug19537: platform is LITTLE endian" << endl;
225 } else if (reg_ptr32[0] == 0x01020304 && reg_ptr32[1] == 0x05060708) {
226 g_err << "runTestBug19537: platform is BIG endian" << endl;
227 } else {
228 g_err << "runTestBug19537: impossible platform"
229 << hex << " [0]=" << reg_ptr32[0] << " [1]=" <<reg_ptr32[1] << endl;
230 pNdb->closeTransaction(pTrans);
231 return NDBT_FAILED;
232 }
233 #endif
234
235 if (pOp->load_const_u64(1, reg_val) == -1 ||
236 pOp->write_attr("KOL2", 1) == -1) {
237 NDB_ERR(pOp->getNdbError());
238 pNdb->closeTransaction(pTrans);
239 return NDBT_FAILED;
240 }
241
242 if (pTrans->execute(Commit) == -1) {
243 NDB_ERR(pTrans->getNdbError());
244 pNdb->closeTransaction(pTrans);
245 return NDBT_FAILED;
246 }
247
248 // Read value via a new transaction
249
250 pTrans = pNdb->startTransaction();
251 if (pTrans == NULL){
252 NDB_ERR(pNdb->getNdbError());
253 return NDBT_FAILED;
254 }
255
256 pOp = pTrans->getNdbOperation(pTab->getName());
257 if (pOp == NULL) {
258 NDB_ERR(pTrans->getNdbError());
259 pNdb->closeTransaction(pTrans);
260 return NDBT_FAILED;
261 }
262
263 Uint32 kol2 = 0x09090909;
264 if (pOp->readTuple() == -1 ||
265 pOp->equal("KOL1", pkVal) == -1 ||
266 pOp->getValue("KOL2", (char*)&kol2) == 0) {
267 NDB_ERR(pOp->getNdbError());
268 pNdb->closeTransaction(pTrans);
269 return NDBT_FAILED;
270 }
271
272 if (pTrans->execute(Commit) == -1) {
273 NDB_ERR(pTrans->getNdbError());
274 pNdb->closeTransaction(pTrans);
275 return NDBT_FAILED;
276 }
277
278 // Expected conversion as in C - truncate to lower (logical) word
279
280 if (kol2 == 0x01020304) {
281 g_err << "runTestBug19537: the bug manifests itself !" << endl;
282 pNdb->closeTransaction(pTrans);
283 return NDBT_FAILED;
284 }
285
286 if (kol2 != 0x05060708) {
287 g_err << "runTestBug19537: impossible KOL2 " << hex << kol2 << endl;
288 pNdb->closeTransaction(pTrans);
289 return NDBT_FAILED;
290 }
291
292 pNdb->closeTransaction(pTrans);
293 return NDBT_OK;
294 }
295
296
runTestBug34107(NDBT_Context * ctx,NDBT_Step * step)297 int runTestBug34107(NDBT_Context* ctx, NDBT_Step* step){
298 const NdbDictionary::Table * pTab = ctx->getTab();
299 Ndb* pNdb = GETNDB(step);
300 const Uint32 okSize= 10000;
301 const Uint32 tooBig= 30000;
302
303 Uint32 codeBuff[tooBig];
304
305 int i;
306 for (i = 0; i <= 1; i++) {
307 g_info << "bug34107:" << (i == 0 ? " small" : " too big") << endl;
308
309 NdbConnection* pTrans = pNdb->startTransaction();
310 if (pTrans == NULL){
311 NDB_ERR(pNdb->getNdbError());
312 return NDBT_FAILED;
313 }
314
315 NdbScanOperation* pOp = pTrans->getNdbScanOperation(pTab->getName());
316 if (pOp == NULL) {
317 NDB_ERR(pTrans->getNdbError());
318 pNdb->closeTransaction(pTrans);
319 return NDBT_FAILED;
320 }
321
322 if (pOp->readTuples() == -1) {
323 NDB_ERR(pOp->getNdbError());
324 pNdb->closeTransaction(pTrans);
325 return NDBT_FAILED;
326 }
327
328 /* Test kernel mechanism for dealing with too large program
329 * We need to provide our own program buffer as default
330 * NdbInterpretedCode buffer will not grow larger than
331 * NDB_MAX_SCANFILTER_SIZE
332 */
333
334 NdbInterpretedCode code(NULL, // Table is irrelevant
335 codeBuff,
336 tooBig); // Size of codeBuff
337
338 int n = i == 0 ? okSize : tooBig;
339 int k;
340
341 for (k = 0; k < n; k++) {
342
343 // inserts 1 word ATTRINFO
344
345 if (code.interpret_exit_ok() == -1) {
346 NDB_ERR(code.getNdbError());
347 pNdb->closeTransaction(pTrans);
348 return NDBT_FAILED;
349 }
350 }
351
352 if (code.finalise() != 0)
353 {
354 NDB_ERR(code.getNdbError());
355 pNdb->closeTransaction(pTrans);
356 return NDBT_FAILED;
357 }
358
359 if (pOp->setInterpretedCode(&code) != 0)
360 {
361 NDB_ERR(pOp->getNdbError());
362 pNdb->closeTransaction(pTrans);
363 return NDBT_FAILED;
364 }
365
366 if (pTrans->execute(NoCommit) == -1) {
367 NDB_ERR(pTrans->getNdbError());
368 pNdb->closeTransaction(pTrans);
369 return NDBT_FAILED;
370 }
371
372 int ret;
373 while ((ret = pOp->nextResult()) == 0)
374 ;
375 g_info << "ret=" << ret << " err=" << pOp->getNdbError().code << endl;
376
377 if (i == 0 && ret != 1) {
378 NDB_ERR(pTrans->getNdbError());
379 pNdb->closeTransaction(pTrans);
380 return NDBT_FAILED;
381 }
382
383 if (i == 1 && ret != -1) {
384 g_err << "unexpected big filter success" << endl;
385 pNdb->closeTransaction(pTrans);
386 return NDBT_FAILED;
387 }
388 if (i == 1 && pOp->getNdbError().code != 874) {
389 g_err << "unexpected big filter error code, wanted 874" << endl;
390 NDB_ERR(pTrans->getNdbError());
391 pNdb->closeTransaction(pTrans);
392 return NDBT_FAILED;
393 }
394
395 pNdb->closeTransaction(pTrans);
396 }
397
398 return NDBT_OK;
399 }
400
401 static char pkIdxName[256];
402
403 int
createPkIndex(NDBT_Context * ctx,NDBT_Step * step)404 createPkIndex(NDBT_Context* ctx, NDBT_Step* step){
405 const NdbDictionary::Table* pTab = ctx->getTab();
406 Ndb* pNdb = GETNDB(step);
407
408 bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0);
409 bool logged = ctx->getProperty("LoggedIndexes", (Uint32)0);
410 bool noddl= ctx->getProperty("NoDDL");
411
412 // Create index
413 BaseString::snprintf(pkIdxName, 255, "IDC_PK_%s", pTab->getName());
414 if (orderedIndex)
415 ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "
416 << pkIdxName << " (";
417 else
418 ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "unique index "
419 << pkIdxName << " (";
420
421 NdbDictionary::Index pIdx(pkIdxName);
422 pIdx.setTable(pTab->getName());
423 if (orderedIndex)
424 pIdx.setType(NdbDictionary::Index::OrderedIndex);
425 else
426 pIdx.setType(NdbDictionary::Index::UniqueHashIndex);
427 for (int c = 0; c< pTab->getNoOfColumns(); c++){
428 const NdbDictionary::Column * col = pTab->getColumn(c);
429 if(col->getPrimaryKey()){
430 pIdx.addIndexColumn(col->getName());
431 ndbout << col->getName() <<" ";
432 }
433 }
434
435 pIdx.setStoredIndex(logged);
436 ndbout << ") ";
437 if (noddl)
438 {
439 const NdbDictionary::Index* idx= pNdb->
440 getDictionary()->getIndex(pkIdxName, pTab->getName());
441
442 if (!idx)
443 {
444 ndbout << "Failed - Index does not exist and DDL not allowed" << endl;
445 NDB_ERR(pNdb->getDictionary()->getNdbError());
446 return NDBT_FAILED;
447 }
448 else
449 {
450 // TODO : Check index definition is ok
451 }
452 }
453 else
454 {
455 if (pNdb->getDictionary()->createIndex(pIdx) != 0){
456 ndbout << "FAILED!" << endl;
457 const NdbError err = pNdb->getDictionary()->getNdbError();
458 NDB_ERR(err);
459 return NDBT_FAILED;
460 }
461 }
462
463 ndbout << "OK!" << endl;
464 return NDBT_OK;
465 }
466
467 int
createPkIndex_Drop(NDBT_Context * ctx,NDBT_Step * step)468 createPkIndex_Drop(NDBT_Context* ctx, NDBT_Step* step)
469 {
470 const NdbDictionary::Table* pTab = ctx->getTab();
471 Ndb* pNdb = GETNDB(step);
472
473 bool noddl= ctx->getProperty("NoDDL");
474
475 // Drop index
476 if (!noddl)
477 {
478 ndbout << "Dropping index " << pkIdxName << " ";
479 if (pNdb->getDictionary()->dropIndex(pkIdxName,
480 pTab->getName()) != 0){
481 ndbout << "FAILED!" << endl;
482 NDB_ERR(pNdb->getDictionary()->getNdbError());
483 return NDBT_FAILED;
484 } else {
485 ndbout << "OK!" << endl;
486 }
487 }
488
489 return NDBT_OK;
490 }
491
492 #define CHK_RET_FAILED(x) if (!(x)) { ndbout_c("Failed on line: %u", __LINE__); return NDBT_FAILED; }
493
494 int
runInterpretedUKLookup(NDBT_Context * ctx,NDBT_Step * step)495 runInterpretedUKLookup(NDBT_Context* ctx, NDBT_Step* step)
496 {
497 const NdbDictionary::Table * pTab = ctx->getTab();
498 Ndb* pNdb = GETNDB(step);
499 NdbDictionary::Dictionary * dict = pNdb->getDictionary();
500
501 const NdbDictionary::Index* pIdx= dict->getIndex(pkIdxName, pTab->getName());
502 CHK_RET_FAILED(pIdx != 0);
503
504 const NdbRecord * pRowRecord = pTab->getDefaultRecord();
505 CHK_RET_FAILED(pRowRecord != 0);
506 const NdbRecord * pIdxRecord = pIdx->getDefaultRecord();
507 CHK_RET_FAILED(pIdxRecord != 0);
508
509 const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
510 Uint8 * pRow = new Uint8[len];
511 bzero(pRow, len);
512
513 HugoCalculator calc(* pTab);
514 calc.equalForRow(pRow, pRowRecord, 0);
515
516 NdbTransaction* pTrans = pNdb->startTransaction();
517 CHK_RET_FAILED(pTrans != 0);
518
519 NdbInterpretedCode code;
520 code.interpret_exit_ok();
521 code.finalise();
522
523 NdbOperation::OperationOptions opts;
524 bzero(&opts, sizeof(opts));
525 opts.optionsPresent = NdbOperation::OperationOptions::OO_INTERPRETED;
526 opts.interpretedCode = &code;
527
528 const NdbOperation * pOp = pTrans->readTuple(pIdxRecord, (char*)pRow,
529 pRowRecord, (char*)pRow,
530 NdbOperation::LM_Read,
531 0,
532 &opts,
533 sizeof(opts));
534 CHK_RET_FAILED(pOp);
535 int res = pTrans->execute(Commit, AbortOnError);
536
537 CHK_RET_FAILED(res == 0);
538
539 delete [] pRow;
540
541 return NDBT_OK;
542 }
543
544 NDBT_TESTSUITE(testInterpreter);
545 TESTCASE("IncValue32",
546 "Test incValue for 32 bit integer\n"){
547 INITIALIZER(runLoadTable);
548 INITIALIZER(runTestIncValue32);
549 FINALIZER(runClearTable);
550 }
551 TESTCASE("IncValue64",
552 "Test incValue for 64 bit integer\n"){
553 INITIALIZER(runLoadTable);
554 INITIALIZER(runTestIncValue64);
555 FINALIZER(runClearTable);
556 }
557 TESTCASE("Bug19537",
558 "Test big-endian write_attr of 32 bit integer\n"){
559 INITIALIZER(runLoadTable);
560 INITIALIZER(runTestBug19537);
561 FINALIZER(runClearTable);
562 }
563 TESTCASE("Bug34107",
564 "Test too big scan filter (error 874)\n"){
565 INITIALIZER(runLoadTable);
566 INITIALIZER(runTestBug34107);
567 FINALIZER(runClearTable);
568 }
569 #if 0
570 TESTCASE("MaxTransactions",
571 "Start transactions until no more can be created\n"){
572 INITIALIZER(runTestMaxTransaction);
573 }
574 TESTCASE("MaxOperations",
575 "Get operations until no more can be created\n"){
576 INITIALIZER(runLoadTable);
577 INITIALIZER(runTestMaxOperations);
578 FINALIZER(runClearTable);
579 }
580 TESTCASE("MaxGetValue",
581 "Call getValue loads of time\n"){
582 INITIALIZER(runLoadTable);
583 INITIALIZER(runTestGetValue);
584 FINALIZER(runClearTable);
585 }
586 TESTCASE("MaxEqual",
587 "Call equal loads of time\n"){
588 INITIALIZER(runTestEqual);
589 }
590 TESTCASE("DeleteNdb",
591 "Make sure that a deleted Ndb object is properly deleted\n"
592 "and removed from transporter\n"){
593 INITIALIZER(runLoadTable);
594 INITIALIZER(runTestDeleteNdb);
595 FINALIZER(runClearTable);
596 }
597 TESTCASE("WaitUntilReady",
598 "Make sure you get an error message when calling waitUntilReady\n"
599 "without an init'ed Ndb\n"){
600 INITIALIZER(runTestWaitUntilReady);
601 }
602 TESTCASE("GetOperationNoTab",
603 "Call getNdbOperation on a table that does not exist\n"){
604 INITIALIZER(runGetNdbOperationNoTab);
605 }
606 TESTCASE("MissingOperation",
607 "Missing operation request(insertTuple) should give an error code\n"){
608 INITIALIZER(runMissingOperation);
609 }
610 TESTCASE("GetValueInUpdate",
611 "Test that it's not possible to perform getValue in an update\n"){
612 INITIALIZER(runLoadTable);
613 INITIALIZER(runGetValueInUpdate);
614 FINALIZER(runClearTable);
615 }
616 TESTCASE("UpdateWithoutKeys",
617 "Test that it's not possible to perform update without setting\n"
618 "PKs"){
619 INITIALIZER(runLoadTable);
620 INITIALIZER(runUpdateWithoutKeys);
621 FINALIZER(runClearTable);
622 }
623 TESTCASE("UpdateWithoutValues",
624 "Test that it's not possible to perform update without setValues\n"){
625 INITIALIZER(runLoadTable);
626 INITIALIZER(runUpdateWithoutValues);
627 FINALIZER(runClearTable);
628 }
629 TESTCASE("NdbErrorOperation",
630 "Test that NdbErrorOperation is properly set"){
631 INITIALIZER(runCheckGetNdbErrorOperation);
632 }
633 #endif
634 TESTCASE("InterpretedUKLookup", "")
635 {
636 INITIALIZER(runLoadTable);
637 INITIALIZER(createPkIndex);
638 INITIALIZER(runInterpretedUKLookup);
639 INITIALIZER(createPkIndex_Drop);
640 }
641 NDBT_TESTSUITE_END(testInterpreter);
642
main(int argc,const char ** argv)643 int main(int argc, const char** argv){
644 ndb_init();
645 // TABLE("T1");
646 NDBT_TESTSUITE_INSTANCE(testInterpreter);
647 return testInterpreter.execute(argc, argv);
648 }
649
650
651