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