testOdbcDriver.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:158k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1.     k++;
  2. }
  3.     }
  4.     freeAll(test, hEnv, hDbc, hStmtList, tabCount);
  5. }
  6. // cartesian join (multiple nested scans)
  7. static void
  8. testCart(Test& test)
  9. {
  10.     SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
  11.     allocAll(test, hEnv, hDbc, hStmtList, tabCount);
  12.     char sql[MAX_SQL], *sqlptr;
  13.     for (unsigned cnt = 2; cnt <= 2; cnt++) {
  14. unsigned rows = 1;
  15. //for (unsigned k = 0; k < opt.m_depth; k++) {
  16.     //rows *= opt.m_scale * opt.m_threads;
  17. //}
  18. for (unsigned i = 0; i < tabCount; i++) {
  19.     SQLHANDLE& hStmt = hStmtList[i];
  20.     Tab& tab = tabList[i];
  21.     if (! tab.optok())
  22. continue;
  23.     tab.selectCart(sqlptr = sql, cnt);
  24.     if (opt.m_v >= 2)
  25. ndbout << "SQL: " << sql << endl;
  26.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  27. }
  28. unsigned k = 0;
  29. while (1) {
  30.     for (unsigned i = 0; i < tabCount; i++) {
  31. SQLHANDLE& hStmt = hStmtList[i];
  32. const Tab& tab = tabList[i];
  33. if (! tab.optok())
  34.     continue;
  35. if (k == rows)
  36.     test.exp(SQL_NO_DATA, 0, 0, true);
  37. test.run(HStmt(hStmt), SQLFetch(hStmt));
  38. if (k == rows) {
  39.     //chkTuplesFetched(test, hStmt, k);
  40.     test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  41. } else {
  42.     //chkTuplesFetched(test, hStmt, k + 1);
  43.     test.timerCnt(1);
  44. }
  45.     }
  46.     if (k == rows)
  47. break;
  48.     k++;
  49. }
  50.     }
  51.     freeAll(test, hEnv, hDbc, hStmtList, tabCount);
  52. }
  53. // delete
  54. static void
  55. testDeleteAll(Test& test)
  56. {
  57.     SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
  58.     allocAll(test, hEnv, hDbc, hStmtList, tabCount);
  59.     char sql[MAX_SQL], *sqlptr;
  60.     for (unsigned i = 0; i < tabCount; i++) {
  61. SQLHANDLE& hStmt = hStmtList[i];
  62. Tab& tab = tabList[i];
  63. if (! tab.optok())
  64.     continue;
  65. long count0 = -1;
  66. selectCount(test, hStmt, tab, &count0);
  67. tab.deleteAll(sqlptr = sql);
  68. if (opt.m_v >= 2)
  69.     ndbout << "SQL: " << sql << endl;
  70. test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
  71. if (count0 == 0)
  72.     test.exp(SQL_NO_DATA, 0, 0, true);
  73. test.run(HStmt(hStmt), SQLExecute(hStmt));
  74. #ifndef iODBC
  75. test.chk(HStmt(hStmt), test.m_functionCode == SQL_DIAG_DELETE_WHERE, "got %d != %d", test.m_functionCode, SQL_DIAG_DELETE_WHERE);
  76. #endif
  77. SQLINTEGER rowCount = -1;
  78. getRowCount(test, hStmt, &rowCount);
  79. test.timerCnt(rowCount);
  80. test.chk(HStmt(hStmt), rowCount == count0, "got %d != %ld", (int)rowCount, count0);
  81. chkTuplesFetched(test, hStmt, rowCount);
  82. if (opt.m_v >= 3)
  83.     ndbout << "deleted " << (int)rowCount <<  " from " << tab.m_name << endl;
  84. long count = -1;
  85. selectCount(test, hStmt, tab, &count);
  86. test.chk(HStmt(hStmt), count == 0, "got %ld != 0", count);
  87.     }
  88.     freeAll(test, hEnv, hDbc, hStmtList, tabCount);
  89. }
  90. static void
  91. testDeletePk(Test& test)
  92. {
  93.     SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
  94.     allocAll(test, hEnv, hDbc, hStmtList, tabCount);
  95.     char sql[MAX_SQL], *sqlptr;
  96.     for (unsigned i = 0; i < tabCount; i++) {
  97. SQLHANDLE& hStmt = hStmtList[i];
  98. const Tab& tab = tabList[i];
  99. if (! tab.optok())
  100.     continue;
  101. // prepare
  102. tab.deletePk(sqlptr = sql);
  103. if (opt.m_v >= 2)
  104.     ndbout << "SQL: " << sql << endl;
  105. test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
  106. // bind parameters
  107. Row row(tab);
  108. SQLSMALLINT parCount = -1;
  109. test.run(HStmt(hStmt), SQLNumParams(hStmt, &parCount));
  110. test.chk(HStmt(hStmt), parCount == tab.m_pkCount, "got %d != %d", (int)parCount, (int)tab.m_colCount);
  111. for (unsigned j = 0; j < tab.m_pkCount; j++) {
  112.     Fld& fld = row.m_fldList[tab.m_pkIndex[j]];
  113.     const Col& col = fld.m_col;
  114.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1 + j, SQL_PARAM_INPUT, col.ctype(), col.type(), col.size(), 0, fld.caddr(), col.csize(), fld.ind()));
  115. }
  116. // bind columns (none)
  117. SQLSMALLINT colCount = -1;
  118. test.run(HStmt(hStmt), SQLNumResultCols(hStmt, &colCount));
  119. test.chk(HStmt(hStmt), colCount == 0, "got %d != 0", (int)colCount);
  120. // execute
  121. for (unsigned k = 0; k < opt.m_scale; k++) {
  122.     row.calcPk(test, k);
  123.     test.run(HStmt(hStmt), SQLExecute(hStmt));
  124.     test.chk(HStmt(hStmt), test.m_functionCode == SQL_DIAG_DELETE_WHERE, "got %d != %d", test.m_functionCode, SQL_DIAG_DELETE_WHERE);
  125.     chkRowCount(test, hStmt, 1);
  126.     // direct delete, no fetch required
  127.     chkTuplesFetched(test, hStmt, 0);
  128. }
  129. test.timerCnt(opt.m_scale);
  130. if (opt.m_v >= 3)
  131.     ndbout << "updated " << opt.m_scale <<  " in " << tab.m_name << endl;
  132.     }
  133.     freeAll(test, hEnv, hDbc, hStmtList, tabCount);
  134. }
  135. static void
  136. testTrans(Test& test)
  137. {
  138. #ifdef unixODBC
  139.     if (opt.m_v >= 1)
  140. ndbout << "unixODBC does not support transactions - test skipped" << endl;
  141. #else
  142.     SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
  143.     allocAll(test, hEnv, hDbc, hStmtList, tabCount);
  144.     char sql[MAX_SQL], *sqlptr;
  145.     // delete all
  146.     for (unsigned i = 0; i < tabCount; i++) {
  147. SQLHANDLE& hStmt = hStmtList[i];
  148. const Tab& tab = tabList[i];
  149. if (! tab.optok())
  150.     continue;
  151. tab.deleteAll(sqlptr = sql);
  152. test.exp(SQL_NO_DATA, 0, 0, false);
  153. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  154. SQLINTEGER rowCount = -1;
  155. getRowCount(test, hStmt, &rowCount);
  156. if (opt.m_v >= 3)
  157.     ndbout << "deleted " << (int)rowCount <<  " from " << tab.m_name << endl;
  158.     }
  159.     setAutocommit(test, hDbc, false);
  160.     if (opt.m_v >= 2)
  161. ndbout << "set autocommit OFF" << endl;
  162.     for (int commit = 0; commit < opt.m_scale; commit += 1) {
  163. bool rollback = (commit % 2 == 0);
  164. // XXX delete with no data leaves trans in error state for 2nd table
  165. if (commit > 0 && rollback) { // previous case was commit
  166.     for (unsigned i = 0; i < tabCount; i++) {
  167. SQLHANDLE& hStmt = hStmtList[i];
  168. const Tab& tab = tabList[i];
  169. if (! tab.optok())
  170.     continue;
  171. tab.deleteDirect(sqlptr = sql, 0);
  172. if (opt.m_v >= 2)
  173.     ndbout << "SQL: " << sql << endl;
  174. test.exp(SQL_NO_DATA, 0, 0, false);
  175. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  176.     }
  177.     test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
  178. }
  179. // insert
  180. for (unsigned i = 0; i < tabCount; i++) {
  181.     SQLHANDLE& hStmt = hStmtList[i];
  182.     const Tab& tab = tabList[i];
  183.     if (! tab.optok())
  184. continue;
  185.     tab.insertDirect(sqlptr = sql, 0);
  186.     if (opt.m_v >= 2)
  187. ndbout << "SQL: " << sql << endl;
  188.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  189.     if (opt.m_v >= 2)
  190. ndbout << tab.m_name << ": inserted 1 row" << endl;
  191. }
  192. // count them via pk
  193. for (unsigned i = 0; i < tabCount; i++) {
  194.     SQLHANDLE& hStmt = hStmtList[i];
  195.     const Tab& tab = tabList[i];
  196.     if (! tab.optok())
  197. continue;
  198.     tab.countDirect(sqlptr = sql, 0);
  199.     long count = -1;
  200.     long countExp = 1;
  201.     selectCount(test, hStmt, sql, &count);
  202.     test.chk(HStmt(hStmt), count == countExp, "got %ld != %ld", count, countExp);
  203. }
  204. // count them via scan
  205. for (unsigned i = 0; i < tabCount; i++) {
  206.     // XXX hupp no work
  207.     break;
  208.     SQLHANDLE& hStmt = hStmtList[i];
  209.     const Tab& tab = tabList[i];
  210.     if (! tab.optok())
  211. continue;
  212.     long count = -1;
  213.     long countExp = 1;
  214.     selectCount(test, hStmt, tab, &count);
  215.     test.chk(HStmt(hStmt), count == countExp, "got %ld != %ld", count, countExp);
  216. }
  217. // rollback or commit
  218. if (rollback) {
  219.     if (opt.m_v >= 2)
  220. ndbout << "end trans ROLLBACK" << endl;
  221.     test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_ROLLBACK));
  222. } else {
  223.     if (opt.m_v >= 2)
  224. ndbout << "end trans COMMIT" << endl;
  225.     test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
  226. }
  227. // count them via pk again
  228. for (unsigned i = 0; i < tabCount; i++) {
  229.     SQLHANDLE& hStmt = hStmtList[i];
  230.     const Tab& tab = tabList[i];
  231.     if (! tab.optok())
  232. continue;
  233.     tab.countDirect(sqlptr = sql, 0);
  234.     long count = -1;
  235.     long countExp = rollback ? 0 : 1;
  236.     selectCount(test, hStmt, sql, &count);
  237.     test.chk(HStmt(hStmt), count == countExp, "got %ld != %ld", count, countExp);
  238. }
  239. // count them via scan again
  240. for (unsigned i = 0; i < tabCount; i++) {
  241.     // XXX hupp no work
  242.     break;
  243.     SQLHANDLE& hStmt = hStmtList[i];
  244.     const Tab& tab = tabList[i];
  245.     if (! tab.optok())
  246. continue;
  247.     long count = -1;
  248.     long countExp = rollback ? 0 : 1;
  249.     selectCount(test, hStmt, tab, &count);
  250.     test.chk(HStmt(hStmt), count == countExp, "got %ld != %ld", count, countExp);
  251. }
  252.     }
  253.     freeAll(test, hEnv, hDbc, hStmtList, tabCount);
  254. #endif
  255. }
  256. static void
  257. testConcur(Test& test)
  258. {
  259.     SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
  260.     allocAll(test, hEnv, hDbc, hStmtList, tabCount);
  261.     char sql[MAX_SQL], *sqlptr;
  262.     for (unsigned i = 0; i < tabCount; i++) {
  263. SQLHANDLE& hStmt = hStmtList[i];
  264. const Tab& tab = tabList[i];
  265. if (! tab.optok())
  266.     continue;
  267. // delete all
  268. tab.deleteAll(sqlptr = sql);
  269. test.exp(SQL_NO_DATA, 0, 0, false);
  270. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  271. // insert some
  272. unsigned rowcount = 10;
  273. for (unsigned n = 0; n < rowcount; n++) {
  274.     tab.insertDirect(sqlptr = sql, n);
  275.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  276. }
  277. verifyCount(test, hStmt, tab, rowcount);
  278. // start query scan followed by pk lookups
  279. tab.selectJoin(sqlptr = sql, 2);
  280. if (opt.m_v >= 2)
  281.     ndbout << "SQL: " << sql << endl;
  282. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  283. // start fetch
  284. unsigned k = 0;
  285. while (1) {
  286.     if (k > 0)
  287. test.exp(SQL_ERROR, "24000", -1, true); // commit closed cursor
  288.     test.run(HStmt(hStmt), SQLFetch(hStmt));
  289.     if (k > 0)
  290. break;
  291.     // delete some random row
  292.     tab.deleteDirect(sqlptr = sql, k);
  293.     // try using same statement
  294.     test.exp(SQL_ERROR, "24000", -1, true); // cursor is open
  295.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  296.     // try using different statement
  297.     SQLHANDLE hStmt2;
  298.     allocStmt(test, hDbc, hStmt2);
  299.     test.run(HStmt(hStmt2), SQLExecDirect(hStmt2, (SQLCHAR*)sql, SQL_NTS));
  300.     k++;
  301. }
  302. test.exp(SQL_ERROR, "24000", -1, true); // cursor is not open
  303. test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  304. test.timerCnt(rowcount);
  305.     }
  306.     freeAll(test, hEnv, hDbc, hStmtList, tabCount);
  307. }
  308. static void
  309. testReadcom(Test& test)
  310. {
  311.     testDeleteAll(test);
  312.     testInsert(test);
  313.     const unsigned nc = 3;
  314.     SQLHANDLE hEnv[nc], hDbc[nc], hStmt[nc];
  315.     char sql[MAX_SQL], *sqlptr;
  316.     for (unsigned j = 0; j < nc; j++)
  317. allocAll(test, hEnv[j], hDbc[j], hStmt[j]);
  318.     for (unsigned i = 0; i < tabCount; i++) {
  319. Tab& tab = tabList[i];
  320. if (! tab.optok())
  321.     continue;
  322. long count;
  323. // check count
  324. count = -1;
  325. selectCount(test, hStmt[0], tab, &count);
  326. test.chk(HStmt(hStmt[0]), count == opt.m_scale, "got %d != %d", (int)count, (int)opt.m_scale);
  327. // scan delete uncommitted with handle 0
  328. setAutocommit(test, hDbc[0], false);
  329. tab.deleteAll(sqlptr = sql);
  330. if (opt.m_scale == 0)
  331.     test.exp(SQL_NO_DATA, 0, 0, false);
  332. if (opt.m_v >= 2)
  333.     ndbout << "SQL: " << sql << endl;
  334. test.run(HStmt(hStmt[0]), SQLExecDirect(hStmt[0], (SQLCHAR*)sql, SQL_NTS));
  335. // scan via other tx should not hang and see all rows
  336. for (unsigned j = 0; j < nc; j++) {
  337.     count = -1;
  338.     int want = j == 0 ? 0 : opt.m_scale;
  339.     selectCount(test, hStmt[j], tab, &count);
  340.     test.chk(HStmt(hStmt[j]), count == want, "tx %u: got %d != %d", j, (int)count, want);
  341.     if (opt.m_v >= 2)
  342. ndbout << "tx " << j << " ok !" << endl;
  343. }
  344. // setting autocommit on commits the delete
  345. setAutocommit(test, hDbc[0], true);
  346. // check count
  347. count = -1;
  348. selectCount(test, hStmt[0], tab, &count);
  349. test.chk(HStmt(hStmt[0]), count == 0, "got %d != 0", (int)count);
  350.     }
  351.     for (unsigned j = 0; j < nc; j++)
  352. freeAll(test, hEnv[j], hDbc[j], hStmt[j]);
  353. }
  354. static void
  355. testPerf(Test& test)
  356. {
  357.     if (test.m_stuff == 0) {
  358. SQLHANDLE hEnv, hDbc, hStmt;
  359. allocAll(test, hEnv, hDbc, hStmt);
  360. char sql[MAX_SQL], *sqlptr;
  361. for (unsigned i = 0; i < tabCount; i++) {
  362.     Tab& tab = tabList[i];
  363.     if (! tab.optok())
  364. continue;
  365.     test.exp(SQL_NO_DATA, 0, 0, false);
  366.     tab.deleteAll(sqlptr = sql);
  367.     if (opt.m_v >= 2)
  368. ndbout << "SQL: " << sql << endl;
  369.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  370.     long count0 = -1;
  371.     // XXX triggers SEGV somewhere
  372.     //selectCount(test, hStmt, tab, &count0);
  373.     //test.chk(HStmt(hStmt), count0 == 0, "got %d != 0", (int)count0);
  374. }
  375. freeAll(test, hEnv, hDbc, hStmt);
  376. return;
  377.     }
  378.     assert(test.m_stuff == 1 || test.m_stuff == 2);
  379.     bool ndbapi = (test.m_stuff == 1);
  380.     tt01: {
  381. const unsigned OFF = 1000000;
  382. const unsigned N = 25;
  383. Tab& tab = tabList[1];
  384. if (! tab.optok())
  385.     goto out;
  386. if (ndbapi) {
  387. #ifndef ndbODBC
  388.     if (opt.m_v >= 1)
  389. ndbout << "running via DM - test skipped" << endl;
  390. #else
  391.     Ndb* ndb = new Ndb("TEST_DB");
  392.     ndb->init();
  393.     if (ndb->waitUntilReady() != 0) {
  394. ndbout << ndb->getNdbError() << endl;
  395. fatal("waitUntilReady");
  396.     }
  397.     Uint32 val[1+N];
  398.     // insert
  399.     for (unsigned k = 1; k <= opt.m_scale; k++) {
  400. NdbConnection* con = ndb->startTransaction();
  401. if (con == 0) {
  402.     ndbout << ndb->getNdbError() << endl;
  403.     fatal("startTransaction");
  404. }
  405. NdbOperation* op = con->getNdbOperation(tab.m_upperName);
  406. if (op == 0) {
  407.     ndbout << con->getNdbError() << endl;
  408.     fatal("getNdbOperation");
  409. }
  410. if (op->insertTuple() == -1) {
  411.     ndbout << op->getNdbError() << endl;
  412.     fatal("insertTuple");
  413. }
  414. for (unsigned j = 0; j <= N; j++) {
  415.     val[j] = (j == 0 ? k + test.m_no * OFF : k * j);
  416.     if (j == 0) {
  417. if (op->equal(j, val[j]) == -1) {
  418.     ndbout << op->getNdbError() << endl;
  419.     fatal("equal");
  420. }
  421.     } else {
  422. if (op->setValue(j, val[j]) == -1) {
  423.     ndbout << op->getNdbError() << endl;
  424.     fatal("setValue");
  425. }
  426.     }
  427. }
  428. if (con->execute(Commit) == -1) {
  429.     ndbout << con->getNdbError() << endl;
  430.     fatal("execute");
  431. }
  432. ndb->closeTransaction(con);
  433.     }
  434.     test.timerCnt(opt.m_scale);
  435.     // select PK
  436.     for (unsigned k = 1; k <= opt.m_scale; k++) {
  437. NdbConnection* con = ndb->startTransaction();
  438. if (con == 0) {
  439.     ndbout << ndb->getNdbError() << endl;
  440.     fatal("startTransaction");
  441. }
  442. NdbOperation* op = con->getNdbOperation(tab.m_upperName);
  443. if (op == 0) {
  444.     ndbout << con->getNdbError() << endl;
  445.     fatal("getNdbOperation");
  446. }
  447. if (op->readTuple() == -1) {
  448.     ndbout << op->getNdbError() << endl;
  449.     fatal("insertTuple");
  450. }
  451. for (unsigned j = 0; j <= N; j++) {
  452.     val[j] = (j == 0 ? k + test.m_no * OFF : 0);
  453.     if (j == 0) {
  454. if (op->equal(j, val[j]) == -1) {
  455.     ndbout << op->getNdbError() << endl;
  456.     fatal("equal");
  457. }
  458.     } else {
  459. if (op->getValue(j, (char*)&val[j]) == 0) {
  460.     ndbout << op->getNdbError() << endl;
  461.     fatal("getValue");
  462. }
  463.     }
  464. }
  465. if (con->execute(Commit) == -1) {
  466.     ndbout << con->getNdbError() << endl;
  467.     fatal("execute");
  468. }
  469. for (unsigned j = 1; j <= N; j++) {
  470.     assert(val[j] == k * j);
  471. }
  472. ndb->closeTransaction(con);
  473.     }
  474.     test.timerCnt(opt.m_scale);
  475.     // delete PK
  476.     for (unsigned k = 1; k <= opt.m_scale; k++) {
  477. NdbConnection* con = ndb->startTransaction();
  478. if (con == 0) {
  479.     ndbout << ndb->getNdbError() << endl;
  480.     fatal("startTransaction");
  481. }
  482. NdbOperation* op = con->getNdbOperation(tab.m_upperName);
  483. if (op == 0) {
  484.     ndbout << con->getNdbError() << endl;
  485.     fatal("getNdbOperation");
  486. }
  487. if (op->deleteTuple() == -1) {
  488.     ndbout << op->getNdbError() << endl;
  489.     fatal("deleteTuple");
  490. }
  491. unsigned j = 0;
  492. val[j] = k + test.m_no * OFF;
  493. if (op->equal(j, val[j]) == -1) {
  494.     ndbout << op->getNdbError() << endl;
  495.     fatal("equal");
  496. }
  497. if (con->execute(Commit) == -1) {
  498.     ndbout << con->getNdbError() << endl;
  499.     fatal("execute");
  500. }
  501. ndb->closeTransaction(con);
  502.     }
  503.     test.timerCnt(opt.m_scale);
  504.     delete ndb;
  505. #endif
  506. } else {
  507.     SQLHANDLE hEnv, hDbc, hStmt;
  508.     allocAll(test, hEnv, hDbc, hStmt);
  509.     long val[1+N];
  510.     char sql[MAX_SQL], *sqlptr;
  511.     // insert
  512.     tab.insertAll(sqlptr = sql);
  513.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
  514.     for (unsigned j = 0; j <= N; j++) {
  515. test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1 + j, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &val[j], 0, 0));
  516.     }
  517.     test.m_perf = true;
  518.     for (unsigned k = 1; k <= opt.m_scale; k++) {
  519. for (unsigned j = 0; j <= N; j++) {
  520.     val[j] = (j == 0 ? k + test.m_no * OFF : k * j);
  521. }
  522. test.run(HStmt(hStmt), SQLExecute(hStmt));
  523.     }
  524.     test.m_perf = false;
  525.     test.timerCnt(opt.m_scale);
  526.     // select PK
  527.     tab.selectPk(sqlptr = sql);
  528.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
  529.     for (unsigned j = 0; j <= N; j++) {
  530. test.run(HStmt(hStmt), SQLBindCol(hStmt, 1 + j, SQL_C_SLONG, &val[j], 0, 0));
  531.     }
  532.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1 + N + 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &val[0], 0, 0));
  533.     test.m_perf = true;
  534.     for (unsigned k = 1; k <= opt.m_scale; k++) {
  535. val[0] = k + test.m_no * OFF;
  536. test.run(HStmt(hStmt), SQLExecute(hStmt));
  537. test.run(HStmt(hStmt), SQLFetch(hStmt));
  538. for (unsigned j = 1; j <= N; j++) {
  539.     assert(val[j] == k * j);
  540. }
  541. test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  542.     }
  543.     test.m_perf = false;
  544.     test.timerCnt(opt.m_scale);
  545.     // delete PK
  546.     tab.deletePk(sqlptr = sql);
  547.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
  548.     unsigned j = 0;
  549.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1 + j, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &val[j], 0, 0));
  550.     test.m_perf = true;
  551.     for (unsigned k = 1; k <= opt.m_scale; k++) {
  552. val[j] = k + test.m_no * OFF;
  553. test.run(HStmt(hStmt), SQLExecute(hStmt));
  554.     }
  555.     test.m_perf = false;
  556.     test.timerCnt(opt.m_scale);
  557.     freeAll(test, hEnv, hDbc, hStmt);
  558. }
  559.     out:
  560.      ;
  561.     }
  562. }
  563. struct Sql {
  564.     const char* m_sql;
  565.     int m_functionCode;
  566.     int m_rowCount;
  567.     int m_tuplesFetched;
  568.     long m_lastValue;
  569.     unsigned long m_bindValue;
  570.     int m_ret;
  571.     const char* m_state;
  572.     SQLINTEGER m_native;
  573.     bool m_reset;
  574.     // run this function instead
  575.     typedef void (*TestFunc)(Test& test);
  576.     TestFunc m_testFunc;
  577.     Sql() :
  578. m_sql(0) {
  579.     }
  580.     Sql(const char* do_cmd) :
  581. m_sql(do_cmd) {
  582.     }
  583.     Sql(const char* sql, int functionCode, int rowCount, int tuplesFetched, long lastValue, long bindValue) :
  584.         m_sql(sql),
  585. m_functionCode(functionCode),
  586. m_rowCount(rowCount),
  587. m_tuplesFetched(tuplesFetched),
  588. m_lastValue(lastValue),
  589. m_bindValue(bindValue),
  590. m_ret(SQL_SUCCESS),
  591. m_state(0),
  592. m_native(0),
  593. m_reset(true),
  594. m_testFunc(0) {
  595.     }
  596.     // the 4 numbers after SQL_DIAG... rowCount tuplesFetched lastValue bindValue
  597.     Sql(const char* sql, int functionCode, int rowCount, int tuplesFetched, long lastValue, long bindValue, int ret, const char* state, SQLINTEGER native, bool reset) :
  598.         m_sql(sql),
  599. m_functionCode(functionCode),
  600. m_rowCount(rowCount),
  601. m_tuplesFetched(tuplesFetched),
  602. m_lastValue(lastValue),
  603. m_bindValue(bindValue),
  604. m_ret(ret),
  605. m_state(state),
  606. m_native(native),
  607. m_reset(reset),
  608. m_testFunc(0) {
  609.     }
  610.     Sql(const char* text, TestFunc testFunc) :
  611. m_sql(text),
  612. m_testFunc(testFunc) {
  613.     }
  614.     static const char* set_autocommit_on() {
  615. return "set autocommit on";
  616.     }
  617.     static const char* set_autocommit_off() {
  618. return "set autocommit off";
  619.     }
  620.     static const char* do_commit() {
  621. return "commit";
  622.     }
  623.     static const char* do_rollback() {
  624. return "rollback";
  625.     }
  626. };
  627. // 90
  628. static const Sql
  629. miscSql90[] = {
  630.     Sql("select * from dual",
  631. SQL_DIAG_SELECT_CURSOR, 1, 0, -1, -1),
  632.     Sql("drop table tt90a",
  633. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  634. SQL_ERROR, "IM000", 2040709, false),
  635.     Sql("create table tt90a (a int, b int, c int, primary key(b, c)) storage(large) logging",
  636. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  637.     Sql()
  638. };
  639. // 91
  640. static const Sql
  641. miscSql91[] = {
  642.     Sql("drop table tt91a",
  643. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  644. SQL_ERROR, "IM000", 2040709, false),
  645.     Sql("create table tt91a (a bigint unsigned primary key, b bigint unsigned  not null, c varchar(10))",
  646. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  647.     Sql("insert into tt91a values (1, 111, 'aaa')",
  648. SQL_DIAG_INSERT, 1, 0, -1, -1),
  649.     // fails
  650.     Sql("insert into tt91a values (2, null, 'ccc')",
  651. SQL_DIAG_INSERT, -1, 0, -1, -1,
  652. SQL_ERROR, "IM000", 2014203, true),
  653.     Sql("update tt91a set b = 222 where a = 2",
  654. SQL_DIAG_UPDATE_WHERE, 0, 0, -1, -1,
  655. SQL_NO_DATA, 0, 0, true),
  656.     // two more
  657.     Sql("insert into tt91a values (2, 222, 'ccc')",
  658. SQL_DIAG_INSERT, 1, 0, -1, -1),
  659.     Sql("insert into tt91a values (3, 333, 'bbb')",
  660. SQL_DIAG_INSERT, 1, 0, -1, -1),
  661.     // direct update
  662.     Sql("update tt91a set b = 112 where a = 1",
  663. SQL_DIAG_UPDATE_WHERE, 1, 0, -1, -1),
  664.     Sql("update tt91a set b = 113 where a = 1 and b > 111",
  665. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  666.     // update and delete with interpreted scan
  667.     Sql("update tt91a set b = 114 where b < 114",
  668. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  669.     Sql("delete from tt91a where b < 115",
  670. SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
  671.     Sql("insert into tt91a values (1, 111, 'aaa')",
  672. SQL_DIAG_INSERT, 1, 0, -1, -1),
  673.     // check rows: 1,111,aaa + 2,222,ccc + 3,333,bbb
  674.     Sql("select * from tt91a order by c",
  675. SQL_DIAG_SELECT_CURSOR, 3, 3, 2, -1),
  676.     Sql("select * from tt91a order by c desc",
  677. SQL_DIAG_SELECT_CURSOR, 3, 3, 1, -1),
  678.     Sql("select * from tt91a where a = 2",
  679. SQL_DIAG_SELECT_CURSOR, 1, 1, -1, -1),
  680.     Sql("select * from tt91a where a + b = 224",
  681. SQL_DIAG_SELECT_CURSOR, 1, 3, -1, -1),
  682.     Sql("select * from tt91a where a = 4",
  683. SQL_DIAG_SELECT_CURSOR, 0, 0, -1, -1),
  684.     Sql("select b-a from tt91a order by a-b",
  685. SQL_DIAG_SELECT_CURSOR, 3, 3, 110, -1),
  686.     Sql("select sum(a+b) from tt91a",
  687. SQL_DIAG_SELECT_CURSOR, 1, 3, 672, -1),
  688.     Sql("select x.b, y.b, z.b from tt91a x, tt91a y, tt91a z where x.b <= y.b and y.b < z.b order by x.b",
  689. SQL_DIAG_SELECT_CURSOR, 4, 13, 222, -1),
  690.     Sql("select x.b, y.b, z.b from tt91a x, tt91a y, tt91a z where x.b + y.b = z.b order by x.b",
  691. SQL_DIAG_SELECT_CURSOR, 3, 15, 222, -1),
  692.     // tmp index
  693.     Sql("create unique hash index xx91a on tt91a(b)",
  694. SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
  695.     Sql("select x.b, y.b, z.b from tt91a x, tt91a y, tt91a z where x.b + y.b = z.b order by x.b",
  696. SQL_DIAG_SELECT_CURSOR, 3, 15, 222, -1),
  697.     Sql("drop index xx91a on tt91a",
  698. SQL_DIAG_DROP_INDEX, -1, -1, -1, -1),
  699.     // add some duplicates
  700.     Sql("insert into tt91a values (4, 222, 'ccc')",
  701. SQL_DIAG_INSERT, 1, -1, -1, -1),
  702.     Sql("insert into tt91a values (5, 333, 'bbb')",
  703. SQL_DIAG_INSERT, 1, -1, -1, -1),
  704.     Sql("insert into tt91a values (6, 333, 'bbb')",
  705. SQL_DIAG_INSERT, 1, -1, -1, -1),
  706.     // check rows: 1,111,aaa + 2 * 2,222,ccc  + 3 * 3,333,bbb
  707.     Sql("select count(*) from tt91a",
  708. SQL_DIAG_SELECT_CURSOR, 1, -1, 6, -1),
  709.     Sql("select a+b from tt91a where (b = 111 or b = 222 ) and (b = 222 or b = 333) and a > 1 and a < 3",
  710. SQL_DIAG_SELECT_CURSOR, 1, -1, 224, -1),
  711.     Sql("select sum(a) from tt91a having min(a) = 1 and max(a) = 6",
  712. SQL_DIAG_SELECT_CURSOR, 1, -1, 21, -1),
  713.     Sql("select sum(a) from tt91a where a = 2 or a = 4 having min(a) = 2 and max(a) = 4",
  714. SQL_DIAG_SELECT_CURSOR, 1, -1, 6, -1),
  715.     Sql("select sum(a) from tt91a having min(a) = 1 and max(a) = 5",
  716. SQL_DIAG_SELECT_CURSOR, 0, -1, -1, -1),
  717.     Sql("select sum(a), b from tt91a group by b order by b",
  718. SQL_DIAG_SELECT_CURSOR, 3, -1, 14, -1),
  719.     Sql("select sum(a), b, c from tt91a group by b, c order by c",
  720. SQL_DIAG_SELECT_CURSOR, 3, -1, 6, -1),
  721.     Sql("select b, sum(a) from tt91a group by b having b = 37 * sum(a)",
  722. SQL_DIAG_SELECT_CURSOR, 1, -1, 222, -1),
  723.     // simple varchar vs interpreter test
  724.     Sql("select count(*) from tt91a where c = 'ccc'",
  725. SQL_DIAG_SELECT_CURSOR, 1, 2, 2, -1),
  726.     Sql("select count(*) from tt91a where c like '%b%'",
  727. SQL_DIAG_SELECT_CURSOR, 1, 3, 3, -1),
  728.     // interpreter limits (crashes in api on v211)
  729. #if NDB_VERSION_MAJOR >= 3
  730.     Sql("select count(*) from tt91a where a in (99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2)",
  731. SQL_DIAG_SELECT_CURSOR, 1, 5, 5, -1),
  732.     Sql("select count(*) from tt91a where c in ('xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','bbb','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy','zzzzz','xxxxx','yyyyy')",
  733. SQL_DIAG_SELECT_CURSOR, 1, 3, 3, -1),
  734. #endif
  735.     // distinct
  736.     Sql("select distinct b from tt91a order by b",
  737. SQL_DIAG_SELECT_CURSOR, 3, -1, 333, -1),
  738.     // some illegal groupings
  739.     Sql("select a from tt91a group by b",
  740. -1, -1, -1, -1, -1,
  741. SQL_ERROR, "IM000", -1, -1),
  742.     Sql("select sum(a) from tt91a group by b having a = 2",
  743. -1, -1, -1, -1, -1,
  744. SQL_ERROR, "IM000", -1, -1),
  745.     Sql("select sum(a) from tt91a group by b order by a",
  746. -1, -1, -1, -1, -1,
  747. SQL_ERROR, "IM000", -1, -1),
  748.     // string functions
  749.     Sql("insert into tt91a (c, b, a) values ('abcdef', 999, 9)",
  750. SQL_DIAG_INSERT, 1, -1, -1, -1),
  751.     Sql("select count(*) from tt91a where left(c, 2) = 'ab' and substr(c, 3, 2) = 'cd' and right(c, 2) = 'ef'",
  752. SQL_DIAG_SELECT_CURSOR, 1, -1, 1, -1),
  753.     // nulls
  754.     Sql("update tt91a set c = null where a > 8",
  755. SQL_DIAG_UPDATE_WHERE, 1, -1, -1, -1),
  756.     Sql("select a from tt91a where c is null and b is not null order by a",
  757. SQL_DIAG_SELECT_CURSOR, 1, -1, 9, -1),
  758.     Sql("select a from tt91a where not (c is not null or b is null) order by a",
  759. SQL_DIAG_SELECT_CURSOR, 1, -1, 9, -1),
  760.     // null value guard in interpreter
  761.     Sql("select count(*) from tt91a where c < 'x' or c > 'x' or c != 'x' or c = 'x'",
  762. SQL_DIAG_SELECT_CURSOR, 1, 6, 6, -1),
  763.     Sql("delete from tt91a where c is null",
  764. SQL_DIAG_DELETE_WHERE, 1, -1, -1, -1),
  765.     // indexes
  766.     Sql("update tt91a set b = a + 5",
  767. SQL_DIAG_UPDATE_WHERE, 6, 6, -1, -1),
  768.     Sql("create unique hash index xx91a on tt91a(b)",
  769. SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
  770.     // scan y primary key x
  771.     Sql("select x.b from tt91a x, tt91a y where x.a = y.b + 0",
  772. SQL_DIAG_SELECT_CURSOR, 1, 7, 11, -1),
  773.     // scan x index y
  774.     Sql("select x.b from tt91a x, tt91a y where x.a + 0 = y.b",
  775. SQL_DIAG_SELECT_CURSOR, 1, -1, 11, -1),
  776.     // scan x scan y
  777.     Sql("select x.b from tt91a x, tt91a y where x.a + 0 = y.b + 0",
  778. SQL_DIAG_SELECT_CURSOR, 1, -1, 11, -1),
  779.     // dml ops
  780.     Sql("delete from tt91a where b = 11 and a > 999",
  781. SQL_DIAG_DELETE_WHERE, 0, 1, -1, -1,
  782. SQL_NO_DATA, 0, 0, true),
  783.     Sql("delete from tt91a where b = 11",
  784. SQL_DIAG_DELETE_WHERE, 1, 0, -1, -1),
  785.     Sql("delete from tt91a where b = 11",
  786. SQL_DIAG_DELETE_WHERE, 0, 0, -1, -1,
  787. SQL_NO_DATA, 0, 0, true),
  788.     Sql("update tt91a set b = 10*10 where b = 10",
  789. SQL_DIAG_UPDATE_WHERE, 1, 0, -1, -1),
  790.     Sql("update tt91a set b = 10 where b = 10*10",
  791. SQL_DIAG_UPDATE_WHERE, 1, 0, -1, -1),
  792.     Sql("update tt91a set b = 10*10 where b = 10 and b >= 10",
  793. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  794.     Sql("update tt91a set b = 10 where b = 10*10 and b >= 10*10",
  795. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  796.     // char vs varchar
  797.     Sql("drop table tt91b",
  798. SQL_DIAG_DROP_TABLE, -1, -1, -1, -1,
  799. SQL_ERROR, "IM000", 2040709, false),
  800.     Sql("create table tt91b (a int primary key, b char(5), c varchar(5))",
  801. SQL_DIAG_CREATE_TABLE, -1, -1, -1, -1),
  802.     Sql("insert into tt91b values (1, 'abc', 'abc')",
  803. SQL_DIAG_INSERT, 1, -1, -1, -1),
  804.     Sql("insert into tt91b values (2, 'xyz', 'xyz')",
  805. SQL_DIAG_INSERT, 1, -1, -1, -1),
  806.     Sql("insert into tt91b values (3, 'xyz', 'xyz  ')",
  807. SQL_DIAG_INSERT, 1, -1, -1, -1),
  808.     // char = char strips blanks
  809.     Sql("select count(*) from tt91b x where (x.b = 'abc') or x.a = x.a+1",
  810. SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
  811.     Sql("select count(*) from tt91b x where (x.b = 'abc')",
  812. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  813.     Sql("select count(*) from tt91b x where (x.b = 'abc       ') or x.a = x.a+1",
  814. SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
  815.     Sql("select count(*) from tt91b x where (x.b = 'abc       ')",
  816. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  817.     // varchar = char
  818.     Sql("select count(*) from tt91b x where (x.c = 'abc') or x.a = x.a+1",
  819. SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
  820.     Sql("select count(*) from tt91b x where (x.c = 'abc')",
  821. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  822.     Sql("select count(*) from tt91b x where (x.c = 'abc ') or x.a = x.a+1",
  823. SQL_DIAG_SELECT_CURSOR, 1, 3, 0, -1),
  824.     Sql("select count(*) from tt91b x where (x.c = 'abc ')",
  825. SQL_DIAG_SELECT_CURSOR, 1, 0, 0, -1),
  826.     // char = varchar
  827.     Sql("select count(*) from tt91b x, tt91b y where (x.b = y.c) or x.a = x.a+1 or y.a = y.a+1",
  828. SQL_DIAG_SELECT_CURSOR, 1, -1, 2, -1),
  829.     Sql("select count(*) from tt91b x, tt91b y where (x.b = y.c)",
  830. SQL_DIAG_SELECT_CURSOR, 1, -1, 2, -1),
  831.     // varchar = varchar
  832.     Sql("select count(*) from tt91b x, tt91b y where (x.c = y.c) or x.a = x.a+1 or y.a = y.a+1",
  833. SQL_DIAG_SELECT_CURSOR, 1, -1, 3, -1),
  834.     Sql("select count(*) from tt91b x, tt91b y where (x.c = y.c)",
  835. SQL_DIAG_SELECT_CURSOR, 1, -1, 3, -1),
  836.     // less
  837.     Sql("select 10 * x.a + y.a from tt91b x, tt91b y where (x.b < y.b) or x.a = x.a+1 or y.a = y.a+1 order by x.a, y.a",
  838. SQL_DIAG_SELECT_CURSOR, 2, -1, 13, -1),
  839.     Sql("select 10 * x.a + y.a from tt91b x, tt91b y where (x.b < y.b) order by x.a, y.a",
  840. SQL_DIAG_SELECT_CURSOR, 2, -1, 13, -1),
  841.     Sql("select 10 * x.a + y.a from tt91b x, tt91b y where (x.c < y.c) or x.a = x.a+1 or y.a = y.a+1 order by x.a, y.a",
  842. SQL_DIAG_SELECT_CURSOR, 3, -1, 23, -1),
  843.     Sql("select 10 * x.a + y.a from tt91b x, tt91b y where (x.c < y.c) order by x.a, y.a",
  844. SQL_DIAG_SELECT_CURSOR, 3, -1, 23, -1),
  845.     // like
  846.     Sql("select count(*) from tt91b x where (x.b like 'a%') or x.a = x.a+1",
  847. SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
  848.     Sql("select count(*) from tt91b x where (x.b like 'a%')",
  849. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  850.     Sql("select count(*) from tt91b x where (x.b like 'x%z') or x.a = x.a+1",
  851. SQL_DIAG_SELECT_CURSOR, 1, 3, 0, -1),
  852.     Sql("select count(*) from tt91b x where (x.b like 'x%z')",
  853. SQL_DIAG_SELECT_CURSOR, 1, 0, 0, -1),
  854.     Sql("select count(*) from tt91b x where (x.a+0 = 2 and x.c like 'x%z') or x.a = x.a+1",
  855. SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
  856.     Sql("select count(*) from tt91b x where (x.a+0 = 2 and x.c like 'x%z')",
  857. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  858.     Sql("select count(*) from tt91b x where (x.a+0 = 3 and x.c like 'x%z  ') or x.a = x.a+1",
  859. SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
  860.     Sql("select count(*) from tt91b x where (x.a+0 = 3 and x.c like 'x%z  ')",
  861. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  862.     Sql()
  863. };
  864. // 92
  865. static void
  866. testMisc92a(Test& test)
  867. {
  868.     SQLHANDLE hEnv, hDbc, hStmt;
  869.     allocAll(test, hEnv, hDbc, hStmt);
  870.     char sql[MAX_SQL];
  871.     char tname[20];
  872.     sprintf(tname, "tt92%c", 0140 + test.m_no);
  873.     if (test.m_loop == 1) {
  874. lock_mutex();
  875. sprintf(sql, "drop table %s", tname);
  876. if (opt.m_v >= 2)
  877.     ndbout << "SQL: " << sql << endl;
  878. test.exp(SQL_ERROR, "IM000", 2040709, false);
  879. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  880. sprintf(sql, "create table %s (a int unsigned primary key, b int unsigned not null)", tname);
  881. if (opt.m_v >= 2)
  882.     ndbout << "SQL: " << sql << endl;
  883. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  884. unlock_mutex();
  885.     } else {
  886. sprintf(sql, "delete from %s", tname);
  887. if (opt.m_v >= 2)
  888.     ndbout << "SQL: " << sql << endl;
  889. test.exp(SQL_NO_DATA, 0, 0, false);
  890. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  891. test.run(HStmt(hStmt), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
  892.     }
  893.     for (int on = true; on >= false; on--) {
  894. if (opt.m_v >= 2)
  895.     ndbout << "set autocommit " << (on ? "ON" : "OFF") << endl;
  896. setAutocommit(test, hDbc, on);
  897. // insert rows
  898. if (opt.m_v >= 2)
  899.     ndbout << "SQL: insert into " << tname << " ..." << opt.m_scale << endl;
  900. for (unsigned k = 0; k < opt.m_scale; k++) {
  901.     sprintf(sql, "insert into %s values (%u, %u)", tname, k, 10 * k);
  902.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  903. }
  904. // commit always
  905. test.run(HStmt(hStmt), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
  906. // scan delete
  907. sprintf(sql, "delete from %s", tname);
  908. if (opt.m_v >= 2)
  909.     ndbout << "SQL: " << sql << endl;
  910. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  911. // rollback or commit
  912. test.run(HStmt(hStmt), SQLEndTran(SQL_HANDLE_DBC, hDbc, on ? SQL_COMMIT : SQL_ROLLBACK));
  913. // count
  914. long count = -1;
  915. sprintf(sql, "select count(*) from %s", tname);
  916. if (opt.m_v >= 2)
  917.     ndbout << "SQL: " << sql << endl;
  918. selectCount(test, hStmt, sql, &count);
  919. test.chk(HStmt(hStmt), count == on ? 0 : opt.m_scale, "%s: got %d != %d", tname, (int)count, (int)opt.m_scale);
  920.     }
  921.     freeAll(test, hEnv, hDbc, hStmt);
  922. }
  923. static const Sql
  924. miscSql92[] = {
  925.     // create in C func
  926.     Sql("testMisc92a", testMisc92a),
  927.     Sql()
  928. };
  929. // 93
  930. static void
  931. testMisc93a(Test& test)
  932. {
  933.     SQLHANDLE hEnv[2], hDbc[2], hStmt[2];
  934.     allocAll(test, hEnv[0], hDbc[0], hStmt[0]);
  935.     allocAll(test, hEnv[1], hDbc[1], hStmt[1]);
  936.     char sql[MAX_SQL];
  937.     // select via primary key
  938.     setAutocommit(test, hDbc[0], false);
  939.     sprintf(sql, "select c1 from tt93a where c0 = 1");
  940.     if (opt.m_v >= 2)
  941. ndbout << "SQL: " << sql << endl;
  942.     test.run(HStmt(hStmt[0]), SQLExecDirect(hStmt[0], (SQLCHAR*)sql, SQL_NTS));
  943.     // update via another trans must time out
  944.     sprintf(sql, "update tt93a set c1 = 'b' where c0 = 1");
  945.     if (opt.m_v >= 2)
  946. ndbout << "SQL: " << sql << endl;
  947.     test.run(HStmt(hStmt[1]), SQLExecDirect(hStmt[1], (SQLCHAR*)sql, SQL_NTS));
  948.     freeAll(test, hEnv[0], hDbc[0], hStmt[0]);
  949.     freeAll(test, hEnv[1], hDbc[1], hStmt[1]);
  950. }
  951. static const Sql
  952. miscSql93[] = {
  953.     // create in C func
  954.     Sql("drop table tt93a",
  955. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  956. SQL_ERROR, "IM000", 2040709, false),
  957.     Sql("create table tt93a (c0 int primary key, c1 char(10))",
  958. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  959.     Sql("insert into tt93a values(1, 'a')",
  960. SQL_DIAG_INSERT, 1, 0, -1, -1),
  961.     Sql("testMisc93a", testMisc93a),
  962.     Sql()
  963. };
  964. // 95
  965. static const Sql
  966. miscSql95[] = {
  967.     Sql("drop table tt95a",
  968. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  969. SQL_ERROR, "IM000", 2040709, false),
  970.     Sql("create table tt95a (a int not null, b char(10) not null, c int not null, d char(10), primary key(a, b)) storage(small)",
  971. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  972.     // ordered index create and drop
  973.     Sql("create index xx95a on tt95a (c, d) nologging",
  974. SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
  975.     Sql("drop index xx95a on tt95a",
  976. SQL_DIAG_DROP_INDEX, -1, -1, -1, -1),
  977.     Sql("create index xx95a on tt95a (c) nologging",
  978. SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
  979.     Sql("insert into tt95a values(1, 'a', 10, 'b')",
  980. SQL_DIAG_INSERT, 1, -1, -1, -1),
  981.     Sql("insert into tt95a values(2, 'a', 20, 'b')",
  982. SQL_DIAG_INSERT, 1, -1, -1, -1),
  983.     Sql("insert into tt95a values(3, 'a', 30, 'b')",
  984. SQL_DIAG_INSERT, 1, -1, -1, -1),
  985.     Sql("select a from tt95a where c = 20",
  986. SQL_DIAG_SELECT_CURSOR, 1, 1, 2, -1),
  987.     Sql("delete from tt95a where c = 10",
  988. SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
  989.     Sql("update tt95a set c = 300 where c = 30",
  990. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  991.     Sql("delete from tt95a where c = 300",
  992. SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
  993.     Sql("delete from tt95a",
  994. SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
  995.     // simple insert and rollback
  996.     Sql("-- simple insert and rollback"),
  997.     Sql(Sql::set_autocommit_off()),
  998.     Sql("insert into tt95a values(1, 'a', 10, 'b')",
  999. SQL_DIAG_INSERT, 1, -1, -1, -1),
  1000.     Sql("select count(*) from tt95a",
  1001. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1002.     Sql("select count(*) from tt95a where c = 10",
  1003. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1004.     Sql(Sql::do_rollback()),
  1005.     Sql(Sql::set_autocommit_on()),
  1006.     Sql("select count(*) from tt95a",
  1007. SQL_DIAG_SELECT_CURSOR, 1, 0, 0, -1),
  1008.     // simple update and rollback
  1009.     Sql("-- simple update and rollback"),
  1010.     Sql("insert into tt95a values(1, 'a', 10, 'b')",
  1011. SQL_DIAG_INSERT, 1, -1, -1, -1),
  1012.     Sql(Sql::set_autocommit_off()),
  1013.     Sql("update tt95a set c = 20 where c = 10",
  1014. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  1015.     Sql("select count(*) from tt95a",
  1016. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1017.     Sql("select count(*) from tt95a where c = 20",
  1018. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1019.     Sql(Sql::do_rollback()),
  1020.     Sql(Sql::set_autocommit_on()),
  1021.     Sql("select count(*) from tt95a where c = 10",
  1022. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1023.     // simple delete and rollback
  1024.     Sql("-- simple delete and rollback"),
  1025.     Sql(Sql::set_autocommit_off()),
  1026.     Sql("delete from tt95a where c = 10",
  1027. SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
  1028.     Sql("select count(*) from tt95a",
  1029. SQL_DIAG_SELECT_CURSOR, 0, 0, 0, -1),
  1030.     Sql("select count(*) from tt95a where c = 10",
  1031. SQL_DIAG_SELECT_CURSOR, 0, 0, 0, -1),
  1032.     Sql(Sql::do_rollback()),
  1033.     Sql(Sql::set_autocommit_on()),
  1034.     Sql("select count(*) from tt95a where c = 10",
  1035. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1036.     // multiple update
  1037.     Sql("-- multiple update and rollback"),
  1038.     Sql(Sql::set_autocommit_off()),
  1039.     Sql("update tt95a set c = 20 where c = 10",
  1040. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  1041.     Sql("select count(*) from tt95a where c = 20",
  1042. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1043.     Sql("update tt95a set c = 30 where c = 20",
  1044. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  1045.     Sql("select count(*) from tt95a where c = 30",
  1046. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1047.     Sql("update tt95a set c = 40 where c = 30",
  1048. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  1049.     Sql("select count(*) from tt95a where c = 40",
  1050. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1051.     Sql("update tt95a set c = 50 where c = 40",
  1052. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  1053.     Sql("select count(*) from tt95a where c = 50",
  1054. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1055.     Sql(Sql::do_rollback()),
  1056.     Sql(Sql::set_autocommit_on()),
  1057.     Sql("select count(*) from tt95a where c = 10",
  1058. SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
  1059.     // another variant which found no tuple via index (aligment issue)
  1060.     Sql("drop table tt95b",
  1061. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  1062. SQL_ERROR, "IM000", 2040709, false),
  1063.     Sql("create table tt95b (a int primary key, b char(10) not null, c int not null)",
  1064. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  1065.     Sql("create index xx95b on tt95b (b, c) nologging",
  1066. SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
  1067.     Sql("insert into tt95b values(0,'0123456789',1)",
  1068. SQL_DIAG_INSERT, 1, -1, -1, -1),
  1069.     Sql("select a from tt95b where b='0123456789'",
  1070. SQL_DIAG_SELECT_CURSOR, 1, 1, 0, -1),
  1071.     // update index key to different value
  1072.     Sql("update tt95b set b = '9876543210' where b = '0123456789'",
  1073. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  1074.     // same value goes nuts...
  1075.     Sql("update tt95b set b = '9876543210'",
  1076. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  1077. #if 0
  1078.     // ...if done via index key (variant of halloween problem)
  1079.     Sql("update tt95b set b = '9876543210' where b = '9876543210'",
  1080. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
  1081. #endif
  1082.     Sql()
  1083. };
  1084. // 96
  1085. static void
  1086. testMisc96a(Test& test)
  1087. {
  1088.     // single thread
  1089.     if (test.m_no != 1)
  1090. return;
  1091.     SQLHANDLE hEnv, hDbc, hStmt;
  1092.     allocAll(test, hEnv, hDbc, hStmt);
  1093.     char sql[MAX_SQL], *sqlptr;
  1094.     char tname[20];
  1095.     strcpy(tname, "tt96a");
  1096.     // drop table
  1097.     scopy(sqlptr = sql, "drop table %s", tname);
  1098.     test.exp(SQL_ERROR, "IM000", 2040709, false);
  1099.     if (opt.m_v >= 2)
  1100.         ndbout << "SQL: " << sql << endl;
  1101.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1102.     // create table with many attributes
  1103.     unsigned attrs = 1 + opt.m_scale;
  1104.     if (attrs > MAX_ATTRIBUTES_IN_TABLE)
  1105.         attrs = MAX_ATTRIBUTES_IN_TABLE;
  1106.     if (attrs > 64)
  1107. attrs = 64;
  1108.     scopy(sqlptr = sql, "create table %s (c0 int primary key", tname);
  1109.     for (unsigned j = 1; j < attrs; j++) {
  1110.         if (j % 2 == 0)
  1111.             scopy(sqlptr, ", c%d int unsigned not null", j);
  1112.         else
  1113.             scopy(sqlptr, ", c%d char(10) not null", j);
  1114.     }
  1115.     scopy(sqlptr, ")");
  1116.     if (opt.m_fragtype != 0)
  1117.         scopy(sqlptr, " storage(%s)", opt.m_fragtype);
  1118.     if (opt.m_v >= 2)
  1119.         ndbout << "SQL: " << sql << endl;
  1120.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1121.     // create or drop indexes
  1122.     const unsigned seed = 1000037 * test.m_loop + 1000039 * opt.m_scale;
  1123.     srandom(seed);
  1124.     const unsigned imax = opt.m_scale < 20 ? opt.m_scale : 20;
  1125.     AttributeMask* imasks = new AttributeMask[imax];
  1126.     unsigned ccnt = 0;
  1127.     unsigned dcnt = 0;
  1128.     for (unsigned n = 0; n < imax; n++)
  1129. imasks[n].clear();
  1130.     while (ccnt + dcnt < opt.m_scale) {
  1131. char iname[20];
  1132. unsigned n = urandom(imax);
  1133. sprintf(iname, "xx96a%02d", n);
  1134. AttributeMask& imask = imasks[n];
  1135. unsigned sel = urandom(10);
  1136. if (imask.isclear()) {
  1137.     // create one
  1138.     unsigned ncol = 0;
  1139.     unsigned cols[MAX_ATTRIBUTES_IN_INDEX];
  1140.     unsigned cnum = urandom(attrs);
  1141.     cols[ncol++] = cnum;
  1142.     while (ncol < MAX_ATTRIBUTES_IN_INDEX) {
  1143. unsigned sel2 = urandom(10);
  1144. if (sel2 < 2)
  1145.     break;
  1146. unsigned cnum2 = urandom(attrs);
  1147. if (sel2 < 9 && cnum2 == 0)
  1148.     continue;
  1149. unsigned j;
  1150. for (j = 0; j < ncol; j++) {
  1151.     if (cols[j] == cnum2)
  1152. break;
  1153. }
  1154. if (j == ncol)
  1155.     cols[ncol++] = cnum2;
  1156.     }
  1157.     if (sel < 3) {
  1158. scopy(sqlptr = sql, "create unique hash index %s on %s (", iname, tname);
  1159. for (unsigned j = 0; j < ncol; j++)
  1160.     scopy(sqlptr, "%sc%d", j == 0 ? "" : ", ", cols[j]);
  1161. scopy(sqlptr, ")");
  1162.     } else {
  1163. scopy(sqlptr = sql, "create index %s on %s (", iname, tname);
  1164. for (unsigned j = 0; j < ncol; j++)
  1165.     scopy(sqlptr, "%sc%d", j == 0 ? "" : ", ", cols[j]);
  1166. scopy(sqlptr, ") nologging");
  1167.     }
  1168.     if (opt.m_v >= 2)
  1169. ndbout << "SQL: " << sql << endl;
  1170.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1171.     for (unsigned j = 0; j < ncol; j++)
  1172. imask.set(cols[j]);
  1173.     ccnt++;
  1174. } else if (sel < 5 && ccnt > dcnt + 1) {
  1175.     scopy(sqlptr = sql, "drop index %s on %s", iname, tname);
  1176.     if (opt.m_v >= 2)
  1177. ndbout << "SQL: " << sql << endl;
  1178.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1179.     imask.clear();
  1180.     dcnt++;
  1181. }
  1182.     }
  1183.     // insert unique data
  1184.     unsigned rows = opt.m_scale;
  1185.     unsigned* uval = new unsigned[rows];
  1186.     for (unsigned i = 0; i < rows; i++) {
  1187. uval[i] = urandom(4);
  1188. scopy(sqlptr = sql, "insert into %s values(", tname);
  1189. for (unsigned j = 0; j < attrs; j++) {
  1190.     if (j != 0)
  1191. scopy(sqlptr, ",");
  1192.     unsigned v = (i << 10) | (j << 2) | uval[i];
  1193.             if (j == 0)
  1194. scopy(sqlptr, "%u", i);
  1195.             else if (j % 2 == 0)
  1196. scopy(sqlptr, "%u", v);
  1197.     else
  1198. scopy(sqlptr, "'%010u'", v);
  1199. }
  1200. scopy(sqlptr, ")");
  1201. if (opt.m_v >= 2)
  1202.     ndbout << "SQL: " << sql << endl;
  1203. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1204.     }
  1205.     // update each row via random index
  1206.     for (unsigned i = 0; i < rows; i++) {
  1207. unsigned uold = uval[i];
  1208. uval[i] = 3 - uval[i];
  1209. AttributeMask imask;
  1210. do {
  1211.     unsigned j = urandom(imax);
  1212.     imask = imasks[j];
  1213. } while (imask.isclear());
  1214. scopy(sqlptr = sql, "update %s set", tname);
  1215. for (unsigned j = 1; j < attrs; j++) {
  1216.     if (j != 1)
  1217. scopy(sqlptr, ",");
  1218.     /*
  1219.      * Equality update is just barely doable before savepoints
  1220.      * provided we change value of keys in every index.
  1221.      */
  1222.     unsigned v = (i << 10) | (j << 2) | uval[i];
  1223.             if (j == 0)
  1224. ;
  1225.     else if (j % 2 == 0)
  1226. scopy(sqlptr, " c%d=%u", j, v);
  1227.     else
  1228. scopy(sqlptr, " c%d='%010u'", j, v);
  1229. }
  1230. scopy(sqlptr, " where 1=1");
  1231. while (! imask.isclear()) {
  1232.     unsigned j = urandom(attrs);
  1233.     if (imask.get(j)) {
  1234. unsigned v = (i << 10) | (j << 2) | uold;
  1235. scopy(sqlptr, " and c%d=", j);
  1236. if (j == 0)
  1237.     scopy(sqlptr, "%u", i);
  1238. else if (j % 2 == 0)
  1239.     scopy(sqlptr, "%u", v);
  1240. else
  1241.     scopy(sqlptr, "'%010u'", v);
  1242. imask.clear(j);
  1243.     }
  1244. }
  1245. if (opt.m_v >= 2)
  1246.     ndbout << "SQL: " << sql << endl;
  1247. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1248. chkRowCount(test, hStmt, 1);
  1249.     }
  1250.     // delete all
  1251.     scopy(sqlptr = sql, "delete from %s", tname);
  1252.     if (opt.m_v >= 2)
  1253.         ndbout << "SQL: " << sql << endl;
  1254.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1255.     //
  1256.     if (opt.m_v >= 2)
  1257. ndbout << tname << ": creates " << ccnt << " drops " << dcnt << endl;
  1258.     delete [] imasks;
  1259.     delete [] uval;
  1260.     freeAll(test, hEnv, hDbc, hStmt);
  1261. }
  1262. static const Sql
  1263. miscSql96[] = {
  1264.     Sql("testMisc96a", testMisc96a),
  1265.     Sql()
  1266. };
  1267. // 97
  1268. static void
  1269. testMisc97a(Test& test)
  1270. {
  1271.     SQLHANDLE hEnv, hDbc, hStmt;
  1272.     allocAll(test, hEnv, hDbc, hStmt);
  1273.     const char* tname = "TT97A";
  1274.     const char* iname = "XX97A";
  1275.     char sql[MAX_SQL];
  1276.     // create in some thread
  1277.     lock_mutex();
  1278.     if (my_sema == 0) {
  1279. if (opt.m_v >= 1)
  1280.     ndbout << "thread " << test.m_no << " does setup" << endl;
  1281. sprintf(sql, "drop table %s", tname);
  1282. if (opt.m_v >= 2)
  1283.     ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
  1284. test.exp(SQL_ERROR, "IM000", 2040709, false);
  1285. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1286. // a-pk b-index c-counter
  1287. sprintf(sql, "create table %s (a int primary key, b int, c int) storage(small)", tname);
  1288. if (opt.m_v >= 2)
  1289.     ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
  1290. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1291. for (unsigned i = 0; i < opt.m_scale; i++) {
  1292.     sprintf(sql, "insert into %s values (%d, %d, %d)", tname, i, 10 * i, 0);
  1293.     if (opt.m_v >= 3)
  1294. ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
  1295.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1296. }
  1297. sprintf(sql, "create index %s on %s (b) nologging", iname, tname);
  1298. if (opt.m_v >= 2)
  1299.     ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
  1300. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1301. my_sema = 1;
  1302.     }
  1303.     unlock_mutex();
  1304.     assert(my_sema == 1);
  1305.     // parallel run - default rotating pk, ts, is
  1306.     // frob: low 3 hex digits give alt sequence e.g. 0x311 = pk, pk, is
  1307.     // frob: 4-th hex digit non-zero says use NDB API e.g. 0x1000
  1308.     unsigned typelist[3] = { 1, 2, 3 };
  1309.     for (unsigned i = 0; i < 3; i++) {
  1310. unsigned t = (opt.m_frob >> (i * 4)) & 0xf;
  1311. if (t != 0)
  1312.     typelist[i] = t;
  1313.     }
  1314.     unsigned type = typelist[(test.m_no - 1) % 3];
  1315.     if ((opt.m_frob & 0xf000) == 0) {
  1316. for (unsigned i = 0; i < opt.m_scale; i++) {
  1317.     if (type == 1) {
  1318. // pk update
  1319. sprintf(sql, "update %s set c = c + 1 where a = %d", tname, i % opt.m_scale);
  1320. if (opt.m_v >= 3)
  1321.     ndbout << lock << "SQL[" << test.m_no << "]: " << sql << endl << unlock;
  1322. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1323.     }
  1324.     if (type == 2) {
  1325. // table scan update
  1326. sprintf(sql, "update %s set c = c + 1 where b + 0 = %d", tname, 10 * i);
  1327. if (opt.m_v >= 3)
  1328.     ndbout << lock << "SQL[" << test.m_no << "]: " << sql << endl << unlock;
  1329. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1330.     }
  1331.     if (type == 3) {
  1332. // index scan update
  1333. sprintf(sql, "update %s set c = c + 1 where b = %d", tname, 10 * i);
  1334. if (opt.m_v >= 3)
  1335.     ndbout << lock << "SQL[" << test.m_no << "]: " << sql << endl << unlock;
  1336. test.exp(SQL_NO_DATA, 0, 0, false);
  1337. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1338.     }
  1339. }
  1340.     } else {
  1341. #ifdef ndbODBC
  1342. #define CHK(o, x) do { if (! (x)) { fatal("line %d: %d %s", __LINE__, o->getNdbError().code, o->getNdbError().message); } } while (0)
  1343. Ndb* ndb = new Ndb("TEST_DB");
  1344. ndb->init();
  1345. CHK(ndb, ndb->waitUntilReady() == 0);
  1346. Int32 a, b, c;
  1347. for (unsigned i = 0; i < opt.m_scale; i++) {
  1348.     if (type == 1) {
  1349. // pk update with exclusive read
  1350. NdbConnection* con;
  1351. NdbOperation* op;
  1352. CHK(ndb, (con = ndb->startTransaction()) != 0);
  1353. a = i;
  1354. c = -1;
  1355. CHK(con, (op = con->getNdbOperation(tname)) != 0);
  1356. CHK(op, op->readTupleExclusive() == 0);
  1357. CHK(op, op->equal((unsigned)0, (char*)&a, 0) == 0);
  1358. CHK(op, op->getValue(2, (char*)&c) != 0);
  1359. CHK(con, con->execute(NoCommit) == 0);
  1360. c = c + 1;
  1361. CHK(con, (op = con->getNdbOperation(tname)) != 0);
  1362. CHK(op, op->updateTuple() == 0);
  1363. CHK(op, op->equal((unsigned)0, (char*)&a, 0) == 0);
  1364. CHK(op, op->setValue(2, (char*)&c) == 0);
  1365. CHK(con, con->execute(Commit) == 0);
  1366. ndb->closeTransaction(con);
  1367. if (opt.m_v >= 3)
  1368.     ndbout << lock << "thr " << test.m_no << " pk a=" << i << " c=" << c << endl << unlock;
  1369.     }
  1370.     if (type == 2) {
  1371. // table scan update
  1372. NdbConnection* con;
  1373. NdbOperation* op;
  1374. CHK(ndb, (con = ndb->startTransaction()) != 0);
  1375. CHK(con, (op = con->getNdbOperation(tname)) != 0);
  1376. CHK(con, op->openScanExclusive(240) == 0);
  1377. CHK(op, op->getValue((unsigned)0, (char*)&a) != 0);
  1378. CHK(op, op->getValue(2, (char*)&c) != 0);
  1379. CHK(con, con->executeScan() == 0);
  1380. unsigned rows = 0;
  1381. unsigned updates = 0;
  1382. while (1) {
  1383.     int ret;
  1384.     a = -1;
  1385.     c = -1;
  1386.     CHK(con, (ret = con->nextScanResult()) == 0 || ret == 1);
  1387.     if (ret == 1)
  1388. break;
  1389.     rows++;
  1390.     if (a == i) {
  1391. NdbConnection* con2;
  1392. NdbOperation* op2;
  1393. CHK(ndb, (con2 = ndb->startTransaction()) != 0);
  1394. CHK(op, (op2 = op->takeOverForUpdate(con2)) != 0);
  1395. c = c + 1;
  1396. CHK(op2, op2->setValue(2, (char*)&c) == 0);
  1397. CHK(con2, con2->execute(Commit) == 0);
  1398. ndb->closeTransaction(con2);
  1399. updates++;
  1400. if (opt.m_v >= 3)
  1401.     ndbout << lock << "thr " << test.m_no << " ts rows=" << rows << " a=" << i << " c=" << c << endl << unlock;
  1402. // test stop scan too
  1403. CHK(con, con->stopScan() == 0);
  1404. break;
  1405.     }
  1406. }
  1407. ndb->closeTransaction(con);
  1408. test.chk(HStmt(hStmt), updates == 1, "got %u != 1", updates);
  1409.     }
  1410.     if (type == 3) {
  1411. // index scan update
  1412. NdbConnection* con;
  1413. NdbOperation* op;
  1414. CHK(ndb, (con = ndb->startTransaction()) != 0);
  1415. CHK(con, (op = con->getNdbOperation(iname, tname)) != 0);
  1416. CHK(con, op->openScanExclusive(240) == 0);
  1417. b = 10 * i;
  1418. CHK(con, op->setBound((unsigned)0, 4, &b, sizeof(b)) == 0);
  1419. CHK(op, op->getValue((unsigned)0, (char*)&a) != 0);
  1420. CHK(op, op->getValue(2, (char*)&c) != 0);
  1421. CHK(con, con->executeScan() == 0);
  1422. unsigned rows = 0;
  1423. unsigned updates = 0;
  1424. while (1) {
  1425.     int ret;
  1426.     a = -1;
  1427.     c = -1;
  1428.     CHK(con, (ret = con->nextScanResult()) == 0 || ret == 1);
  1429.     if (ret == 1)
  1430. break;
  1431.     rows++;
  1432.     if (a == i) {
  1433. NdbConnection* con2;
  1434. NdbOperation* op2;
  1435. CHK(ndb, (con2 = ndb->startTransaction()) != 0);
  1436. CHK(op, (op2 = op->takeOverForUpdate(con2)) != 0);
  1437. c = c + 1;
  1438. CHK(op2, op2->setValue(2, (char*)&c) == 0);
  1439. CHK(con2, con2->execute(Commit) == 0);
  1440. ndb->closeTransaction(con2);
  1441. updates++;
  1442. if (opt.m_v >= 3)
  1443.     ndbout << lock << "thr " << test.m_no << " is rows=" << rows << " a=" << i << " c=" << c << endl << unlock;
  1444. // test stop scan too
  1445. CHK(con, con->stopScan() == 0);
  1446. break;
  1447.     }
  1448. }
  1449. ndb->closeTransaction(con);
  1450. test.chk(HStmt(hStmt), rows == 1, "got %u != 1", rows);
  1451. test.chk(HStmt(hStmt), updates == 1, "got %u != 1", updates);
  1452.     }
  1453. }
  1454. delete ndb;
  1455. #undef CHK
  1456. #endif
  1457.     }
  1458.     // verify result
  1459.     lock_mutex();
  1460.     if (++my_sema == 1 + opt.m_threads) {
  1461. if (opt.m_v >= 1)
  1462.     ndbout << "thread " << test.m_no << " does verification" << endl;
  1463. sprintf(sql, "select * from %s order by a", tname);
  1464. if (opt.m_v >= 2)
  1465.     ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
  1466. test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1467. long a, b, c;
  1468. test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_SLONG, &a, 0, 0));
  1469. test.run(HStmt(hStmt), SQLBindCol(hStmt, 2, SQL_C_SLONG, &b, 0, 0));
  1470. test.run(HStmt(hStmt), SQLBindCol(hStmt, 3, SQL_C_SLONG, &c, 0, 0));
  1471. for (unsigned i = 0; i < opt.m_scale; i++) {
  1472.     a = b = c = -1;
  1473.     test.run(HStmt(hStmt), SQLFetch(hStmt));
  1474.     test.chk(HStmt(hStmt), a == i, "a: got %ld != %u", a, i);
  1475.     test.chk(HStmt(hStmt), b == 10 * i, "b: got %ld != %u", b, 10 * i);
  1476.     test.chk(HStmt(hStmt), c == opt.m_threads, "c: got %ld != %u", c, opt.m_threads);
  1477.     if (opt.m_v >= 4)
  1478. ndbout << "verified " << i << endl;
  1479. }
  1480. test.exp(SQL_NO_DATA, 0, 0, true);
  1481. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1482. if (opt.m_v >= 2)
  1483.     ndbout << "thr " << test.m_no << " verified " << opt.m_scale << " rows" << endl;
  1484. my_sema = 0;
  1485.     }
  1486.     unlock_mutex();
  1487.     freeAll(test, hEnv, hDbc, hStmt);
  1488. }
  1489. static const Sql
  1490. miscSql97[] = {
  1491.     Sql("testMisc97a", testMisc97a),
  1492.     Sql()
  1493. };
  1494. // 99
  1495. static void
  1496. testMisc99a(Test& test)
  1497. {
  1498.     SQLHANDLE hEnv, hDbc, hStmt;
  1499.     allocAll(test, hEnv, hDbc, hStmt);
  1500.     // bad
  1501.     const char* sqlInsertBad = "insert into tt99a values(?, ?, ?, ?, ?)";
  1502.     test.exp(SQL_ERROR, "21S01", -1, true);
  1503.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlInsertBad, SQL_NTS));
  1504.     // good
  1505.     const char* sqlInsert = "insert into tt99a (col1, col2, col3, col4, col5) values(?, ?, ?, ?, ?)";
  1506.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlInsert, SQL_NTS));
  1507.     unsigned long value;
  1508.     for (unsigned i = 1; i <= 5; i++) {
  1509. test.run(HStmt(hStmt), SQLBindParameter(hStmt, i, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &value, 0, 0));
  1510.     }
  1511.     const unsigned long base = 1000000000;
  1512.     const unsigned long scale = 10;
  1513.     for (value = base; value < base + scale; value++) {
  1514. test.run(HStmt(hStmt), SQLExecute(hStmt));
  1515.     }
  1516.     // bug1: re-analyze of converted expression...
  1517.     const char* sqlSelect = "select col5 from tt99a where col2 + 0 = ?";
  1518.     unsigned long output;
  1519.     test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_ULONG, &output, 0, 0));
  1520.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlSelect, SQL_NTS));
  1521.     // bug2: previous bind must survive a new SQLPrepare
  1522.     if (0) {
  1523. test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &value, 0, 0));
  1524.     }
  1525.     for (value = base; value < base + scale; value++) {
  1526. if (value > base + 4) {
  1527.     // bug1: ...when IPD changed by JDBC
  1528.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &value, 0, 0));
  1529. }
  1530. test.run(HStmt(hStmt), SQLExecute(hStmt));
  1531. output = (unsigned long)-1;
  1532. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1533. test.chk(HStmt(hStmt), output == value, "got %lu != %lu", output, value);
  1534. test.exp(SQL_NO_DATA, 0, 0, true);
  1535. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1536. test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  1537. test.timerCnt(1);
  1538.     }
  1539.     freeAll(test, hEnv, hDbc, hStmt);
  1540. }
  1541. static void
  1542. testMisc99c(Test& test)
  1543. {
  1544.     SQLHANDLE hEnv, hDbc, hStmt;
  1545.     allocAll(test, hEnv, hDbc, hStmt);
  1546.     const char* sql = "select b from tt99c where a = ?";
  1547.     const unsigned long c1 = 2100000000U;
  1548.     const unsigned long c2 = 4100000000U;
  1549.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1550.     unsigned long aval, bval;
  1551.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &aval, 0, 0));
  1552.     test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_ULONG, &bval, 0, 0));
  1553.     // uno
  1554.     for (unsigned i = 0; i < opt.m_scale; i++) {
  1555. aval = c1;
  1556. bval = (unsigned long)-1;
  1557. if (opt.m_v >= 2)
  1558.     ndbout << "SQL: " << sql << " [?=" << (Uint64)aval << "]" << endl;
  1559. test.run(HStmt(hStmt), SQLExecute(hStmt));
  1560. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1561. test.chk(HStmt(hStmt), bval == c2, "got %lu != %lu", bval, c2);
  1562. //test.exp(SQL_NO_DATA, 0, 0, true);
  1563. //test.run(HStmt(hStmt), SQLFetch(hStmt));
  1564. test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  1565.     }
  1566.     // dos
  1567.     for (unsigned i = 0; i < opt.m_scale; i++) {
  1568. break; // XXX not yet, hangs in NDB ?!?
  1569. aval = c2;
  1570. bval = (unsigned long)-1;
  1571. if (opt.m_v >= 2)
  1572.     ndbout << "SQL: " << sql << " [?=" << (Uint64)aval << "]" << endl;
  1573. test.run(HStmt(hStmt), SQLExecute(hStmt));
  1574. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1575. test.chk(HStmt(hStmt), bval == c1, "got %lu != %lu", bval, c2);
  1576. //test.exp(SQL_NO_DATA, 0, 0, true);
  1577. //test.run(HStmt(hStmt), SQLFetch(hStmt));
  1578. test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  1579.     }
  1580.     freeAll(test, hEnv, hDbc, hStmt);
  1581. }
  1582. static void
  1583. testMisc99d(Test& test)
  1584. {
  1585.     SQLHANDLE hEnv, hDbc, hStmt;
  1586.     allocAll(test, hEnv, hDbc, hStmt);
  1587.     const char* tname = "TT99D";
  1588.     char sql[MAX_SQL];
  1589.     sprintf(sql, "drop table %s", tname);
  1590.     if (opt.m_v >= 2)
  1591. ndbout << "SQL: " << sql << endl;
  1592.     test.exp(SQL_ERROR, "IM000", 2040709, false);
  1593.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1594.     sprintf(sql, "create table %s (a bigint unsigned, b bigint, primary key (a))", tname);
  1595.     if (opt.m_v >= 2)
  1596. ndbout << "SQL: " << sql << endl;
  1597.     test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1598.     sprintf(sql, "insert into %s values (?, ?)", tname);
  1599.     if (opt.m_v >= 2)
  1600. ndbout << "SQL: " << sql << endl;
  1601.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1602.     // XXX replace by 100 when signed vs unsigned resolved
  1603.     const unsigned num = 78;
  1604.     SQLUBIGINT aval;
  1605.     SQLBIGINT bval;
  1606.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_BIGINT, 0, 0, &aval, 0, 0));
  1607.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, &bval, 0, 0));
  1608.     for (SQLBIGINT i = 0; i < num; i++) {
  1609. if (opt.m_v >= 3)
  1610.     ndbout << "insert " << i << endl;
  1611. aval = i * i * i * i * i * i * i * i * i * i;  // 10
  1612. bval = -aval;
  1613. test.run(HStmt(hStmt), SQLExecute(hStmt));
  1614.     }
  1615.     sprintf(sql, "select a, b from tt99d where a = ?");
  1616.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
  1617.     SQLUBIGINT kval;
  1618.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_BIGINT, 0, 0, &kval, 0, 0));
  1619.     test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_UBIGINT, &aval, 0, 0));
  1620.     test.run(HStmt(hStmt), SQLBindCol(hStmt, 2, SQL_C_SBIGINT, &bval, 0, 0));
  1621.     for (SQLBIGINT i = 0; i < num; i++) {
  1622. kval = i * i * i * i * i * i * i * i * i * i; // 10
  1623. if (opt.m_v >= 3)
  1624.     ndbout << "fetch " << i << " key " << kval << endl;
  1625. test.run(HStmt(hStmt), SQLExecute(hStmt));
  1626. aval = bval = 0;
  1627. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1628. test.chk(HStmt(hStmt), aval == kval && bval == -kval, "got %llu, %lld != %llu, %lld", aval, bval, kval, -kval);
  1629. test.exp(SQL_NO_DATA, 0, 0, true);
  1630. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1631. test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  1632.     }
  1633.     freeAll(test, hEnv, hDbc, hStmt);
  1634. }
  1635. static void
  1636. testMiscC2(Test& test)
  1637. {
  1638.     SQLHANDLE hEnv, hDbc, hStmt;
  1639.     allocAll(test, hEnv, hDbc, hStmt);
  1640. #if 0
  1641.  {
  1642.     char POP[255];
  1643.     char PORT[255];
  1644.     char ACCESSNODE[255];
  1645.     const char* sqlSelect = "select PORT from AAA where POP=? and ACCESSNODE=?";
  1646.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlSelect, SQL_NTS));
  1647.     for (int j=0; j<5; j++) {
  1648.       printf("Loop %un", j);
  1649.       printf("LINE %un", __LINE__);
  1650.       test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 255, 0, POP, 255, 0));
  1651.       test.run(HStmt(hStmt), SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 255, 0, ACCESSNODE, 255, 0));
  1652.       test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_CHAR, PORT, 255, 0));
  1653.       sprintf(POP, "a");
  1654.       sprintf(ACCESSNODE, "b");
  1655.       test.run(HStmt(hStmt), SQLExecute(hStmt));
  1656.       test.run(HStmt(hStmt), SQLFetch(hStmt));
  1657.       printf("got %sn", PORT);
  1658.       printf("LINE %un", __LINE__);
  1659.       test.exp(SQL_NO_DATA, 0, 0, true);
  1660.       printf("LINE %un", __LINE__);
  1661.       test.run(HStmt(hStmt), SQLFetch(hStmt));
  1662.       printf("LINE %un", __LINE__);
  1663.       test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  1664.       printf("LINE %un", __LINE__);
  1665.     }
  1666.  }
  1667.     return;
  1668. #endif
  1669.     char POP[255];
  1670.     char PORT[255];
  1671.     char ACCESSNODE[255];
  1672.     unsigned long VLAN = 0;
  1673.     unsigned long SNMP_INDEX = 0;
  1674.     unsigned long PORT_STATE = 0;
  1675.     unsigned long STATIC_PORT = 0;
  1676.     unsigned long COMMENT = 0;
  1677.     const char* sqlSelect = "select PORT, PORT_STATE  from PORTS where POP=? and ACCESSNODE=?";
  1678.     test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlSelect, SQL_NTS));
  1679.     for (int j=0; j<5; j++) {
  1680.       printf("Loop %un", j);
  1681.       printf("LINE %un", __LINE__);
  1682.     test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 255, 0, POP, 255, 0));
  1683.       test.run(HStmt(hStmt), SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 255, 0, ACCESSNODE, 255, 0));
  1684.       test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_CHAR, PORT, 255, 0));
  1685.       test.run(HStmt(hStmt), SQLBindCol(hStmt, 2, SQL_C_ULONG, &PORT_STATE, 0, 0));
  1686.       sprintf(POP, "row%u.i%u.bredband.com", 2, 3);
  1687.       sprintf(ACCESSNODE, "as%u", 2);
  1688.       test.run(HStmt(hStmt), SQLExecute(hStmt));
  1689.       for (int i=0; i < 3; i++) {
  1690. PORT_STATE=0;
  1691. sprintf(PORT, "XXXXXXXXXXXXXXXXXXXXX");
  1692. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1693. printf("got %s %lun", PORT, PORT_STATE);
  1694. //    test.chk(HStmt(hStmt), false, "got %s != %s", "xxx", PORT);
  1695.       }
  1696.       printf("LINE %un", __LINE__);
  1697.       test.exp(SQL_NO_DATA, 0, 0, true);
  1698.       printf("LINE %un", __LINE__);
  1699.       test.run(HStmt(hStmt), SQLFetch(hStmt));
  1700.       printf("LINE %un", __LINE__);
  1701.       test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  1702.       printf("LINE %un", __LINE__);
  1703.     }
  1704. }
  1705. static const Sql
  1706. miscSqlC2[] = {
  1707.     Sql("drop table PORTS",
  1708. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  1709. SQL_ERROR, "IM000", 2040709, false),
  1710.     Sql("create table PORTS (POP varchar(200) not null, ACCESSNODE varchar(200) not null, PORT varchar(200) not null, VLAN int unsigned, SNMP_INDEX int unsigned, PORT_STATE int unsigned, STATIC_PORT int unsigned, COMMENT int unsigned, primary key (POP,ACCESSNODE,PORT))",
  1711. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  1712.     Sql("create index xxPORTS on PORTS (POP, ACCESSNODE) nologging",
  1713.      SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
  1714.     Sql("insert into PORTS values ('row2.i3.bredband.com','as2','Fa0/0',0,1,2,3,4)",
  1715. SQL_DIAG_INSERT, 1, 0, -1, -1),
  1716.     Sql("insert into PORTS values ('row2.i3.bredband.com','as2','Fa0/1',1,2,3,4,5)",
  1717. SQL_DIAG_INSERT, 1, 0, -1, -1),
  1718.     Sql("insert into PORTS values ('row2.i3.bredband.com','as2','Fa0/2',2,3,4,5,6)",
  1719. SQL_DIAG_INSERT, 1, 0, -1, -1),
  1720.     Sql("select PORT, PORT_STATE  from PORTS where POP='row2.i3.bredband.com' and ACCESSNODE='as2'",
  1721. SQL_DIAG_SELECT_CURSOR, 3, 3, -1, -1),
  1722.     Sql("drop table AAA",
  1723. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  1724. SQL_ERROR, "IM000", 2040709, false),
  1725.     Sql("create table AAA (POP varchar(200), ACCESSNODE varchar(200) not null, PORT varchar(200) not null, primary key (POP,ACCESSNODE,PORT))",
  1726. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  1727.     Sql("create index xxAAA on AAA (POP, ACCESSNODE) nologging",
  1728.      SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
  1729.     Sql("insert into AAA values ('a','b','A')",
  1730. SQL_DIAG_INSERT, 1, 0, -1, -1),
  1731.     Sql("testMiscC2", testMiscC2),
  1732.     Sql()
  1733. };
  1734. /*
  1735. > SELECT PORT, PORT_STATE  FROM PORTS where pop=? and accessnode=?
  1736. > SELECT VLAN, SNMP_INDEX, PORT_STATE, STATIC_PORT, COMMENT FROM PORTS WHERE POP=? AND ACCESSNODE=? AND PORT=?
  1737. > select count(*) from ports
  1738. > select snmp_index from ports where pop='row2.i3.bredband.com' and accessnode='as2' and port='Fa0/2'
  1739. > SELECT MAC, MAC_EXPIRE, IP, IP_EXPIRE, HOSTNAME, DETECTED, STATUS, STATIC_DNS, BLOCKED, NUM_REQUESTS, ACCESSTYPE, OS_TYPE, GATE_WAY, DIRTY_FLAG, LOCKED_IP FROM CLIENTS WHERE PORT=? AND ACCESSNODE=? AND POP=?
  1740. > SELECT SERVICES.ACCESSTYPE, SERVICES.NUM_IP, SERVICES.TEXPIRE, SERVICES.CUSTOMER_ID, SERVICES.LEASED_NUM_IP, SERVICES.PROVIDER, SERVICES.LOCKED_IP, SERVICES.STATIC_DNS, SERVICES.SUSPENDED_SERVICE FROM SERVICES , ACCESSTYPES WHERE SERVICES.PORT =  ? AND SERVICES.ACCESSNODE = ? AND  SERVICES.POP =  ? AND SERVICES.ACCESSTYPE=ACCESSTYPES.ACCESSTYPE
  1741. */
  1742. static const Sql
  1743. miscSql99[] = {
  1744.     Sql("drop table tt99a",
  1745. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  1746. SQL_ERROR, "IM000", 2040709, false),
  1747.     Sql("create table tt99a (col1 int unsigned primary key, col2 int unsigned, col3 int unsigned, col4 int unsigned, col5 int unsigned, col6 varchar(7) default 'abc123')",
  1748. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  1749.     // inserts 10 rows, all same, start value 1000000000
  1750.     Sql("testMisc99a", testMisc99a),
  1751.     // interpreted scan plus bind parameter
  1752.     Sql("select col1 from tt99a where col2 = ?",
  1753. SQL_DIAG_SELECT_CURSOR, 1, 1, 1000000004, 1000000004),
  1754.     Sql("select col1 from tt99a where col2 = 1000000000 + ?",
  1755. SQL_DIAG_SELECT_CURSOR, 1, 1, 1000000004, 4),
  1756.     Sql("select col1 from tt99a where col2 = ? + 1000000000",
  1757. SQL_DIAG_SELECT_CURSOR, 1, 1, 1000000004, 4),
  1758.     // same not interpreted, tuple count 10
  1759.     Sql("select col1 from tt99a where col2 + 0 = 1000000000 + ?",
  1760. SQL_DIAG_SELECT_CURSOR, 1, 10, 1000000004, 4),
  1761.     // varchar variations
  1762.     Sql("select count(*) from tt99a where col6 = 'abc123'",
  1763. SQL_DIAG_SELECT_CURSOR, 1, 10, 10, -1),
  1764.     Sql("select count(*) from tt99a where left(col6, ?) = 'abc1'",
  1765. SQL_DIAG_SELECT_CURSOR, 1, 10, 10, 4),
  1766.     Sql("select count(*) from tt99a where left(col6, ?) = 'abc1'",
  1767. SQL_DIAG_SELECT_CURSOR, 1, 10, 0, 3),
  1768.     // tpc-b inspired, wrong optimization to direct update
  1769.     Sql("drop table tt99b",
  1770. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  1771. SQL_ERROR, "IM000", 2040709, false),
  1772.     Sql("create table tt99b(a int primary key, b int not null, c double precision)",
  1773. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  1774.     Sql("insert into tt99b values(1, 10, 100.0)",
  1775. SQL_DIAG_INSERT, 1, 0, -1, -1),
  1776.     Sql("insert into tt99b values(9, 90, 900.0)",
  1777. SQL_DIAG_INSERT, 1, 0, -1, -1),
  1778.     Sql("create unique hash index tt99y on tt99b (b)",
  1779. SQL_DIAG_CREATE_INDEX, -1, 0, -1, -1),
  1780.     // first scan update..
  1781.     Sql("update tt99b set c = c + ? where a+0 = 1",
  1782. SQL_DIAG_UPDATE_WHERE, 1, 2, -1, 10),
  1783.     Sql("update tt99b set c = c + ? where b+0 = 10",
  1784. SQL_DIAG_UPDATE_WHERE, 1, 2, -1, 10),
  1785.     // then optimized..
  1786.     Sql("update tt99b set c = c + ? where a = 1",
  1787. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, 10),
  1788.     Sql("update tt99b set c = c + ? where b = 10",
  1789. SQL_DIAG_UPDATE_WHERE, 1, 1, -1, 10),
  1790.     // verify..
  1791.     Sql("select count(*) from tt99b where 100-1 < c and c < 140-1",
  1792. SQL_DIAG_SELECT_CURSOR, 1, 2, 0, -1),
  1793.     Sql("select count(*) from tt99b where 140-.001 < c and c < 140+.001",
  1794. SQL_DIAG_SELECT_CURSOR, 1, 2, 1, -1),
  1795.     // unsigned test
  1796.     Sql("drop table tt99c",
  1797. SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
  1798. SQL_ERROR, "IM000", 2040709, false),
  1799.     Sql("create table tt99c(a int unsigned primary key, b int unsigned)",
  1800. SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
  1801.     Sql("insert into tt99c values(2100000000, 4100000000)",
  1802. SQL_DIAG_INSERT, 1, 0, -1, -1),
  1803.     Sql("insert into tt99c (a, b) select b, a from tt99c",
  1804. SQL_DIAG_INSERT, 1, 1, -1, -1),
  1805.     Sql("testMisc99c", testMisc99c),
  1806.     // new external type SQL_C_[SU]BIGINT
  1807.     Sql("testMisc99d", testMisc99d),
  1808.     Sql()
  1809. };
  1810. static const struct { const Sql* sql; int minscale; }
  1811. miscSql[11] = {
  1812.     { miscSql90, 0 },
  1813.     { miscSql91, 0 },
  1814.     { miscSql92, 0 },
  1815.     { miscSql93, 0 },
  1816.     { 0, 0 }, // 94
  1817.     { miscSql95, 0 },
  1818.     { miscSql96, 0 },
  1819.     { miscSql97, 0 },
  1820.     { 0, 0 }, // 98
  1821.     { miscSql99, 0 },
  1822.     { miscSqlC2,  0 }
  1823. };
  1824. static void
  1825. testSql(Test& test)
  1826. {
  1827.     const unsigned salt = test.m_stuff; // mess
  1828.     if (opt.m_scale < miscSql[salt].minscale) {
  1829. if (opt.m_v >= 1)
  1830.     ndbout << "skip - requires scale >= " << miscSql[salt].minscale << endl;
  1831. return;
  1832.     }
  1833.     assert(0 <= salt && salt < 11 && miscSql[salt].sql != 0);
  1834.     SQLHANDLE hEnv, hDbc, hStmt;
  1835.     allocAll(test, hEnv, hDbc, hStmt);
  1836.     for (unsigned i = 0; ; i++) {
  1837. const Sql& sql = miscSql[salt].sql[i];
  1838. if (sql.m_sql == 0)
  1839.     break;
  1840. if (opt.m_v >= 2)
  1841.     ndbout << "SQL: " << sql.m_sql << endl;
  1842. if (sql.m_testFunc != 0) {
  1843.     (*sql.m_testFunc)(test);
  1844.     continue;
  1845. }
  1846. if (strncmp(sql.m_sql, "--", 2) == 0) {
  1847.     continue;
  1848. }
  1849. if (strcmp(sql.m_sql, Sql::set_autocommit_on()) == 0) {
  1850.     setAutocommit(test, hDbc, true);
  1851.     continue;
  1852. }
  1853. if (strcmp(sql.m_sql, Sql::set_autocommit_off()) == 0) {
  1854.     setAutocommit(test, hDbc, false);
  1855.     continue;
  1856. }
  1857. if (strcmp(sql.m_sql, Sql::do_commit()) == 0) {
  1858.     test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
  1859.     continue;
  1860. }
  1861. if (strcmp(sql.m_sql, Sql::do_rollback()) == 0) {
  1862.     test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_ROLLBACK));
  1863.     continue;
  1864. }
  1865. if (opt.m_v >= 3) {
  1866.     ndbout <<  "expect:";
  1867.     ndbout << " ret=" << sql.m_ret;
  1868.     ndbout << " rows=" << sql.m_rowCount;
  1869.     ndbout << " tuples=" << sql.m_tuplesFetched;
  1870.     ndbout << endl;
  1871. }
  1872. test.run(HStmt(hStmt), SQLFreeStmt(hStmt, SQL_UNBIND));
  1873. test.run(HStmt(hStmt), SQLFreeStmt(hStmt, SQL_RESET_PARAMS));
  1874. // prep
  1875. test.exp(sql.m_ret, sql.m_state, sql.m_native, false);
  1876. test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql.m_sql, SQL_NTS));
  1877. if (test.m_ret != SQL_SUCCESS)
  1878.     continue;
  1879. // bind between prep and exec like JDBC
  1880. unsigned long bindValue = sql.m_bindValue;
  1881. for (int k = 0; k <= 1; k++) {
  1882.     if (bindValue != -1) {
  1883. assert(strchr(sql.m_sql, '?') != 0);
  1884. test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &bindValue, 0, 0));
  1885.     }
  1886.     if (k == 0) {
  1887. if (bindValue != -1) {
  1888.     test.run(HStmt(hStmt), SQLFreeStmt(hStmt, SQL_RESET_PARAMS));
  1889.     // exec with unbound parameter
  1890.     test.exp(SQL_ERROR, "HY010", -1, true);
  1891.     test.run(HStmt(hStmt), SQLExecute(hStmt));
  1892.     test.chk(HStmt(hStmt), test.m_functionCode == sql.m_functionCode || sql.m_functionCode == -1, "func: got %d != %d", (int)test.m_functionCode, (int)sql.m_functionCode);
  1893. }
  1894.     } else {
  1895. // exec
  1896. test.exp(sql.m_ret, sql.m_state, sql.m_native, sql.m_reset);
  1897. test.run(HStmt(hStmt), SQLExecute(hStmt));
  1898. test.chk(HStmt(hStmt), test.m_functionCode == sql.m_functionCode || sql.m_functionCode == -1, "func: got %d != %d", (int)test.m_functionCode, (int)sql.m_functionCode);
  1899.     }
  1900. }
  1901. if (sql.m_rowCount != -1) {
  1902.     if (sql.m_functionCode == SQL_DIAG_SELECT_CURSOR) {
  1903. long lastValue;
  1904. if (sql.m_lastValue != -1)
  1905.     test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_SLONG, &lastValue, 0, 0));
  1906. unsigned k = 0;
  1907. do {
  1908.     int rowCount = 0;
  1909.     lastValue = -1;
  1910.     while (1) {
  1911. test.exp(SQL_NO_DATA, 0, 0, false);
  1912. test.run(HStmt(hStmt), SQLFetch(hStmt));
  1913. if (test.m_ret == SQL_NO_DATA)
  1914.     break;
  1915. rowCount++;
  1916.     }
  1917.     test.chk(HStmt(hStmt), rowCount == sql.m_rowCount, "rowCount: got %d != %d", (int)rowCount, (int)sql.m_rowCount);
  1918.     if (sql.m_tuplesFetched != -1)
  1919. chkTuplesFetched(test, hStmt, sql.m_tuplesFetched);
  1920.     if (rowCount > 0 && sql.m_lastValue != -1)
  1921. test.chk(HStmt(hStmt), lastValue == sql.m_lastValue, "lastValue: got %ld != %ld", (long)lastValue, (long)sql.m_lastValue);
  1922.     test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
  1923.     if (++k >= opt.m_scale)
  1924. break;
  1925.     test.run(HStmt(hStmt), SQLExecute(hStmt));
  1926. } while (1);
  1927. test.timerCnt(opt.m_scale);
  1928.     } else {
  1929. assert(sql.m_lastValue == -1);
  1930. chkRowCount(test, hStmt, sql.m_rowCount);
  1931. if (sql.m_tuplesFetched != -1)
  1932.     chkTuplesFetched(test, hStmt, sql.m_tuplesFetched);
  1933. test.timerCnt(1);
  1934.     }
  1935. }
  1936.     }
  1937.     freeAll(test, hEnv, hDbc, hStmt);
  1938. }
  1939. // name, function, runmode, salt (0=const or n/a), description
  1940. static const Case caseList[] = {
  1941.     Case( "00alloc", testAlloc, Case::Thread, 0, "allocate handles" ),
  1942.     Case( "01create", testCreate, Case::Single, 0, "create tables for the test" ),
  1943.     Case( "02prepare", testPrepare, Case::Thread, 0, "prepare without execute" ),
  1944.     Case( "03catalog", testCatalog, Case::Thread, 0, "catalog functions" ),
  1945.     Case( "10insert", testInsert, Case::Thread, 1, "insert computed rows" ),
  1946.     Case( "11delall", testDeleteAll, Case::Single, 0, "delete all rows via scan" ),
  1947.     Case( "12insert", testInsert, Case::Thread, 1, "insert computed rows again" ),
  1948.     Case( "13count", testCount, Case::Single, 0, "count rows" ),
  1949.     Case( "14verpk", testVerifyPk, Case::Thread, 1, "verify via primary key" ),
  1950.     Case( "15verscan", testVerifyScan, Case::Serial, 1, "verify via range scans" ),
  1951.     Case( "16join", testJoin, Case::Single, 0, "multiple self-join" ),
  1952.     Case( "17cart", testCart, Case::Single, 0, "cartesian join" ),
  1953.     Case( "20updpk", testUpdatePk, Case::Thread, 2, "update via primary key" ),
  1954.     Case( "21verpk", testVerifyPk, Case::Thread, 2, "verify via primary key" ),
  1955.     Case( "22verscan", testVerifyScan, Case::Serial, 2, "verify via range scans" ),
  1956.     Case( "23updscan", testUpdateScan, Case::Serial, 0, "update via scan" ),
  1957.     Case( "24verpk", testVerifyPk, Case::Thread, 0, "verify via primary key" ),
  1958.     Case( "25verscan", testVerifyScan, Case::Serial, 0, "verify via range scans" ),
  1959.     Case( "26delpk", testDeletePk, Case::Thread, 0, "delete via primary key" ),
  1960.     Case( "30trans", testTrans, Case::Single, 3, "rollback and commit" ),
  1961.     Case( "31concur", testConcur, Case::Single, 0, "commit across open cursor" ),
  1962.     Case( "32readcom", testReadcom, Case::Single, 0, "read committed" ),
  1963.     Case( "40perf", testPerf, Case::Single, 0, "perf test prepare" ),
  1964.     Case( "41perf", testPerf, Case::Thread, 1, "perf test NDB API" ),
  1965.     Case( "42perf", testPerf, Case::Thread, 2, "perf test NDB ODBC" ),
  1966.     Case( "90sql", testSql, Case::Single, 0, "misc SQL: metadata" ),
  1967.     Case( "91sql", testSql, Case::Single, 1, "misc SQL: misc" ),
  1968.     Case( "92sql", testSql, Case::Thread, 2, "misc SQL: scan rollback" ),
  1969.     Case( "93sql", testSql, Case::Single, 3, "misc SQL: locking" ),
  1970.     Case( "95sql", testSql, Case::Single, 5, "misc SQL: indexes (simple)" ),
  1971.     Case( "96sql", testSql, Case::Single, 6, "misc SQL: indexes" ),
  1972.     Case( "97sql", testSql, Case::Thread, 7, "misc SQL: indexes" ),
  1973.     Case( "99sql", testSql, Case::Single, 9, "misc SQL: bug du jour" ),
  1974.     Case( "C2",  testSql, Case::Single, 10, "misc SQL: C2"                 )
  1975. };
  1976. static const unsigned caseCount = arraySize(caseList);
  1977. static bool
  1978. findCase(const char* name)
  1979. {
  1980.     for (unsigned i = 0; i < caseCount; i++) {
  1981. const Case& cc = caseList[i];
  1982. if (strstr(cc.m_name, name) != 0)
  1983.     return true;
  1984.     }
  1985.     return false;
  1986. }
  1987. static void
  1988. listCases()
  1989. {
  1990.     ndbout << "cases:" << endl;
  1991.     unsigned m = 0;
  1992.     for (unsigned i = 0; i < caseCount; i++) {
  1993. const Case& cc = caseList[i];
  1994. if (m < strlen(cc.m_name))
  1995.     m = strlen(cc.m_name);
  1996.     }
  1997.     for (unsigned i = 0; i < caseCount; i++) {
  1998. const Case& cc = caseList[i];
  1999. char buf[200];
  2000. sprintf(buf, "%-*s  [%-6s]  %s", m, cc.m_name, cc.modename(), cc.m_desc);
  2001. ndbout << buf << endl;
  2002.     }
  2003. }
  2004. // threads
  2005. extern "C" { static void* testThr(void* arg); }
  2006. struct Thr {
  2007.     enum State {
  2008. Wait = 1, // wait for test case
  2009. Run = 2, // run the test case
  2010. Done = 3, // done with the case
  2011. Exit = 4 // exit thread
  2012.     };
  2013.     unsigned m_no; // thread number 1 .. max
  2014.     NdbThread* m_thr; // thread id etc
  2015.     const Case* m_case; // current case
  2016.     State m_state; // condition variable
  2017.     NdbMutex* m_mutex; // condition guard
  2018.     NdbCondition* m_cond;
  2019.     void* m_status; // exit status (not used)
  2020.     Test m_test; // test runner
  2021.     Thr(unsigned no, unsigned loop) :
  2022. m_no(no),
  2023. m_thr(0),
  2024. m_case(0),
  2025. m_state(Wait),
  2026. m_mutex(NdbMutex_Create()),
  2027. m_cond(NdbCondition_Create()),
  2028. m_status(0),
  2029. m_test(no, loop) {
  2030.     }
  2031.     ~Thr() {
  2032. destroy();
  2033. NdbCondition_Destroy(m_cond);
  2034. NdbMutex_Destroy(m_mutex);
  2035.     }
  2036.     void create() {
  2037. assert(m_thr == 0);
  2038. m_thr = NdbThread_Create(testThr, (void**)this, 64*1024, "test", NDB_THREAD_PRIO_LOW);
  2039.     }
  2040.     void destroy() {
  2041. if (m_thr != 0)
  2042.     NdbThread_Destroy(&m_thr);
  2043. m_thr = 0;
  2044.     }
  2045.     void lock() {
  2046. NdbMutex_Lock(m_mutex);
  2047.     }
  2048.     void unlock() {
  2049. NdbMutex_Unlock(m_mutex);
  2050.     }
  2051.     void wait() {
  2052. NdbCondition_Wait(m_cond, m_mutex);
  2053.     }
  2054.     void signal() {
  2055. NdbCondition_Signal(m_cond);
  2056.     }
  2057.     void join() {
  2058. NdbThread_WaitFor(m_thr, &m_status);
  2059. m_thr = 0;
  2060.     }
  2061.     // called from main
  2062.     void mainStart(const Case& cc) {
  2063. lock();
  2064. m_case = &cc;
  2065. m_state = Run;
  2066. signal();
  2067. unlock();
  2068.     }
  2069.     void mainStop() {
  2070. lock();
  2071. while (m_state != Done) {
  2072.     if (opt.m_v >= 4)
  2073. ndbout << ::lock << "thr " << m_no << " [main] wait state=" << m_state << endl << ::unlock;
  2074.     wait();
  2075. }
  2076. if (opt.m_v >= 4)
  2077.     ndbout << ::lock << "thr " << m_no << " [main] done" << endl << ::unlock;
  2078. m_state = Wait;
  2079. unlock();
  2080.     }
  2081.     // run in thread
  2082.     void testSelf() {
  2083. while (1) {
  2084.     lock();
  2085.     while (m_state != Run && m_state != Exit) {
  2086. if (opt.m_v >= 4)
  2087.     ndbout << ::lock << "thr " << m_no << " [self] wait state=" << m_state << endl << ::unlock;
  2088. wait();
  2089.     }
  2090.     if (m_state == Run) {
  2091. if (opt.m_v >= 4)
  2092.     ndbout << ::lock << "thr " << m_no << " [self] run" << endl << ::unlock;
  2093. assert(m_case != 0);
  2094. m_test.timerOn();
  2095. m_test.runCase(*m_case);
  2096. m_test.timerOff();
  2097. m_state = Done;
  2098. if (opt.m_v >= 4)
  2099.     ndbout << ::lock << "thr " << m_no << " [self] done" << endl << ::unlock;
  2100. signal();
  2101. unlock();
  2102.     } else if (m_state == Exit) {
  2103. unlock();
  2104. break;
  2105.     } else {
  2106. assert(false);
  2107.     }
  2108. }
  2109. if (opt.m_v >= 4)
  2110.     ndbout << ::lock << "thr " << m_no << " [self] exit" << endl << ::unlock;
  2111.     }
  2112. };
  2113. static void*
  2114. testThr(void* arg)
  2115. {
  2116.     Thr& thr = *(Thr*)arg;
  2117.     thr.testSelf();
  2118.     return 0;
  2119. }
  2120. #ifdef DMALLOC
  2121. extern "C" {
  2122. static int malloc_bytes = 0;
  2123. static int free_bytes = 0;
  2124. static void
  2125. malloc_track(const char *file, const unsigned int line, const int func_id, const DMALLOC_SIZE byte_size, const DMALLOC_SIZE alignment, const DMALLOC_PNT old_addr, const DMALLOC_PNT new_addr)
  2126. {
  2127.     if (func_id == DMALLOC_FUNC_MALLOC) {
  2128. malloc_bytes += byte_size;
  2129. return;
  2130.     }
  2131.     if (func_id == DMALLOC_FUNC_FREE) {
  2132. DMALLOC_SIZE size = 0;
  2133. dmalloc_examine(old_addr, &size, 0, 0, 0);
  2134. free_bytes += size;
  2135. // XXX useless - byte_size and size are 0
  2136. return;
  2137.     }
  2138. }
  2139. }
  2140. #endif /* DMALLOC */
  2141. static void
  2142. testMain()
  2143. {
  2144. #ifndef NDB_LINUX /* valgrind-1.0.3 does not support */
  2145.     NdbThread_SetConcurrencyLevel(opt.m_threads + 2);
  2146. #endif
  2147. #ifdef DMALLOC
  2148.     dmalloc_track(malloc_track);
  2149. #endif
  2150.     Test test(0, 0);
  2151. #ifdef ndbODBC
  2152.     Ndb* ndb = 0;
  2153.     if (1) { // pre-alloc one Ndb object
  2154. ndb = new Ndb("TEST_DB");
  2155. ndb->init();
  2156. if (ndb->waitUntilReady() != 0) {
  2157.     ndbout << ndb->getNdbError() << endl;
  2158.     fatal("waitUntilReady");
  2159. }
  2160.     }
  2161. #endif
  2162.     for (unsigned loop = 1; opt.m_loop == 0 || loop <= opt.m_loop; loop++) {
  2163. if (opt.m_v >= 2)
  2164.     ndbout << "loop " << loop << endl;
  2165. // create new set of threads in each loop
  2166. Thr** thrList = new Thr* [1 + opt.m_threads];
  2167. for (unsigned n = 1; n <= opt.m_threads; n++) {
  2168.     Thr& thr = *(thrList[n] = new Thr(n, loop));
  2169.     thr.create();
  2170.     if (opt.m_v >= 4)
  2171. ndbout << "thr " << n << " [main] created" << endl;
  2172. }
  2173. #ifdef DMALLOC
  2174. malloc_bytes = free_bytes = 0;
  2175. #endif
  2176. for (unsigned i = 0; i < caseCount; i++) {
  2177.     const Case& cc = caseList[i];
  2178.     if (! cc.matchcase())
  2179. continue;
  2180.     if (opt.m_v >= 2)
  2181. ndbout << "RUN: " << cc.m_name << " - " << cc.m_desc << endl;
  2182.     test.timerOn();
  2183.     for (unsigned subloop = 1; subloop <= opt.m_subloop; subloop++) {
  2184. my_sema = 0;
  2185. if (opt.m_v >= 3)
  2186.     ndbout << "subloop " << subloop << endl;
  2187. if (cc.m_mode == Case::Single) {
  2188.     Thr& thr = *thrList[1];
  2189.     thr.mainStart(cc);
  2190.     thr.mainStop();
  2191.     test.timerCnt(thr.m_test);
  2192. } else if (cc.m_mode == Case::Serial) {
  2193.     for (unsigned n = 1; n <= opt.m_threads; n++) {
  2194. Thr& thr = *thrList[n];
  2195. thr.mainStart(cc);
  2196. thr.mainStop();
  2197. test.timerCnt(thr.m_test);
  2198.     }
  2199. } else if (cc.m_mode == Case::Thread) {
  2200.     for (unsigned n = 1; n <= opt.m_threads; n++) {
  2201. Thr& thr = *thrList[n];
  2202. thr.mainStart(cc);
  2203.     }
  2204.     for (unsigned n = 1; n <= opt.m_threads; n++) {
  2205. Thr& thr = *thrList[n];
  2206. thr.mainStop();
  2207. test.timerCnt(thr.m_test);
  2208.     }
  2209. } else {
  2210.     assert(false);
  2211. }
  2212.     }
  2213.     test.timerOff();
  2214.     if (opt.m_v >= 1)
  2215. ndbout << cc.m_name << " total " << test << endl;
  2216. }
  2217. #ifdef DMALLOC
  2218. if (opt.m_v >= 9) // XXX useless now
  2219.     ndbout << "malloc " << malloc_bytes << " free " << free_bytes << " lost " << malloc_bytes - free_bytes << endl;
  2220. #endif
  2221. // tell threads to exit
  2222. for (unsigned n = 1; n <= opt.m_threads; n++) {
  2223.     Thr& thr = *thrList[n];
  2224.     thr.lock();
  2225.     thr.m_state = Thr::Exit;
  2226.     thr.signal();
  2227.     thr.unlock();
  2228.     if (opt.m_v >= 4)
  2229. ndbout << "thr " << n << " [main] told to exit" << endl;
  2230. }
  2231. for (unsigned n = 1; n <= opt.m_threads; n++) {
  2232.     Thr& thr = *thrList[n];
  2233.     thr.join();
  2234.     if (opt.m_v >= 4)
  2235. ndbout << "thr " << n << " [main] joined" << endl;
  2236.     delete &thr;
  2237. }
  2238. delete[] thrList;
  2239.     }
  2240. #ifdef ndbODBC
  2241.     delete ndb;
  2242. #endif
  2243. }
  2244. static bool
  2245. str2num(const char* arg, const char* str, unsigned* num, unsigned lo = 0, unsigned hi = 0)
  2246. {
  2247.     char* end = 0;
  2248.     long n = strtol(str, &end, 0);
  2249.     if (end == 0 || *end != 0 || n < 0) {
  2250. ndbout << arg << " " << str << " is invalid number" << endl;
  2251. return false;
  2252.     }
  2253.     if (lo != 0 && n < lo) {
  2254. ndbout << arg << " " << str << " is too small min = " << lo << endl;
  2255. return false;
  2256.     }
  2257.     if (hi != 0 && n > hi) {
  2258. ndbout << arg << " " << str << " is too large max = " << hi << endl;
  2259. return false;
  2260.     }
  2261.     *num = n;
  2262.     return true;
  2263. }
  2264. NDB_COMMAND(testOdbcDriver, "testOdbcDriver", "testOdbcDriver", "testOdbcDriver", 65535)
  2265. {
  2266.     while (++argv, --argc > 0) {
  2267. const char* arg = argv[0];
  2268. if (strcmp(arg, "-case") == 0) {
  2269.     if (++argv, --argc > 0) {
  2270. assert(opt.m_namecnt < arraySize(opt.m_name));
  2271. opt.m_name[opt.m_namecnt++] = argv[0];
  2272. if (findCase(argv[0]))
  2273.     continue;
  2274.     }
  2275. }
  2276. if (strcmp(arg, "-core") == 0) {
  2277.     opt.m_core = true;
  2278.     continue;
  2279. }
  2280. if (strcmp(arg, "-depth") == 0) {
  2281.     if (++argv, --argc > 0) {
  2282. if (str2num(arg, argv[0], &opt.m_depth))
  2283.     continue;
  2284.     }
  2285. }
  2286. if (strcmp(arg, "-dsn") == 0) {
  2287.     if (++argv, --argc > 0) {
  2288. opt.m_dsn = argv[0];
  2289. continue;
  2290.     }
  2291. }
  2292. if (strcmp(arg, "-frob") == 0) {
  2293.     if (++argv, --argc > 0) {
  2294. if (str2num(arg, argv[0], &opt.m_frob))
  2295.     continue;
  2296.     }
  2297. }
  2298. if (strcmp(arg, "-errs") == 0) {
  2299.     if (++argv, --argc > 0) {
  2300. if (str2num(arg, argv[0], &opt.m_errs))
  2301.     continue;
  2302.     }
  2303. }
  2304. if (strcmp(arg, "-fragtype") == 0) {
  2305.     if (++argv, --argc > 0) {
  2306. opt.m_fragtype = argv[0];
  2307.                 continue;
  2308.     }
  2309. }
  2310. if (strcmp(arg, "-home") == 0) {
  2311.     if (++argv, --argc > 0) {
  2312. opt.m_home = argv[0];
  2313. continue;
  2314.     }
  2315. }
  2316. if (strcmp(arg, "-loop") == 0) {
  2317.     if (++argv, --argc > 0) {
  2318. if (str2num(arg, argv[0], &opt.m_loop))
  2319.     continue;
  2320.     }
  2321. }
  2322. if (strcmp(arg, "-nogetd") == 0) {
  2323.     opt.m_nogetd = true;
  2324.     continue;
  2325. }
  2326. if (strcmp(arg, "-noputd") == 0) {
  2327.     opt.m_noputd = true;
  2328.     continue;
  2329. }
  2330. if (strcmp(arg, "-nosort") == 0) {
  2331.     opt.m_nosort = true;
  2332.     continue;
  2333. }
  2334. if (strcmp(arg, "-scale") == 0) {
  2335.     if (++argv, --argc > 0) {
  2336. if (str2num(arg, argv[0], &opt.m_scale))
  2337.     continue;
  2338.     }
  2339. }
  2340. if (strcmp(arg, "-serial") == 0) {
  2341.     opt.m_serial = true;
  2342.     continue;
  2343. }
  2344. if (strcmp(arg, "-skip") == 0) {
  2345.     if (++argv, --argc > 0) {
  2346. assert(opt.m_skipcnt < arraySize(opt.m_skip));
  2347. opt.m_skip[opt.m_skipcnt++] = argv[0];
  2348. if (findCase(argv[0]))
  2349.     continue;
  2350.     }
  2351. }
  2352. if (strcmp(arg, "-subloop") == 0) {
  2353.     if (++argv, --argc > 0) {
  2354. if (str2num(arg, argv[0], &opt.m_subloop))
  2355.     continue;
  2356.     }
  2357. }
  2358. if (strcmp(arg, "-table") == 0) {
  2359.     if (++argv, --argc > 0) {
  2360. opt.m_table = argv[0];
  2361. if (findTable())
  2362.     continue;
  2363.     }
  2364. }
  2365. if (strcmp(arg, "-threads") == 0) {
  2366.     if (++argv, --argc > 0) {
  2367. if (str2num(arg, argv[0], &opt.m_threads, 1, MAX_THR))
  2368.     continue;
  2369.     }
  2370. }
  2371. if (strcmp(arg, "-trace") == 0) {
  2372.     if (++argv, --argc > 0) {
  2373. if (str2num(arg, argv[0], &opt.m_trace))
  2374.     continue;
  2375.     }
  2376. }
  2377. if (strcmp(arg, "-v") == 0) {
  2378.     if (++argv, --argc > 0) {
  2379. if (str2num(arg, argv[0], &opt.m_v))
  2380.     continue;
  2381.     }
  2382. }
  2383. if (strncmp(arg, "-v", 2) == 0 && isdigit(arg[2])) {
  2384.     if (str2num(arg, &arg[2], &opt.m_v))
  2385. continue;
  2386. }
  2387. printusage();
  2388. return NDBT_ProgramExit(NDBT_WRONGARGS);
  2389.     }
  2390.     homeEnv: {
  2391. static char env[1000];
  2392. if (opt.m_home != 0) {
  2393.     sprintf(env, "NDB_HOME=%s", opt.m_home);
  2394.     putenv(env);
  2395. }
  2396.     }
  2397.     traceEnv: {
  2398. static char env[40];
  2399. sprintf(env, "NDB_ODBC_TRACE=%u", opt.m_trace);
  2400. putenv(env);
  2401.     }
  2402.     debugEnv: {
  2403. static char env[40];
  2404. sprintf(env, "NDB_ODBC_DEBUG=%d", 1);
  2405. putenv(env);
  2406.     }
  2407.     testMain();
  2408.     return NDBT_ProgramExit(NDBT_OK);
  2409. }
  2410. // vim: set sw=4: