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 ERR(pNdb->getNdbError());
98 return NDBT_FAILED;
99 }
100
101 NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
102 if (pOp == NULL) {
103 ERR(pTrans->getNdbError());
104 pNdb->closeTransaction(pTrans);
105 return NDBT_FAILED;
106 }
107
108 int check = pOp->interpretedUpdateTuple();
109 if( check == -1 ) {
110 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 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 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 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 ERR(pTrans->getNdbError());
148 pNdb->closeTransaction(pTrans);
149 return NDBT_FAILED;
150 }
151
152 check = pTrans->execute(Commit);
153 if( check == -1 ) {
154 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 ERR(pNdb->getNdbError());
191 return NDBT_FAILED;
192 }
193
194 NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
195 if (pOp == NULL) {
196 ERR(pTrans->getNdbError());
197 pNdb->closeTransaction(pTrans);
198 return NDBT_FAILED;
199 }
200
201 if (pOp->interpretedUpdateTuple() == -1) {
202 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 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 Uint32 reg_ptr32[2];
220 memcpy(reg_ptr32+0, (Uint8*)®_val, sizeof(Uint32));
221 memcpy(reg_ptr32+1, ((Uint8*)®_val)+4, sizeof(Uint32));
222 if (reg_ptr32[0] == 0x05060708 && reg_ptr32[1] == 0x01020304) {
223 g_err << "runTestBug19537: platform is LITTLE endian" << endl;
224 } else if (reg_ptr32[0] == 0x01020304 && reg_ptr32[1] == 0x05060708) {
225 g_err << "runTestBug19537: platform is BIG endian" << endl;
226 } else {
227 g_err << "runTestBug19537: impossible platform"
228 << hex << " [0]=" << reg_ptr32[0] << " [1]=" <<reg_ptr32[1] << endl;
229 pNdb->closeTransaction(pTrans);
230 return NDBT_FAILED;
231 }
232
233 if (pOp->load_const_u64(1, reg_val) == -1 ||
234 pOp->write_attr("KOL2", 1) == -1) {
235 ERR(pOp->getNdbError());
236 pNdb->closeTransaction(pTrans);
237 return NDBT_FAILED;
238 }
239
240 if (pTrans->execute(Commit) == -1) {
241 ERR(pTrans->getNdbError());
242 pNdb->closeTransaction(pTrans);
243 return NDBT_FAILED;
244 }
245
246 // Read value via a new transaction
247
248 pTrans = pNdb->startTransaction();
249 if (pTrans == NULL){
250 ERR(pNdb->getNdbError());
251 return NDBT_FAILED;
252 }
253
254 pOp = pTrans->getNdbOperation(pTab->getName());
255 if (pOp == NULL) {
256 ERR(pTrans->getNdbError());
257 pNdb->closeTransaction(pTrans);
258 return NDBT_FAILED;
259 }
260
261 Uint32 kol2 = 0x09090909;
262 if (pOp->readTuple() == -1 ||
263 pOp->equal("KOL1", pkVal) == -1 ||
264 pOp->getValue("KOL2", (char*)&kol2) == 0) {
265 ERR(pOp->getNdbError());
266 pNdb->closeTransaction(pTrans);
267 return NDBT_FAILED;
268 }
269
270 if (pTrans->execute(Commit) == -1) {
271 ERR(pTrans->getNdbError());
272 pNdb->closeTransaction(pTrans);
273 return NDBT_FAILED;
274 }
275
276 // Expected conversion as in C - truncate to lower (logical) word
277
278 if (kol2 == 0x01020304) {
279 g_err << "runTestBug19537: the bug manifests itself !" << endl;
280 pNdb->closeTransaction(pTrans);
281 return NDBT_FAILED;
282 }
283
284 if (kol2 != 0x05060708) {
285 g_err << "runTestBug19537: impossible KOL2 " << hex << kol2 << endl;
286 pNdb->closeTransaction(pTrans);
287 return NDBT_FAILED;
288 }
289
290 pNdb->closeTransaction(pTrans);
291 return NDBT_OK;
292 }
293
294
runTestBug34107(NDBT_Context * ctx,NDBT_Step * step)295 int runTestBug34107(NDBT_Context* ctx, NDBT_Step* step){
296 const NdbDictionary::Table * pTab = ctx->getTab();
297 Ndb* pNdb = GETNDB(step);
298 const Uint32 okSize= 10000;
299 const Uint32 tooBig= 30000;
300
301 Uint32 codeBuff[tooBig];
302
303 int i;
304 for (i = 0; i <= 1; i++) {
305 g_info << "bug34107:" << (i == 0 ? " small" : " too big") << endl;
306
307 NdbConnection* pTrans = pNdb->startTransaction();
308 if (pTrans == NULL){
309 ERR(pNdb->getNdbError());
310 return NDBT_FAILED;
311 }
312
313 NdbScanOperation* pOp = pTrans->getNdbScanOperation(pTab->getName());
314 if (pOp == NULL) {
315 ERR(pTrans->getNdbError());
316 pNdb->closeTransaction(pTrans);
317 return NDBT_FAILED;
318 }
319
320 if (pOp->readTuples() == -1) {
321 ERR(pOp->getNdbError());
322 pNdb->closeTransaction(pTrans);
323 return NDBT_FAILED;
324 }
325
326 /* Test kernel mechanism for dealing with too large program
327 * We need to provide our own program buffer as default
328 * NdbInterpretedCode buffer will not grow larger than
329 * NDB_MAX_SCANFILTER_SIZE
330 */
331
332 NdbInterpretedCode code(NULL, // Table is irrelevant
333 codeBuff,
334 tooBig); // Size of codeBuff
335
336 int n = i == 0 ? okSize : tooBig;
337 int k;
338
339 for (k = 0; k < n; k++) {
340
341 // inserts 1 word ATTRINFO
342
343 if (code.interpret_exit_ok() == -1) {
344 ERR(code.getNdbError());
345 pNdb->closeTransaction(pTrans);
346 return NDBT_FAILED;
347 }
348 }
349
350 if (code.finalise() != 0)
351 {
352 ERR(code.getNdbError());
353 pNdb->closeTransaction(pTrans);
354 return NDBT_FAILED;
355 }
356
357 if (pOp->setInterpretedCode(&code) != 0)
358 {
359 ERR(pOp->getNdbError());
360 pNdb->closeTransaction(pTrans);
361 return NDBT_FAILED;
362 }
363
364 if (pTrans->execute(NoCommit) == -1) {
365 ERR(pTrans->getNdbError());
366 pNdb->closeTransaction(pTrans);
367 return NDBT_FAILED;
368 }
369
370 int ret;
371 while ((ret = pOp->nextResult()) == 0)
372 ;
373 g_info << "ret=" << ret << " err=" << pOp->getNdbError().code << endl;
374
375 if (i == 0 && ret != 1) {
376 ERR(pTrans->getNdbError());
377 pNdb->closeTransaction(pTrans);
378 return NDBT_FAILED;
379 }
380
381 if (i == 1 && ret != -1) {
382 g_err << "unexpected big filter success" << endl;
383 pNdb->closeTransaction(pTrans);
384 return NDBT_FAILED;
385 }
386 if (i == 1 && pOp->getNdbError().code != 874) {
387 g_err << "unexpected big filter error code, wanted 874" << endl;
388 ERR(pTrans->getNdbError());
389 pNdb->closeTransaction(pTrans);
390 return NDBT_FAILED;
391 }
392
393 pNdb->closeTransaction(pTrans);
394 }
395
396 return NDBT_OK;
397 }
398
399 static char pkIdxName[256];
400
401 int
createPkIndex(NDBT_Context * ctx,NDBT_Step * step)402 createPkIndex(NDBT_Context* ctx, NDBT_Step* step){
403 const NdbDictionary::Table* pTab = ctx->getTab();
404 Ndb* pNdb = GETNDB(step);
405
406 bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0);
407 bool logged = ctx->getProperty("LoggedIndexes", (Uint32)0);
408 bool noddl= ctx->getProperty("NoDDL");
409
410 // Create index
411 BaseString::snprintf(pkIdxName, 255, "IDC_PK_%s", pTab->getName());
412 if (orderedIndex)
413 ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "
414 << pkIdxName << " (";
415 else
416 ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "unique index "
417 << pkIdxName << " (";
418
419 NdbDictionary::Index pIdx(pkIdxName);
420 pIdx.setTable(pTab->getName());
421 if (orderedIndex)
422 pIdx.setType(NdbDictionary::Index::OrderedIndex);
423 else
424 pIdx.setType(NdbDictionary::Index::UniqueHashIndex);
425 for (int c = 0; c< pTab->getNoOfColumns(); c++){
426 const NdbDictionary::Column * col = pTab->getColumn(c);
427 if(col->getPrimaryKey()){
428 pIdx.addIndexColumn(col->getName());
429 ndbout << col->getName() <<" ";
430 }
431 }
432
433 pIdx.setStoredIndex(logged);
434 ndbout << ") ";
435 if (noddl)
436 {
437 const NdbDictionary::Index* idx= pNdb->
438 getDictionary()->getIndex(pkIdxName, pTab->getName());
439
440 if (!idx)
441 {
442 ndbout << "Failed - Index does not exist and DDL not allowed" << endl;
443 ERR(pNdb->getDictionary()->getNdbError());
444 return NDBT_FAILED;
445 }
446 else
447 {
448 // TODO : Check index definition is ok
449 }
450 }
451 else
452 {
453 if (pNdb->getDictionary()->createIndex(pIdx) != 0){
454 ndbout << "FAILED!" << endl;
455 const NdbError err = pNdb->getDictionary()->getNdbError();
456 ERR(err);
457 return NDBT_FAILED;
458 }
459 }
460
461 ndbout << "OK!" << endl;
462 return NDBT_OK;
463 }
464
465 int
createPkIndex_Drop(NDBT_Context * ctx,NDBT_Step * step)466 createPkIndex_Drop(NDBT_Context* ctx, NDBT_Step* step)
467 {
468 const NdbDictionary::Table* pTab = ctx->getTab();
469 Ndb* pNdb = GETNDB(step);
470
471 bool noddl= ctx->getProperty("NoDDL");
472
473 // Drop index
474 if (!noddl)
475 {
476 ndbout << "Dropping index " << pkIdxName << " ";
477 if (pNdb->getDictionary()->dropIndex(pkIdxName,
478 pTab->getName()) != 0){
479 ndbout << "FAILED!" << endl;
480 ERR(pNdb->getDictionary()->getNdbError());
481 return NDBT_FAILED;
482 } else {
483 ndbout << "OK!" << endl;
484 }
485 }
486
487 return NDBT_OK;
488 }
489
490 #define CHK_RET_FAILED(x) if (!(x)) { ndbout_c("Failed on line: %u", __LINE__); return NDBT_FAILED; }
491
492 int
runInterpretedUKLookup(NDBT_Context * ctx,NDBT_Step * step)493 runInterpretedUKLookup(NDBT_Context* ctx, NDBT_Step* step)
494 {
495 const NdbDictionary::Table * pTab = ctx->getTab();
496 Ndb* pNdb = GETNDB(step);
497 NdbDictionary::Dictionary * dict = pNdb->getDictionary();
498
499 const NdbDictionary::Index* pIdx= dict->getIndex(pkIdxName, pTab->getName());
500 CHK_RET_FAILED(pIdx != 0);
501
502 const NdbRecord * pRowRecord = pTab->getDefaultRecord();
503 CHK_RET_FAILED(pRowRecord != 0);
504 const NdbRecord * pIdxRecord = pIdx->getDefaultRecord();
505 CHK_RET_FAILED(pIdxRecord != 0);
506
507 const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
508 Uint8 * pRow = new Uint8[len];
509 bzero(pRow, len);
510
511 HugoCalculator calc(* pTab);
512 calc.equalForRow(pRow, pRowRecord, 0);
513
514 NdbTransaction* pTrans = pNdb->startTransaction();
515 CHK_RET_FAILED(pTrans != 0);
516
517 NdbInterpretedCode code;
518 code.interpret_exit_ok();
519 code.finalise();
520
521 NdbOperation::OperationOptions opts;
522 bzero(&opts, sizeof(opts));
523 opts.optionsPresent = NdbOperation::OperationOptions::OO_INTERPRETED;
524 opts.interpretedCode = &code;
525
526 const NdbOperation * pOp = pTrans->readTuple(pIdxRecord, (char*)pRow,
527 pRowRecord, (char*)pRow,
528 NdbOperation::LM_Read,
529 0,
530 &opts,
531 sizeof(opts));
532 CHK_RET_FAILED(pOp);
533 int res = pTrans->execute(Commit, AbortOnError);
534
535 CHK_RET_FAILED(res == 0);
536
537 delete [] pRow;
538
539 return NDBT_OK;
540 }
541
542 NDBT_TESTSUITE(testInterpreter);
543 TESTCASE("IncValue32",
544 "Test incValue for 32 bit integer\n"){
545 INITIALIZER(runLoadTable);
546 INITIALIZER(runTestIncValue32);
547 FINALIZER(runClearTable);
548 }
549 TESTCASE("IncValue64",
550 "Test incValue for 64 bit integer\n"){
551 INITIALIZER(runLoadTable);
552 INITIALIZER(runTestIncValue64);
553 FINALIZER(runClearTable);
554 }
555 TESTCASE("Bug19537",
556 "Test big-endian write_attr of 32 bit integer\n"){
557 INITIALIZER(runLoadTable);
558 INITIALIZER(runTestBug19537);
559 FINALIZER(runClearTable);
560 }
561 TESTCASE("Bug34107",
562 "Test too big scan filter (error 874)\n"){
563 INITIALIZER(runLoadTable);
564 INITIALIZER(runTestBug34107);
565 FINALIZER(runClearTable);
566 }
567 #if 0
568 TESTCASE("MaxTransactions",
569 "Start transactions until no more can be created\n"){
570 INITIALIZER(runTestMaxTransaction);
571 }
572 TESTCASE("MaxOperations",
573 "Get operations until no more can be created\n"){
574 INITIALIZER(runLoadTable);
575 INITIALIZER(runTestMaxOperations);
576 FINALIZER(runClearTable);
577 }
578 TESTCASE("MaxGetValue",
579 "Call getValue loads of time\n"){
580 INITIALIZER(runLoadTable);
581 INITIALIZER(runTestGetValue);
582 FINALIZER(runClearTable);
583 }
584 TESTCASE("MaxEqual",
585 "Call equal loads of time\n"){
586 INITIALIZER(runTestEqual);
587 }
588 TESTCASE("DeleteNdb",
589 "Make sure that a deleted Ndb object is properly deleted\n"
590 "and removed from transporter\n"){
591 INITIALIZER(runLoadTable);
592 INITIALIZER(runTestDeleteNdb);
593 FINALIZER(runClearTable);
594 }
595 TESTCASE("WaitUntilReady",
596 "Make sure you get an error message when calling waitUntilReady\n"
597 "without an init'ed Ndb\n"){
598 INITIALIZER(runTestWaitUntilReady);
599 }
600 TESTCASE("GetOperationNoTab",
601 "Call getNdbOperation on a table that does not exist\n"){
602 INITIALIZER(runGetNdbOperationNoTab);
603 }
604 TESTCASE("MissingOperation",
605 "Missing operation request(insertTuple) should give an error code\n"){
606 INITIALIZER(runMissingOperation);
607 }
608 TESTCASE("GetValueInUpdate",
609 "Test that it's not possible to perform getValue in an update\n"){
610 INITIALIZER(runLoadTable);
611 INITIALIZER(runGetValueInUpdate);
612 FINALIZER(runClearTable);
613 }
614 TESTCASE("UpdateWithoutKeys",
615 "Test that it's not possible to perform update without setting\n"
616 "PKs"){
617 INITIALIZER(runLoadTable);
618 INITIALIZER(runUpdateWithoutKeys);
619 FINALIZER(runClearTable);
620 }
621 TESTCASE("UpdateWithoutValues",
622 "Test that it's not possible to perform update without setValues\n"){
623 INITIALIZER(runLoadTable);
624 INITIALIZER(runUpdateWithoutValues);
625 FINALIZER(runClearTable);
626 }
627 TESTCASE("NdbErrorOperation",
628 "Test that NdbErrorOperation is properly set"){
629 INITIALIZER(runCheckGetNdbErrorOperation);
630 }
631 #endif
632 TESTCASE("InterpretedUKLookup", "")
633 {
634 INITIALIZER(runLoadTable);
635 INITIALIZER(createPkIndex);
636 INITIALIZER(runInterpretedUKLookup);
637 INITIALIZER(createPkIndex_Drop);
638 }
639 NDBT_TESTSUITE_END(testInterpreter);
640
main(int argc,const char ** argv)641 int main(int argc, const char** argv){
642 ndb_init();
643 // TABLE("T1");
644 NDBT_TESTSUITE_INSTANCE(testInterpreter);
645 return testInterpreter.execute(argc, argv);
646 }
647
648
649