24 #include <ndb_global.h>
29 #include <NdbTest.hpp>
31 #include <NdbCondition.h>
32 #include <NdbThread.h>
36 #include <NdbSqlUtil.hpp>
37 #include <ndb_version.h>
111 static void printcases();
112 static void printtables();
119 <<
"usage: testOIbasic [options]" << endl
120 <<
" -batch N pk operations in batch [" << d.m_batch <<
"]" << endl
121 <<
" -bound xyz use only these bound types 0-4 [" << d.m_bound <<
"]" << endl
122 <<
" -case abc only given test cases (letters a-z)" << endl
123 <<
" -collsp use strnncollsp instead of strnxfrm" << endl
124 <<
" -cont on error continue to next test case [" << d.m_cont <<
"]" << endl
125 <<
" -core core dump on error [" << d.m_core <<
"]" << endl
126 <<
" -csname S charset or collation [" << d.m_csname <<
"]" << endl
127 <<
" -die nnn exit immediately on NDB error code nnn" << endl
128 <<
" -dups allow duplicate tuples from index scan [" << d.m_dups <<
"]" << endl
129 <<
" -fragtype T fragment type single/small/medium/large" << endl
130 <<
" -index xyz only given index numbers (digits 0-9)" << endl
131 <<
" -loop N loop count full suite 0=forever [" << d.m_loop <<
"]" << endl
132 <<
" -mrrmaxrng N max ranges to supply for MRR scan [" << d.m_mrrmaxrng <<
"]" << endl
133 <<
" -nologging create tables in no-logging mode" << endl
134 <<
" -noverify skip index verifications" << endl
135 <<
" -pctmrr N pct of index scans to use MRR [" << d.m_pctmrr <<
"]" << endl
136 <<
" -pctnull N pct NULL values in nullable column [" << d.m_pctnull <<
"]" << endl
137 <<
" -rows N rows per thread [" << d.m_rows <<
"]" << endl
138 <<
" -samples N samples for some timings (0=all) [" << d.m_samples <<
"]" << endl
139 <<
" -scanbatch N scan batch 0=default [" << d.m_scanbatch <<
"]" << endl
140 <<
" -scanpar N scan parallel 0=default [" << d.m_scanpar <<
"]" << endl
141 <<
" -seed N srandom seed 0=loop number -1=random [" << d.m_seed <<
"]" << endl
142 <<
" -skip abc skip given test cases (letters a-z)" << endl
143 <<
" -sloop N level 2 (sub)loop count [" << d.m_sloop <<
"]" << endl
144 <<
" -ssloop N level 3 (sub)loop count [" << d.m_ssloop <<
"]" << endl
145 <<
" -table xyz only given table numbers (digits 0-9)" << endl
146 <<
" -threads N number of threads [" << d.m_threads <<
"]" << endl
147 <<
" -vN verbosity [" << d.m_v <<
"]" << endl
148 <<
" -h or -help print this help text" << endl
155 static const bool g_store_null_key =
true;
158 static const bool g_compare_null =
true;
160 static const char* hexstr =
"0123456789abcdef";
164 #define random() rand()
165 #define srandom(SEED) srand(SEED)
173 uint
i = random() %
n;
182 int i = random() %
n;
195 return urandom(100) < pct;
199 random_coprime(uint n)
201 uint prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 };
202 uint count =
sizeof(prime) /
sizeof(prime[0]);
206 uint i = urandom(count);
207 if (n % prime[i] != 0)
228 m_start = urandom(n);
229 m_prime = random_coprime(n);
236 return (m_start + m_i++ * m_prime) % m_n;
241 static NdbMutex *ndbout_mutex = NULL;
242 static const char* getthrprefix();
246 if ((n) > g_opt.m_v) break; \
247 if (g_opt.m_msglock) NdbMutex_Lock(ndbout_mutex); \
248 ndbout << getthrprefix(); \
250 ndbout << "line " << __LINE__ << ": "; \
251 ndbout << s << endl; \
252 if (g_opt.m_msglock) NdbMutex_Unlock(ndbout_mutex); \
255 #define LL0(s) LLN(0, s)
256 #define LL1(s) LLN(1, s)
257 #define LL2(s) LLN(2, s)
258 #define LL3(s) LLN(3, s)
259 #define LL4(s) LLN(4, s)
260 #define LL5(s) LLN(5, s)
262 #define HEX(x) hex << (x) << dec
266 #undef CHK // simple check
267 #undef CHKTRY // check with action on fail
268 #undef CHKCON // print NDB API errors on failure
270 #define CHK(x) CHKTRY(x, ;)
272 #define CHKTRY(x, act) \
275 LL0("line " << __LINE__ << ": " << #x << " failed"); \
276 if (g_opt.m_core) abort(); \
281 #define CHKCON(x, con) \
284 LL0("line " << __LINE__ << ": " << #x << " failed"); \
285 (con).printerror(ndbout); \
286 if (g_opt.m_core) abort(); \
302 Con& con()
const { assert(m_con != 0);
return *m_con; }
304 const Tab& tab()
const { assert(m_tab != 0);
return *m_tab; }
306 const ITab& itab()
const { assert(m_itab != 0);
return *m_itab; }
308 Set&
set()
const { assert(m_set != 0);
return *m_set; }
310 Tmr& tmr()
const { assert(m_tmr != 0);
return *m_tmr; }
320 bool m_noindexkeyupdate;
352 m_noindexkeyupdate(
false),
369 usetable(
Par par, uint i)
371 return par.m_table == 0 || strchr(par.m_table,
'0' + i) != 0;
375 useindex(
Par par, uint i)
377 return par.m_index == 0 || strchr(par.m_index,
'0' + i) != 0;
381 thrrow(
Par par, uint j)
383 return par.m_usedthreads * j + par.m_no;
388 isthrrow(
Par par, uint i)
390 return i % par.m_usedthreads == par.m_no;
399 void off(uint cnt = 0);
401 const char* pct(
const Tmr& t1);
402 const char* over(
const Tmr& t1);
414 m_on = m_ms = m_cnt = m_time[0] = m_text[0] = 0;
421 m_on = NdbTick_CurrentMillisecond();
427 NDB_TICKS off = NdbTick_CurrentMillisecond();
428 assert(m_on != 0 && off >= m_on);
438 sprintf(m_time,
"%u ms", (
unsigned)m_ms);
440 sprintf(m_time,
"%u ms per %u ( %u ms per 1000 )", (
unsigned)m_ms, m_cnt, (
unsigned)((1000 * m_ms) / m_cnt));
446 Tmr::pct(
const Tmr& t1)
449 sprintf(m_text,
"%u pct", (
unsigned)((100 * m_ms) / t1.m_ms));
451 sprintf(m_text,
"[cannot measure]");
457 Tmr::over(
const Tmr& t1)
461 sprintf(m_text,
"%u pct", (
unsigned)((100 * (m_ms - t1.m_ms)) / t1.m_ms));
463 sprintf(m_text,
"-%u pct", (
unsigned)((100 * (t1.m_ms - m_ms)) / t1.m_ms));
465 sprintf(m_text,
"[cannot measure]");
472 static const uint maxcsnumber = 512;
473 static const uint maxcharcount = 32;
474 static const uint maxcharsize = 4;
475 static const uint maxxmulsize = 8;
479 uchar m_bytes[maxcharsize];
480 uchar m_xbytes[maxxmulsize * maxcharsize];
487 memset(m_bytes, 0,
sizeof(m_bytes));
488 memset(m_xbytes, 0,
sizeof(m_xbytes));
502 operator<<(NdbOut& out,
const Chs& chs);
507 m_xmul = m_cs->strxfrm_multiply;
510 assert(m_xmul <= maxxmulsize);
511 m_chr =
new Chr [maxcharcount];
517 while (i < maxcharcount) {
518 uchar* bytes = m_chr[
i].m_bytes;
519 uchar* xbytes = m_chr[
i].m_xbytes;
520 uint&
size = m_chr[
i].m_size;
522 size = m_cs->mbminlen + urandom(m_cs->mbmaxlen - m_cs->mbminlen + 1);
523 assert(m_cs->mbminlen <= size && size <= m_cs->mbmaxlen);
525 if (size == m_cs->mbminlen && m_cs->mbminlen < m_cs->mbmaxlen && urandom(5) != 0)
527 for (uint j = 0; j <
size; j++) {
528 bytes[j] = urandom(256);
532 const char* sbytes = (
const char*)bytes;
533 if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes +
size, 1, ¬_used) != size) {
539 for (uint j = 1; j <
size; j++) {
540 if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + j, 1, ¬_used) == j) {
550 memset(xbytes, 0,
sizeof(xbytes));
555 for (uint j = 0; j < (uint)xlen; j++) {
556 if (xbytes[j] != 0) {
567 for (uint j = 0; j <
i; j++) {
568 const Chr& chr = m_chr[j];
569 if (chr.m_size == size && memcmp(chr.m_bytes, bytes, size) == 0) {
580 bool disorder =
true;
584 for (uint i = 1; i < maxcharcount; i++) {
585 uint len =
sizeof(m_chr[
i].m_xbytes);
586 if (memcmp(m_chr[i-1].m_xbytes, m_chr[i].m_xbytes, len) > 0) {
588 m_chr[
i] = m_chr[i-1];
595 LL3(
"inited charset " << *
this <<
" miss=" << miss1 <<
"," << miss2 <<
"," << miss3 <<
"," << miss4 <<
" bubbles=" << bubbles);
604 operator<<(NdbOut& out,
const Chs& chs)
607 out << cs->name <<
"[" << cs->mbminlen <<
"-" << cs->mbmaxlen <<
"," << chs.m_xmul <<
"]";
611 static Chs* cslist[maxcsnumber];
616 for (uint i = 0; i < maxcsnumber; i++) {
630 uint n = urandom(maxcsnumber);
631 cs = get_charset(n, MYF(0));
635 if (cs->state & MY_CS_HIDDEN)
638 if (cs->mbmaxlen != 1 || urandom(5) == 0)
643 if (cslist[cs->number] == 0)
644 cslist[cs->number] =
new Chs(cs);
645 return cslist[cs->number];
659 const struct Tab& m_tab;
671 Col(
const struct Tab& tab, uint num,
const char*
name,
bool pk, Type
type, uint length,
bool nullable,
const Chs* chs);
673 bool equal(
const Col& col2)
const;
674 void wellformed(
const void* addr)
const;
677 Col::Col(
const struct Tab& tab, uint num,
const char*
name,
bool pk, Type
type, uint length,
bool nullable,
const Chs* chs) :
680 m_name(strcpy(new char [strlen(name) + 1], name)),
684 m_bytelength(length * (chs == 0 ? 1 : chs->m_cs->mbmaxlen)),
686 type == Unsigned ? sizeof(Uint32) :
687 type == Char ? sizeof(char) :
688 type == Varchar ? sizeof(char) :
689 type == Longvarchar ? sizeof(char) : ~0),
691 type == Unsigned ? 0 :
693 type == Varchar ? 1 :
694 type == Longvarchar ? 2 : ~0),
695 m_bytesize(m_headsize + m_attrsize * m_bytelength),
696 m_nullable(nullable),
700 if (type == Varchar && m_bytelength > 255) {
701 m_type = Longvarchar;
713 Col::equal(
const Col& col2)
const
715 return m_type == col2.m_type && m_length == col2.m_length && m_chs == col2.m_chs;
719 Col::wellformed(
const void* addr)
const
727 const char* src = (
const char*)addr;
728 uint len = m_bytelength;
731 assert((*cs->cset->well_formed_len)(cs, src, src + len, 0xffff, ¬_used) == len);
737 const uchar* src = (
const uchar*)addr;
738 const char* ssrc = (
const char*)src;
742 assert(len <= m_bytelength);
743 assert((*cs->cset->well_formed_len)(cs, ssrc + 1, ssrc + 1 + len, 0xffff, ¬_used) == len);
746 case Col::Longvarchar:
749 const uchar* src = (
const uchar*)addr;
750 const char* ssrc = (
const char*)src;
751 uint len = src[0] + (src[1] << 8);
754 assert(len <= m_bytelength);
755 assert((*cs->cset->well_formed_len)(cs, ssrc + 2, ssrc + 2 + len, 0xffff, ¬_used) == len);
765 operator<<(NdbOut& out,
const Col& col)
767 out <<
"col[" << col.m_num <<
"] " << col.m_name;
768 switch (col.m_type) {
775 out <<
" char(" << col.m_length <<
"*" << cs->mbmaxlen <<
";" << cs->name <<
")";
781 out <<
" varchar(" << col.m_length <<
"*" << cs->mbmaxlen <<
";" << cs->name <<
")";
784 case Col::Longvarchar:
787 out <<
" longvarchar(" << col.m_length <<
"*" << cs->mbmaxlen <<
";" << cs->name <<
")";
791 out <<
"type" << (int)col.m_type;
795 out << (col.m_pk ?
" pk" :
"");
796 out << (col.m_nullable ?
" nullable" :
"");
803 const struct ITab& m_itab;
806 ICol(
const struct ITab& itab, uint num,
const Col& col);
810 ICol::ICol(
const struct ITab& itab, uint num,
const Col& col) :
822 operator<<(NdbOut& out,
const ICol& icol)
824 out <<
"icol[" << icol.m_num <<
"] " << icol.m_col;
835 const struct Tab& m_tab;
841 ITab(
const struct Tab& tab,
const char* name, Type type, uint icols);
843 void icoladd(uint k,
const ICol* icolptr);
846 ITab::ITab(
const struct Tab& tab,
const char* name, Type type, uint icols) :
848 m_name(strcpy(new char [strlen(name) + 1], name)),
851 m_icol(new const
ICol* [icols + 1]),
854 for (uint k = 0; k <= m_icols; k++)
861 for (uint i = 0; i < m_icols; i++)
867 ITab::icoladd(uint k,
const ICol* icolptr)
869 assert(k == icolptr->m_num && k < m_icols && m_icol[k] == 0);
871 m_keymask |= (1 << icolptr->m_col.m_num);
875 operator<<(NdbOut& out,
const ITab& itab)
877 out <<
"itab " << itab.m_name <<
" icols=" << itab.m_icols;
878 for (uint k = 0; k < itab.m_icols; k++) {
879 const ICol& icol = *itab.m_icol[k];
894 uint m_orderedindexes;
898 void coladd(uint k,
Col* colptr);
899 void itabadd(uint j,
ITab* itab);
900 Tab(
const char* name, uint cols, uint itabs, uint keycol);
904 Tab::Tab(
const char* name, uint cols, uint itabs, uint keycol) :
905 m_name(strcpy(new char [strlen(name) + 1], name)),
907 m_col(new const
Col* [cols + 1]),
910 m_itab(new const
ITab* [itabs + 1]),
915 for (uint k = 0; k <= cols; k++)
917 for (uint j = 0; j <= itabs; j++)
924 for (uint i = 0; i < m_cols; i++)
927 for (uint i = 0; i < m_itabs; i++)
933 Tab::coladd(uint k,
Col* colptr)
935 assert(k == colptr->m_num && k < m_cols && m_col[k] == 0);
938 m_pkmask |= (1 << k);
942 Tab::itabadd(uint j,
ITab* itabptr)
944 assert(j < m_itabs && m_itab[j] == 0 && itabptr != 0);
946 if (itabptr->m_type == ITab::OrderedIndex)
953 operator<<(NdbOut& out,
const Tab& tab)
955 out <<
"tab " << tab.m_name <<
" cols=" << tab.m_cols;
956 for (uint k = 0; k < tab.m_cols; k++) {
957 const Col& col = *tab.m_col[k];
960 for (uint i = 0; i < tab.m_itabs; i++) {
961 if (tab.m_itab[i] == 0)
963 const ITab& itab = *tab.m_itab[
i];
971 static const Tab** tablist = 0;
972 static uint tabcount = 0;
977 for (uint j = 0; j < tabcount; j++) {
978 const Tab* t = tablist[j];
981 assert(t->m_cols != 0 && t->m_col != 0);
982 for (uint k = 0; k < t->m_cols; k++) {
983 const Col* c = t->m_col[k];
984 assert(c != 0 && c->m_num == k);
985 assert(!(c->m_pk && c->m_nullable));
987 assert(t->m_col[t->m_cols] == 0);
989 assert(t->m_keycol < t->m_cols);
990 const Col* c = t->m_col[t->m_keycol];
991 assert(c->m_pk && c->m_type == Col::Unsigned);
993 assert(t->m_itabs != 0 && t->m_itab != 0);
994 for (uint i = 0; i < t->m_itabs; i++) {
995 const ITab* x = t->m_itab[
i];
998 assert(x != 0 && x->m_icols != 0 && x->m_icol != 0);
999 for (uint k = 0; k < x->m_icols; k++) {
1000 const ICol* c = x->m_icol[k];
1001 assert(c != 0 && c->m_num == k && c->m_col.m_num < t->m_cols);
1002 if (x->m_type == ITab::UniqueHashIndex) {
1003 assert(!c->m_col.m_nullable);
1007 assert(t->m_itab[t->m_itabs] == 0);
1012 makebuiltintables(
Par par)
1014 LL2(
"makebuiltintables");
1018 tablist =
new const Tab* [tabcount];
1019 for (uint j = 0; j < tabcount; j++) {
1023 for (uint j = 0; j < tabcount; j++) {
1029 if (usetable(par, 0)) {
1030 Tab* t =
new Tab(
"ti0", 5, 7, 0);
1032 t->coladd(0,
new Col(*t, 0,
"a", 1, Col::Unsigned, 1, 0, 0));
1033 t->coladd(1,
new Col(*t, 1,
"b", 0, Col::Unsigned, 1, 1, 0));
1034 t->coladd(2,
new Col(*t, 2,
"c", 0, Col::Unsigned, 1, 0, 0));
1035 t->coladd(3,
new Col(*t, 3,
"d", 0, Col::Unsigned, 1, 1, 0));
1036 t->coladd(4,
new Col(*t, 4,
"e", 0, Col::Unsigned, 1, 0, 0));
1037 if (useindex(par, 0)) {
1039 ITab* x =
new ITab(*t,
"ti0x0", ITab::OrderedIndex, 1);
1040 x->icoladd(0,
new ICol(*x, 0, *t->m_col[0]));
1043 if (useindex(par, 1)) {
1045 ITab* x =
new ITab(*t,
"ti0x1", ITab::OrderedIndex, 1);
1046 x->icoladd(0,
new ICol(*x, 0, *t->m_col[1]));
1049 if (useindex(par, 2)) {
1051 ITab* x =
new ITab(*t,
"ti0x2", ITab::OrderedIndex, 2);
1052 x->icoladd(0,
new ICol(*x, 0, *t->m_col[1]));
1053 x->icoladd(1,
new ICol(*x, 1, *t->m_col[2]));
1056 if (useindex(par, 3)) {
1058 ITab* x =
new ITab(*t,
"ti0x3", ITab::OrderedIndex, 4);
1059 x->icoladd(0,
new ICol(*x, 0, *t->m_col[1]));
1060 x->icoladd(1,
new ICol(*x, 1, *t->m_col[4]));
1061 x->icoladd(2,
new ICol(*x, 2, *t->m_col[2]));
1062 x->icoladd(3,
new ICol(*x, 3, *t->m_col[3]));
1065 if (useindex(par, 4)) {
1067 ITab* x =
new ITab(*t,
"ti0z4", ITab::UniqueHashIndex, 2);
1068 x->icoladd(0,
new ICol(*x, 0, *t->m_col[0]));
1069 x->icoladd(1,
new ICol(*x, 1, *t->m_col[2]));
1072 if (useindex(par, 5)) {
1074 ITab* x =
new ITab(*t,
"ti0z5", ITab::UniqueHashIndex, 2);
1075 x->icoladd(0,
new ICol(*x, 0, *t->m_col[0]));
1076 x->icoladd(1,
new ICol(*x, 1, *t->m_col[4]));
1082 if (usetable(par, 1)) {
1083 Tab* t =
new Tab(
"ti1", 5, 7, 1);
1085 t->coladd(0,
new Col(*t, 0,
"a", 0, Col::Unsigned, 1, 0, 0));
1086 t->coladd(1,
new Col(*t, 1,
"b", 1, Col::Unsigned, 1, 0, 0));
1087 t->coladd(2,
new Col(*t, 2,
"c", 0, Col::Varchar, 20, 0, getcs(par)));
1088 t->coladd(3,
new Col(*t, 3,
"d", 0, Col::Char, 5, 0, getcs(par)));
1089 t->coladd(4,
new Col(*t, 4,
"e", 0, Col::Longvarchar, 5, 1, getcs(par)));
1090 if (useindex(par, 0)) {
1092 ITab* x =
new ITab(*t,
"ti1x0", ITab::OrderedIndex, 1);
1093 x->icoladd(0,
new ICol(*x, 0, *t->m_col[1]));
1096 if (useindex(par, 1)) {
1098 ITab* x =
new ITab(*t,
"ti1x1", ITab::OrderedIndex, 2);
1099 x->icoladd(0,
new ICol(*x, 0, *t->m_col[2]));
1100 x->icoladd(1,
new ICol(*x, 1, *t->m_col[0]));
1103 if (useindex(par, 2)) {
1105 ITab* x =
new ITab(*t,
"ti1x2", ITab::OrderedIndex, 1);
1106 x->icoladd(0,
new ICol(*x, 0, *t->m_col[3]));
1109 if (useindex(par, 3)) {
1111 ITab* x =
new ITab(*t,
"ti1x3", ITab::OrderedIndex, 4);
1112 x->icoladd(0,
new ICol(*x, 0, *t->m_col[4]));
1113 x->icoladd(1,
new ICol(*x, 1, *t->m_col[3]));
1114 x->icoladd(2,
new ICol(*x, 2, *t->m_col[2]));
1115 x->icoladd(3,
new ICol(*x, 3, *t->m_col[1]));
1118 if (useindex(par, 4)) {
1120 ITab* x =
new ITab(*t,
"ti1z4", ITab::UniqueHashIndex, 2);
1121 x->icoladd(0,
new ICol(*x, 0, *t->m_col[0]));
1122 x->icoladd(1,
new ICol(*x, 1, *t->m_col[1]));
1125 if (useindex(par, 5)) {
1127 ITab* x =
new ITab(*t,
"ti1z5", ITab::UniqueHashIndex, 3);
1128 x->icoladd(0,
new ICol(*x, 0, *t->m_col[1]));
1129 x->icoladd(1,
new ICol(*x, 1, *t->m_col[2]));
1130 x->icoladd(2,
new ICol(*x, 2, *t->m_col[3]));
1136 if (usetable(par, 2)) {
1137 Tab* t =
new Tab(
"ti2", 5, 7, 2);
1139 t->coladd(0,
new Col(*t, 0,
"a", 1, Col::Char, 31, 0, getcs(par)));
1140 t->coladd(1,
new Col(*t, 1,
"b", 0, Col::Char, 4, 1, getcs(par)));
1141 t->coladd(2,
new Col(*t, 2,
"c", 1, Col::Unsigned, 1, 0, 0));
1142 t->coladd(3,
new Col(*t, 3,
"d", 1, Col::Varchar, 128, 0, getcs(par)));
1143 t->coladd(4,
new Col(*t, 4,
"e", 0, Col::Varchar, 7, 0, getcs(par)));
1144 if (useindex(par, 0)) {
1146 ITab* x =
new ITab(*t,
"ti2x0", ITab::OrderedIndex, 3);
1147 x->icoladd(0,
new ICol(*x, 0, *t->m_col[0]));
1148 x->icoladd(1,
new ICol(*x, 1, *t->m_col[2]));
1149 x->icoladd(2,
new ICol(*x, 2, *t->m_col[3]));
1152 if (useindex(par, 1)) {
1154 ITab* x =
new ITab(*t,
"ti2x1", ITab::OrderedIndex, 5);
1155 x->icoladd(0,
new ICol(*x, 0, *t->m_col[4]));
1156 x->icoladd(1,
new ICol(*x, 1, *t->m_col[3]));
1157 x->icoladd(2,
new ICol(*x, 2, *t->m_col[2]));
1158 x->icoladd(3,
new ICol(*x, 3, *t->m_col[1]));
1159 x->icoladd(4,
new ICol(*x, 4, *t->m_col[0]));
1162 if (useindex(par, 2)) {
1164 ITab* x =
new ITab(*t,
"ti2x2", ITab::OrderedIndex, 1);
1165 x->icoladd(0,
new ICol(*x, 0, *t->m_col[3]));
1168 if (useindex(par, 3)) {
1170 ITab* x =
new ITab(*t,
"ti2x3", ITab::OrderedIndex, 1);
1171 x->icoladd(0,
new ICol(*x, 0, *t->m_col[1]));
1174 if (useindex(par, 4)) {
1176 ITab* x =
new ITab(*t,
"ti2z4", ITab::UniqueHashIndex, 2);
1177 x->icoladd(0,
new ICol(*x, 0, *t->m_col[0]));
1178 x->icoladd(1,
new ICol(*x, 1, *t->m_col[2]));
1181 if (useindex(par, 5)) {
1183 ITab* x =
new ITab(*t,
"ti2z5", ITab::UniqueHashIndex, 4);
1184 x->icoladd(0,
new ICol(*x, 0, *t->m_col[0]));
1185 x->icoladd(1,
new ICol(*x, 1, *t->m_col[2]));
1186 x->icoladd(2,
new ICol(*x, 2, *t->m_col[3]));
1187 x->icoladd(3,
new ICol(*x, 3, *t->m_col[4]));
1209 enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive };
1210 ScanMode m_scanmode;
1218 char m_errname[100];
1220 m_ndb(0), m_dic(0), m_tx(0), m_txid(0), m_op(0), m_indexop(0),
1221 m_scanop(0), m_indexscanop(0), m_scanfilter(0),
1222 m_scanmode(ScanNo), m_errtype(ErrNone) {}
1228 void connect(
const Con& con);
1230 int startTransaction();
1231 int getNdbOperation(
const Tab& tab);
1232 int getNdbIndexOperation1(
const ITab& itab,
const Tab& tab);
1233 int getNdbIndexOperation(
const ITab& itab,
const Tab& tab);
1234 int getNdbScanOperation(
const Tab& tab);
1235 int getNdbIndexScanOperation1(
const ITab& itab,
const Tab& tab);
1236 int getNdbIndexScanOperation(
const ITab& itab,
const Tab& tab);
1237 int getNdbScanFilter();
1238 int equal(
int num,
const char* addr);
1240 int setValue(
int num,
const char* addr);
1241 int setBound(
int num,
int type,
const void* value);
1242 int beginFilter(
int group);
1244 int setFilter(
int num,
int cond,
const void* value, uint len);
1245 int execute(ExecType et);
1246 int execute(ExecType et, uint& err);
1247 int readTuple(
Par par);
1248 int readTuples(
Par par);
1249 int readIndexTuples(
Par par);
1251 int nextScanResult(
bool fetchAllowed);
1252 int nextScanResult(
bool fetchAllowed, uint& err);
1253 int updateScanTuple(
Con& con2);
1254 int deleteScanTuple(
Con& con2);
1256 void closeTransaction();
1257 const char* errname(uint err);
1258 void printerror(NdbOut& out);
1265 m_ndb =
new Ndb(g_ncc,
"TEST_DB");
1266 CHKCON(m_ndb->
init() == 0, *
this);
1268 m_tx = 0, m_txid = 0, m_op = 0;
1273 Con::connect(
const Con& con)
1283 m_ndb = 0, m_dic = 0, m_tx = 0, m_txid = 0, m_op = 0;
1287 Con::startTransaction()
1298 Con::getNdbOperation(
const Tab& tab)
1306 Con::getNdbIndexOperation1(
const ITab& itab,
const Tab& tab)
1314 Con::getNdbIndexOperation(
const ITab& itab,
const Tab& tab)
1319 if (getNdbIndexOperation1(itab, tab) == 0)
1322 NdbSleep_MilliSleep(100);
1328 Con::getNdbScanOperation(
const Tab& tab)
1336 Con::getNdbIndexScanOperation1(
const ITab& itab,
const Tab& tab)
1344 Con::getNdbIndexScanOperation(
const ITab& itab,
const Tab& tab)
1349 if (getNdbIndexScanOperation1(itab, tab) == 0)
1352 NdbSleep_MilliSleep(100);
1358 Con::getNdbScanFilter()
1360 assert(m_tx != 0 && m_scanop != 0);
1361 delete m_scanfilter;
1367 Con::equal(
int num,
const char* addr)
1369 assert(m_tx != 0 && m_op != 0);
1370 CHKCON(m_op->
equal(num, addr) == 0, *
this);
1377 assert(m_tx != 0 && m_op != 0);
1378 CHKCON((rec = m_op->
getValue(num, 0)) != 0, *
this);
1383 Con::setValue(
int num,
const char* addr)
1385 assert(m_tx != 0 && m_op != 0);
1386 CHKCON(m_op->
setValue(num, addr) == 0, *
this);
1391 Con::setBound(
int num,
int type,
const void* value)
1393 assert(m_tx != 0 && m_indexscanop != 0);
1394 CHKCON(m_indexscanop->
setBound(num, type, value) == 0, *
this);
1399 Con::beginFilter(
int group)
1401 assert(m_tx != 0 && m_scanfilter != 0);
1409 assert(m_tx != 0 && m_scanfilter != 0);
1410 CHKCON(m_scanfilter->
end() == 0, *
this);
1415 Con::setFilter(
int num,
int cond,
const void* value, uint len)
1417 assert(m_tx != 0 && m_scanfilter != 0);
1423 Con::execute(ExecType et)
1426 CHKCON(m_tx->
execute(et) == 0, *
this);
1431 Con::execute(ExecType et, uint& err)
1433 int ret = execute(et);
1435 const uint errin = err;
1438 if (m_errtype == ErrDeadlock && (errin & ErrDeadlock)) {
1439 LL3(
"caught deadlock");
1443 if (m_errtype == ErrNospace && (errin & ErrNospace)) {
1444 LL3(
"caught nospace");
1454 Con::readTuple(
Par par)
1456 assert(m_tx != 0 && m_op != 0);
1458 CHKCON(m_op->
readTuple(lm) == 0, *
this);
1463 Con::readTuples(
Par par)
1465 assert(m_tx != 0 && m_scanop != 0);
1468 scan_flags |= NdbScanOperation::SF_TupScan;
1469 CHKCON(m_scanop->
readTuples(par.m_lockmode, scan_flags, par.m_scanpar, par.m_scanbatch) == 0, *
this);
1474 Con::readIndexTuples(
Par par)
1476 assert(m_tx != 0 && m_indexscanop != 0);
1479 scan_flags |= NdbScanOperation::SF_OrderBy;
1480 if (par.m_descending)
1481 scan_flags |= NdbScanOperation::SF_Descending;
1482 if (par.m_multiRange)
1484 scan_flags |= NdbScanOperation::SF_MultiRange;
1485 scan_flags |= NdbScanOperation::SF_ReadRangeNo;
1487 CHKCON(m_indexscanop->
readTuples(par.m_lockmode, scan_flags, par.m_scanpar, par.m_scanbatch) == 0, *
this);
1494 CHKCON(m_tx->
execute(NoCommit) == 0, *
this);
1499 Con::nextScanResult(
bool fetchAllowed)
1502 assert(m_scanop != 0);
1503 CHKCON((ret = m_scanop->
nextResult(fetchAllowed)) != -1, *
this);
1504 assert(ret == 0 || ret == 1 || (!fetchAllowed && ret == 2));
1509 Con::nextScanResult(
bool fetchAllowed, uint& err)
1511 int ret = nextScanResult(fetchAllowed);
1513 const uint errin = err;
1516 if (m_errtype == ErrDeadlock && (errin & ErrDeadlock)) {
1517 LL3(
"caught deadlock");
1522 CHK(ret == 0 || ret == 1 || (!fetchAllowed && ret == 2));
1527 Con::updateScanTuple(
Con& con2)
1529 assert(con2.m_tx != 0);
1531 con2.m_txid = m_txid;
1536 Con::deleteScanTuple(
Con& con2)
1538 assert(con2.m_tx != 0);
1540 con2.m_txid = m_txid;
1547 assert(m_scanop != 0);
1549 m_scanop = 0, m_indexscanop = 0;
1554 Con::closeTransaction()
1556 assert(m_ndb != 0 && m_tx != 0);
1558 m_tx = 0, m_txid = 0, m_op = 0;
1559 m_scanop = 0, m_indexscanop = 0;
1563 Con::errname(uint err)
1565 sprintf(m_errname,
"0x%x", err);
1566 if (err & ErrDeadlock)
1567 strcat(m_errname,
",deadlock");
1568 if (err & ErrNospace)
1569 strcat(m_errname,
",nospace");
1574 Con::printerror(NdbOut& out)
1576 m_errtype = ErrOther;
1582 LL0(++any <<
" ndb: error " << m_ndb->
getNdbError());
1583 die += (code == g_opt.m_die);
1586 LL0(++any <<
" dic: error " << m_dic->
getNdbError());
1587 die += (code == g_opt.m_die);
1591 LL0(++any <<
" con: error " << m_tx->
getNdbError());
1592 die += (code == g_opt.m_die);
1594 if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499 || code == 631)
1595 m_errtype = ErrDeadlock;
1596 if (code == 826 || code == 827 || code == 902)
1597 m_errtype = ErrNospace;
1600 LL0(++any <<
" op : error " << m_op->
getNdbError());
1601 die += (code == g_opt.m_die);
1606 LL0(
"failed but no NDB error code");
1618 invalidateindex(
Par par,
const ITab& itab)
1620 Con& con = par.con();
1621 const Tab& tab = par.tab();
1627 invalidateindex(
Par par)
1629 const Tab& tab = par.tab();
1630 for (uint i = 0; i < tab.m_itabs; i++) {
1631 if (tab.m_itab[i] == 0)
1633 const ITab& itab = *tab.m_itab[
i];
1634 invalidateindex(par, itab);
1640 invalidatetable(
Par par)
1642 Con& con = par.con();
1643 const Tab& tab = par.tab();
1644 invalidateindex(par);
1652 Con& con = par.con();
1653 const Tab& tab = par.tab();
1655 if (con.m_dic->
getTable(tab.m_name) == 0) {
1657 LL4(
"no table " << tab.m_name);
1659 LL3(
"drop table " << tab.m_name);
1660 CHKCON(con.m_dic->
dropTable(tab.m_name) == 0, con);
1667 createtable(
Par par)
1669 Con& con = par.con();
1670 const Tab& tab = par.tab();
1671 LL3(
"create table " << tab.m_name);
1675 t.setFragmentType(par.m_fragtype);
1677 if (par.m_nologging) {
1678 t.setLogging(
false);
1680 for (uint k = 0; k < tab.m_cols; k++) {
1681 const Col& col = *tab.m_col[k];
1684 c.setLength(col.m_bytelength);
1685 c.setPrimaryKey(col.m_pk);
1686 c.setNullable(col.m_nullable);
1688 c.setCharset(col.m_chs->m_cs);
1698 dropindex(
Par par,
const ITab& itab)
1700 Con& con = par.con();
1701 const Tab& tab = par.tab();
1703 if (con.m_dic->
getIndex(itab.m_name, tab.m_name) == 0) {
1705 LL4(
"no index " << itab.m_name);
1707 LL3(
"drop index " << itab.m_name);
1708 CHKCON(con.m_dic->
dropIndex(itab.m_name, tab.m_name) == 0, con);
1717 const Tab& tab = par.tab();
1718 for (uint i = 0; i < tab.m_itabs; i++) {
1719 if (tab.m_itab[i] == 0)
1721 const ITab& itab = *tab.m_itab[
i];
1722 CHK(dropindex(par, itab) == 0);
1728 createindex(
Par par,
const ITab& itab)
1730 Con& con = par.con();
1731 const Tab& tab = par.tab();
1732 LL3(
"create index " << itab.m_name);
1735 x.setTable(tab.m_name);
1737 if (par.m_nologging || itab.m_type == ITab::OrderedIndex) {
1738 x.setLogging(
false);
1740 for (uint k = 0; k < itab.m_icols; k++) {
1741 const ICol& icol = *itab.m_icol[k];
1742 const Col& col = icol.m_col;
1743 x.addColumnName(col.m_name);
1752 createindex(
Par par)
1754 const Tab& tab = par.tab();
1755 for (uint i = 0; i < tab.m_itabs; i++) {
1756 if (tab.m_itab[i] == 0)
1758 const ITab& itab = *tab.m_itab[
i];
1759 CHK(createindex(par, itab) == 0);
1774 uchar* m_longvarchar;
1780 void copy(
const Val& val2);
1781 void copy(
const void* addr);
1782 const void* dataaddr()
const;
1783 void calc(
Par par, uint i);
1784 void calckey(
Par par, uint i);
1785 void calckeychars(
Par par, uint i, uint& n, uchar*
buf);
1786 void calcnokey(
Par par);
1787 void calcnokeychars(
Par par, uint& n, uchar*
buf);
1789 int setval(
Par par)
const;
1790 int setval(
Par par,
const ICol& icol)
const;
1792 int cmp(
Par par,
const Val& val2)
const;
1793 int cmpchars(
Par par,
const uchar* buf1, uint len1,
const uchar* buf2, uint len2)
const;
1794 int verify(
Par par,
const Val& val2)
const;
1796 Val& operator=(
const Val& val2);
1800 operator<<(NdbOut& out,
const Val& val);
1804 Val::Val(
const Col& col) :
1807 switch (col.m_type) {
1809 m_uint32 = 0x7e7e7e7e;
1812 m_char =
new uchar [col.m_bytelength];
1813 memset(m_char, 0x7e, col.m_bytelength);
1816 m_varchar =
new uchar [1 + col.m_bytelength];
1817 memset(m_char, 0x7e, 1 + col.m_bytelength);
1819 case Col::Longvarchar:
1820 m_longvarchar =
new uchar [2 + col.m_bytelength];
1821 memset(m_char, 0x7e, 2 + col.m_bytelength);
1831 const Col& col = m_col;
1832 switch (col.m_type) {
1839 delete [] m_varchar;
1841 case Col::Longvarchar:
1842 delete [] m_longvarchar;
1851 Val::copy(
const Val& val2)
1853 const Col& col = m_col;
1854 const Col& col2 = val2.m_col;
1855 assert(col.m_type == col2.m_type && col.m_length == col2.m_length);
1860 copy(val2.dataaddr());
1864 Val::copy(
const void* addr)
1866 const Col& col = m_col;
1867 switch (col.m_type) {
1869 m_uint32 = *(
const Uint32*)addr;
1872 memcpy(m_char, addr, col.m_bytelength);
1875 memcpy(m_varchar, addr, 1 + col.m_bytelength);
1877 case Col::Longvarchar:
1878 memcpy(m_longvarchar, addr, 2 + col.m_bytelength);
1888 Val::dataaddr()
const
1890 const Col& col = m_col;
1891 switch (col.m_type) {
1898 case Col::Longvarchar:
1899 return m_longvarchar;
1908 Val::calc(
Par par, uint i)
1910 const Col& col = m_col;
1911 col.m_pk ? calckey(par, i) : calcnokey(par);
1913 col.wellformed(dataaddr());
1917 Val::calckey(
Par par, uint i)
1919 const Col& col = m_col;
1921 switch (col.m_type) {
1927 const Chs* chs = col.m_chs;
1930 calckeychars(par, i, n, m_char);
1932 (*cs->cset->fill)(cs, (
char*)&m_char[
n], col.m_bytelength -
n, 0x20);
1938 calckeychars(par, i, n, m_varchar + 1);
1941 memset(&m_varchar[1 + n], 0, col.m_bytelength - n);
1944 case Col::Longvarchar:
1947 calckeychars(par, i, n, m_longvarchar + 2);
1949 m_longvarchar[0] = (n & 0xff);
1950 m_longvarchar[1] = (n >> 8);
1951 memset(&m_longvarchar[2 + n], 0, col.m_bytelength - n);
1961 Val::calckeychars(
Par par, uint i, uint& n, uchar*
buf)
1963 const Col& col = m_col;
1964 const Chs* chs = col.m_chs;
1967 while (len < col.m_length) {
1968 if (i % (1 + n) == 0) {
1971 const Chr& chr = chs->m_chr[i % maxcharcount];
1972 assert(n + chr.m_size <= col.m_bytelength);
1973 memcpy(buf + n, chr.m_bytes, chr.m_size);
1980 Val::calcnokey(
Par par)
1982 const Col& col = m_col;
1984 if (col.m_nullable && urandom(100) < par.m_pctnull) {
1988 int r = irandom((par.m_pctrange * par.m_range) / 100);
1989 if (par.m_bdir != 0 && urandom(10) != 0) {
1990 if ((r < 0 && par.m_bdir > 0) || (r > 0 && par.m_bdir < 0))
1993 uint v = par.m_range + r;
1994 switch (col.m_type) {
2000 const Chs* chs = col.m_chs;
2003 calcnokeychars(par, n, m_char);
2005 (*cs->cset->fill)(cs, (
char*)&m_char[
n], col.m_bytelength -
n, 0x20);
2011 calcnokeychars(par, n, m_varchar + 1);
2014 memset(&m_varchar[1 + n], 0, col.m_bytelength - n);
2017 case Col::Longvarchar:
2020 calcnokeychars(par, n, m_longvarchar + 2);
2022 m_longvarchar[0] = (n & 0xff);
2023 m_longvarchar[1] = (n >> 8);
2024 memset(&m_longvarchar[2 + n], 0, col.m_bytelength - n);
2034 Val::calcnokeychars(
Par par, uint& n, uchar* buf)
2036 const Col& col = m_col;
2037 const Chs* chs = col.m_chs;
2040 while (len < col.m_length) {
2041 if (urandom(1 + col.m_bytelength) == 0) {
2044 uint half = maxcharcount / 2;
2045 int r = irandom((par.m_pctrange * half) / 100);
2046 if (par.m_bdir != 0 && urandom(10) != 0) {
2047 if ((r < 0 && par.m_bdir > 0) || (r > 0 && par.m_bdir < 0))
2051 assert(i < maxcharcount);
2052 const Chr& chr = chs->m_chr[
i];
2053 assert(n + chr.m_size <= col.m_bytelength);
2054 memcpy(buf + n, chr.m_bytes, chr.m_size);
2063 Val::setval(
Par par)
const
2065 Con& con = par.con();
2066 const Col& col = m_col;
2069 const char* addr = (
const char*)dataaddr();
2070 LL5(
"setval pk [" << col <<
"] " << *
this);
2071 CHK(con.equal(col.m_num, addr) == 0);
2073 const char* addr = !m_null ? (
const char*)dataaddr() : 0;
2074 LL5(
"setval non-pk [" << col <<
"] " << *
this);
2075 CHK(con.setValue(col.m_num, addr) == 0);
2081 Val::setval(
Par par,
const ICol& icol)
const
2083 Con& con = par.con();
2085 const char* addr = (
const char*)dataaddr();
2086 LL5(
"setval key [" << icol <<
"] " << *
this);
2087 CHK(con.equal(icol.m_num, addr) == 0);
2094 Val::cmp(
Par par,
const Val& val2)
const
2096 const Col& col = m_col;
2097 const Col& col2 = val2.m_col;
2098 assert(col.equal(col2));
2099 if (m_null || val2.m_null) {
2107 col.wellformed(dataaddr());
2108 col.wellformed(val2.dataaddr());
2110 switch (col.m_type) {
2113 if (m_uint32 < val2.m_uint32)
2115 if (m_uint32 > val2.m_uint32)
2122 uint len = col.m_bytelength;
2123 return cmpchars(par, m_char, len, val2.m_char, len);
2128 uint len1 = m_varchar[0];
2129 uint len2 = val2.m_varchar[0];
2130 return cmpchars(par, m_varchar + 1, len1, val2.m_varchar + 1, len2);
2133 case Col::Longvarchar:
2135 uint len1 = m_longvarchar[0] + (m_longvarchar[1] << 8);
2136 uint len2 = val2.m_longvarchar[0] + (val2.m_longvarchar[1] << 8);
2137 return cmpchars(par, m_longvarchar + 2, len1, val2.m_longvarchar + 2, len2);
2148 Val::cmpchars(
Par par,
const uchar* buf1, uint len1,
const uchar* buf2, uint len2)
const
2150 const Col& col = m_col;
2151 const Chs* chs = col.m_chs;
2154 if (!par.m_collsp) {
2155 uchar x1[maxxmulsize * NDB_MAX_TUPLE_SIZE];
2156 uchar x2[maxxmulsize * NDB_MAX_TUPLE_SIZE];
2158 uint len = maxxmulsize * col.m_bytelength;
2161 assert(n1 != -1 && n1 == n2);
2162 k = memcmp(x1, x2, n1);
2164 k = (*cs->coll->strnncollsp)(cs, buf1, len1, buf2, len2,
false);
2166 return k < 0 ? -1 : k > 0 ? +1 : 0;
2170 Val::verify(
Par par,
const Val& val2)
const
2172 CHK(cmp(par, val2) == 0);
2179 printstring(NdbOut& out,
const uchar* str, uint len,
bool showlen)
2181 char buf[4 * NDB_MAX_TUPLE_SIZE];
2185 sprintf(p,
"%u:", len);
2188 for (uint i = 0; i < len; i++) {
2193 }
else if (0x20 <= c && c <= 0x7e) {
2197 *p++ = hexstr[c >> 4];
2198 *p++ = hexstr[c & 15];
2207 operator<<(NdbOut& out,
const Val& val)
2209 const Col& col = val.m_col;
2214 switch (col.m_type) {
2216 out << val.m_uint32;
2220 uint len = col.m_bytelength;
2221 printstring(out, val.m_char, len,
false);
2226 uint len = val.m_varchar[0];
2227 printstring(out, val.m_varchar + 1, len,
true);
2230 case Col::Longvarchar:
2232 uint len = val.m_longvarchar[0] + (val.m_longvarchar[1] << 8);
2233 printstring(out, val.m_longvarchar + 2, len,
true);
2237 out <<
"type" << col.m_type;
2264 OpREAD = 16 | 32 | 64
2273 void copy(
const Row& row2,
bool copy_bi);
2274 void copyval(
const Row& row2, uint colmask = ~0);
2275 void calc(
Par par, uint i, uint colmask = ~0);
2277 int setval(
Par par, uint colmask = ~0);
2278 int setval(
Par par,
const ITab& itab);
2279 int insrow(
Par par);
2280 int updrow(
Par par);
2281 int updrow(
Par par,
const ITab& itab);
2282 int delrow(
Par par);
2283 int delrow(
Par par,
const ITab& itab);
2284 int selrow(
Par par);
2285 int selrow(
Par par,
const ITab& itab);
2286 int setrow(
Par par);
2288 int cmp(
Par par,
const Row& row2)
const;
2289 int cmp(
Par par,
const Row& row2,
const ITab& itab)
const;
2290 int verify(
Par par,
const Row& row2,
bool pkonly)
const;
2292 Row& operator=(
const Row& row2);
2296 operator<<(NdbOut& out,
const Row* rowp);
2299 operator<<(NdbOut& out,
const Row& row);
2303 Row::Row(
const Tab& tab) :
2306 m_val =
new Val* [tab.m_cols];
2307 for (uint k = 0; k < tab.m_cols; k++) {
2308 const Col& col = *tab.m_col[k];
2309 m_val[k] =
new Val(col);
2319 const Tab& tab = m_tab;
2320 for (uint k = 0; k < tab.m_cols; k++) {
2328 Row::copy(
const Row& row2,
bool copy_bi)
2330 const Tab& tab = m_tab;
2334 m_txid = row2.m_txid;
2336 if (copy_bi && row2.m_bi != 0) {
2337 m_bi =
new Row(tab);
2338 m_bi->copy(*row2.m_bi, copy_bi);
2343 Row::copyval(
const Row& row2, uint colmask)
2345 const Tab& tab = m_tab;
2346 assert(&tab == &row2.m_tab);
2347 for (uint k = 0; k < tab.m_cols; k++) {
2348 Val& val = *m_val[k];
2349 const Val& val2 = *row2.m_val[k];
2350 if ((1 << k) & colmask)
2356 Row::calc(
Par par, uint i, uint colmask)
2358 const Tab& tab = m_tab;
2359 for (uint k = 0; k < tab.m_cols; k++) {
2360 if ((1 << k) & colmask) {
2361 Val& val = *m_val[k];
2370 Row::setval(
Par par, uint colmask)
2372 const Tab& tab = m_tab;
2373 Rsq rsq(tab.m_cols);
2374 for (uint k = 0; k < tab.m_cols; k++) {
2375 uint k2 = rsq.next();
2376 if ((1 << k2) & colmask) {
2377 const Val& val = *m_val[k2];
2378 CHK(val.setval(par) == 0);
2385 Row::setval(
Par par,
const ITab& itab)
2387 Rsq rsq(itab.m_icols);
2388 for (uint k = 0; k < itab.m_icols; k++) {
2389 uint k2 = rsq.next();
2390 const ICol& icol = *itab.m_icol[k2];
2391 const Col& col = icol.m_col;
2393 const Val& val = *m_val[m];
2394 CHK(val.setval(par, icol) == 0);
2400 Row::insrow(
Par par)
2402 Con& con = par.con();
2403 const Tab& tab = m_tab;
2404 CHK(con.getNdbOperation(tab) == 0);
2406 CHK(setval(par, tab.m_pkmask) == 0);
2407 CHK(setval(par, ~tab.m_pkmask) == 0);
2408 assert(m_st == StUndef);
2411 m_txid = con.m_txid;
2416 Row::updrow(
Par par)
2418 Con& con = par.con();
2419 const Tab& tab = m_tab;
2420 CHK(con.getNdbOperation(tab) == 0);
2422 CHK(setval(par, tab.m_pkmask) == 0);
2423 CHK(setval(par, ~tab.m_pkmask) == 0);
2424 assert(m_st == StUndef);
2427 m_txid = con.m_txid;
2432 Row::updrow(
Par par,
const ITab& itab)
2434 Con& con = par.con();
2435 const Tab& tab = m_tab;
2436 assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
2437 CHK(con.getNdbIndexOperation(itab, tab) == 0);
2439 CHK(setval(par, itab) == 0);
2440 CHK(setval(par, ~tab.m_pkmask) == 0);
2441 assert(m_st == StUndef);
2444 m_txid = con.m_txid;
2449 Row::delrow(
Par par)
2451 Con& con = par.con();
2452 const Tab& tab = m_tab;
2453 CHK(con.getNdbOperation(m_tab) == 0);
2455 CHK(setval(par, tab.m_pkmask) == 0);
2456 assert(m_st == StUndef);
2459 m_txid = con.m_txid;
2464 Row::delrow(
Par par,
const ITab& itab)
2466 Con& con = par.con();
2467 const Tab& tab = m_tab;
2468 assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
2469 CHK(con.getNdbIndexOperation(itab, tab) == 0);
2471 CHK(setval(par, itab) == 0);
2472 assert(m_st == StUndef);
2475 m_txid = con.m_txid;
2480 Row::selrow(
Par par)
2482 Con& con = par.con();
2483 const Tab& tab = m_tab;
2484 CHK(con.getNdbOperation(m_tab) == 0);
2485 CHKCON(con.readTuple(par) == 0, con);
2486 CHK(setval(par, tab.m_pkmask) == 0);
2492 Row::selrow(
Par par,
const ITab& itab)
2494 Con& con = par.con();
2495 const Tab& tab = m_tab;
2496 assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
2497 CHK(con.getNdbIndexOperation(itab, tab) == 0);
2498 CHKCON(con.readTuple(par) == 0, con);
2499 CHK(setval(par, itab) == 0);
2505 Row::setrow(
Par par)
2507 Con& con = par.con();
2508 const Tab& tab = m_tab;
2509 CHK(setval(par, ~tab.m_pkmask) == 0);
2510 assert(m_st == StUndef);
2513 m_txid = con.m_txid;
2520 Row::cmp(
Par par,
const Row& row2)
const
2522 const Tab& tab = m_tab;
2523 assert(&tab == &row2.m_tab);
2525 for (uint k = 0; k < tab.m_cols; k++) {
2526 const Val& val = *m_val[k];
2527 const Val& val2 = *row2.m_val[k];
2528 if ((c = val.cmp(par, val2)) != 0)
2535 Row::cmp(
Par par,
const Row& row2,
const ITab& itab)
const
2537 const Tab& tab = m_tab;
2539 for (uint i = 0; i < itab.m_icols; i++) {
2540 const ICol& icol = *itab.m_icol[
i];
2541 const Col& col = icol.m_col;
2543 assert(k < tab.m_cols);
2544 const Val& val = *m_val[k];
2545 const Val& val2 = *row2.m_val[k];
2546 if ((c = val.cmp(par, val2)) != 0)
2553 Row::verify(
Par par,
const Row& row2,
bool pkonly)
const
2555 const Tab& tab = m_tab;
2556 const Row& row1 = *
this;
2557 assert(&row1.m_tab == &row2.m_tab);
2558 for (uint k = 0; k < tab.m_cols; k++) {
2559 const Col& col = row1.m_val[k]->m_col;
2560 if (!pkonly || col.m_pk) {
2561 const Val& val1 = *row1.m_val[k];
2562 const Val& val2 = *row2.m_val[k];
2563 CHK(val1.verify(par, val2) == 0);
2572 operator<<(NdbOut& out,
const Row::St st)
2574 if (st == Row::StUndef)
2576 else if (st == Row::StDefine)
2578 else if (st == Row::StPrepare)
2580 else if (st == Row::StCommit)
2588 operator<<(NdbOut& out,
const Row::Op op)
2590 if (op == Row::OpNone)
2592 else if (op == Row::OpIns)
2594 else if (op == Row::OpUpd)
2596 else if (op == Row::OpDel)
2598 else if (op == Row::OpRead)
2600 else if (op == Row::OpReadEx)
2602 else if (op == Row::OpReadCom)
2610 operator<<(NdbOut& out,
const Row* rowp)
2620 operator<<(NdbOut& out,
const Row& row)
2622 const Tab& tab = row.m_tab;
2624 for (uint i = 0; i < tab.m_cols; i++) {
2627 out << *row.m_val[
i];
2629 out <<
" " << row.m_st;
2630 out <<
" " << row.m_op;
2631 out <<
" " << HEX(row.m_txid);
2633 out <<
" " << row.m_bi;
2648 Set(
const Tab& tab, uint rows);
2651 bool compat(
Par par, uint i,
const Row::Op op)
const;
2653 void copyval(uint i, uint colmask = ~0);
2654 void calc(
Par par, uint i, uint colmask = ~0);
2656 const Row* getrow(uint i,
bool dirty =
false)
const;
2657 int setrow(uint i,
const Row* src,
bool force=
false);
2659 void post(
Par par, ExecType et);
2661 int insrow(
Par par, uint i);
2662 int updrow(
Par par, uint i);
2663 int updrow(
Par par,
const ITab& itab, uint i);
2664 int delrow(
Par par, uint i);
2665 int delrow(
Par par,
const ITab& itab, uint i);
2666 int selrow(
Par par,
const Row& keyrow);
2667 int selrow(
Par par,
const ITab& itab,
const Row& keyrow);
2668 int setrow(
Par par, uint i);
2669 int getval(
Par par);
2670 int getkey(
Par par, uint* i);
2671 int putval(uint i,
bool force, uint n = ~0);
2673 void sort(
Par par,
const ITab& itab);
2674 int verify(
Par par,
const Set& set2,
bool pkonly,
bool dirty =
false)
const;
2675 int verifyorder(
Par par,
const ITab& itab,
bool descending)
const;
2679 NdbMutex_Lock(m_mutex);
2681 void unlock()
const {
2682 NdbMutex_Unlock(m_mutex);
2685 void sort(
Par par,
const ITab& itab, uint lo, uint hi);
2686 Set& operator=(
const Set& set2);
2691 Set::Set(
const Tab& tab, uint rows) :
2695 m_row =
new Row* [m_rows];
2696 for (uint i = 0; i < m_rows; i++) {
2699 m_rowkey =
new uint [m_rows];
2700 for (uint n = 0; n < m_rows; n++) {
2703 m_keyrow =
new Row(tab);
2705 for (uint k = 0; k < tab.m_cols; k++) {
2708 m_mutex = NdbMutex_Create();
2709 assert(m_mutex != 0);
2714 for (uint i = 0; i < m_rows; i++) {
2721 NdbMutex_Destroy(m_mutex);
2727 for (uint i = 0; i < m_rows; i++) {
2734 Set::compat(
Par par, uint i,
const Row::Op op)
const
2736 Con& con = par.con();
2740 const Row* rowp = getrow(i);
2742 ret = op == Row::OpIns;
2746 const Row& row = *rowp;
2747 if (!(op & Row::OpREAD)) {
2748 if (row.m_st == Row::StDefine || row.m_st == Row::StPrepare) {
2749 assert(row.m_op & Row::OpDML);
2750 assert(row.m_txid != 0);
2751 if (con.m_txid != row.m_txid) {
2756 if (row.m_op != Row::OpDel) {
2757 ret = op == Row::OpUpd || op == Row::OpDel;
2761 ret = op == Row::OpIns;
2765 if (row.m_st == Row::StCommit) {
2766 assert(row.m_op == Row::OpNone);
2767 assert(row.m_txid == 0);
2768 ret = op == Row::OpUpd || op == Row::OpDel;
2773 if (op & Row::OpREAD) {
2775 con.m_txid != row.m_txid &&
2777 const Row* rowp2 = getrow(i, dirty);
2778 if (rowp2 == 0 || rowp2->m_op == Row::OpDel) {
2788 LL4(
"compat ret=" << ret <<
" place=" << place);
2789 assert(ret ==
false || ret ==
true);
2796 const Tab& tab = m_tab;
2799 m_row[
i] =
new Row(tab);
2800 Row& row = *m_row[
i];
2807 Set::copyval(uint i, uint colmask)
2809 assert(m_row[i] != 0);
2810 Row& row = *m_row[
i];
2811 assert(row.m_bi != 0);
2812 row.copyval(*row.m_bi, colmask);
2816 Set::calc(
Par par, uint i, uint colmask)
2818 assert(m_row[i] != 0);
2819 Row& row = *m_row[
i];
2820 row.calc(par, i, colmask);
2827 for (uint i = 0; i < m_rows; i++) {
2835 Set::getrow(uint i,
bool dirty)
const
2838 const Row* rowp = m_row[
i];
2841 bool b1 = rowp->m_op == Row::OpNone;
2842 bool b2 = rowp->m_st == Row::StCommit;
2845 assert(rowp->m_bi == 0);
2855 Set::setrow(uint i,
const Row* src,
bool force)
2862 Row* newRow=
new Row(src->m_tab);
2863 newRow->copy(*src,
true);
2871 Set::post(
Par par, ExecType et)
2874 Con& con = par.con();
2875 assert(con.m_txid != 0);
2877 for (i = 0; i < m_rows; i++) {
2878 Row* rowp = m_row[
i];
2880 LL5(
"skip " << i <<
" " << rowp);
2883 if (rowp->m_st == Row::StCommit) {
2884 assert(rowp->m_op == Row::OpNone);
2885 assert(rowp->m_txid == 0);
2886 assert(rowp->m_bi == 0);
2887 LL5(
"skip committed " << i <<
" " << rowp);
2890 assert(rowp->m_st == Row::StDefine || rowp->m_st == Row::StPrepare);
2891 assert(rowp->m_txid != 0);
2892 if (con.m_txid != rowp->m_txid) {
2893 LL5(
"skip txid " << i <<
" " << HEX(con.m_txid) <<
" " << rowp);
2897 assert(rowp->m_op & Row::OpDML);
2898 LL4(
"post BEFORE " << rowp);
2899 if (et == NoCommit) {
2900 if (rowp->m_st == Row::StDefine) {
2901 rowp->m_st = Row::StPrepare;
2902 Row* bi = rowp->m_bi;
2903 while (bi != 0 && bi->m_st == Row::StDefine) {
2904 bi->m_st = Row::StPrepare;
2908 }
else if (et == Commit) {
2909 if (rowp->m_op != Row::OpDel) {
2910 rowp->m_st = Row::StCommit;
2911 rowp->m_op = Row::OpNone;
2919 }
else if (et == Rollback) {
2920 while (rowp != 0 && rowp->m_st != Row::StCommit) {
2930 LL4(
"post AFTER " << rowp);
2937 Set::insrow(
Par par, uint i)
2939 assert(m_row[i] != 0);
2940 Row& row = *m_row[
i];
2941 CHK(row.insrow(par) == 0);
2946 Set::updrow(
Par par, uint i)
2948 assert(m_row[i] != 0);
2949 Row& row = *m_row[
i];
2950 CHK(row.updrow(par) == 0);
2955 Set::updrow(
Par par,
const ITab& itab, uint i)
2957 assert(m_row[i] != 0);
2958 Row& row = *m_row[
i];
2959 CHK(row.updrow(par, itab) == 0);
2964 Set::delrow(
Par par, uint i)
2966 assert(m_row[i] != 0);
2967 Row& row = *m_row[
i];
2968 CHK(row.delrow(par) == 0);
2973 Set::delrow(
Par par,
const ITab& itab, uint i)
2975 assert(m_row[i] != 0);
2976 Row& row = *m_row[
i];
2977 CHK(row.delrow(par, itab) == 0);
2982 Set::selrow(
Par par,
const Row& keyrow)
2984 const Tab& tab = par.tab();
2985 LL5(
"selrow " << tab.m_name <<
" keyrow " << keyrow);
2986 m_keyrow->copyval(keyrow, tab.m_pkmask);
2987 CHK(m_keyrow->selrow(par) == 0);
2988 CHK(getval(par) == 0);
2993 Set::selrow(
Par par,
const ITab& itab,
const Row& keyrow)
2995 LL5(
"selrow " << itab.m_name <<
" keyrow " << keyrow);
2996 m_keyrow->copyval(keyrow, itab.m_keymask);
2997 CHK(m_keyrow->selrow(par, itab) == 0);
2998 CHK(getval(par) == 0);
3003 Set::setrow(
Par par, uint i)
3005 assert(m_row[i] != 0);
3006 CHK(m_row[i]->setrow(par) == 0);
3011 Set::getval(
Par par)
3013 Con& con = par.con();
3014 const Tab& tab = m_tab;
3015 Rsq rsq1(tab.m_cols);
3016 for (uint k = 0; k < tab.m_cols; k++) {
3017 uint k2 = rsq1.next();
3018 CHK(con.getValue(k2, m_rec[k2]) == 0);
3024 Set::getkey(
Par par, uint* i)
3026 const Tab& tab = m_tab;
3027 uint k = tab.m_keycol;
3028 assert(m_rec[k] != 0);
3029 const char* aRef = m_rec[k]->
aRef();
3030 Uint32 key = *(
const Uint32*)aRef;
3031 LL5(
"getkey: " << key);
3038 Set::putval(uint i,
bool force, uint n)
3040 const Tab& tab = m_tab;
3041 LL4(
"putval key=" << i <<
" row=" << n <<
" old=" << m_row[i]);
3043 if (m_row[i] != 0) {
3048 m_row[
i] =
new Row(tab);
3049 Row& row = *m_row[
i];
3050 for (uint k = 0; k < tab.m_cols; k++) {
3051 Val& val = *row.m_val[k];
3058 const char* aRef = m_rec[k]->
aRef();
3073 Set::sort(
Par par,
const ITab& itab)
3076 sort(par, itab, 0, m_rows - 1);
3080 Set::sort(
Par par,
const ITab& itab, uint lo, uint hi)
3082 assert(lo < m_rows && hi < m_rows && lo <= hi);
3083 Row*
const p = m_row[lo];
3087 while (i < j && m_row[j]->cmp(par, *p, itab) >= 0)
3090 m_row[
i] = m_row[j];
3093 while (i < j && m_row[i]->cmp(par, *p, itab) <= 0)
3096 m_row[j] = m_row[
i];
3102 sort(par, itab, lo, i - 1);
3104 sort(par, itab, i + 1, hi);
3113 Set::verify(
Par par,
const Set& set2,
bool pkonly,
bool dirty)
const
3115 const Set& set1 = *
this;
3116 assert(&set1.m_tab == &set2.m_tab && set1.m_rows == set2.m_rows);
3117 LL3(
"verify dirty:" << dirty);
3118 for (uint i = 0; i < set1.m_rows; i++) {
3120 const Row* row1p = set1.getrow(i, dirty);
3121 const Row* row2p = set2.getrow(i);
3130 Row::Op op1 = row1p->m_op;
3131 if (op1 != Row::OpDel) {
3135 }
else if (row1p->verify(par, *row2p, pkonly) == -1) {
3139 }
else if (row2p != 0) {
3145 LL1(
"verify " << i <<
" failed at " << place);
3146 LL1(
"row1 " << row1p);
3147 LL1(
"row2 " << row2p);
3155 Set::verifyorder(
Par par,
const ITab& itab,
bool descending)
const
3157 for (uint n = 0; n < m_rows; n++) {
3158 uint i2 = m_rowkey[
n];
3159 if (i2 == (uint) ~0)
3163 uint i1 = m_rowkey[n - 1];
3164 assert(m_row[i1] != 0 && m_row[i2] != 0);
3165 const Row& row1 = *m_row[i1];
3166 const Row& row2 = *m_row[i2];
3169 ok= (row1.cmp(par, row2, itab) <= 0);
3171 ok= (row1.cmp(par, row2, itab) >= 0);
3175 LL1(
"verifyorder " << n <<
" failed");
3176 LL1(
"row1 " << row1);
3177 LL1(
"row2 " << row2);
3188 operator<<(NdbOut& out,
const Set&
set)
3190 for (uint i = 0; i <
set.m_rows; i++) {
3191 const Row& row = *
set.m_row[
i];
3206 int setbnd(
Par par)
const;
3207 int setflt(
Par par)
const;
3210 BVal::BVal(
const ICol& icol) :
3217 BVal::setbnd(
Par par)
const
3219 Con& con = par.con();
3220 assert(g_compare_null || !m_null);
3221 const char* addr = !m_null ? (
const char*)dataaddr() : 0;
3222 const ICol& icol = m_icol;
3223 CHK(con.setBound(icol.m_num, m_type, addr) == 0);
3228 BVal::setflt(
Par par)
const
3230 static uint index_bound_to_filter_bound[5] = {
3237 Con& con = par.con();
3238 assert(g_compare_null || !m_null);
3239 const char* addr = !m_null ? (
const char*)dataaddr() : 0;
3240 const ICol& icol = m_icol;
3241 const Col& col = icol.m_col;
3242 uint length = col.m_bytesize;
3243 uint cond = index_bound_to_filter_bound[m_type];
3244 CHK(con.setFilter(col.m_num, cond, addr, length) == 0);
3249 operator<<(NdbOut& out,
const BVal& bval)
3251 const ICol& icol = bval.m_icol;
3252 const Col& col = icol.m_col;
3253 const Val& val = bval;
3254 out <<
"type=" << bval.m_type;
3255 out <<
" icol=" << icol.m_num;
3256 out <<
" col=" << col.m_num <<
"," << col.m_name;
3257 out <<
" value=" << val;
3273 void calcpk(
Par par, uint i);
3274 int setbnd(
Par par)
const;
3275 int setflt(
Par par)
const;
3276 void filter(
Par par,
const Set&
set,
Set& set2)
const;
3279 BSet::BSet(
const Tab& tab,
const ITab& itab) :
3282 m_alloc(2 * itab.m_icols),
3285 m_bval =
new BVal* [m_alloc];
3286 for (uint i = 0; i < m_alloc; i++) {
3299 while (m_bvals > 0) {
3309 const ITab& itab = m_itab;
3310 par.m_pctrange = par.m_pctbrange;
3312 for (uint k = 0; k < itab.m_icols; k++) {
3313 const ICol& icol = *itab.m_icol[k];
3314 for (uint i = 0; i <= 1; i++) {
3315 if (m_bvals == 0 && urandom(100) == 0)
3317 if (m_bvals != 0 && urandom(3) == 0)
3319 assert(m_bvals < m_alloc);
3321 m_bval[m_bvals++] = &bval;
3322 bval.m_null =
false;
3326 sel = urandom(5 - i);
3327 }
while (strchr(par.m_bound,
'0' + sel) == 0);
3329 bval.m_type = 0 | (1 <<
i);
3331 bval.m_type = 1 | (1 <<
i);
3334 if (k + 1 < itab.m_icols)
3336 if (!g_compare_null)
3338 if (bval.m_type == 0 || bval.m_type == 1)
3340 if (bval.m_type == 2 || bval.m_type == 3)
3343 bval.calcnokey(par);
3345 assert(m_bvals >= 2);
3346 const BVal& bv1 = *m_bval[m_bvals - 2];
3347 const BVal& bv2 = *m_bval[m_bvals - 1];
3348 if (bv1.cmp(par, bv2) > 0 && urandom(100) != 0)
3353 if (bval.m_type == 4)
3360 BSet::calcpk(
Par par, uint i)
3362 const ITab& itab = m_itab;
3364 for (uint k = 0; k < itab.m_icols; k++) {
3365 const ICol& icol = *itab.m_icol[k];
3366 const Col& col = icol.m_col;
3368 assert(m_bvals < m_alloc);
3370 m_bval[m_bvals++] = &bval;
3377 BSet::setbnd(
Par par)
const
3381 for (uint j = 0; j < m_bvals; j++) {
3382 uint j2 = rsq1.next();
3383 const BVal& bval = *m_bval[j2];
3384 CHK(bval.setbnd(par) == 0);
3391 BSet::setflt(
Par par)
const
3393 Con& con = par.con();
3394 CHK(con.getNdbScanFilter() == 0);
3398 for (uint j = 0; j < m_bvals; j++) {
3399 uint j2 = rsq1.next();
3400 const BVal& bval = *m_bval[j2];
3401 CHK(bval.setflt(par) == 0);
3404 if (urandom(5) == 0) {
3405 uint j3 = urandom(m_bvals);
3406 const BVal& bval = *m_bval[j3];
3407 CHK(bval.setflt(par) == 0);
3410 CHK(con.endFilter() == 0);
3415 BSet::filter(
Par par,
const Set&
set,
Set& set2)
const
3417 const Tab& tab = m_tab;
3418 const ITab& itab = m_itab;
3419 assert(&tab == &set2.m_tab &&
set.m_rows == set2.m_rows);
3420 assert(set2.count() == 0);
3421 for (uint i = 0; i <
set.m_rows; i++) {
3424 if (
set.m_row[i] == 0) {
3427 const Row& row = *
set.m_row[
i];
3428 if (!g_store_null_key) {
3430 for (uint k = 0; k < itab.m_icols; k++) {
3431 const ICol& icol = *itab.m_icol[k];
3432 const Col& col = icol.m_col;
3433 const Val& val = *row.m_val[col.m_num];
3443 for (uint j = 0; j < m_bvals; j++) {
3444 const BVal& bval = *m_bval[j];
3445 const ICol& icol = bval.m_icol;
3446 const Col& col = icol.m_col;
3447 const Val& val = *row.m_val[col.m_num];
3448 int ret = bval.cmp(par, val);
3449 LL5(
"cmp: ret=" << ret <<
" " << bval <<
" vs " << val);
3450 if (bval.m_type == 0)
3452 else if (bval.m_type == 1)
3454 else if (bval.m_type == 2)
3456 else if (bval.m_type == 3)
3458 else if (bval.m_type == 4)
3468 assert(set2.m_row[i] == 0);
3469 set2.m_row[
i] =
new Row(tab);
3470 Row& row2 = *set2.m_row[
i];
3471 row2.copy(row,
true);
3478 operator<<(NdbOut& out,
const BSet& bset)
3480 out <<
"bounds=" << bset.m_bvals;
3481 for (uint j = 0; j < bset.m_bvals; j++) {
3482 const BVal& bval = *bset.m_bval[j];
3483 out <<
" [bound " << j <<
": " << bval <<
"]";
3493 Con& con = par.con();
3494 const Tab& tab = par.tab();
3495 Set&
set = par.set();
3496 LL3(
"pkinsert " << tab.m_name);
3497 CHK(con.startTransaction() == 0);
3499 for (uint j = 0; j < par.m_rows; j++) {
3500 uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
3501 uint i = thrrow(par, j2);
3503 if (!
set.compat(par, i, Row::OpIns)) {
3504 LL3(
"pkinsert SKIP " << i <<
" " <<
set.getrow(i));
3509 CHK(
set.insrow(par, i) == 0);
3511 LL4(
"pkinsert key=" << i <<
" " <<
set.getrow(i));
3514 bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
3515 if (batch == par.m_batch || lastbatch) {
3516 uint err = par.m_catcherr;
3517 ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
3518 CHK(con.execute(et, err) == 0);
3520 set.post(par, !err ? et : Rollback);
3523 LL1(
"pkinsert key=" << i <<
" stop on " << con.errname(err));
3528 con.closeTransaction();
3529 CHK(con.startTransaction() == 0);
3533 con.closeTransaction();
3540 Con& con = par.con();
3541 const Tab& tab = par.tab();
3542 Set&
set = par.set();
3543 LL3(
"pkupdate " << tab.m_name);
3544 CHK(con.startTransaction() == 0);
3546 for (uint j = 0; j < par.m_rows; j++) {
3547 uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
3548 uint i = thrrow(par, j2);
3550 if (!
set.compat(par, i, Row::OpUpd)) {
3551 LL3(
"pkupdate SKIP " << i <<
" " <<
set.getrow(i));
3555 set.copyval(i, tab.m_pkmask);
3556 set.calc(par, i, ~tab.m_pkmask);
3557 CHK(
set.updrow(par, i) == 0);
3559 LL4(
"pkupdate key=" << i <<
" " <<
set.getrow(i));
3562 bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
3563 if (batch == par.m_batch || lastbatch) {
3564 uint err = par.m_catcherr;
3565 ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
3566 CHK(con.execute(et, err) == 0);
3568 set.post(par, !err ? et : Rollback);
3571 LL1(
"pkupdate key=" << i <<
": stop on " << con.errname(err));
3576 con.closeTransaction();
3577 CHK(con.startTransaction() == 0);
3581 con.closeTransaction();
3588 Con& con = par.con();
3589 const Tab& tab = par.tab();
3590 Set&
set = par.set();
3591 LL3(
"pkdelete " << tab.m_name);
3592 CHK(con.startTransaction() == 0);
3594 for (uint j = 0; j < par.m_rows; j++) {
3595 uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
3596 uint i = thrrow(par, j2);
3598 if (!
set.compat(par, i, Row::OpDel)) {
3599 LL3(
"pkdelete SKIP " << i <<
" " <<
set.getrow(i));
3603 set.copyval(i, tab.m_pkmask);
3604 CHK(
set.delrow(par, i) == 0);
3606 LL4(
"pkdelete key=" << i <<
" " <<
set.getrow(i));
3609 bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
3610 if (batch == par.m_batch || lastbatch) {
3611 uint err = par.m_catcherr;
3612 ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
3613 CHK(con.execute(et, err) == 0);
3615 set.post(par, !err ? et : Rollback);
3618 LL1(
"pkdelete key=" << i <<
" stop on " << con.errname(err));
3623 con.closeTransaction();
3624 CHK(con.startTransaction() == 0);
3628 con.closeTransaction();
3636 Con& con = par.con();
3637 const Tab& tab = par.tab();
3638 Set&
set = par.set();
3639 LL3(
"pkread " << tab.m_name <<
" verify=" << par.m_verify);
3641 const Set& set1 =
set;
3642 Set set2(tab,
set.m_rows);
3643 for (uint i = 0; i <
set.m_rows; i++) {
3646 if (!
set.compat(par, i, Row::OpREAD)) {
3647 LL3(
"pkread SKIP " << i <<
" " <<
set.getrow(i));
3652 CHK(con.startTransaction() == 0);
3653 CHK(set2.selrow(par, *set1.m_row[i]) == 0);
3654 CHK(con.execute(Commit) == 0);
3656 CHK(set2.getkey(par, &i2) == 0 && i == i2);
3657 CHK(set2.putval(i,
false) == 0);
3658 LL4(
"row " << set2.count() <<
" " << set2.getrow(i));
3659 con.closeTransaction();
3662 CHK(set1.verify(par, set2,
false) == 0);
3668 pkreadfast(
Par par, uint count)
3670 Con& con = par.con();
3671 const Tab& tab = par.tab();
3672 const Set&
set = par.set();
3673 LL3(
"pkfast " << tab.m_name);
3676 for (uint j = 0; j < count; j++) {
3677 uint i = urandom(
set.m_rows);
3678 assert(
set.compat(par, i, Row::OpREAD));
3679 CHK(con.startTransaction() == 0);
3681 keyrow.calc(par, i);
3682 CHK(keyrow.selrow(par) == 0);
3685 CHK(con.getValue((Uint32)0, rec) == 0);
3686 CHK(con.execute(Commit) == 0);
3687 con.closeTransaction();
3695 hashindexupdate(
Par par,
const ITab& itab)
3697 Con& con = par.con();
3698 const Tab& tab = par.tab();
3699 Set&
set = par.set();
3700 LL3(
"hashindexupdate " << itab.m_name);
3701 CHK(con.startTransaction() == 0);
3703 for (uint j = 0; j < par.m_rows; j++) {
3704 uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
3705 uint i = thrrow(par, j2);
3707 if (!
set.compat(par, i, Row::OpUpd)) {
3708 LL3(
"hashindexupdate SKIP " << i <<
" " <<
set.getrow(i));
3713 uint keymask = tab.m_pkmask | itab.m_keymask;
3714 set.copyval(i, keymask);
3715 set.calc(par, i, ~keymask);
3716 CHK(
set.updrow(par, itab, i) == 0);
3718 LL4(
"hashindexupdate " << i <<
" " <<
set.getrow(i));
3721 bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
3722 if (batch == par.m_batch || lastbatch) {
3723 uint err = par.m_catcherr;
3724 ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
3725 CHK(con.execute(et, err) == 0);
3727 set.post(par, !err ? et : Rollback);
3730 LL1(
"hashindexupdate " << i <<
" stop on " << con.errname(err));
3735 con.closeTransaction();
3736 CHK(con.startTransaction() == 0);
3740 con.closeTransaction();
3745 hashindexdelete(
Par par,
const ITab& itab)
3747 Con& con = par.con();
3748 Set&
set = par.set();
3749 LL3(
"hashindexdelete " << itab.m_name);
3750 CHK(con.startTransaction() == 0);
3752 for (uint j = 0; j < par.m_rows; j++) {
3753 uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
3754 uint i = thrrow(par, j2);
3756 if (!
set.compat(par, i, Row::OpDel)) {
3757 LL3(
"hashindexdelete SKIP " << i <<
" " <<
set.getrow(i));
3761 set.copyval(i, itab.m_keymask);
3762 CHK(
set.delrow(par, itab, i) == 0);
3764 LL4(
"hashindexdelete " << i <<
" " <<
set.getrow(i));
3767 bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
3768 if (batch == par.m_batch || lastbatch) {
3769 uint err = par.m_catcherr;
3770 ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
3771 CHK(con.execute(et, err) == 0);
3773 set.post(par, !err ? et : Rollback);
3776 LL1(
"hashindexdelete " << i <<
" stop on " << con.errname(err));
3781 con.closeTransaction();
3782 CHK(con.startTransaction() == 0);
3786 con.closeTransaction();
3791 hashindexread(
Par par,
const ITab& itab)
3793 Con& con = par.con();
3794 const Tab& tab = par.tab();
3795 Set&
set = par.set();
3796 LL3(
"hashindexread " << itab.m_name <<
" verify=" << par.m_verify);
3798 const Set& set1 =
set;
3799 Set set2(tab,
set.m_rows);
3800 for (uint i = 0; i <
set.m_rows; i++) {
3803 if (!
set.compat(par, i, Row::OpREAD)) {
3804 LL3(
"hashindexread SKIP " << i <<
" " <<
set.getrow(i));
3809 CHK(con.startTransaction() == 0);
3810 CHK(set2.selrow(par, itab, *set1.m_row[i]) == 0);
3811 CHK(con.execute(Commit) == 0);
3813 CHK(set2.getkey(par, &i2) == 0 && i == i2);
3814 CHK(set2.putval(i,
false) == 0);
3815 LL4(
"row " << set2.count() <<
" " << *set2.m_row[
i]);
3816 con.closeTransaction();
3819 CHK(set1.verify(par, set2,
false) == 0);
3826 scanreadtable(
Par par)
3828 Con& con = par.con();
3829 const Tab& tab = par.tab();
3830 const Set&
set = par.set();
3832 const Set& set1 =
set;
3833 LL3(
"scanreadtable " << tab.m_name <<
" lockmode=" << par.m_lockmode <<
" tupscan=" << par.m_tupscan <<
" expect=" << set1.count() <<
" verify=" << par.m_verify);
3834 Set set2(tab,
set.m_rows);
3835 CHK(con.startTransaction() == 0);
3836 CHK(con.getNdbScanOperation(tab) == 0);
3837 CHK(con.readTuples(par) == 0);
3839 CHK(con.executeScan() == 0);
3843 uint err = par.m_catcherr;
3844 CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
3848 LL1(
"scanreadtable stop on " << con.errname(err));
3852 CHK(set2.getkey(par, &i) == 0);
3853 CHK(set2.putval(i,
false, n) == 0);
3854 LL4(
"row " << n <<
" " << *set2.m_row[i]);
3857 con.closeTransaction();
3859 CHK(set1.verify(par, set2,
false) == 0);
3860 LL3(
"scanreadtable " << tab.m_name <<
" done rows=" << n);
3865 scanreadtablefast(
Par par, uint countcheck)
3867 Con& con = par.con();
3868 const Tab& tab = par.tab();
3869 LL3(
"scanfast " << tab.m_name);
3870 CHK(con.startTransaction() == 0);
3871 CHK(con.getNdbScanOperation(tab) == 0);
3872 CHK(con.readTuples(par) == 0);
3875 CHK(con.getValue((Uint32)0, rec) == 0);
3876 CHK(con.executeScan() == 0);
3880 CHK((ret = con.nextScanResult(
true)) == 0 || ret == 1);
3885 con.closeTransaction();
3886 CHK(count == countcheck);
3892 calcscanbounds(
Par par,
const ITab& itab,
BSet& bset,
const Set&
set,
Set& set1)
3896 bset.filter(par,
set, set1);
3897 uint n = set1.count();
3899 if (0 < n && n <
set.m_rows)
3901 if (urandom(5) == 0)
3908 scanreadindex(
Par par,
const ITab& itab,
BSet& bset,
bool calc)
3910 Con& con = par.con();
3911 const Tab& tab = par.tab();
3912 const Set&
set = par.set();
3913 Set set1(tab,
set.m_rows);
3915 calcscanbounds(par, itab, bset,
set, set1);
3917 bset.filter(par,
set, set1);
3919 LL3(
"scanreadindex " << itab.m_name <<
" " << bset <<
" lockmode=" << par.m_lockmode <<
" expect=" << set1.count() <<
" ordered=" << par.m_ordered <<
" descending=" << par.m_descending <<
" verify=" << par.m_verify);
3920 Set set2(tab,
set.m_rows);
3921 CHK(con.startTransaction() == 0);
3922 CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
3923 CHK(con.readIndexTuples(par) == 0);
3924 CHK(bset.setbnd(par) == 0);
3926 CHK(con.executeScan() == 0);
3930 uint err = par.m_catcherr;
3931 CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
3935 LL1(
"scanreadindex stop on " << con.errname(err));
3939 CHK(set2.getkey(par, &i) == 0);
3940 CHK(set2.putval(i, par.m_dups, n) == 0);
3941 LL4(
"key " << i <<
" row " << n <<
" " << *set2.m_row[i]);
3944 con.closeTransaction();
3946 CHK(set1.verify(par, set2,
false) == 0);
3948 CHK(set2.verifyorder(par, itab, par.m_descending) == 0);
3950 LL3(
"scanreadindex " << itab.m_name <<
" done rows=" << n);
3956 scanreadindexmrr(
Par par,
const ITab& itab,
int numBsets)
3958 Con& con = par.con();
3959 const Tab& tab = par.tab();
3960 const Set&
set = par.set();
3967 Set** expectedResults;
3968 Set** actualResults;
3971 CHK((boundSets= (
BSet**) malloc(numBsets *
sizeof(
BSet*))) != 0);
3972 CHK((expectedResults= (
Set**) malloc(numBsets *
sizeof(
Set*))) != 0);
3973 CHK((actualResults= (
Set**) malloc(numBsets *
sizeof(
Set*))) != 0);
3974 CHK((setSizes= (uint*) malloc(numBsets *
sizeof(uint))) != 0);
3976 for (
int n=0; n < numBsets; n++)
3978 CHK((boundSets[n]=
new BSet(tab, itab)) != NULL );
3979 CHK((expectedResults[n]=
new Set(tab,
set.m_rows)) != NULL);
3980 CHK((actualResults[n]=
new Set(tab,
set.m_rows)) != NULL);
3983 Set& results= *expectedResults[
n];
3987 calcscanbounds(par, itab, *boundSets[n],
set, results);
3988 }
while ((*boundSets[n]).m_bvals == 0);
3992 LL3(
"scanreadindexmrr " << itab.m_name <<
" ranges= " << numBsets <<
" lockmode=" << par.m_lockmode <<
" ordered=" << par.m_ordered <<
" descending=" << par.m_descending <<
" verify=" << par.m_verify);
3993 Set set2(tab,
set.m_rows);
3995 par.m_multiRange=
true;
3996 CHK(con.startTransaction() == 0);
3997 CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
3998 CHK(con.readIndexTuples(par) == 0);
4000 for (
int n=0; n < numBsets; n++)
4002 CHK(boundSets[n]->setbnd(par) == 0);
4006 LL1(
"end_of_bound error : " << con.m_indexscanop->
getNdbError().
code);
4011 CHK(con.executeScan() == 0);
4012 int rows_received= 0;
4015 uint err = par.m_catcherr;
4016 CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
4020 LL1(
"scanreadindexmrr stop on " << con.errname(err));
4025 CHK(set2.getkey(par, &i) == 0);
4026 CHK(set2.putval(i,
false, -1) == 0);
4030 CHK(rangeNum < numBsets);
4031 CHK(set2.m_row[i] != NULL);
4033 CHK(setSizes[rangeNum] == actualResults[rangeNum]->count());
4034 int rowNum= setSizes[rangeNum];
4035 setSizes[rangeNum] ++;
4036 CHK((uint) rowNum < set2.m_rows);
4037 actualResults[rangeNum]->m_row[
i]= set2.m_row[
i];
4038 actualResults[rangeNum]->m_rowkey[rowNum]=
i;
4040 LL4(
"range " << rangeNum <<
" key " << i <<
" row " << rowNum <<
" " << *set2.m_row[i]);
4043 con.closeTransaction();
4050 LL4(
"Verifying " << numBsets <<
" sets, " << rows_received <<
" rows");
4051 for (
int n=0; n < numBsets; n++)
4053 LL5(
"Set " << n <<
" of " << expectedResults[n]->count() <<
" rows");
4054 CHK(expectedResults[n]->verify(par, *actualResults[n],
false) == 0);
4057 LL5(
"Verifying ordering");
4058 CHK(actualResults[n]->verifyorder(par, itab, par.m_descending) == 0);
4064 for (
int n=0; n < numBsets; n++)
4066 boundSets[
n]->reset();
4067 delete boundSets[
n];
4068 delete expectedResults[
n];
4069 delete actualResults[
n];
4073 free(expectedResults);
4074 free(actualResults);
4077 LL3(
"scanreadindexmrr " << itab.m_name <<
" done rows=" << rows_received);
4082 scanreadindexfast(
Par par,
const ITab& itab,
const BSet& bset, uint countcheck)
4084 Con& con = par.con();
4085 const Tab& tab = par.tab();
4086 LL3(
"scanfast " << itab.m_name <<
" " << bset);
4088 CHK(con.startTransaction() == 0);
4089 CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
4090 CHK(con.readIndexTuples(par) == 0);
4091 CHK(bset.setbnd(par) == 0);
4094 CHK(con.getValue((Uint32)0, rec) == 0);
4095 CHK(con.executeScan() == 0);
4099 CHK((ret = con.nextScanResult(
true)) == 0 || ret == 1);
4104 con.closeTransaction();
4105 CHK(count == countcheck);
4110 scanreadfilter(
Par par,
const ITab& itab,
BSet& bset,
bool calc)
4112 Con& con = par.con();
4113 const Tab& tab = par.tab();
4114 const Set&
set = par.set();
4115 Set set1(tab,
set.m_rows);
4117 calcscanbounds(par, itab, bset,
set, set1);
4119 bset.filter(par,
set, set1);
4121 LL3(
"scanfilter " << itab.m_name <<
" " << bset <<
" lockmode=" << par.m_lockmode <<
" expect=" << set1.count() <<
" verify=" << par.m_verify);
4122 Set set2(tab,
set.m_rows);
4123 CHK(con.startTransaction() == 0);
4124 CHK(con.getNdbScanOperation(tab) == 0);
4125 CHK(con.readTuples(par) == 0);
4126 CHK(bset.setflt(par) == 0);
4128 CHK(con.executeScan() == 0);
4132 uint err = par.m_catcherr;
4133 CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
4137 LL1(
"scanfilter stop on " << con.errname(err));
4141 CHK(set2.getkey(par, &i) == 0);
4142 CHK(set2.putval(i, par.m_dups, n) == 0);
4143 LL4(
"key " << i <<
" row " << n <<
" " << *set2.m_row[i]);
4146 con.closeTransaction();
4148 CHK(set1.verify(par, set2,
false) == 0);
4150 LL3(
"scanfilter " << itab.m_name <<
" done rows=" << n);
4155 scanreadindex(
Par par,
const ITab& itab)
4157 const Tab& tab = par.tab();
4158 for (uint i = 0; i < par.m_ssloop; i++) {
4159 if (itab.m_type == ITab::OrderedIndex) {
4160 BSet bset(tab, itab);
4161 CHK(scanreadfilter(par, itab, bset,
true) == 0);
4163 if (randompct(g_opt.m_pctmrr))
4164 CHK(scanreadindexmrr(par,
4166 1+urandom(g_opt.m_mrrmaxrng-1)) == 0);
4168 CHK(scanreadindex(par, itab, bset,
true) == 0);
4175 scanreadindex(
Par par)
4177 const Tab& tab = par.tab();
4178 for (uint i = 0; i < tab.m_itabs; i++) {
4179 if (tab.m_itab[i] == 0)
4181 const ITab& itab = *tab.m_itab[
i];
4182 if (itab.m_type == ITab::OrderedIndex) {
4183 CHK(scanreadindex(par, itab) == 0);
4185 CHK(hashindexread(par, itab) == 0);
4193 scanreadall(
Par par)
4195 CHK(scanreadtable(par) == 0);
4196 CHK(scanreadindex(par) == 0);
4204 timescantable(
Par par)
4207 CHK(scanreadtablefast(par, par.m_totrows) == 0);
4208 par.tmr().off(par.set().m_rows);
4213 timescanpkindex(
Par par)
4215 const Tab& tab = par.tab();
4216 const ITab& itab = *tab.m_itab[0];
4217 BSet bset(tab, itab);
4219 CHK(scanreadindexfast(par, itab, bset, par.m_totrows) == 0);
4220 par.tmr().off(par.set().m_rows);
4225 timepkreadtable(
Par par)
4228 uint count = par.m_samples;
4230 count = par.m_totrows;
4231 CHK(pkreadfast(par, count) == 0);
4232 par.tmr().off(count);
4237 timepkreadindex(
Par par)
4239 const Tab& tab = par.tab();
4240 const ITab& itab = *tab.m_itab[0];
4241 BSet bset(tab, itab);
4242 uint count = par.m_samples;
4244 count = par.m_totrows;
4246 for (uint j = 0; j < count; j++) {
4247 uint i = urandom(par.m_totrows);
4248 bset.calcpk(par, i);
4249 CHK(scanreadindexfast(par, itab, bset, 1) == 0);
4251 par.tmr().off(count);
4258 scanupdatetable(
Par par)
4260 Con& con = par.con();
4261 const Tab& tab = par.tab();
4262 Set&
set = par.set();
4263 LL3(
"scanupdatetable " << tab.m_name);
4264 Set set2(tab,
set.m_rows);
4266 CHK(con.startTransaction() == 0);
4267 CHK(con.getNdbScanOperation(tab) == 0);
4268 CHK(con.readTuples(par) == 0);
4270 CHK(con.executeScan() == 0);
4275 CHK(con2.startTransaction() == 0);
4279 uint32 err = par.m_catcherr;
4280 CHK((ret = con.nextScanResult(
true, err)) != -1);
4284 LL1(
"scanupdatetable [scan] stop on " << con.errname(err));
4287 if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) {
4293 CHK(set2.getkey(par, &i) == 0);
4295 if (!
set.compat(par, i, Row::OpUpd)) {
4296 LL3(
"scanupdatetable SKIP " << i <<
" " <<
set.getrow(i));
4298 CHKTRY(set2.putval(i,
false) == 0,
set.unlock());
4299 CHKTRY(con.updateScanTuple(con2) == 0,
set.unlock());
4303 set.calc(par, i, ~tab.m_pkmask);
4304 CHKTRY(
set.setrow(par2, i) == 0,
set.unlock());
4305 LL4(
"scanupdatetable " << i <<
" " <<
set.getrow(i));
4309 CHK((ret = con.nextScanResult(
false)) != -1);
4310 bool lastbatch = (batch != 0 && ret != 0);
4311 if (batch == par.m_batch || lastbatch) {
4312 uint err = par.m_catcherr;
4313 ExecType et = Commit;
4314 CHK(con2.execute(et, err) == 0);
4316 set.post(par, !err ? et : Rollback);
4319 LL1(
"scanupdatetable [update] stop on " << con2.errname(err));
4322 LL4(
"scanupdatetable committed batch");
4325 con2.closeTransaction();
4326 CHK(con2.startTransaction() == 0);
4333 con2.closeTransaction();
4334 LL3(
"scanupdatetable " << tab.m_name <<
" rows updated=" << count);
4335 con.closeTransaction();
4340 scanupdateindex(
Par par,
const ITab& itab,
BSet& bset,
bool calc)
4342 Con& con = par.con();
4343 const Tab& tab = par.tab();
4344 Set&
set = par.set();
4346 Set set1(tab,
set.m_rows);
4348 calcscanbounds(par, itab, bset,
set, set1);
4350 bset.filter(par,
set, set1);
4352 LL3(
"scanupdateindex " << itab.m_name <<
" " << bset <<
" expect=" << set1.count() <<
" ordered=" << par.m_ordered <<
" descending=" << par.m_descending <<
" verify=" << par.m_verify);
4353 Set set2(tab,
set.m_rows);
4355 CHK(con.startTransaction() == 0);
4356 CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
4357 CHK(con.readTuples(par) == 0);
4358 CHK(bset.setbnd(par) == 0);
4360 CHK(con.executeScan() == 0);
4365 CHK(con2.startTransaction() == 0);
4369 uint err = par.m_catcherr;
4370 CHK((ret = con.nextScanResult(
true, err)) != -1);
4374 LL1(
"scanupdateindex [scan] stop on " << con.errname(err));
4377 if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) {
4383 CHK(set2.getkey(par, &i) == 0);
4385 if (!
set.compat(par, i, Row::OpUpd)) {
4386 LL4(
"scanupdateindex SKIP " <<
set.getrow(i));
4388 CHKTRY(set2.putval(i, par.m_dups) == 0,
set.unlock());
4389 CHKTRY(con.updateScanTuple(con2) == 0,
set.unlock());
4393 uint colmask = !par.m_noindexkeyupdate ? ~0 : ~itab.m_keymask;
4394 set.calc(par, i, colmask);
4395 CHKTRY(
set.setrow(par2, i) == 0,
set.unlock());
4396 LL4(
"scanupdateindex " << i <<
" " <<
set.getrow(i));
4400 CHK((ret = con.nextScanResult(
false)) != -1);
4401 bool lastbatch = (batch != 0 && ret != 0);
4402 if (batch == par.m_batch || lastbatch) {
4403 uint err = par.m_catcherr;
4404 ExecType et = Commit;
4405 CHK(con2.execute(et, err) == 0);
4407 set.post(par, !err ? et : Rollback);
4410 LL1(
"scanupdateindex [update] stop on " << con2.errname(err));
4413 LL4(
"scanupdateindex committed batch");
4416 con2.closeTransaction();
4417 CHK(con2.startTransaction() == 0);
4424 con2.closeTransaction();
4426 CHK(set1.verify(par, set2,
true) == 0);
4428 CHK(set2.verifyorder(par, itab, par.m_descending) == 0);
4430 LL3(
"scanupdateindex " << itab.m_name <<
" rows updated=" << count);
4431 con.closeTransaction();
4436 scanupdateindex(
Par par,
const ITab& itab)
4438 const Tab& tab = par.tab();
4439 for (uint i = 0; i < par.m_ssloop; i++) {
4440 if (itab.m_type == ITab::OrderedIndex) {
4441 BSet bset(tab, itab);
4442 CHK(scanupdateindex(par, itab, bset,
true) == 0);
4444 CHK(hashindexupdate(par, itab) == 0);
4451 scanupdateindex(
Par par)
4453 const Tab& tab = par.tab();
4454 for (uint i = 0; i < tab.m_itabs; i++) {
4455 if (tab.m_itab[i] == 0)
4457 const ITab& itab = *tab.m_itab[
i];
4458 CHK(scanupdateindex(par, itab) == 0);
4465 scanupdateall(
Par par)
4467 CHK(scanupdatetable(par) == 0);
4468 CHK(scanupdateindex(par) == 0);
4476 readverifyfull(
Par par)
4480 par.m_verify =
true;
4481 if (par.m_abortpct != 0) {
4482 LL2(
"skip verify in this version");
4483 par.m_verify =
false;
4486 const Tab& tab = par.tab();
4487 if (par.m_no == 0) {
4489 CHK(scanreadtable(par) == 0);
4491 par.m_tupscan =
true;
4492 CHK(scanreadtable(par) == 0);
4495 for (uint i = 0; i < tab.m_itabs; i++) {
4496 if (i % par.m_usedthreads != par.m_no)
4498 if (tab.m_itab[i] == 0)
4500 const ITab& itab = *tab.m_itab[
i];
4501 if (itab.m_type == ITab::OrderedIndex) {
4502 BSet bset(tab, itab);
4503 CHK(scanreadindex(par, itab, bset,
false) == 0);
4505 CHK(hashindexread(par, itab) == 0);
4512 readverifyindex(
Par par)
4516 par.m_verify =
true;
4518 uint sel = urandom(10);
4520 par.m_ordered =
true;
4521 par.m_descending = (sel < 5);
4523 CHK(scanreadindex(par) == 0);
4530 const Tab& tab = par.tab();
4531 par.m_randomkey =
true;
4532 for (uint i = 0; i < par.m_ssloop; i++) {
4534 while (j < tab.m_itabs) {
4535 if (tab.m_itab[j] != 0) {
4536 const ITab& itab = *tab.m_itab[j];
4537 if (itab.m_type == ITab::UniqueHashIndex && urandom(5) == 0)
4542 uint sel = urandom(10);
4543 if (par.m_slno % 2 == 0) {
4546 CHK(pkinsert(par) == 0);
4547 }
else if (sel < 9) {
4548 if (j == tab.m_itabs)
4549 CHK(pkupdate(par) == 0);
4551 const ITab& itab = *tab.m_itab[j];
4552 CHK(hashindexupdate(par, itab) == 0);
4555 if (j == tab.m_itabs)
4556 CHK(pkdelete(par) == 0);
4558 const ITab& itab = *tab.m_itab[j];
4559 CHK(hashindexdelete(par, itab) == 0);
4565 CHK(pkinsert(par) == 0);
4566 }
else if (sel < 2) {
4567 if (j == tab.m_itabs)
4568 CHK(pkupdate(par) == 0);
4570 const ITab& itab = *tab.m_itab[j];
4571 CHK(hashindexupdate(par, itab) == 0);
4574 if (j == tab.m_itabs)
4575 CHK(pkdelete(par) == 0);
4577 const ITab& itab = *tab.m_itab[j];
4578 CHK(hashindexdelete(par, itab) == 0);
4587 pkupdatescanread(
Par par)
4590 par.m_catcherr |= Con::ErrDeadlock;
4591 uint sel = urandom(10);
4593 CHK(pkupdate(par) == 0);
4594 }
else if (sel < 6) {
4595 par.m_verify =
false;
4596 CHK(scanreadtable(par) == 0);
4598 par.m_verify =
false;
4600 par.m_ordered =
true;
4601 par.m_descending = (sel < 7);
4603 CHK(scanreadindex(par) == 0);
4609 mixedoperations(
Par par)
4612 par.m_catcherr |= Con::ErrDeadlock;
4613 par.m_scanstop = par.m_totrows;
4614 uint sel = urandom(10);
4616 CHK(pkdelete(par) == 0);
4617 }
else if (sel < 4) {
4618 CHK(pkupdate(par) == 0);
4619 }
else if (sel < 6) {
4620 CHK(scanupdatetable(par) == 0);
4623 par.m_ordered =
true;
4624 par.m_descending = (sel < 7);
4626 CHK(scanupdateindex(par) == 0);
4632 parallelorderedupdate(
Par par)
4634 const Tab& tab = par.tab();
4636 for (uint i = 0; i < tab.m_itabs; i++) {
4637 if (tab.m_itab[i] == 0)
4639 const ITab& itab = *tab.m_itab[
i];
4640 if (itab.m_type != ITab::OrderedIndex)
4643 if (k++ == par.m_slno % tab.m_orderedindexes) {
4644 LL3(
"parallelorderedupdate: " << itab.m_name);
4645 par.m_noindexkeyupdate =
true;
4646 par.m_ordered =
true;
4647 par.m_descending = (par.m_slno != 0);
4649 par.m_verify =
true;
4650 BSet bset(tab, itab);
4652 uint sel = urandom(10);
4653 CHK(scanupdateindex(par, itab, bset, sel < 2) == 0);
4660 pkupdateindexbuild(
Par par)
4662 if (par.m_no == 0) {
4663 NdbSleep_MilliSleep(10 + urandom(100));
4664 CHK(createindex(par) == 0);
4666 NdbSleep_MilliSleep(10 + urandom(100));
4667 par.m_randomkey =
true;
4668 CHK(pkupdate(par) == 0);
4676 enum Res { Committed, Latest, Deadlock };
4682 static Spt sptlist[] = {
4690 static uint sptcount =
sizeof(sptlist)/
sizeof(sptlist[0]);
4693 savepointreadpk(
Par par,
Spt spt)
4695 LL3(
"savepointreadpk");
4696 Con& con = par.con();
4697 const Tab& tab = par.tab();
4698 Set&
set = par.set();
4699 const Set& set1 =
set;
4700 Set set2(tab,
set.m_rows);
4702 for (uint i = 0; i <
set.m_rows; i++) {
4704 if (!
set.compat(par, i, Row::OpREAD)) {
4705 LL4(
"savepointreadpk SKIP " << i <<
" " <<
set.getrow(i));
4710 CHK(set2.selrow(par, *set1.m_row[i]) == 0);
4711 uint err = par.m_catcherr | Con::ErrDeadlock;
4712 ExecType et = NoCommit;
4713 CHK(con.execute(et, err) == 0);
4715 if (err & Con::ErrDeadlock) {
4716 CHK(spt.m_res == Spt::Deadlock);
4720 LL1(
"savepointreadpk stop on " << con.errname(err));
4724 CHK(set2.getkey(par, &i2) == 0 && i == i2);
4725 CHK(set2.putval(i,
false) == 0);
4726 LL4(
"row " << set2.count() <<
" " << set2.getrow(i));
4730 if (spt.m_res != Spt::Deadlock)
4731 CHK(set1.verify(par, set2,
false, dirty) == 0);
4736 savepointreadhashindex(
Par par,
Spt spt)
4739 LL1(
"skip hash index dirty read");
4742 LL3(
"savepointreadhashindex");
4743 Con& con = par.con();
4744 const Tab& tab = par.tab();
4745 const ITab& itab = par.itab();
4746 Set&
set = par.set();
4747 const Set& set1 =
set;
4748 Set set2(tab,
set.m_rows);
4750 for (uint i = 0; i <
set.m_rows; i++) {
4752 if (!
set.compat(par, i, Row::OpREAD)) {
4753 LL3(
"savepointreadhashindex SKIP " << i <<
" " <<
set.getrow(i));
4758 CHK(set2.selrow(par, itab, *set1.m_row[i]) == 0);
4759 uint err = par.m_catcherr | Con::ErrDeadlock;
4760 ExecType et = NoCommit;
4761 CHK(con.execute(et, err) == 0);
4763 if (err & Con::ErrDeadlock) {
4764 CHK(spt.m_res == Spt::Deadlock);
4768 LL1(
"savepointreadhashindex stop on " << con.errname(err));
4772 CHK(set2.getkey(par, &i2) == 0 && i == i2);
4773 CHK(set2.putval(i,
false) == 0);
4774 LL4(
"row " << set2.count() <<
" " << *set2.m_row[
i]);
4778 if (spt.m_res != Spt::Deadlock)
4779 CHK(set1.verify(par, set2,
false, dirty) == 0);
4784 savepointscantable(
Par par,
Spt spt)
4786 LL3(
"savepointscantable");
4787 Con& con = par.con();
4788 const Tab& tab = par.tab();
4789 const Set&
set = par.set();
4790 const Set& set1 =
set;
4791 Set set2(tab,
set.m_rows);
4792 CHK(con.getNdbScanOperation(tab) == 0);
4793 CHK(con.readTuples(par) == 0);
4795 CHK(con.executeScan() == 0);
4796 bool deadlock =
false;
4800 uint err = par.m_catcherr | Con::ErrDeadlock;
4801 CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
4805 if (err & Con::ErrDeadlock) {
4806 CHK(spt.m_res == Spt::Deadlock);
4811 LL1(
"savepointscantable stop on " << con.errname(err));
4814 CHK(spt.m_res != Spt::Deadlock);
4816 CHK(set2.getkey(par, &i) == 0);
4817 CHK(set2.putval(i,
false, n) == 0);
4818 LL4(
"row " << n <<
" key " << i <<
" " << set2.getrow(i));
4821 if (set1.m_rows > 0) {
4823 CHK(spt.m_res != Spt::Deadlock);
4825 CHK(spt.m_res == Spt::Deadlock);
4827 LL2(
"savepointscantable " << n <<
" rows");
4829 if (spt.m_res != Spt::Deadlock)
4830 CHK(set1.verify(par, set2,
false, dirty) == 0);
4835 savepointscanindex(
Par par,
Spt spt)
4837 LL3(
"savepointscanindex");
4838 Con& con = par.con();
4839 const Tab& tab = par.tab();
4840 const ITab& itab = par.itab();
4841 const Set&
set = par.set();
4842 const Set& set1 =
set;
4843 Set set2(tab,
set.m_rows);
4844 CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
4845 CHK(con.readIndexTuples(par) == 0);
4847 CHK(con.executeScan() == 0);
4848 bool deadlock =
false;
4852 uint err = par.m_catcherr | Con::ErrDeadlock;
4853 CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
4857 if (err & Con::ErrDeadlock) {
4858 CHK(spt.m_res == Spt::Deadlock);
4863 LL1(
"savepointscanindex stop on " << con.errname(err));
4866 CHK(spt.m_res != Spt::Deadlock);
4868 CHK(set2.getkey(par, &i) == 0);
4869 CHK(set2.putval(i, par.m_dups, n) == 0);
4870 LL4(
"row " << n <<
" key " << i <<
" " << set2.getrow(i));
4873 if (set1.m_rows > 0) {
4875 CHK(spt.m_res != Spt::Deadlock);
4877 CHK(spt.m_res == Spt::Deadlock);
4879 LL2(
"savepointscanindex " << n <<
" rows");
4881 if (spt.m_res != Spt::Deadlock)
4882 CHK(set1.verify(par, set2,
false, dirty) == 0);
4886 typedef int (*SptFun)(
Par,
Spt);
4889 savepointtest(Par par,
Spt spt, SptFun fun)
4891 Con& con = par.con();
4897 CHK(con2.startTransaction() == 0);
4899 par2.m_lockmode = spt.m_lm;
4900 CHK((*fun)(par2, spt) == 0);
4902 con2.closeTransaction();
4908 savepointtest(Par par,
const char* op)
4910 Con& con = par.con();
4911 const Tab& tab = par.tab();
4912 Set&
set = par.set();
4913 LL2(
"savepointtest op=\"" << op <<
"\"");
4914 CHK(con.startTransaction() == 0);
4917 while ((c = *p++) != 0) {
4919 for (j = 0; j < par.m_rows; j++) {
4920 uint i = thrrow(par, j);
4922 ExecType et = Commit;
4923 CHK(con.execute(et) == 0);
4927 CHK(con.startTransaction() == 0);
4933 CHK(
set.insrow(par, i) == 0);
4934 }
else if (c ==
'u') {
4935 set.copyval(i, tab.m_pkmask);
4936 set.calc(par, i, ~tab.m_pkmask);
4937 CHK(
set.updrow(par, i) == 0);
4938 }
else if (c ==
'd') {
4939 set.copyval(i, tab.m_pkmask);
4940 CHK(
set.delrow(par, i) == 0);
4949 ExecType et = NoCommit;
4950 CHK(con.execute(et) == 0);
4955 for (uint k = 0; k < sptcount; k++) {
4956 Spt spt = sptlist[k];
4957 LL2(
"spt lm=" << spt.m_lm <<
" same=" << spt.m_same);
4958 CHK(savepointtest(par, spt, &savepointreadpk) == 0);
4959 CHK(savepointtest(par, spt, &savepointscantable) == 0);
4960 for (uint i = 0; i < tab.m_itabs; i++) {
4961 if (tab.m_itab[i] == 0)
4963 const ITab& itab = *tab.m_itab[
i];
4965 if (itab.m_type == ITab::OrderedIndex)
4966 CHK(savepointtest(par, spt, &savepointscanindex) == 0);
4968 CHK(savepointtest(par, spt, &savepointreadhashindex) == 0);
4973 ExecType et = Rollback;
4974 CHK(con.execute(et) == 0);
4979 con.closeTransaction();
4984 savepointtest(Par par)
4986 assert(par.m_usedthreads == 1);
4987 const char* oplist[] = {
4997 for (i = 0; oplist[
i] != 0; i++) {
4998 CHK(savepointtest(par, oplist[i]) == 0);
5004 halloweentest(Par par,
const ITab& itab)
5006 LL2(
"halloweentest " << itab.m_name);
5007 Con& con = par.con();
5008 const Tab& tab = par.tab();
5009 Set&
set = par.set();
5010 CHK(con.startTransaction() == 0);
5015 CHK(
set.insrow(par, i) == 0);
5016 CHK(con.execute(NoCommit) == 0);
5024 Set set1(tab,
set.m_rows);
5025 Set set2(tab,
set.m_rows);
5026 BSet bset(tab, itab);
5027 calcscanbounds(par, itab, bset,
set, set1);
5028 CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
5029 CHK(con.readIndexTuples(par) == 0);
5030 CHK(bset.setbnd(par) == 0);
5032 CHK(con.executeScan() == 0);
5033 const uint savepoint =
i;
5034 LL3(
"scancount=" << scancount <<
" savepoint=" << savepoint);
5038 CHK((ret = con.nextScanResult(
true)) == 0 || ret == 1);
5042 CHK(set2.getkey(par, &k) == 0);
5043 CHK(set2.putval(k,
false, n) == 0);
5044 LL3(
"row=" << n <<
" key=" << k);
5045 CHK(k <= savepoint);
5046 if (++i ==
set.m_rows) {
5052 CHK(
set.insrow(par, i) == 0);
5053 CHK(con.execute(NoCommit) == 0);
5057 LL3(
"scanrows=" << n);
5059 CHK(set1.verify(par, set2,
false) == 0);
5063 CHK(con.execute(Commit) == 0);
5064 set.post(par, Commit);
5065 assert(
set.count() ==
set.m_rows);
5066 CHK(pkdelete(par) == 0);
5071 halloweentest(Par par)
5073 assert(par.m_usedthreads == 1);
5074 const Tab& tab = par.tab();
5075 for (uint i = 0; i < tab.m_itabs; i++) {
5076 if (tab.m_itab[i] == 0)
5078 const ITab& itab = *tab.m_itab[
i];
5079 if (itab.m_type == ITab::OrderedIndex)
5080 CHK(halloweentest(par, itab) == 0);
5087 typedef int (*TFunc)(Par par);
5088 enum TMode { ST = 1, MT = 2 };
5090 extern "C" {
static void* runthread(
void* arg); }
5093 enum State { Wait, Start, Stop, Exit };
5104 Thr(Par par, uint n);
5112 NdbMutex_Lock(m_mutex);
5115 NdbMutex_Unlock(m_mutex);
5118 NdbCondition_Wait(m_cond, m_mutex);
5121 NdbCondition_Signal(m_cond);
5124 NdbThread_WaitFor(m_thread, &m_status);
5129 Thr::Thr(Par par, uint n) :
5141 sprintf(buf,
"thr%03u", par.m_no);
5142 const char* name = strcpy(
new char[10], buf);
5144 m_mutex = NdbMutex_Create();
5145 m_cond = NdbCondition_Create();
5146 assert(m_mutex != 0 && m_cond != 0);
5148 const uint stacksize = 256 * 1024;
5149 const NDB_THREAD_PRIO prio = NDB_THREAD_PRIO_LOW;
5150 m_thread = NdbThread_Create(runthread, (
void**)
this, stacksize, name, prio);
5155 if (m_thread != 0) {
5156 NdbThread_Destroy(&m_thread);
5160 NdbCondition_Destroy(m_cond);
5164 NdbMutex_Destroy(m_mutex);
5170 runthread(
void* arg)
5173 thr.m_id = pthread_self();
5174 if (thr.run() < 0) {
5175 LL1(
"exit on error");
5187 CHK(con.connect() == 0);
5192 while (m_state != Start && m_state != Exit) {
5196 if (m_state == Exit) {
5202 assert(m_state == Start);
5203 m_ret = (*m_func)(m_par);
5210 LL1(
"continue running due to -cont");
5232 while (m_state != Stop)
5249 static Thr** g_thrlist = 0;
5254 if (g_thrlist != 0) {
5255 pthread_t
id = pthread_self();
5256 for (uint n = 0; n < g_opt.m_threads; n++) {
5257 if (g_thrlist[n] != 0) {
5258 Thr& thr = *g_thrlist[
n];
5259 if (pthread_equal(thr.m_id,
id))
5271 Thr* thrp = getthr();
5274 uint n = thr.m_par.m_no;
5276 g_opt.m_threads < 10 ? 1 :
5277 g_opt.m_threads < 100 ? 2 : 3;
5278 sprintf(thr.m_tmp,
"[%0*u] ", m, n);
5285 runstep(Par par,
const char* fname, TFunc func, uint
mode)
5287 LL2(
"step: " << fname);
5288 const int threads = (mode & ST ? 1 : par.m_usedthreads);
5290 for (n = 0; n < threads; n++) {
5292 Thr& thr = *g_thrlist[
n];
5293 Par oldpar = thr.m_par;
5296 thr.m_par.m_no = oldpar.m_no;
5297 thr.m_par.m_con = oldpar.m_con;
5302 for (n = threads - 1; n >= 0; n--) {
5304 Thr& thr = *g_thrlist[
n];
5313 #define RUNSTEP(par, func, mode) \
5314 CHK(runstep(par, #func, func, mode) == 0)
5316 #define SUBLOOP(par) \
5317 "sloop: " << par.m_lno << "/" << par.m_currcase << "/" << \
5318 par.m_tab->m_name << "/" << par.m_slno
5323 RUNSTEP(par, droptable, ST);
5324 RUNSTEP(par, createtable, ST);
5325 RUNSTEP(par, invalidatetable, MT);
5326 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5328 if (par.m_slno % 3 == 0) {
5329 RUNSTEP(par, createindex, ST);
5330 RUNSTEP(par, invalidateindex, MT);
5331 RUNSTEP(par, pkinsert, MT);
5332 RUNSTEP(par, pkupdate, MT);
5333 }
else if (par.m_slno % 3 == 1) {
5334 RUNSTEP(par, pkinsert, MT);
5335 RUNSTEP(par, createindex, ST);
5336 RUNSTEP(par, invalidateindex, MT);
5337 RUNSTEP(par, pkupdate, MT);
5339 RUNSTEP(par, pkinsert, MT);
5340 RUNSTEP(par, pkupdate, MT);
5341 RUNSTEP(par, createindex, ST);
5342 RUNSTEP(par, invalidateindex, MT);
5344 RUNSTEP(par, readverifyfull, MT);
5346 if (par.m_slno + 1 < par.m_sloop) {
5347 RUNSTEP(par, pkdelete, MT);
5348 RUNSTEP(par, readverifyfull, MT);
5349 RUNSTEP(par, dropindex, ST);
5358 RUNSTEP(par, droptable, ST);
5359 RUNSTEP(par, createtable, ST);
5360 RUNSTEP(par, invalidatetable, MT);
5361 RUNSTEP(par, createindex, ST);
5362 RUNSTEP(par, invalidateindex, MT);
5363 RUNSTEP(par, pkinsert, MT);
5364 RUNSTEP(par, readverifyfull, MT);
5365 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5367 RUNSTEP(par, readverifyindex, MT);
5376 RUNSTEP(par, droptable, ST);
5377 RUNSTEP(par, createtable, ST);
5378 RUNSTEP(par, invalidatetable, MT);
5379 RUNSTEP(par, createindex, ST);
5380 RUNSTEP(par, invalidateindex, MT);
5381 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5383 RUNSTEP(par, pkops, MT);
5384 LL2(
"rows=" << par.set().count());
5385 RUNSTEP(par, readverifyfull, MT);
5393 RUNSTEP(par, droptable, ST);
5394 RUNSTEP(par, createtable, ST);
5395 RUNSTEP(par, invalidatetable, MT);
5396 RUNSTEP(par, pkinsert, MT);
5397 RUNSTEP(par, createindex, ST);
5398 RUNSTEP(par, invalidateindex, MT);
5399 RUNSTEP(par, readverifyfull, MT);
5400 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5402 RUNSTEP(par, pkupdatescanread, MT);
5403 RUNSTEP(par, readverifyfull, MT);
5405 RUNSTEP(par, pkdelete, MT);
5406 RUNSTEP(par, readverifyfull, MT);
5413 RUNSTEP(par, droptable, ST);
5414 RUNSTEP(par, createtable, ST);
5415 RUNSTEP(par, invalidatetable, MT);
5416 RUNSTEP(par, pkinsert, MT);
5417 RUNSTEP(par, createindex, ST);
5418 RUNSTEP(par, invalidateindex, MT);
5419 RUNSTEP(par, readverifyfull, MT);
5420 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5422 RUNSTEP(par, mixedoperations, MT);
5423 RUNSTEP(par, readverifyfull, MT);
5431 RUNSTEP(par, droptable, ST);
5432 RUNSTEP(par, createtable, ST);
5433 RUNSTEP(par, invalidatetable, MT);
5434 RUNSTEP(par, pkinsert, MT);
5435 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5437 RUNSTEP(par, pkupdateindexbuild, MT);
5438 RUNSTEP(par, invalidateindex, MT);
5439 RUNSTEP(par, readverifyfull, MT);
5440 RUNSTEP(par, dropindex, ST);
5448 par.m_abortpct = 50;
5449 RUNSTEP(par, droptable, ST);
5450 RUNSTEP(par, createtable, ST);
5451 RUNSTEP(par, invalidatetable, MT);
5452 RUNSTEP(par, pkinsert, MT);
5453 RUNSTEP(par, createindex, ST);
5454 RUNSTEP(par, invalidateindex, MT);
5455 RUNSTEP(par, readverifyfull, MT);
5456 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5458 RUNSTEP(par, mixedoperations, MT);
5459 RUNSTEP(par, readverifyfull, MT);
5467 RUNSTEP(par, droptable, ST);
5468 RUNSTEP(par, createtable, ST);
5469 RUNSTEP(par, invalidatetable, MT);
5470 RUNSTEP(par, pkinsert, MT);
5471 RUNSTEP(par, createindex, ST);
5472 RUNSTEP(par, invalidateindex, MT);
5473 RUNSTEP(par, readverifyfull, MT);
5474 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5476 RUNSTEP(par, parallelorderedupdate, MT);
5477 RUNSTEP(par, readverifyfull, MT);
5485 RUNSTEP(par, droptable, ST);
5486 RUNSTEP(par, createtable, ST);
5487 RUNSTEP(par, invalidatetable, MT);
5488 RUNSTEP(par, createindex, ST);
5489 RUNSTEP(par, invalidateindex, MT);
5490 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5492 RUNSTEP(par, savepointtest, MT);
5493 RUNSTEP(par, readverifyfull, MT);
5501 RUNSTEP(par, droptable, ST);
5502 RUNSTEP(par, createtable, ST);
5503 RUNSTEP(par, invalidatetable, MT);
5504 RUNSTEP(par, createindex, ST);
5505 RUNSTEP(par, invalidateindex, MT);
5506 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5508 RUNSTEP(par, halloweentest, MT);
5517 RUNSTEP(par, droptable, ST);
5518 RUNSTEP(par, createtable, ST);
5519 RUNSTEP(par, invalidatetable, MT);
5520 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5522 RUNSTEP(par, pkinsert, MT);
5524 RUNSTEP(par, createindex, ST);
5525 t1.off(par.m_totrows);
5526 RUNSTEP(par, invalidateindex, MT);
5527 RUNSTEP(par, dropindex, ST);
5529 LL1(
"build index - " << t1.time());
5537 RUNSTEP(par, droptable, ST);
5538 RUNSTEP(par, createtable, ST);
5539 RUNSTEP(par, invalidatetable, MT);
5540 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5542 RUNSTEP(par, pkinsert, MT);
5544 RUNSTEP(par, pkupdate, MT);
5545 t1.off(par.m_totrows);
5546 RUNSTEP(par, createindex, ST);
5547 RUNSTEP(par, invalidateindex, MT);
5549 RUNSTEP(par, pkupdate, MT);
5550 t2.off(par.m_totrows);
5551 RUNSTEP(par, dropindex, ST);
5553 LL1(
"update - " << t1.time());
5554 LL1(
"update indexed - " << t2.time());
5555 LL1(
"overhead - " << t2.over(t1));
5562 if (par.tab().m_itab[0] == 0) {
5563 LL1(
"ttimescan - no index 0, skipped");
5567 RUNSTEP(par, droptable, ST);
5568 RUNSTEP(par, createtable, ST);
5569 RUNSTEP(par, invalidatetable, MT);
5570 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5572 RUNSTEP(par, pkinsert, MT);
5573 RUNSTEP(par, createindex, ST);
5575 RUNSTEP(par, timescantable, ST);
5577 RUNSTEP(par, timescanpkindex, ST);
5578 RUNSTEP(par, dropindex, ST);
5580 LL1(
"full scan table - " << t1.time());
5581 LL1(
"full scan PK index - " << t2.time());
5582 LL1(
"overhead - " << t2.over(t1));
5587 ttimepkread(Par par)
5589 if (par.tab().m_itab[0] == 0) {
5590 LL1(
"ttimescan - no index 0, skipped");
5594 RUNSTEP(par, droptable, ST);
5595 RUNSTEP(par, createtable, ST);
5596 RUNSTEP(par, invalidatetable, MT);
5597 for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
5599 RUNSTEP(par, pkinsert, MT);
5600 RUNSTEP(par, createindex, ST);
5602 RUNSTEP(par, timepkreadtable, ST);
5604 RUNSTEP(par, timepkreadindex, ST);
5605 RUNSTEP(par, dropindex, ST);
5607 LL1(
"pk read table - " << t1.time());
5608 LL1(
"pk read PK index - " << t2.time());
5609 LL1(
"overhead - " << t2.over(t1));
5616 RUNSTEP(par, droptable, ST);
5624 TCase(
const char* name, TFunc func,
const char* desc) :
5633 TCase(
"a", tbuild,
"index build"),
5634 TCase(
"b", tindexscan,
"index scans"),
5635 TCase(
"c", tpkops,
"pk operations"),
5636 TCase(
"d", tpkopsread,
"pk operations and scan reads"),
5637 TCase(
"e", tmixedops,
"pk operations and scan operations"),
5638 TCase(
"f", tbusybuild,
"pk operations and index build"),
5639 TCase(
"g", trollback,
"operations with random rollbacks"),
5640 TCase(
"h", tparupdate,
"parallel ordered update bug#20446"),
5641 TCase(
"i", tsavepoint,
"savepoint test locking bug#31477"),
5642 TCase(
"j", thalloween,
"savepoint test halloween problem"),
5643 TCase(
"t", ttimebuild,
"time index build"),
5644 TCase(
"u", ttimemaint,
"time index maintenance"),
5645 TCase(
"v", ttimescan,
"time full scan table vs index on pk"),
5646 TCase(
"w", ttimepkread,
"time pk read table vs index on pk"),
5647 TCase(
"z", tdrop,
"drop test tables")
5651 tcasecount =
sizeof(tcaselist) /
sizeof(tcaselist[0]);
5656 ndbout <<
"test cases:" << endl;
5657 for (uint i = 0; i < tcasecount; i++) {
5658 const TCase& tcase = tcaselist[
i];
5659 ndbout <<
" " << tcase.m_name <<
" - " << tcase.m_desc << endl;
5667 makebuiltintables(par);
5668 ndbout <<
"tables and indexes (x=ordered z=hash x0=on pk):" << endl;
5669 for (uint j = 0; j < tabcount; j++) {
5670 if (tablist[j] == 0)
5672 const Tab& tab = *tablist[j];
5673 const char* tname = tab.m_name;
5674 ndbout <<
" " << tname;
5675 for (uint i = 0; i < tab.m_itabs; i++) {
5676 if (tab.m_itab[i] == 0)
5678 const ITab& itab = *tab.m_itab[
i];
5679 const char* iname = itab.m_name;
5680 if (strncmp(tname, iname, strlen(tname)) == 0)
5681 iname += strlen(tname);
5682 ndbout <<
" " << iname;
5684 for (uint k = 0; k < itab.m_icols; k++) {
5687 const ICol& icol = *itab.m_icol[k];
5688 const Col& col = icol.m_col;
5689 ndbout << col.m_name;
5698 setcasepar(Par& par)
5701 const char* c = par.m_currcase;
5705 if (par.m_usedthreads > 1) {
5706 par.m_usedthreads = 1;
5707 LL1(
"case " << c <<
" reduce threads to " << par.m_usedthreads);
5709 const uint rows = 100;
5710 if (par.m_rows > rows) {
5712 LL1(
"case " << c <<
" reduce rows to " << rows);
5718 if (par.m_usedthreads > 1) {
5719 par.m_usedthreads = 1;
5720 LL1(
"case " << c <<
" reduce threads to " << par.m_usedthreads);
5734 if (par.m_seed == -1) {
5736 ushort seed = (ushort)getpid();
5737 LL0(
"random seed: " << seed);
5738 srandom((uint)seed);
5739 }
else if (par.m_seed != 0) {
5740 LL0(
"random seed: " << par.m_seed);
5741 srandom(par.m_seed);
5743 LL0(
"random seed: loop number");
5746 assert(par.m_csname != 0);
5747 if (strcmp(par.m_csname,
"random") != 0) {
5749 CHK((cs = get_charset_by_name(par.m_csname, MYF(0))) != 0 || (cs = get_charset_by_csname(par.m_csname, MY_CS_PRIMARY, MYF(0))) != 0);
5754 CHK(con.connect() == 0);
5756 par.m_catcherr |= Con::ErrNospace;
5758 g_thrlist =
new Thr* [par.m_threads];
5760 for (n = 0; n < par.m_threads; n++) {
5763 for (n = 0; n < par.m_threads; n++) {
5764 g_thrlist[
n] =
new Thr(par, n);
5765 Thr& thr = *g_thrlist[
n];
5766 assert(thr.m_thread != 0);
5768 for (par.m_lno = 0; par.m_loop == 0 || par.m_lno < par.m_loop; par.m_lno++) {
5769 LL1(
"loop: " << par.m_lno);
5770 if (par.m_seed == 0) {
5771 LL1(
"random seed: " << par.m_lno);
5774 for (uint i = 0; i < tcasecount; i++) {
5775 const TCase& tcase = tcaselist[
i];
5776 if ((par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0) ||
5777 (par.m_skip != 0 && strchr(par.m_skip, tcase.m_name[0]) != 0)) {
5780 sprintf(par.m_currcase,
"%c", tcase.m_name[0]);
5781 par.m_usedthreads = par.m_threads;
5782 if (!setcasepar(par)) {
5783 LL1(
"case " << tcase.m_name <<
" cannot run with given options");
5786 par.m_totrows = par.m_usedthreads * par.m_rows;
5787 makebuiltintables(par);
5788 LL1(
"case: " << par.m_lno <<
"/" << tcase.m_name <<
" - " << tcase.m_desc);
5789 for (uint j = 0; j < tabcount; j++) {
5790 if (tablist[j] == 0)
5792 const Tab& tab = *tablist[j];
5794 par.m_set =
new Set(tab, par.m_totrows);
5795 LL1(
"table: " << par.m_lno <<
"/" << tcase.m_name <<
"/" << tab.m_name);
5796 int ret = tcase.m_func(par);
5803 LL1(
"continue to next case due to -cont");
5809 for (n = 0; n < par.m_threads; n++) {
5810 Thr& thr = *g_thrlist[
n];
5813 for (n = 0; n < par.m_threads; n++) {
5814 Thr& thr = *g_thrlist[
n];
5818 delete [] g_thrlist;
5824 static const char* g_progname =
"testOIBasic";
5827 main(
int argc,
char** argv)
5831 ndbout << g_progname;
5832 for (i = 1; i < (uint) argc; i++)
5833 ndbout <<
" " << argv[i];
5835 ndbout_mutex = NdbMutex_Create();
5836 while (++argv, --argc > 0) {
5837 const char* arg = argv[0];
5839 ndbout <<
"testOIBasic: unknown argument " << arg;
5842 if (strcmp(arg,
"-batch") == 0) {
5843 if (++argv, --argc > 0) {
5844 g_opt.m_batch = atoi(argv[0]);
5848 if (strcmp(arg,
"-bound") == 0) {
5849 if (++argv, --argc > 0) {
5850 const char* p = argv[0];
5851 if (strlen(p) != 0 && strlen(p) == strspn(p,
"01234")) {
5852 g_opt.m_bound = strdup(p);
5857 if (strcmp(arg,
"-case") == 0) {
5858 if (++argv, --argc > 0) {
5859 g_opt.m_case = strdup(argv[0]);
5863 if (strcmp(arg,
"-collsp") == 0) {
5864 g_opt.m_collsp =
true;
5867 if (strcmp(arg,
"-cont") == 0) {
5868 g_opt.m_cont =
true;
5871 if (strcmp(arg,
"-core") == 0) {
5872 g_opt.m_core =
true;
5875 if (strcmp(arg,
"-csname") == 0) {
5876 if (++argv, --argc > 0) {
5877 g_opt.m_csname = strdup(argv[0]);
5881 if (strcmp(arg,
"-die") == 0) {
5882 if (++argv, --argc > 0) {
5883 g_opt.m_die = atoi(argv[0]);
5887 if (strcmp(arg,
"-dups") == 0) {
5888 g_opt.m_dups =
true;
5891 if (strcmp(arg,
"-fragtype") == 0) {
5892 if (++argv, --argc > 0) {
5893 if (strcmp(argv[0],
"single") == 0) {
5897 if (strcmp(argv[0],
"small") == 0) {
5901 if (strcmp(argv[0],
"medium") == 0) {
5905 if (strcmp(argv[0],
"large") == 0) {
5911 if (strcmp(arg,
"-index") == 0) {
5912 if (++argv, --argc > 0) {
5913 g_opt.m_index = strdup(argv[0]);
5917 if (strcmp(arg,
"-loop") == 0) {
5918 if (++argv, --argc > 0) {
5919 g_opt.m_loop = atoi(argv[0]);
5923 if (strcmp(arg,
"-mrrmaxrng") == 0) {
5924 if (++argv, --argc > 0) {
5925 g_opt.m_mrrmaxrng = atoi(argv[0]);
5929 if (strcmp(arg,
"-nologging") == 0) {
5930 g_opt.m_nologging =
true;
5933 if (strcmp(arg,
"-noverify") == 0) {
5934 g_opt.m_noverify =
true;
5937 if (strcmp(arg,
"-pctmrr") == 0) {
5938 if (++argv, --argc > 0) {
5939 g_opt.m_pctmrr = atoi(argv[0]);
5943 if (strcmp(arg,
"-pctnull") == 0) {
5944 if (++argv, --argc > 0) {
5945 g_opt.m_pctnull = atoi(argv[0]);
5949 if (strcmp(arg,
"-rows") == 0) {
5950 if (++argv, --argc > 0) {
5951 g_opt.m_rows = atoi(argv[0]);
5955 if (strcmp(arg,
"-samples") == 0) {
5956 if (++argv, --argc > 0) {
5957 g_opt.m_samples = atoi(argv[0]);
5961 if (strcmp(arg,
"-scanbatch") == 0) {
5962 if (++argv, --argc > 0) {
5963 g_opt.m_scanbatch = atoi(argv[0]);
5967 if (strcmp(arg,
"-scanpar") == 0) {
5968 if (++argv, --argc > 0) {
5969 g_opt.m_scanpar = atoi(argv[0]);
5973 if (strcmp(arg,
"-seed") == 0) {
5974 if (++argv, --argc > 0) {
5975 g_opt.m_seed = atoi(argv[0]);
5979 if (strcmp(arg,
"-skip") == 0) {
5980 if (++argv, --argc > 0) {
5981 g_opt.m_skip = strdup(argv[0]);
5985 if (strcmp(arg,
"-sloop") == 0) {
5986 if (++argv, --argc > 0) {
5987 g_opt.m_sloop = atoi(argv[0]);
5991 if (strcmp(arg,
"-ssloop") == 0) {
5992 if (++argv, --argc > 0) {
5993 g_opt.m_ssloop = atoi(argv[0]);
5997 if (strcmp(arg,
"-table") == 0) {
5998 if (++argv, --argc > 0) {
5999 g_opt.m_table = strdup(argv[0]);
6003 if (strcmp(arg,
"-threads") == 0) {
6004 if (++argv, --argc > 0) {
6005 g_opt.m_threads = atoi(argv[0]);
6006 if (1 <= g_opt.m_threads)
6010 if (strcmp(arg,
"-v") == 0) {
6011 if (++argv, --argc > 0) {
6012 g_opt.m_v = atoi(argv[0]);
6016 if (strncmp(arg,
"-v", 2) == 0 && isdigit(arg[2])) {
6017 g_opt.m_v = atoi(&arg[2]);
6020 if (strcmp(arg,
"-h") == 0 || strcmp(arg,
"-help") == 0) {
6024 ndbout <<
"testOIBasic: bad or unknown option " << arg;
6030 if (g_ncc->
connect(30) != 0 || runtest(par) < 0)
6036 return NDBT_ProgramExit(NDBT_OK);
6038 return NDBT_ProgramExit(NDBT_FAILED);
6040 ndbout <<
" (use -h for help)" << endl;
6042 return NDBT_ProgramExit(NDBT_WRONGARGS);