testOdbcDriver.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:158k
源码类别:
MySQL数据库
开发平台:
Visual C++
- k++;
- }
- }
- freeAll(test, hEnv, hDbc, hStmtList, tabCount);
- }
- // cartesian join (multiple nested scans)
- static void
- testCart(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
- allocAll(test, hEnv, hDbc, hStmtList, tabCount);
- char sql[MAX_SQL], *sqlptr;
- for (unsigned cnt = 2; cnt <= 2; cnt++) {
- unsigned rows = 1;
- //for (unsigned k = 0; k < opt.m_depth; k++) {
- //rows *= opt.m_scale * opt.m_threads;
- //}
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- tab.selectCart(sqlptr = sql, cnt);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- unsigned k = 0;
- while (1) {
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- if (k == rows)
- test.exp(SQL_NO_DATA, 0, 0, true);
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- if (k == rows) {
- //chkTuplesFetched(test, hStmt, k);
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- } else {
- //chkTuplesFetched(test, hStmt, k + 1);
- test.timerCnt(1);
- }
- }
- if (k == rows)
- break;
- k++;
- }
- }
- freeAll(test, hEnv, hDbc, hStmtList, tabCount);
- }
- // delete
- static void
- testDeleteAll(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
- allocAll(test, hEnv, hDbc, hStmtList, tabCount);
- char sql[MAX_SQL], *sqlptr;
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- long count0 = -1;
- selectCount(test, hStmt, tab, &count0);
- tab.deleteAll(sqlptr = sql);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
- if (count0 == 0)
- test.exp(SQL_NO_DATA, 0, 0, true);
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- #ifndef iODBC
- test.chk(HStmt(hStmt), test.m_functionCode == SQL_DIAG_DELETE_WHERE, "got %d != %d", test.m_functionCode, SQL_DIAG_DELETE_WHERE);
- #endif
- SQLINTEGER rowCount = -1;
- getRowCount(test, hStmt, &rowCount);
- test.timerCnt(rowCount);
- test.chk(HStmt(hStmt), rowCount == count0, "got %d != %ld", (int)rowCount, count0);
- chkTuplesFetched(test, hStmt, rowCount);
- if (opt.m_v >= 3)
- ndbout << "deleted " << (int)rowCount << " from " << tab.m_name << endl;
- long count = -1;
- selectCount(test, hStmt, tab, &count);
- test.chk(HStmt(hStmt), count == 0, "got %ld != 0", count);
- }
- freeAll(test, hEnv, hDbc, hStmtList, tabCount);
- }
- static void
- testDeletePk(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
- allocAll(test, hEnv, hDbc, hStmtList, tabCount);
- char sql[MAX_SQL], *sqlptr;
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- // prepare
- tab.deletePk(sqlptr = sql);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // bind parameters
- Row row(tab);
- SQLSMALLINT parCount = -1;
- test.run(HStmt(hStmt), SQLNumParams(hStmt, &parCount));
- test.chk(HStmt(hStmt), parCount == tab.m_pkCount, "got %d != %d", (int)parCount, (int)tab.m_colCount);
- for (unsigned j = 0; j < tab.m_pkCount; j++) {
- Fld& fld = row.m_fldList[tab.m_pkIndex[j]];
- const Col& col = fld.m_col;
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1 + j, SQL_PARAM_INPUT, col.ctype(), col.type(), col.size(), 0, fld.caddr(), col.csize(), fld.ind()));
- }
- // bind columns (none)
- SQLSMALLINT colCount = -1;
- test.run(HStmt(hStmt), SQLNumResultCols(hStmt, &colCount));
- test.chk(HStmt(hStmt), colCount == 0, "got %d != 0", (int)colCount);
- // execute
- for (unsigned k = 0; k < opt.m_scale; k++) {
- row.calcPk(test, k);
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- test.chk(HStmt(hStmt), test.m_functionCode == SQL_DIAG_DELETE_WHERE, "got %d != %d", test.m_functionCode, SQL_DIAG_DELETE_WHERE);
- chkRowCount(test, hStmt, 1);
- // direct delete, no fetch required
- chkTuplesFetched(test, hStmt, 0);
- }
- test.timerCnt(opt.m_scale);
- if (opt.m_v >= 3)
- ndbout << "updated " << opt.m_scale << " in " << tab.m_name << endl;
- }
- freeAll(test, hEnv, hDbc, hStmtList, tabCount);
- }
- static void
- testTrans(Test& test)
- {
- #ifdef unixODBC
- if (opt.m_v >= 1)
- ndbout << "unixODBC does not support transactions - test skipped" << endl;
- #else
- SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
- allocAll(test, hEnv, hDbc, hStmtList, tabCount);
- char sql[MAX_SQL], *sqlptr;
- // delete all
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- tab.deleteAll(sqlptr = sql);
- test.exp(SQL_NO_DATA, 0, 0, false);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- SQLINTEGER rowCount = -1;
- getRowCount(test, hStmt, &rowCount);
- if (opt.m_v >= 3)
- ndbout << "deleted " << (int)rowCount << " from " << tab.m_name << endl;
- }
- setAutocommit(test, hDbc, false);
- if (opt.m_v >= 2)
- ndbout << "set autocommit OFF" << endl;
- for (int commit = 0; commit < opt.m_scale; commit += 1) {
- bool rollback = (commit % 2 == 0);
- // XXX delete with no data leaves trans in error state for 2nd table
- if (commit > 0 && rollback) { // previous case was commit
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- tab.deleteDirect(sqlptr = sql, 0);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.exp(SQL_NO_DATA, 0, 0, false);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
- }
- // insert
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- tab.insertDirect(sqlptr = sql, 0);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- if (opt.m_v >= 2)
- ndbout << tab.m_name << ": inserted 1 row" << endl;
- }
- // count them via pk
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- tab.countDirect(sqlptr = sql, 0);
- long count = -1;
- long countExp = 1;
- selectCount(test, hStmt, sql, &count);
- test.chk(HStmt(hStmt), count == countExp, "got %ld != %ld", count, countExp);
- }
- // count them via scan
- for (unsigned i = 0; i < tabCount; i++) {
- // XXX hupp no work
- break;
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- long count = -1;
- long countExp = 1;
- selectCount(test, hStmt, tab, &count);
- test.chk(HStmt(hStmt), count == countExp, "got %ld != %ld", count, countExp);
- }
- // rollback or commit
- if (rollback) {
- if (opt.m_v >= 2)
- ndbout << "end trans ROLLBACK" << endl;
- test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_ROLLBACK));
- } else {
- if (opt.m_v >= 2)
- ndbout << "end trans COMMIT" << endl;
- test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
- }
- // count them via pk again
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- tab.countDirect(sqlptr = sql, 0);
- long count = -1;
- long countExp = rollback ? 0 : 1;
- selectCount(test, hStmt, sql, &count);
- test.chk(HStmt(hStmt), count == countExp, "got %ld != %ld", count, countExp);
- }
- // count them via scan again
- for (unsigned i = 0; i < tabCount; i++) {
- // XXX hupp no work
- break;
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- long count = -1;
- long countExp = rollback ? 0 : 1;
- selectCount(test, hStmt, tab, &count);
- test.chk(HStmt(hStmt), count == countExp, "got %ld != %ld", count, countExp);
- }
- }
- freeAll(test, hEnv, hDbc, hStmtList, tabCount);
- #endif
- }
- static void
- testConcur(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmtList[tabCount];
- allocAll(test, hEnv, hDbc, hStmtList, tabCount);
- char sql[MAX_SQL], *sqlptr;
- for (unsigned i = 0; i < tabCount; i++) {
- SQLHANDLE& hStmt = hStmtList[i];
- const Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- // delete all
- tab.deleteAll(sqlptr = sql);
- test.exp(SQL_NO_DATA, 0, 0, false);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // insert some
- unsigned rowcount = 10;
- for (unsigned n = 0; n < rowcount; n++) {
- tab.insertDirect(sqlptr = sql, n);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- verifyCount(test, hStmt, tab, rowcount);
- // start query scan followed by pk lookups
- tab.selectJoin(sqlptr = sql, 2);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // start fetch
- unsigned k = 0;
- while (1) {
- if (k > 0)
- test.exp(SQL_ERROR, "24000", -1, true); // commit closed cursor
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- if (k > 0)
- break;
- // delete some random row
- tab.deleteDirect(sqlptr = sql, k);
- // try using same statement
- test.exp(SQL_ERROR, "24000", -1, true); // cursor is open
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // try using different statement
- SQLHANDLE hStmt2;
- allocStmt(test, hDbc, hStmt2);
- test.run(HStmt(hStmt2), SQLExecDirect(hStmt2, (SQLCHAR*)sql, SQL_NTS));
- k++;
- }
- test.exp(SQL_ERROR, "24000", -1, true); // cursor is not open
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- test.timerCnt(rowcount);
- }
- freeAll(test, hEnv, hDbc, hStmtList, tabCount);
- }
- static void
- testReadcom(Test& test)
- {
- testDeleteAll(test);
- testInsert(test);
- const unsigned nc = 3;
- SQLHANDLE hEnv[nc], hDbc[nc], hStmt[nc];
- char sql[MAX_SQL], *sqlptr;
- for (unsigned j = 0; j < nc; j++)
- allocAll(test, hEnv[j], hDbc[j], hStmt[j]);
- for (unsigned i = 0; i < tabCount; i++) {
- Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- long count;
- // check count
- count = -1;
- selectCount(test, hStmt[0], tab, &count);
- test.chk(HStmt(hStmt[0]), count == opt.m_scale, "got %d != %d", (int)count, (int)opt.m_scale);
- // scan delete uncommitted with handle 0
- setAutocommit(test, hDbc[0], false);
- tab.deleteAll(sqlptr = sql);
- if (opt.m_scale == 0)
- test.exp(SQL_NO_DATA, 0, 0, false);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt[0]), SQLExecDirect(hStmt[0], (SQLCHAR*)sql, SQL_NTS));
- // scan via other tx should not hang and see all rows
- for (unsigned j = 0; j < nc; j++) {
- count = -1;
- int want = j == 0 ? 0 : opt.m_scale;
- selectCount(test, hStmt[j], tab, &count);
- test.chk(HStmt(hStmt[j]), count == want, "tx %u: got %d != %d", j, (int)count, want);
- if (opt.m_v >= 2)
- ndbout << "tx " << j << " ok !" << endl;
- }
- // setting autocommit on commits the delete
- setAutocommit(test, hDbc[0], true);
- // check count
- count = -1;
- selectCount(test, hStmt[0], tab, &count);
- test.chk(HStmt(hStmt[0]), count == 0, "got %d != 0", (int)count);
- }
- for (unsigned j = 0; j < nc; j++)
- freeAll(test, hEnv[j], hDbc[j], hStmt[j]);
- }
- static void
- testPerf(Test& test)
- {
- if (test.m_stuff == 0) {
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- char sql[MAX_SQL], *sqlptr;
- for (unsigned i = 0; i < tabCount; i++) {
- Tab& tab = tabList[i];
- if (! tab.optok())
- continue;
- test.exp(SQL_NO_DATA, 0, 0, false);
- tab.deleteAll(sqlptr = sql);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- long count0 = -1;
- // XXX triggers SEGV somewhere
- //selectCount(test, hStmt, tab, &count0);
- //test.chk(HStmt(hStmt), count0 == 0, "got %d != 0", (int)count0);
- }
- freeAll(test, hEnv, hDbc, hStmt);
- return;
- }
- assert(test.m_stuff == 1 || test.m_stuff == 2);
- bool ndbapi = (test.m_stuff == 1);
- tt01: {
- const unsigned OFF = 1000000;
- const unsigned N = 25;
- Tab& tab = tabList[1];
- if (! tab.optok())
- goto out;
- if (ndbapi) {
- #ifndef ndbODBC
- if (opt.m_v >= 1)
- ndbout << "running via DM - test skipped" << endl;
- #else
- Ndb* ndb = new Ndb("TEST_DB");
- ndb->init();
- if (ndb->waitUntilReady() != 0) {
- ndbout << ndb->getNdbError() << endl;
- fatal("waitUntilReady");
- }
- Uint32 val[1+N];
- // insert
- for (unsigned k = 1; k <= opt.m_scale; k++) {
- NdbConnection* con = ndb->startTransaction();
- if (con == 0) {
- ndbout << ndb->getNdbError() << endl;
- fatal("startTransaction");
- }
- NdbOperation* op = con->getNdbOperation(tab.m_upperName);
- if (op == 0) {
- ndbout << con->getNdbError() << endl;
- fatal("getNdbOperation");
- }
- if (op->insertTuple() == -1) {
- ndbout << op->getNdbError() << endl;
- fatal("insertTuple");
- }
- for (unsigned j = 0; j <= N; j++) {
- val[j] = (j == 0 ? k + test.m_no * OFF : k * j);
- if (j == 0) {
- if (op->equal(j, val[j]) == -1) {
- ndbout << op->getNdbError() << endl;
- fatal("equal");
- }
- } else {
- if (op->setValue(j, val[j]) == -1) {
- ndbout << op->getNdbError() << endl;
- fatal("setValue");
- }
- }
- }
- if (con->execute(Commit) == -1) {
- ndbout << con->getNdbError() << endl;
- fatal("execute");
- }
- ndb->closeTransaction(con);
- }
- test.timerCnt(opt.m_scale);
- // select PK
- for (unsigned k = 1; k <= opt.m_scale; k++) {
- NdbConnection* con = ndb->startTransaction();
- if (con == 0) {
- ndbout << ndb->getNdbError() << endl;
- fatal("startTransaction");
- }
- NdbOperation* op = con->getNdbOperation(tab.m_upperName);
- if (op == 0) {
- ndbout << con->getNdbError() << endl;
- fatal("getNdbOperation");
- }
- if (op->readTuple() == -1) {
- ndbout << op->getNdbError() << endl;
- fatal("insertTuple");
- }
- for (unsigned j = 0; j <= N; j++) {
- val[j] = (j == 0 ? k + test.m_no * OFF : 0);
- if (j == 0) {
- if (op->equal(j, val[j]) == -1) {
- ndbout << op->getNdbError() << endl;
- fatal("equal");
- }
- } else {
- if (op->getValue(j, (char*)&val[j]) == 0) {
- ndbout << op->getNdbError() << endl;
- fatal("getValue");
- }
- }
- }
- if (con->execute(Commit) == -1) {
- ndbout << con->getNdbError() << endl;
- fatal("execute");
- }
- for (unsigned j = 1; j <= N; j++) {
- assert(val[j] == k * j);
- }
- ndb->closeTransaction(con);
- }
- test.timerCnt(opt.m_scale);
- // delete PK
- for (unsigned k = 1; k <= opt.m_scale; k++) {
- NdbConnection* con = ndb->startTransaction();
- if (con == 0) {
- ndbout << ndb->getNdbError() << endl;
- fatal("startTransaction");
- }
- NdbOperation* op = con->getNdbOperation(tab.m_upperName);
- if (op == 0) {
- ndbout << con->getNdbError() << endl;
- fatal("getNdbOperation");
- }
- if (op->deleteTuple() == -1) {
- ndbout << op->getNdbError() << endl;
- fatal("deleteTuple");
- }
- unsigned j = 0;
- val[j] = k + test.m_no * OFF;
- if (op->equal(j, val[j]) == -1) {
- ndbout << op->getNdbError() << endl;
- fatal("equal");
- }
- if (con->execute(Commit) == -1) {
- ndbout << con->getNdbError() << endl;
- fatal("execute");
- }
- ndb->closeTransaction(con);
- }
- test.timerCnt(opt.m_scale);
- delete ndb;
- #endif
- } else {
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- long val[1+N];
- char sql[MAX_SQL], *sqlptr;
- // insert
- tab.insertAll(sqlptr = sql);
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
- for (unsigned j = 0; j <= N; j++) {
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1 + j, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &val[j], 0, 0));
- }
- test.m_perf = true;
- for (unsigned k = 1; k <= opt.m_scale; k++) {
- for (unsigned j = 0; j <= N; j++) {
- val[j] = (j == 0 ? k + test.m_no * OFF : k * j);
- }
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- }
- test.m_perf = false;
- test.timerCnt(opt.m_scale);
- // select PK
- tab.selectPk(sqlptr = sql);
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
- for (unsigned j = 0; j <= N; j++) {
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 1 + j, SQL_C_SLONG, &val[j], 0, 0));
- }
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1 + N + 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &val[0], 0, 0));
- test.m_perf = true;
- for (unsigned k = 1; k <= opt.m_scale; k++) {
- val[0] = k + test.m_no * OFF;
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- for (unsigned j = 1; j <= N; j++) {
- assert(val[j] == k * j);
- }
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- }
- test.m_perf = false;
- test.timerCnt(opt.m_scale);
- // delete PK
- tab.deletePk(sqlptr = sql);
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
- unsigned j = 0;
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1 + j, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &val[j], 0, 0));
- test.m_perf = true;
- for (unsigned k = 1; k <= opt.m_scale; k++) {
- val[j] = k + test.m_no * OFF;
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- }
- test.m_perf = false;
- test.timerCnt(opt.m_scale);
- freeAll(test, hEnv, hDbc, hStmt);
- }
- out:
- ;
- }
- }
- struct Sql {
- const char* m_sql;
- int m_functionCode;
- int m_rowCount;
- int m_tuplesFetched;
- long m_lastValue;
- unsigned long m_bindValue;
- int m_ret;
- const char* m_state;
- SQLINTEGER m_native;
- bool m_reset;
- // run this function instead
- typedef void (*TestFunc)(Test& test);
- TestFunc m_testFunc;
- Sql() :
- m_sql(0) {
- }
- Sql(const char* do_cmd) :
- m_sql(do_cmd) {
- }
- Sql(const char* sql, int functionCode, int rowCount, int tuplesFetched, long lastValue, long bindValue) :
- m_sql(sql),
- m_functionCode(functionCode),
- m_rowCount(rowCount),
- m_tuplesFetched(tuplesFetched),
- m_lastValue(lastValue),
- m_bindValue(bindValue),
- m_ret(SQL_SUCCESS),
- m_state(0),
- m_native(0),
- m_reset(true),
- m_testFunc(0) {
- }
- // the 4 numbers after SQL_DIAG... rowCount tuplesFetched lastValue bindValue
- Sql(const char* sql, int functionCode, int rowCount, int tuplesFetched, long lastValue, long bindValue, int ret, const char* state, SQLINTEGER native, bool reset) :
- m_sql(sql),
- m_functionCode(functionCode),
- m_rowCount(rowCount),
- m_tuplesFetched(tuplesFetched),
- m_lastValue(lastValue),
- m_bindValue(bindValue),
- m_ret(ret),
- m_state(state),
- m_native(native),
- m_reset(reset),
- m_testFunc(0) {
- }
- Sql(const char* text, TestFunc testFunc) :
- m_sql(text),
- m_testFunc(testFunc) {
- }
- static const char* set_autocommit_on() {
- return "set autocommit on";
- }
- static const char* set_autocommit_off() {
- return "set autocommit off";
- }
- static const char* do_commit() {
- return "commit";
- }
- static const char* do_rollback() {
- return "rollback";
- }
- };
- // 90
- static const Sql
- miscSql90[] = {
- Sql("select * from dual",
- SQL_DIAG_SELECT_CURSOR, 1, 0, -1, -1),
- Sql("drop table tt90a",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- Sql("create table tt90a (a int, b int, c int, primary key(b, c)) storage(large) logging",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- Sql()
- };
- // 91
- static const Sql
- miscSql91[] = {
- Sql("drop table tt91a",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- Sql("create table tt91a (a bigint unsigned primary key, b bigint unsigned not null, c varchar(10))",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- Sql("insert into tt91a values (1, 111, 'aaa')",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- // fails
- Sql("insert into tt91a values (2, null, 'ccc')",
- SQL_DIAG_INSERT, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2014203, true),
- Sql("update tt91a set b = 222 where a = 2",
- SQL_DIAG_UPDATE_WHERE, 0, 0, -1, -1,
- SQL_NO_DATA, 0, 0, true),
- // two more
- Sql("insert into tt91a values (2, 222, 'ccc')",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("insert into tt91a values (3, 333, 'bbb')",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- // direct update
- Sql("update tt91a set b = 112 where a = 1",
- SQL_DIAG_UPDATE_WHERE, 1, 0, -1, -1),
- Sql("update tt91a set b = 113 where a = 1 and b > 111",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- // update and delete with interpreted scan
- Sql("update tt91a set b = 114 where b < 114",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- Sql("delete from tt91a where b < 115",
- SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
- Sql("insert into tt91a values (1, 111, 'aaa')",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- // check rows: 1,111,aaa + 2,222,ccc + 3,333,bbb
- Sql("select * from tt91a order by c",
- SQL_DIAG_SELECT_CURSOR, 3, 3, 2, -1),
- Sql("select * from tt91a order by c desc",
- SQL_DIAG_SELECT_CURSOR, 3, 3, 1, -1),
- Sql("select * from tt91a where a = 2",
- SQL_DIAG_SELECT_CURSOR, 1, 1, -1, -1),
- Sql("select * from tt91a where a + b = 224",
- SQL_DIAG_SELECT_CURSOR, 1, 3, -1, -1),
- Sql("select * from tt91a where a = 4",
- SQL_DIAG_SELECT_CURSOR, 0, 0, -1, -1),
- Sql("select b-a from tt91a order by a-b",
- SQL_DIAG_SELECT_CURSOR, 3, 3, 110, -1),
- Sql("select sum(a+b) from tt91a",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 672, -1),
- 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",
- SQL_DIAG_SELECT_CURSOR, 4, 13, 222, -1),
- 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",
- SQL_DIAG_SELECT_CURSOR, 3, 15, 222, -1),
- // tmp index
- Sql("create unique hash index xx91a on tt91a(b)",
- SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
- 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",
- SQL_DIAG_SELECT_CURSOR, 3, 15, 222, -1),
- Sql("drop index xx91a on tt91a",
- SQL_DIAG_DROP_INDEX, -1, -1, -1, -1),
- // add some duplicates
- Sql("insert into tt91a values (4, 222, 'ccc')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("insert into tt91a values (5, 333, 'bbb')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("insert into tt91a values (6, 333, 'bbb')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- // check rows: 1,111,aaa + 2 * 2,222,ccc + 3 * 3,333,bbb
- Sql("select count(*) from tt91a",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 6, -1),
- Sql("select a+b from tt91a where (b = 111 or b = 222 ) and (b = 222 or b = 333) and a > 1 and a < 3",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 224, -1),
- Sql("select sum(a) from tt91a having min(a) = 1 and max(a) = 6",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 21, -1),
- Sql("select sum(a) from tt91a where a = 2 or a = 4 having min(a) = 2 and max(a) = 4",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 6, -1),
- Sql("select sum(a) from tt91a having min(a) = 1 and max(a) = 5",
- SQL_DIAG_SELECT_CURSOR, 0, -1, -1, -1),
- Sql("select sum(a), b from tt91a group by b order by b",
- SQL_DIAG_SELECT_CURSOR, 3, -1, 14, -1),
- Sql("select sum(a), b, c from tt91a group by b, c order by c",
- SQL_DIAG_SELECT_CURSOR, 3, -1, 6, -1),
- Sql("select b, sum(a) from tt91a group by b having b = 37 * sum(a)",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 222, -1),
- // simple varchar vs interpreter test
- Sql("select count(*) from tt91a where c = 'ccc'",
- SQL_DIAG_SELECT_CURSOR, 1, 2, 2, -1),
- Sql("select count(*) from tt91a where c like '%b%'",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 3, -1),
- // interpreter limits (crashes in api on v211)
- #if NDB_VERSION_MAJOR >= 3
- 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)",
- SQL_DIAG_SELECT_CURSOR, 1, 5, 5, -1),
- 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')",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 3, -1),
- #endif
- // distinct
- Sql("select distinct b from tt91a order by b",
- SQL_DIAG_SELECT_CURSOR, 3, -1, 333, -1),
- // some illegal groupings
- Sql("select a from tt91a group by b",
- -1, -1, -1, -1, -1,
- SQL_ERROR, "IM000", -1, -1),
- Sql("select sum(a) from tt91a group by b having a = 2",
- -1, -1, -1, -1, -1,
- SQL_ERROR, "IM000", -1, -1),
- Sql("select sum(a) from tt91a group by b order by a",
- -1, -1, -1, -1, -1,
- SQL_ERROR, "IM000", -1, -1),
- // string functions
- Sql("insert into tt91a (c, b, a) values ('abcdef', 999, 9)",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("select count(*) from tt91a where left(c, 2) = 'ab' and substr(c, 3, 2) = 'cd' and right(c, 2) = 'ef'",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 1, -1),
- // nulls
- Sql("update tt91a set c = null where a > 8",
- SQL_DIAG_UPDATE_WHERE, 1, -1, -1, -1),
- Sql("select a from tt91a where c is null and b is not null order by a",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 9, -1),
- Sql("select a from tt91a where not (c is not null or b is null) order by a",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 9, -1),
- // null value guard in interpreter
- Sql("select count(*) from tt91a where c < 'x' or c > 'x' or c != 'x' or c = 'x'",
- SQL_DIAG_SELECT_CURSOR, 1, 6, 6, -1),
- Sql("delete from tt91a where c is null",
- SQL_DIAG_DELETE_WHERE, 1, -1, -1, -1),
- // indexes
- Sql("update tt91a set b = a + 5",
- SQL_DIAG_UPDATE_WHERE, 6, 6, -1, -1),
- Sql("create unique hash index xx91a on tt91a(b)",
- SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
- // scan y primary key x
- Sql("select x.b from tt91a x, tt91a y where x.a = y.b + 0",
- SQL_DIAG_SELECT_CURSOR, 1, 7, 11, -1),
- // scan x index y
- Sql("select x.b from tt91a x, tt91a y where x.a + 0 = y.b",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 11, -1),
- // scan x scan y
- Sql("select x.b from tt91a x, tt91a y where x.a + 0 = y.b + 0",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 11, -1),
- // dml ops
- Sql("delete from tt91a where b = 11 and a > 999",
- SQL_DIAG_DELETE_WHERE, 0, 1, -1, -1,
- SQL_NO_DATA, 0, 0, true),
- Sql("delete from tt91a where b = 11",
- SQL_DIAG_DELETE_WHERE, 1, 0, -1, -1),
- Sql("delete from tt91a where b = 11",
- SQL_DIAG_DELETE_WHERE, 0, 0, -1, -1,
- SQL_NO_DATA, 0, 0, true),
- Sql("update tt91a set b = 10*10 where b = 10",
- SQL_DIAG_UPDATE_WHERE, 1, 0, -1, -1),
- Sql("update tt91a set b = 10 where b = 10*10",
- SQL_DIAG_UPDATE_WHERE, 1, 0, -1, -1),
- Sql("update tt91a set b = 10*10 where b = 10 and b >= 10",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- Sql("update tt91a set b = 10 where b = 10*10 and b >= 10*10",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- // char vs varchar
- Sql("drop table tt91b",
- SQL_DIAG_DROP_TABLE, -1, -1, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- Sql("create table tt91b (a int primary key, b char(5), c varchar(5))",
- SQL_DIAG_CREATE_TABLE, -1, -1, -1, -1),
- Sql("insert into tt91b values (1, 'abc', 'abc')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("insert into tt91b values (2, 'xyz', 'xyz')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("insert into tt91b values (3, 'xyz', 'xyz ')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- // char = char strips blanks
- Sql("select count(*) from tt91b x where (x.b = 'abc') or x.a = x.a+1",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
- Sql("select count(*) from tt91b x where (x.b = 'abc')",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("select count(*) from tt91b x where (x.b = 'abc ') or x.a = x.a+1",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
- Sql("select count(*) from tt91b x where (x.b = 'abc ')",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- // varchar = char
- Sql("select count(*) from tt91b x where (x.c = 'abc') or x.a = x.a+1",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
- Sql("select count(*) from tt91b x where (x.c = 'abc')",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("select count(*) from tt91b x where (x.c = 'abc ') or x.a = x.a+1",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 0, -1),
- Sql("select count(*) from tt91b x where (x.c = 'abc ')",
- SQL_DIAG_SELECT_CURSOR, 1, 0, 0, -1),
- // char = varchar
- 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",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 2, -1),
- Sql("select count(*) from tt91b x, tt91b y where (x.b = y.c)",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 2, -1),
- // varchar = varchar
- 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",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 3, -1),
- Sql("select count(*) from tt91b x, tt91b y where (x.c = y.c)",
- SQL_DIAG_SELECT_CURSOR, 1, -1, 3, -1),
- // less
- 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",
- SQL_DIAG_SELECT_CURSOR, 2, -1, 13, -1),
- Sql("select 10 * x.a + y.a from tt91b x, tt91b y where (x.b < y.b) order by x.a, y.a",
- SQL_DIAG_SELECT_CURSOR, 2, -1, 13, -1),
- 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",
- SQL_DIAG_SELECT_CURSOR, 3, -1, 23, -1),
- Sql("select 10 * x.a + y.a from tt91b x, tt91b y where (x.c < y.c) order by x.a, y.a",
- SQL_DIAG_SELECT_CURSOR, 3, -1, 23, -1),
- // like
- Sql("select count(*) from tt91b x where (x.b like 'a%') or x.a = x.a+1",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
- Sql("select count(*) from tt91b x where (x.b like 'a%')",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("select count(*) from tt91b x where (x.b like 'x%z') or x.a = x.a+1",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 0, -1),
- Sql("select count(*) from tt91b x where (x.b like 'x%z')",
- SQL_DIAG_SELECT_CURSOR, 1, 0, 0, -1),
- Sql("select count(*) from tt91b x where (x.a+0 = 2 and x.c like 'x%z') or x.a = x.a+1",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
- Sql("select count(*) from tt91b x where (x.a+0 = 2 and x.c like 'x%z')",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("select count(*) from tt91b x where (x.a+0 = 3 and x.c like 'x%z ') or x.a = x.a+1",
- SQL_DIAG_SELECT_CURSOR, 1, 3, 1, -1),
- Sql("select count(*) from tt91b x where (x.a+0 = 3 and x.c like 'x%z ')",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql()
- };
- // 92
- static void
- testMisc92a(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- char sql[MAX_SQL];
- char tname[20];
- sprintf(tname, "tt92%c", 0140 + test.m_no);
- if (test.m_loop == 1) {
- lock_mutex();
- sprintf(sql, "drop table %s", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.exp(SQL_ERROR, "IM000", 2040709, false);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- sprintf(sql, "create table %s (a int unsigned primary key, b int unsigned not null)", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- unlock_mutex();
- } else {
- sprintf(sql, "delete from %s", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.exp(SQL_NO_DATA, 0, 0, false);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- test.run(HStmt(hStmt), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
- }
- for (int on = true; on >= false; on--) {
- if (opt.m_v >= 2)
- ndbout << "set autocommit " << (on ? "ON" : "OFF") << endl;
- setAutocommit(test, hDbc, on);
- // insert rows
- if (opt.m_v >= 2)
- ndbout << "SQL: insert into " << tname << " ..." << opt.m_scale << endl;
- for (unsigned k = 0; k < opt.m_scale; k++) {
- sprintf(sql, "insert into %s values (%u, %u)", tname, k, 10 * k);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- // commit always
- test.run(HStmt(hStmt), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
- // scan delete
- sprintf(sql, "delete from %s", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // rollback or commit
- test.run(HStmt(hStmt), SQLEndTran(SQL_HANDLE_DBC, hDbc, on ? SQL_COMMIT : SQL_ROLLBACK));
- // count
- long count = -1;
- sprintf(sql, "select count(*) from %s", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- selectCount(test, hStmt, sql, &count);
- test.chk(HStmt(hStmt), count == on ? 0 : opt.m_scale, "%s: got %d != %d", tname, (int)count, (int)opt.m_scale);
- }
- freeAll(test, hEnv, hDbc, hStmt);
- }
- static const Sql
- miscSql92[] = {
- // create in C func
- Sql("testMisc92a", testMisc92a),
- Sql()
- };
- // 93
- static void
- testMisc93a(Test& test)
- {
- SQLHANDLE hEnv[2], hDbc[2], hStmt[2];
- allocAll(test, hEnv[0], hDbc[0], hStmt[0]);
- allocAll(test, hEnv[1], hDbc[1], hStmt[1]);
- char sql[MAX_SQL];
- // select via primary key
- setAutocommit(test, hDbc[0], false);
- sprintf(sql, "select c1 from tt93a where c0 = 1");
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt[0]), SQLExecDirect(hStmt[0], (SQLCHAR*)sql, SQL_NTS));
- // update via another trans must time out
- sprintf(sql, "update tt93a set c1 = 'b' where c0 = 1");
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt[1]), SQLExecDirect(hStmt[1], (SQLCHAR*)sql, SQL_NTS));
- freeAll(test, hEnv[0], hDbc[0], hStmt[0]);
- freeAll(test, hEnv[1], hDbc[1], hStmt[1]);
- }
- static const Sql
- miscSql93[] = {
- // create in C func
- Sql("drop table tt93a",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- Sql("create table tt93a (c0 int primary key, c1 char(10))",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- Sql("insert into tt93a values(1, 'a')",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("testMisc93a", testMisc93a),
- Sql()
- };
- // 95
- static const Sql
- miscSql95[] = {
- Sql("drop table tt95a",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- 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)",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- // ordered index create and drop
- Sql("create index xx95a on tt95a (c, d) nologging",
- SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
- Sql("drop index xx95a on tt95a",
- SQL_DIAG_DROP_INDEX, -1, -1, -1, -1),
- Sql("create index xx95a on tt95a (c) nologging",
- SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
- Sql("insert into tt95a values(1, 'a', 10, 'b')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("insert into tt95a values(2, 'a', 20, 'b')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("insert into tt95a values(3, 'a', 30, 'b')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("select a from tt95a where c = 20",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 2, -1),
- Sql("delete from tt95a where c = 10",
- SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
- Sql("update tt95a set c = 300 where c = 30",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- Sql("delete from tt95a where c = 300",
- SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
- Sql("delete from tt95a",
- SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
- // simple insert and rollback
- Sql("-- simple insert and rollback"),
- Sql(Sql::set_autocommit_off()),
- Sql("insert into tt95a values(1, 'a', 10, 'b')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("select count(*) from tt95a",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("select count(*) from tt95a where c = 10",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql(Sql::do_rollback()),
- Sql(Sql::set_autocommit_on()),
- Sql("select count(*) from tt95a",
- SQL_DIAG_SELECT_CURSOR, 1, 0, 0, -1),
- // simple update and rollback
- Sql("-- simple update and rollback"),
- Sql("insert into tt95a values(1, 'a', 10, 'b')",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql(Sql::set_autocommit_off()),
- Sql("update tt95a set c = 20 where c = 10",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- Sql("select count(*) from tt95a",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("select count(*) from tt95a where c = 20",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql(Sql::do_rollback()),
- Sql(Sql::set_autocommit_on()),
- Sql("select count(*) from tt95a where c = 10",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- // simple delete and rollback
- Sql("-- simple delete and rollback"),
- Sql(Sql::set_autocommit_off()),
- Sql("delete from tt95a where c = 10",
- SQL_DIAG_DELETE_WHERE, 1, 1, -1, -1),
- Sql("select count(*) from tt95a",
- SQL_DIAG_SELECT_CURSOR, 0, 0, 0, -1),
- Sql("select count(*) from tt95a where c = 10",
- SQL_DIAG_SELECT_CURSOR, 0, 0, 0, -1),
- Sql(Sql::do_rollback()),
- Sql(Sql::set_autocommit_on()),
- Sql("select count(*) from tt95a where c = 10",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- // multiple update
- Sql("-- multiple update and rollback"),
- Sql(Sql::set_autocommit_off()),
- Sql("update tt95a set c = 20 where c = 10",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- Sql("select count(*) from tt95a where c = 20",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("update tt95a set c = 30 where c = 20",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- Sql("select count(*) from tt95a where c = 30",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("update tt95a set c = 40 where c = 30",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- Sql("select count(*) from tt95a where c = 40",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql("update tt95a set c = 50 where c = 40",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- Sql("select count(*) from tt95a where c = 50",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- Sql(Sql::do_rollback()),
- Sql(Sql::set_autocommit_on()),
- Sql("select count(*) from tt95a where c = 10",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1, -1),
- // another variant which found no tuple via index (aligment issue)
- Sql("drop table tt95b",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- Sql("create table tt95b (a int primary key, b char(10) not null, c int not null)",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- Sql("create index xx95b on tt95b (b, c) nologging",
- SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
- Sql("insert into tt95b values(0,'0123456789',1)",
- SQL_DIAG_INSERT, 1, -1, -1, -1),
- Sql("select a from tt95b where b='0123456789'",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 0, -1),
- // update index key to different value
- Sql("update tt95b set b = '9876543210' where b = '0123456789'",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- // same value goes nuts...
- Sql("update tt95b set b = '9876543210'",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- #if 0
- // ...if done via index key (variant of halloween problem)
- Sql("update tt95b set b = '9876543210' where b = '9876543210'",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, -1),
- #endif
- Sql()
- };
- // 96
- static void
- testMisc96a(Test& test)
- {
- // single thread
- if (test.m_no != 1)
- return;
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- char sql[MAX_SQL], *sqlptr;
- char tname[20];
- strcpy(tname, "tt96a");
- // drop table
- scopy(sqlptr = sql, "drop table %s", tname);
- test.exp(SQL_ERROR, "IM000", 2040709, false);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // create table with many attributes
- unsigned attrs = 1 + opt.m_scale;
- if (attrs > MAX_ATTRIBUTES_IN_TABLE)
- attrs = MAX_ATTRIBUTES_IN_TABLE;
- if (attrs > 64)
- attrs = 64;
- scopy(sqlptr = sql, "create table %s (c0 int primary key", tname);
- for (unsigned j = 1; j < attrs; j++) {
- if (j % 2 == 0)
- scopy(sqlptr, ", c%d int unsigned not null", j);
- else
- scopy(sqlptr, ", c%d char(10) not null", j);
- }
- scopy(sqlptr, ")");
- if (opt.m_fragtype != 0)
- scopy(sqlptr, " storage(%s)", opt.m_fragtype);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // create or drop indexes
- const unsigned seed = 1000037 * test.m_loop + 1000039 * opt.m_scale;
- srandom(seed);
- const unsigned imax = opt.m_scale < 20 ? opt.m_scale : 20;
- AttributeMask* imasks = new AttributeMask[imax];
- unsigned ccnt = 0;
- unsigned dcnt = 0;
- for (unsigned n = 0; n < imax; n++)
- imasks[n].clear();
- while (ccnt + dcnt < opt.m_scale) {
- char iname[20];
- unsigned n = urandom(imax);
- sprintf(iname, "xx96a%02d", n);
- AttributeMask& imask = imasks[n];
- unsigned sel = urandom(10);
- if (imask.isclear()) {
- // create one
- unsigned ncol = 0;
- unsigned cols[MAX_ATTRIBUTES_IN_INDEX];
- unsigned cnum = urandom(attrs);
- cols[ncol++] = cnum;
- while (ncol < MAX_ATTRIBUTES_IN_INDEX) {
- unsigned sel2 = urandom(10);
- if (sel2 < 2)
- break;
- unsigned cnum2 = urandom(attrs);
- if (sel2 < 9 && cnum2 == 0)
- continue;
- unsigned j;
- for (j = 0; j < ncol; j++) {
- if (cols[j] == cnum2)
- break;
- }
- if (j == ncol)
- cols[ncol++] = cnum2;
- }
- if (sel < 3) {
- scopy(sqlptr = sql, "create unique hash index %s on %s (", iname, tname);
- for (unsigned j = 0; j < ncol; j++)
- scopy(sqlptr, "%sc%d", j == 0 ? "" : ", ", cols[j]);
- scopy(sqlptr, ")");
- } else {
- scopy(sqlptr = sql, "create index %s on %s (", iname, tname);
- for (unsigned j = 0; j < ncol; j++)
- scopy(sqlptr, "%sc%d", j == 0 ? "" : ", ", cols[j]);
- scopy(sqlptr, ") nologging");
- }
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- for (unsigned j = 0; j < ncol; j++)
- imask.set(cols[j]);
- ccnt++;
- } else if (sel < 5 && ccnt > dcnt + 1) {
- scopy(sqlptr = sql, "drop index %s on %s", iname, tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- imask.clear();
- dcnt++;
- }
- }
- // insert unique data
- unsigned rows = opt.m_scale;
- unsigned* uval = new unsigned[rows];
- for (unsigned i = 0; i < rows; i++) {
- uval[i] = urandom(4);
- scopy(sqlptr = sql, "insert into %s values(", tname);
- for (unsigned j = 0; j < attrs; j++) {
- if (j != 0)
- scopy(sqlptr, ",");
- unsigned v = (i << 10) | (j << 2) | uval[i];
- if (j == 0)
- scopy(sqlptr, "%u", i);
- else if (j % 2 == 0)
- scopy(sqlptr, "%u", v);
- else
- scopy(sqlptr, "'%010u'", v);
- }
- scopy(sqlptr, ")");
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- // update each row via random index
- for (unsigned i = 0; i < rows; i++) {
- unsigned uold = uval[i];
- uval[i] = 3 - uval[i];
- AttributeMask imask;
- do {
- unsigned j = urandom(imax);
- imask = imasks[j];
- } while (imask.isclear());
- scopy(sqlptr = sql, "update %s set", tname);
- for (unsigned j = 1; j < attrs; j++) {
- if (j != 1)
- scopy(sqlptr, ",");
- /*
- * Equality update is just barely doable before savepoints
- * provided we change value of keys in every index.
- */
- unsigned v = (i << 10) | (j << 2) | uval[i];
- if (j == 0)
- ;
- else if (j % 2 == 0)
- scopy(sqlptr, " c%d=%u", j, v);
- else
- scopy(sqlptr, " c%d='%010u'", j, v);
- }
- scopy(sqlptr, " where 1=1");
- while (! imask.isclear()) {
- unsigned j = urandom(attrs);
- if (imask.get(j)) {
- unsigned v = (i << 10) | (j << 2) | uold;
- scopy(sqlptr, " and c%d=", j);
- if (j == 0)
- scopy(sqlptr, "%u", i);
- else if (j % 2 == 0)
- scopy(sqlptr, "%u", v);
- else
- scopy(sqlptr, "'%010u'", v);
- imask.clear(j);
- }
- }
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- chkRowCount(test, hStmt, 1);
- }
- // delete all
- scopy(sqlptr = sql, "delete from %s", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- //
- if (opt.m_v >= 2)
- ndbout << tname << ": creates " << ccnt << " drops " << dcnt << endl;
- delete [] imasks;
- delete [] uval;
- freeAll(test, hEnv, hDbc, hStmt);
- }
- static const Sql
- miscSql96[] = {
- Sql("testMisc96a", testMisc96a),
- Sql()
- };
- // 97
- static void
- testMisc97a(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- const char* tname = "TT97A";
- const char* iname = "XX97A";
- char sql[MAX_SQL];
- // create in some thread
- lock_mutex();
- if (my_sema == 0) {
- if (opt.m_v >= 1)
- ndbout << "thread " << test.m_no << " does setup" << endl;
- sprintf(sql, "drop table %s", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
- test.exp(SQL_ERROR, "IM000", 2040709, false);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // a-pk b-index c-counter
- sprintf(sql, "create table %s (a int primary key, b int, c int) storage(small)", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- for (unsigned i = 0; i < opt.m_scale; i++) {
- sprintf(sql, "insert into %s values (%d, %d, %d)", tname, i, 10 * i, 0);
- if (opt.m_v >= 3)
- ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- sprintf(sql, "create index %s on %s (b) nologging", iname, tname);
- if (opt.m_v >= 2)
- ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- my_sema = 1;
- }
- unlock_mutex();
- assert(my_sema == 1);
- // parallel run - default rotating pk, ts, is
- // frob: low 3 hex digits give alt sequence e.g. 0x311 = pk, pk, is
- // frob: 4-th hex digit non-zero says use NDB API e.g. 0x1000
- unsigned typelist[3] = { 1, 2, 3 };
- for (unsigned i = 0; i < 3; i++) {
- unsigned t = (opt.m_frob >> (i * 4)) & 0xf;
- if (t != 0)
- typelist[i] = t;
- }
- unsigned type = typelist[(test.m_no - 1) % 3];
- if ((opt.m_frob & 0xf000) == 0) {
- for (unsigned i = 0; i < opt.m_scale; i++) {
- if (type == 1) {
- // pk update
- sprintf(sql, "update %s set c = c + 1 where a = %d", tname, i % opt.m_scale);
- if (opt.m_v >= 3)
- ndbout << lock << "SQL[" << test.m_no << "]: " << sql << endl << unlock;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- if (type == 2) {
- // table scan update
- sprintf(sql, "update %s set c = c + 1 where b + 0 = %d", tname, 10 * i);
- if (opt.m_v >= 3)
- ndbout << lock << "SQL[" << test.m_no << "]: " << sql << endl << unlock;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- if (type == 3) {
- // index scan update
- sprintf(sql, "update %s set c = c + 1 where b = %d", tname, 10 * i);
- if (opt.m_v >= 3)
- ndbout << lock << "SQL[" << test.m_no << "]: " << sql << endl << unlock;
- test.exp(SQL_NO_DATA, 0, 0, false);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- }
- }
- } else {
- #ifdef ndbODBC
- #define CHK(o, x) do { if (! (x)) { fatal("line %d: %d %s", __LINE__, o->getNdbError().code, o->getNdbError().message); } } while (0)
- Ndb* ndb = new Ndb("TEST_DB");
- ndb->init();
- CHK(ndb, ndb->waitUntilReady() == 0);
- Int32 a, b, c;
- for (unsigned i = 0; i < opt.m_scale; i++) {
- if (type == 1) {
- // pk update with exclusive read
- NdbConnection* con;
- NdbOperation* op;
- CHK(ndb, (con = ndb->startTransaction()) != 0);
- a = i;
- c = -1;
- CHK(con, (op = con->getNdbOperation(tname)) != 0);
- CHK(op, op->readTupleExclusive() == 0);
- CHK(op, op->equal((unsigned)0, (char*)&a, 0) == 0);
- CHK(op, op->getValue(2, (char*)&c) != 0);
- CHK(con, con->execute(NoCommit) == 0);
- c = c + 1;
- CHK(con, (op = con->getNdbOperation(tname)) != 0);
- CHK(op, op->updateTuple() == 0);
- CHK(op, op->equal((unsigned)0, (char*)&a, 0) == 0);
- CHK(op, op->setValue(2, (char*)&c) == 0);
- CHK(con, con->execute(Commit) == 0);
- ndb->closeTransaction(con);
- if (opt.m_v >= 3)
- ndbout << lock << "thr " << test.m_no << " pk a=" << i << " c=" << c << endl << unlock;
- }
- if (type == 2) {
- // table scan update
- NdbConnection* con;
- NdbOperation* op;
- CHK(ndb, (con = ndb->startTransaction()) != 0);
- CHK(con, (op = con->getNdbOperation(tname)) != 0);
- CHK(con, op->openScanExclusive(240) == 0);
- CHK(op, op->getValue((unsigned)0, (char*)&a) != 0);
- CHK(op, op->getValue(2, (char*)&c) != 0);
- CHK(con, con->executeScan() == 0);
- unsigned rows = 0;
- unsigned updates = 0;
- while (1) {
- int ret;
- a = -1;
- c = -1;
- CHK(con, (ret = con->nextScanResult()) == 0 || ret == 1);
- if (ret == 1)
- break;
- rows++;
- if (a == i) {
- NdbConnection* con2;
- NdbOperation* op2;
- CHK(ndb, (con2 = ndb->startTransaction()) != 0);
- CHK(op, (op2 = op->takeOverForUpdate(con2)) != 0);
- c = c + 1;
- CHK(op2, op2->setValue(2, (char*)&c) == 0);
- CHK(con2, con2->execute(Commit) == 0);
- ndb->closeTransaction(con2);
- updates++;
- if (opt.m_v >= 3)
- ndbout << lock << "thr " << test.m_no << " ts rows=" << rows << " a=" << i << " c=" << c << endl << unlock;
- // test stop scan too
- CHK(con, con->stopScan() == 0);
- break;
- }
- }
- ndb->closeTransaction(con);
- test.chk(HStmt(hStmt), updates == 1, "got %u != 1", updates);
- }
- if (type == 3) {
- // index scan update
- NdbConnection* con;
- NdbOperation* op;
- CHK(ndb, (con = ndb->startTransaction()) != 0);
- CHK(con, (op = con->getNdbOperation(iname, tname)) != 0);
- CHK(con, op->openScanExclusive(240) == 0);
- b = 10 * i;
- CHK(con, op->setBound((unsigned)0, 4, &b, sizeof(b)) == 0);
- CHK(op, op->getValue((unsigned)0, (char*)&a) != 0);
- CHK(op, op->getValue(2, (char*)&c) != 0);
- CHK(con, con->executeScan() == 0);
- unsigned rows = 0;
- unsigned updates = 0;
- while (1) {
- int ret;
- a = -1;
- c = -1;
- CHK(con, (ret = con->nextScanResult()) == 0 || ret == 1);
- if (ret == 1)
- break;
- rows++;
- if (a == i) {
- NdbConnection* con2;
- NdbOperation* op2;
- CHK(ndb, (con2 = ndb->startTransaction()) != 0);
- CHK(op, (op2 = op->takeOverForUpdate(con2)) != 0);
- c = c + 1;
- CHK(op2, op2->setValue(2, (char*)&c) == 0);
- CHK(con2, con2->execute(Commit) == 0);
- ndb->closeTransaction(con2);
- updates++;
- if (opt.m_v >= 3)
- ndbout << lock << "thr " << test.m_no << " is rows=" << rows << " a=" << i << " c=" << c << endl << unlock;
- // test stop scan too
- CHK(con, con->stopScan() == 0);
- break;
- }
- }
- ndb->closeTransaction(con);
- test.chk(HStmt(hStmt), rows == 1, "got %u != 1", rows);
- test.chk(HStmt(hStmt), updates == 1, "got %u != 1", updates);
- }
- }
- delete ndb;
- #undef CHK
- #endif
- }
- // verify result
- lock_mutex();
- if (++my_sema == 1 + opt.m_threads) {
- if (opt.m_v >= 1)
- ndbout << "thread " << test.m_no << " does verification" << endl;
- sprintf(sql, "select * from %s order by a", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL[" << test.m_no << "]: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- long a, b, c;
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_SLONG, &a, 0, 0));
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 2, SQL_C_SLONG, &b, 0, 0));
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 3, SQL_C_SLONG, &c, 0, 0));
- for (unsigned i = 0; i < opt.m_scale; i++) {
- a = b = c = -1;
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.chk(HStmt(hStmt), a == i, "a: got %ld != %u", a, i);
- test.chk(HStmt(hStmt), b == 10 * i, "b: got %ld != %u", b, 10 * i);
- test.chk(HStmt(hStmt), c == opt.m_threads, "c: got %ld != %u", c, opt.m_threads);
- if (opt.m_v >= 4)
- ndbout << "verified " << i << endl;
- }
- test.exp(SQL_NO_DATA, 0, 0, true);
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- if (opt.m_v >= 2)
- ndbout << "thr " << test.m_no << " verified " << opt.m_scale << " rows" << endl;
- my_sema = 0;
- }
- unlock_mutex();
- freeAll(test, hEnv, hDbc, hStmt);
- }
- static const Sql
- miscSql97[] = {
- Sql("testMisc97a", testMisc97a),
- Sql()
- };
- // 99
- static void
- testMisc99a(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- // bad
- const char* sqlInsertBad = "insert into tt99a values(?, ?, ?, ?, ?)";
- test.exp(SQL_ERROR, "21S01", -1, true);
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlInsertBad, SQL_NTS));
- // good
- const char* sqlInsert = "insert into tt99a (col1, col2, col3, col4, col5) values(?, ?, ?, ?, ?)";
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlInsert, SQL_NTS));
- unsigned long value;
- for (unsigned i = 1; i <= 5; i++) {
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, i, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &value, 0, 0));
- }
- const unsigned long base = 1000000000;
- const unsigned long scale = 10;
- for (value = base; value < base + scale; value++) {
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- }
- // bug1: re-analyze of converted expression...
- const char* sqlSelect = "select col5 from tt99a where col2 + 0 = ?";
- unsigned long output;
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_ULONG, &output, 0, 0));
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlSelect, SQL_NTS));
- // bug2: previous bind must survive a new SQLPrepare
- if (0) {
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &value, 0, 0));
- }
- for (value = base; value < base + scale; value++) {
- if (value > base + 4) {
- // bug1: ...when IPD changed by JDBC
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &value, 0, 0));
- }
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- output = (unsigned long)-1;
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.chk(HStmt(hStmt), output == value, "got %lu != %lu", output, value);
- test.exp(SQL_NO_DATA, 0, 0, true);
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- test.timerCnt(1);
- }
- freeAll(test, hEnv, hDbc, hStmt);
- }
- static void
- testMisc99c(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- const char* sql = "select b from tt99c where a = ?";
- const unsigned long c1 = 2100000000U;
- const unsigned long c2 = 4100000000U;
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
- unsigned long aval, bval;
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &aval, 0, 0));
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_ULONG, &bval, 0, 0));
- // uno
- for (unsigned i = 0; i < opt.m_scale; i++) {
- aval = c1;
- bval = (unsigned long)-1;
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << " [?=" << (Uint64)aval << "]" << endl;
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.chk(HStmt(hStmt), bval == c2, "got %lu != %lu", bval, c2);
- //test.exp(SQL_NO_DATA, 0, 0, true);
- //test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- }
- // dos
- for (unsigned i = 0; i < opt.m_scale; i++) {
- break; // XXX not yet, hangs in NDB ?!?
- aval = c2;
- bval = (unsigned long)-1;
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << " [?=" << (Uint64)aval << "]" << endl;
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.chk(HStmt(hStmt), bval == c1, "got %lu != %lu", bval, c2);
- //test.exp(SQL_NO_DATA, 0, 0, true);
- //test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- }
- freeAll(test, hEnv, hDbc, hStmt);
- }
- static void
- testMisc99d(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- const char* tname = "TT99D";
- char sql[MAX_SQL];
- sprintf(sql, "drop table %s", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.exp(SQL_ERROR, "IM000", 2040709, false);
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- sprintf(sql, "create table %s (a bigint unsigned, b bigint, primary key (a))", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLExecDirect(hStmt, (SQLCHAR*)sql, SQL_NTS));
- sprintf(sql, "insert into %s values (?, ?)", tname);
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql << endl;
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
- // XXX replace by 100 when signed vs unsigned resolved
- const unsigned num = 78;
- SQLUBIGINT aval;
- SQLBIGINT bval;
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_BIGINT, 0, 0, &aval, 0, 0));
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, &bval, 0, 0));
- for (SQLBIGINT i = 0; i < num; i++) {
- if (opt.m_v >= 3)
- ndbout << "insert " << i << endl;
- aval = i * i * i * i * i * i * i * i * i * i; // 10
- bval = -aval;
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- }
- sprintf(sql, "select a, b from tt99d where a = ?");
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql, SQL_NTS));
- SQLUBIGINT kval;
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_BIGINT, 0, 0, &kval, 0, 0));
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_UBIGINT, &aval, 0, 0));
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 2, SQL_C_SBIGINT, &bval, 0, 0));
- for (SQLBIGINT i = 0; i < num; i++) {
- kval = i * i * i * i * i * i * i * i * i * i; // 10
- if (opt.m_v >= 3)
- ndbout << "fetch " << i << " key " << kval << endl;
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- aval = bval = 0;
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.chk(HStmt(hStmt), aval == kval && bval == -kval, "got %llu, %lld != %llu, %lld", aval, bval, kval, -kval);
- test.exp(SQL_NO_DATA, 0, 0, true);
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- }
- freeAll(test, hEnv, hDbc, hStmt);
- }
- static void
- testMiscC2(Test& test)
- {
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- #if 0
- {
- char POP[255];
- char PORT[255];
- char ACCESSNODE[255];
- const char* sqlSelect = "select PORT from AAA where POP=? and ACCESSNODE=?";
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlSelect, SQL_NTS));
- for (int j=0; j<5; j++) {
- printf("Loop %un", j);
- printf("LINE %un", __LINE__);
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 255, 0, POP, 255, 0));
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 255, 0, ACCESSNODE, 255, 0));
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_CHAR, PORT, 255, 0));
- sprintf(POP, "a");
- sprintf(ACCESSNODE, "b");
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- printf("got %sn", PORT);
- printf("LINE %un", __LINE__);
- test.exp(SQL_NO_DATA, 0, 0, true);
- printf("LINE %un", __LINE__);
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- printf("LINE %un", __LINE__);
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- printf("LINE %un", __LINE__);
- }
- }
- return;
- #endif
- char POP[255];
- char PORT[255];
- char ACCESSNODE[255];
- unsigned long VLAN = 0;
- unsigned long SNMP_INDEX = 0;
- unsigned long PORT_STATE = 0;
- unsigned long STATIC_PORT = 0;
- unsigned long COMMENT = 0;
- const char* sqlSelect = "select PORT, PORT_STATE from PORTS where POP=? and ACCESSNODE=?";
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sqlSelect, SQL_NTS));
- for (int j=0; j<5; j++) {
- printf("Loop %un", j);
- printf("LINE %un", __LINE__);
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 255, 0, POP, 255, 0));
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 255, 0, ACCESSNODE, 255, 0));
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_CHAR, PORT, 255, 0));
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 2, SQL_C_ULONG, &PORT_STATE, 0, 0));
- sprintf(POP, "row%u.i%u.bredband.com", 2, 3);
- sprintf(ACCESSNODE, "as%u", 2);
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- for (int i=0; i < 3; i++) {
- PORT_STATE=0;
- sprintf(PORT, "XXXXXXXXXXXXXXXXXXXXX");
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- printf("got %s %lun", PORT, PORT_STATE);
- // test.chk(HStmt(hStmt), false, "got %s != %s", "xxx", PORT);
- }
- printf("LINE %un", __LINE__);
- test.exp(SQL_NO_DATA, 0, 0, true);
- printf("LINE %un", __LINE__);
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- printf("LINE %un", __LINE__);
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- printf("LINE %un", __LINE__);
- }
- }
- static const Sql
- miscSqlC2[] = {
- Sql("drop table PORTS",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- 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))",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- Sql("create index xxPORTS on PORTS (POP, ACCESSNODE) nologging",
- SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
- Sql("insert into PORTS values ('row2.i3.bredband.com','as2','Fa0/0',0,1,2,3,4)",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("insert into PORTS values ('row2.i3.bredband.com','as2','Fa0/1',1,2,3,4,5)",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("insert into PORTS values ('row2.i3.bredband.com','as2','Fa0/2',2,3,4,5,6)",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("select PORT, PORT_STATE from PORTS where POP='row2.i3.bredband.com' and ACCESSNODE='as2'",
- SQL_DIAG_SELECT_CURSOR, 3, 3, -1, -1),
- Sql("drop table AAA",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- Sql("create table AAA (POP varchar(200), ACCESSNODE varchar(200) not null, PORT varchar(200) not null, primary key (POP,ACCESSNODE,PORT))",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- Sql("create index xxAAA on AAA (POP, ACCESSNODE) nologging",
- SQL_DIAG_CREATE_INDEX, -1, -1, -1, -1),
- Sql("insert into AAA values ('a','b','A')",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("testMiscC2", testMiscC2),
- Sql()
- };
- /*
- > SELECT PORT, PORT_STATE FROM PORTS where pop=? and accessnode=?
- > SELECT VLAN, SNMP_INDEX, PORT_STATE, STATIC_PORT, COMMENT FROM PORTS WHERE POP=? AND ACCESSNODE=? AND PORT=?
- > select count(*) from ports
- > select snmp_index from ports where pop='row2.i3.bredband.com' and accessnode='as2' and port='Fa0/2'
- > 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=?
- > 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
- */
- static const Sql
- miscSql99[] = {
- Sql("drop table tt99a",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- 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')",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- // inserts 10 rows, all same, start value 1000000000
- Sql("testMisc99a", testMisc99a),
- // interpreted scan plus bind parameter
- Sql("select col1 from tt99a where col2 = ?",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1000000004, 1000000004),
- Sql("select col1 from tt99a where col2 = 1000000000 + ?",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1000000004, 4),
- Sql("select col1 from tt99a where col2 = ? + 1000000000",
- SQL_DIAG_SELECT_CURSOR, 1, 1, 1000000004, 4),
- // same not interpreted, tuple count 10
- Sql("select col1 from tt99a where col2 + 0 = 1000000000 + ?",
- SQL_DIAG_SELECT_CURSOR, 1, 10, 1000000004, 4),
- // varchar variations
- Sql("select count(*) from tt99a where col6 = 'abc123'",
- SQL_DIAG_SELECT_CURSOR, 1, 10, 10, -1),
- Sql("select count(*) from tt99a where left(col6, ?) = 'abc1'",
- SQL_DIAG_SELECT_CURSOR, 1, 10, 10, 4),
- Sql("select count(*) from tt99a where left(col6, ?) = 'abc1'",
- SQL_DIAG_SELECT_CURSOR, 1, 10, 0, 3),
- // tpc-b inspired, wrong optimization to direct update
- Sql("drop table tt99b",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- Sql("create table tt99b(a int primary key, b int not null, c double precision)",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- Sql("insert into tt99b values(1, 10, 100.0)",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("insert into tt99b values(9, 90, 900.0)",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("create unique hash index tt99y on tt99b (b)",
- SQL_DIAG_CREATE_INDEX, -1, 0, -1, -1),
- // first scan update..
- Sql("update tt99b set c = c + ? where a+0 = 1",
- SQL_DIAG_UPDATE_WHERE, 1, 2, -1, 10),
- Sql("update tt99b set c = c + ? where b+0 = 10",
- SQL_DIAG_UPDATE_WHERE, 1, 2, -1, 10),
- // then optimized..
- Sql("update tt99b set c = c + ? where a = 1",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, 10),
- Sql("update tt99b set c = c + ? where b = 10",
- SQL_DIAG_UPDATE_WHERE, 1, 1, -1, 10),
- // verify..
- Sql("select count(*) from tt99b where 100-1 < c and c < 140-1",
- SQL_DIAG_SELECT_CURSOR, 1, 2, 0, -1),
- Sql("select count(*) from tt99b where 140-.001 < c and c < 140+.001",
- SQL_DIAG_SELECT_CURSOR, 1, 2, 1, -1),
- // unsigned test
- Sql("drop table tt99c",
- SQL_DIAG_DROP_TABLE, -1, 0, -1, -1,
- SQL_ERROR, "IM000", 2040709, false),
- Sql("create table tt99c(a int unsigned primary key, b int unsigned)",
- SQL_DIAG_CREATE_TABLE, -1, 0, -1, -1),
- Sql("insert into tt99c values(2100000000, 4100000000)",
- SQL_DIAG_INSERT, 1, 0, -1, -1),
- Sql("insert into tt99c (a, b) select b, a from tt99c",
- SQL_DIAG_INSERT, 1, 1, -1, -1),
- Sql("testMisc99c", testMisc99c),
- // new external type SQL_C_[SU]BIGINT
- Sql("testMisc99d", testMisc99d),
- Sql()
- };
- static const struct { const Sql* sql; int minscale; }
- miscSql[11] = {
- { miscSql90, 0 },
- { miscSql91, 0 },
- { miscSql92, 0 },
- { miscSql93, 0 },
- { 0, 0 }, // 94
- { miscSql95, 0 },
- { miscSql96, 0 },
- { miscSql97, 0 },
- { 0, 0 }, // 98
- { miscSql99, 0 },
- { miscSqlC2, 0 }
- };
- static void
- testSql(Test& test)
- {
- const unsigned salt = test.m_stuff; // mess
- if (opt.m_scale < miscSql[salt].minscale) {
- if (opt.m_v >= 1)
- ndbout << "skip - requires scale >= " << miscSql[salt].minscale << endl;
- return;
- }
- assert(0 <= salt && salt < 11 && miscSql[salt].sql != 0);
- SQLHANDLE hEnv, hDbc, hStmt;
- allocAll(test, hEnv, hDbc, hStmt);
- for (unsigned i = 0; ; i++) {
- const Sql& sql = miscSql[salt].sql[i];
- if (sql.m_sql == 0)
- break;
- if (opt.m_v >= 2)
- ndbout << "SQL: " << sql.m_sql << endl;
- if (sql.m_testFunc != 0) {
- (*sql.m_testFunc)(test);
- continue;
- }
- if (strncmp(sql.m_sql, "--", 2) == 0) {
- continue;
- }
- if (strcmp(sql.m_sql, Sql::set_autocommit_on()) == 0) {
- setAutocommit(test, hDbc, true);
- continue;
- }
- if (strcmp(sql.m_sql, Sql::set_autocommit_off()) == 0) {
- setAutocommit(test, hDbc, false);
- continue;
- }
- if (strcmp(sql.m_sql, Sql::do_commit()) == 0) {
- test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT));
- continue;
- }
- if (strcmp(sql.m_sql, Sql::do_rollback()) == 0) {
- test.run(HDbc(hDbc), SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_ROLLBACK));
- continue;
- }
- if (opt.m_v >= 3) {
- ndbout << "expect:";
- ndbout << " ret=" << sql.m_ret;
- ndbout << " rows=" << sql.m_rowCount;
- ndbout << " tuples=" << sql.m_tuplesFetched;
- ndbout << endl;
- }
- test.run(HStmt(hStmt), SQLFreeStmt(hStmt, SQL_UNBIND));
- test.run(HStmt(hStmt), SQLFreeStmt(hStmt, SQL_RESET_PARAMS));
- // prep
- test.exp(sql.m_ret, sql.m_state, sql.m_native, false);
- test.run(HStmt(hStmt), SQLPrepare(hStmt, (SQLCHAR*)sql.m_sql, SQL_NTS));
- if (test.m_ret != SQL_SUCCESS)
- continue;
- // bind between prep and exec like JDBC
- unsigned long bindValue = sql.m_bindValue;
- for (int k = 0; k <= 1; k++) {
- if (bindValue != -1) {
- assert(strchr(sql.m_sql, '?') != 0);
- test.run(HStmt(hStmt), SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &bindValue, 0, 0));
- }
- if (k == 0) {
- if (bindValue != -1) {
- test.run(HStmt(hStmt), SQLFreeStmt(hStmt, SQL_RESET_PARAMS));
- // exec with unbound parameter
- test.exp(SQL_ERROR, "HY010", -1, true);
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- 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);
- }
- } else {
- // exec
- test.exp(sql.m_ret, sql.m_state, sql.m_native, sql.m_reset);
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- 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);
- }
- }
- if (sql.m_rowCount != -1) {
- if (sql.m_functionCode == SQL_DIAG_SELECT_CURSOR) {
- long lastValue;
- if (sql.m_lastValue != -1)
- test.run(HStmt(hStmt), SQLBindCol(hStmt, 1, SQL_C_SLONG, &lastValue, 0, 0));
- unsigned k = 0;
- do {
- int rowCount = 0;
- lastValue = -1;
- while (1) {
- test.exp(SQL_NO_DATA, 0, 0, false);
- test.run(HStmt(hStmt), SQLFetch(hStmt));
- if (test.m_ret == SQL_NO_DATA)
- break;
- rowCount++;
- }
- test.chk(HStmt(hStmt), rowCount == sql.m_rowCount, "rowCount: got %d != %d", (int)rowCount, (int)sql.m_rowCount);
- if (sql.m_tuplesFetched != -1)
- chkTuplesFetched(test, hStmt, sql.m_tuplesFetched);
- if (rowCount > 0 && sql.m_lastValue != -1)
- test.chk(HStmt(hStmt), lastValue == sql.m_lastValue, "lastValue: got %ld != %ld", (long)lastValue, (long)sql.m_lastValue);
- test.run(HStmt(hStmt), SQLCloseCursor(hStmt));
- if (++k >= opt.m_scale)
- break;
- test.run(HStmt(hStmt), SQLExecute(hStmt));
- } while (1);
- test.timerCnt(opt.m_scale);
- } else {
- assert(sql.m_lastValue == -1);
- chkRowCount(test, hStmt, sql.m_rowCount);
- if (sql.m_tuplesFetched != -1)
- chkTuplesFetched(test, hStmt, sql.m_tuplesFetched);
- test.timerCnt(1);
- }
- }
- }
- freeAll(test, hEnv, hDbc, hStmt);
- }
- // name, function, runmode, salt (0=const or n/a), description
- static const Case caseList[] = {
- Case( "00alloc", testAlloc, Case::Thread, 0, "allocate handles" ),
- Case( "01create", testCreate, Case::Single, 0, "create tables for the test" ),
- Case( "02prepare", testPrepare, Case::Thread, 0, "prepare without execute" ),
- Case( "03catalog", testCatalog, Case::Thread, 0, "catalog functions" ),
- Case( "10insert", testInsert, Case::Thread, 1, "insert computed rows" ),
- Case( "11delall", testDeleteAll, Case::Single, 0, "delete all rows via scan" ),
- Case( "12insert", testInsert, Case::Thread, 1, "insert computed rows again" ),
- Case( "13count", testCount, Case::Single, 0, "count rows" ),
- Case( "14verpk", testVerifyPk, Case::Thread, 1, "verify via primary key" ),
- Case( "15verscan", testVerifyScan, Case::Serial, 1, "verify via range scans" ),
- Case( "16join", testJoin, Case::Single, 0, "multiple self-join" ),
- Case( "17cart", testCart, Case::Single, 0, "cartesian join" ),
- Case( "20updpk", testUpdatePk, Case::Thread, 2, "update via primary key" ),
- Case( "21verpk", testVerifyPk, Case::Thread, 2, "verify via primary key" ),
- Case( "22verscan", testVerifyScan, Case::Serial, 2, "verify via range scans" ),
- Case( "23updscan", testUpdateScan, Case::Serial, 0, "update via scan" ),
- Case( "24verpk", testVerifyPk, Case::Thread, 0, "verify via primary key" ),
- Case( "25verscan", testVerifyScan, Case::Serial, 0, "verify via range scans" ),
- Case( "26delpk", testDeletePk, Case::Thread, 0, "delete via primary key" ),
- Case( "30trans", testTrans, Case::Single, 3, "rollback and commit" ),
- Case( "31concur", testConcur, Case::Single, 0, "commit across open cursor" ),
- Case( "32readcom", testReadcom, Case::Single, 0, "read committed" ),
- Case( "40perf", testPerf, Case::Single, 0, "perf test prepare" ),
- Case( "41perf", testPerf, Case::Thread, 1, "perf test NDB API" ),
- Case( "42perf", testPerf, Case::Thread, 2, "perf test NDB ODBC" ),
- Case( "90sql", testSql, Case::Single, 0, "misc SQL: metadata" ),
- Case( "91sql", testSql, Case::Single, 1, "misc SQL: misc" ),
- Case( "92sql", testSql, Case::Thread, 2, "misc SQL: scan rollback" ),
- Case( "93sql", testSql, Case::Single, 3, "misc SQL: locking" ),
- Case( "95sql", testSql, Case::Single, 5, "misc SQL: indexes (simple)" ),
- Case( "96sql", testSql, Case::Single, 6, "misc SQL: indexes" ),
- Case( "97sql", testSql, Case::Thread, 7, "misc SQL: indexes" ),
- Case( "99sql", testSql, Case::Single, 9, "misc SQL: bug du jour" ),
- Case( "C2", testSql, Case::Single, 10, "misc SQL: C2" )
- };
- static const unsigned caseCount = arraySize(caseList);
- static bool
- findCase(const char* name)
- {
- for (unsigned i = 0; i < caseCount; i++) {
- const Case& cc = caseList[i];
- if (strstr(cc.m_name, name) != 0)
- return true;
- }
- return false;
- }
- static void
- listCases()
- {
- ndbout << "cases:" << endl;
- unsigned m = 0;
- for (unsigned i = 0; i < caseCount; i++) {
- const Case& cc = caseList[i];
- if (m < strlen(cc.m_name))
- m = strlen(cc.m_name);
- }
- for (unsigned i = 0; i < caseCount; i++) {
- const Case& cc = caseList[i];
- char buf[200];
- sprintf(buf, "%-*s [%-6s] %s", m, cc.m_name, cc.modename(), cc.m_desc);
- ndbout << buf << endl;
- }
- }
- // threads
- extern "C" { static void* testThr(void* arg); }
- struct Thr {
- enum State {
- Wait = 1, // wait for test case
- Run = 2, // run the test case
- Done = 3, // done with the case
- Exit = 4 // exit thread
- };
- unsigned m_no; // thread number 1 .. max
- NdbThread* m_thr; // thread id etc
- const Case* m_case; // current case
- State m_state; // condition variable
- NdbMutex* m_mutex; // condition guard
- NdbCondition* m_cond;
- void* m_status; // exit status (not used)
- Test m_test; // test runner
- Thr(unsigned no, unsigned loop) :
- m_no(no),
- m_thr(0),
- m_case(0),
- m_state(Wait),
- m_mutex(NdbMutex_Create()),
- m_cond(NdbCondition_Create()),
- m_status(0),
- m_test(no, loop) {
- }
- ~Thr() {
- destroy();
- NdbCondition_Destroy(m_cond);
- NdbMutex_Destroy(m_mutex);
- }
- void create() {
- assert(m_thr == 0);
- m_thr = NdbThread_Create(testThr, (void**)this, 64*1024, "test", NDB_THREAD_PRIO_LOW);
- }
- void destroy() {
- if (m_thr != 0)
- NdbThread_Destroy(&m_thr);
- m_thr = 0;
- }
- void lock() {
- NdbMutex_Lock(m_mutex);
- }
- void unlock() {
- NdbMutex_Unlock(m_mutex);
- }
- void wait() {
- NdbCondition_Wait(m_cond, m_mutex);
- }
- void signal() {
- NdbCondition_Signal(m_cond);
- }
- void join() {
- NdbThread_WaitFor(m_thr, &m_status);
- m_thr = 0;
- }
- // called from main
- void mainStart(const Case& cc) {
- lock();
- m_case = &cc;
- m_state = Run;
- signal();
- unlock();
- }
- void mainStop() {
- lock();
- while (m_state != Done) {
- if (opt.m_v >= 4)
- ndbout << ::lock << "thr " << m_no << " [main] wait state=" << m_state << endl << ::unlock;
- wait();
- }
- if (opt.m_v >= 4)
- ndbout << ::lock << "thr " << m_no << " [main] done" << endl << ::unlock;
- m_state = Wait;
- unlock();
- }
- // run in thread
- void testSelf() {
- while (1) {
- lock();
- while (m_state != Run && m_state != Exit) {
- if (opt.m_v >= 4)
- ndbout << ::lock << "thr " << m_no << " [self] wait state=" << m_state << endl << ::unlock;
- wait();
- }
- if (m_state == Run) {
- if (opt.m_v >= 4)
- ndbout << ::lock << "thr " << m_no << " [self] run" << endl << ::unlock;
- assert(m_case != 0);
- m_test.timerOn();
- m_test.runCase(*m_case);
- m_test.timerOff();
- m_state = Done;
- if (opt.m_v >= 4)
- ndbout << ::lock << "thr " << m_no << " [self] done" << endl << ::unlock;
- signal();
- unlock();
- } else if (m_state == Exit) {
- unlock();
- break;
- } else {
- assert(false);
- }
- }
- if (opt.m_v >= 4)
- ndbout << ::lock << "thr " << m_no << " [self] exit" << endl << ::unlock;
- }
- };
- static void*
- testThr(void* arg)
- {
- Thr& thr = *(Thr*)arg;
- thr.testSelf();
- return 0;
- }
- #ifdef DMALLOC
- extern "C" {
- static int malloc_bytes = 0;
- static int free_bytes = 0;
- static void
- 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)
- {
- if (func_id == DMALLOC_FUNC_MALLOC) {
- malloc_bytes += byte_size;
- return;
- }
- if (func_id == DMALLOC_FUNC_FREE) {
- DMALLOC_SIZE size = 0;
- dmalloc_examine(old_addr, &size, 0, 0, 0);
- free_bytes += size;
- // XXX useless - byte_size and size are 0
- return;
- }
- }
- }
- #endif /* DMALLOC */
- static void
- testMain()
- {
- #ifndef NDB_LINUX /* valgrind-1.0.3 does not support */
- NdbThread_SetConcurrencyLevel(opt.m_threads + 2);
- #endif
- #ifdef DMALLOC
- dmalloc_track(malloc_track);
- #endif
- Test test(0, 0);
- #ifdef ndbODBC
- Ndb* ndb = 0;
- if (1) { // pre-alloc one Ndb object
- ndb = new Ndb("TEST_DB");
- ndb->init();
- if (ndb->waitUntilReady() != 0) {
- ndbout << ndb->getNdbError() << endl;
- fatal("waitUntilReady");
- }
- }
- #endif
- for (unsigned loop = 1; opt.m_loop == 0 || loop <= opt.m_loop; loop++) {
- if (opt.m_v >= 2)
- ndbout << "loop " << loop << endl;
- // create new set of threads in each loop
- Thr** thrList = new Thr* [1 + opt.m_threads];
- for (unsigned n = 1; n <= opt.m_threads; n++) {
- Thr& thr = *(thrList[n] = new Thr(n, loop));
- thr.create();
- if (opt.m_v >= 4)
- ndbout << "thr " << n << " [main] created" << endl;
- }
- #ifdef DMALLOC
- malloc_bytes = free_bytes = 0;
- #endif
- for (unsigned i = 0; i < caseCount; i++) {
- const Case& cc = caseList[i];
- if (! cc.matchcase())
- continue;
- if (opt.m_v >= 2)
- ndbout << "RUN: " << cc.m_name << " - " << cc.m_desc << endl;
- test.timerOn();
- for (unsigned subloop = 1; subloop <= opt.m_subloop; subloop++) {
- my_sema = 0;
- if (opt.m_v >= 3)
- ndbout << "subloop " << subloop << endl;
- if (cc.m_mode == Case::Single) {
- Thr& thr = *thrList[1];
- thr.mainStart(cc);
- thr.mainStop();
- test.timerCnt(thr.m_test);
- } else if (cc.m_mode == Case::Serial) {
- for (unsigned n = 1; n <= opt.m_threads; n++) {
- Thr& thr = *thrList[n];
- thr.mainStart(cc);
- thr.mainStop();
- test.timerCnt(thr.m_test);
- }
- } else if (cc.m_mode == Case::Thread) {
- for (unsigned n = 1; n <= opt.m_threads; n++) {
- Thr& thr = *thrList[n];
- thr.mainStart(cc);
- }
- for (unsigned n = 1; n <= opt.m_threads; n++) {
- Thr& thr = *thrList[n];
- thr.mainStop();
- test.timerCnt(thr.m_test);
- }
- } else {
- assert(false);
- }
- }
- test.timerOff();
- if (opt.m_v >= 1)
- ndbout << cc.m_name << " total " << test << endl;
- }
- #ifdef DMALLOC
- if (opt.m_v >= 9) // XXX useless now
- ndbout << "malloc " << malloc_bytes << " free " << free_bytes << " lost " << malloc_bytes - free_bytes << endl;
- #endif
- // tell threads to exit
- for (unsigned n = 1; n <= opt.m_threads; n++) {
- Thr& thr = *thrList[n];
- thr.lock();
- thr.m_state = Thr::Exit;
- thr.signal();
- thr.unlock();
- if (opt.m_v >= 4)
- ndbout << "thr " << n << " [main] told to exit" << endl;
- }
- for (unsigned n = 1; n <= opt.m_threads; n++) {
- Thr& thr = *thrList[n];
- thr.join();
- if (opt.m_v >= 4)
- ndbout << "thr " << n << " [main] joined" << endl;
- delete &thr;
- }
- delete[] thrList;
- }
- #ifdef ndbODBC
- delete ndb;
- #endif
- }
- static bool
- str2num(const char* arg, const char* str, unsigned* num, unsigned lo = 0, unsigned hi = 0)
- {
- char* end = 0;
- long n = strtol(str, &end, 0);
- if (end == 0 || *end != 0 || n < 0) {
- ndbout << arg << " " << str << " is invalid number" << endl;
- return false;
- }
- if (lo != 0 && n < lo) {
- ndbout << arg << " " << str << " is too small min = " << lo << endl;
- return false;
- }
- if (hi != 0 && n > hi) {
- ndbout << arg << " " << str << " is too large max = " << hi << endl;
- return false;
- }
- *num = n;
- return true;
- }
- NDB_COMMAND(testOdbcDriver, "testOdbcDriver", "testOdbcDriver", "testOdbcDriver", 65535)
- {
- while (++argv, --argc > 0) {
- const char* arg = argv[0];
- if (strcmp(arg, "-case") == 0) {
- if (++argv, --argc > 0) {
- assert(opt.m_namecnt < arraySize(opt.m_name));
- opt.m_name[opt.m_namecnt++] = argv[0];
- if (findCase(argv[0]))
- continue;
- }
- }
- if (strcmp(arg, "-core") == 0) {
- opt.m_core = true;
- continue;
- }
- if (strcmp(arg, "-depth") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_depth))
- continue;
- }
- }
- if (strcmp(arg, "-dsn") == 0) {
- if (++argv, --argc > 0) {
- opt.m_dsn = argv[0];
- continue;
- }
- }
- if (strcmp(arg, "-frob") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_frob))
- continue;
- }
- }
- if (strcmp(arg, "-errs") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_errs))
- continue;
- }
- }
- if (strcmp(arg, "-fragtype") == 0) {
- if (++argv, --argc > 0) {
- opt.m_fragtype = argv[0];
- continue;
- }
- }
- if (strcmp(arg, "-home") == 0) {
- if (++argv, --argc > 0) {
- opt.m_home = argv[0];
- continue;
- }
- }
- if (strcmp(arg, "-loop") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_loop))
- continue;
- }
- }
- if (strcmp(arg, "-nogetd") == 0) {
- opt.m_nogetd = true;
- continue;
- }
- if (strcmp(arg, "-noputd") == 0) {
- opt.m_noputd = true;
- continue;
- }
- if (strcmp(arg, "-nosort") == 0) {
- opt.m_nosort = true;
- continue;
- }
- if (strcmp(arg, "-scale") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_scale))
- continue;
- }
- }
- if (strcmp(arg, "-serial") == 0) {
- opt.m_serial = true;
- continue;
- }
- if (strcmp(arg, "-skip") == 0) {
- if (++argv, --argc > 0) {
- assert(opt.m_skipcnt < arraySize(opt.m_skip));
- opt.m_skip[opt.m_skipcnt++] = argv[0];
- if (findCase(argv[0]))
- continue;
- }
- }
- if (strcmp(arg, "-subloop") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_subloop))
- continue;
- }
- }
- if (strcmp(arg, "-table") == 0) {
- if (++argv, --argc > 0) {
- opt.m_table = argv[0];
- if (findTable())
- continue;
- }
- }
- if (strcmp(arg, "-threads") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_threads, 1, MAX_THR))
- continue;
- }
- }
- if (strcmp(arg, "-trace") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_trace))
- continue;
- }
- }
- if (strcmp(arg, "-v") == 0) {
- if (++argv, --argc > 0) {
- if (str2num(arg, argv[0], &opt.m_v))
- continue;
- }
- }
- if (strncmp(arg, "-v", 2) == 0 && isdigit(arg[2])) {
- if (str2num(arg, &arg[2], &opt.m_v))
- continue;
- }
- printusage();
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
- homeEnv: {
- static char env[1000];
- if (opt.m_home != 0) {
- sprintf(env, "NDB_HOME=%s", opt.m_home);
- putenv(env);
- }
- }
- traceEnv: {
- static char env[40];
- sprintf(env, "NDB_ODBC_TRACE=%u", opt.m_trace);
- putenv(env);
- }
- debugEnv: {
- static char env[40];
- sprintf(env, "NDB_ODBC_DEBUG=%d", 1);
- putenv(env);
- }
- testMain();
- return NDBT_ProgramExit(NDBT_OK);
- }
- // vim: set sw=4: