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*)&reg_val, sizeof(Uint32));
222   memcpy(&(reg_ptr32[1]), ((Uint8*)&reg_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