18 #include <ndb_global.h> 
   21 #include <NdbIndexStat.hpp> 
   22 #include <NdbTest.hpp> 
   23 #include <ndb_version.h> 
   24 #include <NDBT_Stats.hpp> 
   29 #define min(a, b) ((a) <= (b) ? (a) : (b)) 
   30 #define max(a, b) ((a) >= (b) ? (a) : (b)) 
   33 NdbOut::operator<<(
double x)
 
   36   sprintf(buf, 
"%.2f", x);
 
   75 static uint g_loop = 0;
 
   77 static const char* g_tabname = 
"ts1";
 
   78 static const char* g_indname = 
"ts1x1";
 
   79 static const uint g_numattrs = 3;
 
   80 static const uint g_charlen = 10;
 
   81 static const char* g_csname = 
"latin1_swedish_ci";
 
   85 static const bool g_b_nullable = 
true;
 
   86 static const bool g_c_nullable = 
true;
 
   87 static const bool g_d_nullable = 
true;
 
  100 static Lim g_lim_bnd;
 
  103 static Ndb* g_ndb = 0;
 
  104 static Ndb* g_ndb_sys = 0;
 
  117   char m_c[1+g_charlen];
 
  121 static const Uint32 g_ndbrec_a_offset=offsetof(
my_record, m_a);
 
  122 static const Uint32 g_ndbrec_b_offset=offsetof(
my_record, m_b);
 
  123 static const Uint32 g_ndbrec_b_nb_offset=1;
 
  124 static const Uint32 g_ndbrec_c_offset=offsetof(
my_record, m_c);
 
  125 static const Uint32 g_ndbrec_c_nb_offset=2;
 
  126 static const Uint32 g_ndbrec_d_offset=offsetof(
my_record, m_d);
 
  127 static const Uint32 g_ndbrec_d_nb_offset=3;
 
  128 static const Uint32 g_ndbrecord_bytes=
sizeof(
my_record);
 
  136 static bool g_has_created_stat_tables = 
false;
 
  137 static bool g_has_created_stat_events = 
false;
 
  142   uint r = (uint)random();
 
  156 static int& g_loglevel = g_opts.loglevel; 
 
  159   do { if (likely(x)) break; ndbout << "line " << __LINE__ << " FAIL " << #x << endl; errdb(); if (g_opts.abort) abort(); return -1; } while (0) 
  162   do { if (likely(x)) break; ndbout << "line " << __LINE__ << " FAIL " << #x << endl; ndbout << "errno: " << errno; if (g_opts.abort) abort(); return -1; } while (0) 
  165   do { if (likely(x)) break; ndbout << "line " << __LINE__ << " FAIL " << #x << endl; if (g_opts.abort) abort(); return -1; } while (0) 
  168   do { if (likely(g_loglevel < n)) break; ndbout << x << endl; } while (0) 
  170 #define ll0(x) llx(0, x) 
  171 #define ll1(x) llx(1, x) 
  172 #define ll2(x) llx(2, x) 
  173 #define ll3(x) llx(3, x) 
  181     e.
code = g_ncc->get_latest_error();
 
  182     e.
message = g_ncc->get_latest_error_msg();
 
  184       ll0(++any << 
" ncc: error" << e);
 
  189       ll0(++any << 
" ndb: error " << e);
 
  194       ll0(++any << 
" dic: error " << e);
 
  199       ll0(++any << 
" con: error " << e);
 
  204       ll0(++any << 
" op: error " << e);
 
  206   if (g_scan_op != 0) {
 
  209       ll0(++any << 
" scan_op: error " << e);
 
  211   if (g_rangescan_op != 0) {
 
  214       ll0(++any << 
" rangescan_op: error " << e);
 
  219       ll0(++any << 
" stat: error " << e);
 
  222     ll0(
"unknown db error");
 
  229   ll1(
"createNdbRecords");
 
  230   const Uint32 numCols=4;
 
  231   const Uint32 numIndexCols=3;
 
  234   recSpec[0].column= g_tab->
getColumn(
"a"); 
 
  235   recSpec[0].offset= g_ndbrec_a_offset;
 
  236   recSpec[0].nullbit_byte_offset= ~(Uint32)0;
 
  237   recSpec[0].nullbit_bit_in_byte= ~(Uint32)0;
 
  239   recSpec[1].column= g_tab->
getColumn(
"b"); 
 
  240   recSpec[1].offset= g_ndbrec_b_offset;
 
  242     recSpec[1].nullbit_byte_offset= 0;
 
  243     recSpec[1].nullbit_bit_in_byte= g_ndbrec_b_nb_offset;
 
  245     recSpec[1].nullbit_byte_offset= ~(Uint32)0;
 
  246     recSpec[1].nullbit_bit_in_byte= ~(Uint32)0;
 
  249   recSpec[2].column= g_tab->
getColumn(
"c"); 
 
  250   recSpec[2].offset= g_ndbrec_c_offset;
 
  252     recSpec[2].nullbit_byte_offset= 0;
 
  253     recSpec[2].nullbit_bit_in_byte= g_ndbrec_c_nb_offset;
 
  255     recSpec[2].nullbit_byte_offset= ~(Uint32)0;
 
  256     recSpec[2].nullbit_bit_in_byte= ~(Uint32)0;
 
  259   recSpec[3].column= g_tab->
getColumn(
"d"); 
 
  260   recSpec[3].offset= g_ndbrec_d_offset;
 
  262     recSpec[3].nullbit_byte_offset= 0;
 
  263     recSpec[3].nullbit_bit_in_byte= g_ndbrec_d_nb_offset;
 
  265     recSpec[3].nullbit_byte_offset= ~(Uint32)0;
 
  266     recSpec[3].nullbit_bit_in_byte= ~(Uint32)0;
 
  270   g_tab_rec= g_dic->createRecord(g_tab,
 
  276   chkdb(g_tab_rec != NULL);
 
  278   g_ind_rec= g_dic->createRecord(g_ind,
 
  284   chkdb(g_ind_rec != NULL);
 
  300   tab.setLogging(
false);
 
  304     col.setPrimaryKey(
true);
 
  310     col.setNullable(g_b_nullable);
 
  316     col.setLength(g_charlen);
 
  317     col.setCharset(g_cs);
 
  318     col.setNullable(g_c_nullable);
 
  324     col.setNullable(g_d_nullable);
 
  329   if (g_dic->
getTable(g_tabname) != 0)
 
  332   chkdb((g_tab = g_dic->
getTable(g_tabname)) != 0);
 
  342   ind.setTable(g_tabname);
 
  344   ind.setLogging(
false);
 
  345   ind.addColumnName(
"b");
 
  346   ind.addColumnName(
"c");
 
  347   ind.addColumnName(
"d");
 
  351   chkdb((g_ind = g_dic->
getIndex(g_indname, g_tabname)) != 0);
 
  374   uchar c[1 + g_charlen];
 
  378   void copy(
const Val& val2);
 
  379   void make(uint numattrs, 
const Lim& lim);
 
  380   int cmp(
const Val& val2, uint numattrs = g_numattrs, uint* num_eq = 0) 
const;
 
  384   Val& operator=(
const Val&);
 
  389 operator<<(NdbOut& out, 
const Val& val)
 
  392   if (val.m_numattrs >= 1) {
 
  398   if (val.m_numattrs >= 2) {
 
  403       char buf[1 + g_charlen];
 
  404       sprintf(buf, 
"%.*s", val.c[0], &val.c[1]);
 
  405       out << 
"'" << buf << 
"'";
 
  408   if (val.m_numattrs >= 3) {
 
  433   memset(c, 0xff, 
sizeof(c));
 
  438 Val::copy(
const Val& val2)
 
  440   require(
this != &val2);
 
  442   m_numattrs = val2.m_numattrs;
 
  443   if (m_numattrs >= 1) {
 
  444     require(val2.b_null == 0 || val2.b_null == 1);
 
  445     b_null = val2.b_null;
 
  449   if (m_numattrs >= 2) {
 
  450     require(val2.c_null == 0 || val2.c_null == 1);
 
  451     c_null = val2.c_null;
 
  453       memcpy(c, val2.c, 
sizeof(c));
 
  455   if (m_numattrs >= 3) {
 
  456     require(val2.d_null == 0 || val2.d_null == 1);
 
  457     d_null = val2.d_null;
 
  464 Val::make(uint numattrs, 
const Lim& lim)
 
  466   require(numattrs <= g_numattrs);
 
  468     const bool nullable = g_b_nullable || lim.all_nullable;
 
  469     if (nullable && urandom(100) < g_opts.nullkeys)
 
  472       require(lim.b_min <= lim.b_max);
 
  473       b = lim.b_min + urandom(lim.b_max - lim.b_min + 1);
 
  478     const bool nullable = g_c_nullable || lim.all_nullable;
 
  479     if (nullable && urandom(100) < g_opts.nullkeys)
 
  483       const uint len = urandom(urandom(g_charlen + 1) + 1);
 
  485       for (uint j = 0; j < len; j++) {
 
  486         uint k = urandom(strlen(lim.c_char));
 
  487         c[1 + j] = lim.c_char[k];
 
  493     const bool nullable = g_d_nullable || lim.all_nullable;
 
  494     if (nullable && urandom(100) < g_opts.nullkeys)
 
  497       require(lim.d_min <= lim.d_max);
 
  498       d = lim.d_min + urandom(lim.d_max - lim.d_min + 1);
 
  502   m_numattrs = numattrs;
 
  506 Val::cmp(
const Val& val2, uint numattrs, uint* num_eq)
 const 
  508   require(numattrs <= m_numattrs);
 
  509   require(numattrs <= val2.m_numattrs);
 
  512   if (k == 0 && numattrs >= 1) {
 
  513     if (! b_null && ! val2.b_null) {
 
  518     } 
else if (! b_null) {
 
  520     } 
else if (! val2.b_null) {
 
  526   if (k == 0 && numattrs >= 2) {
 
  527     if (! c_null && ! val2.c_null) {
 
  528       const uchar* s1 = &c[1];
 
  529       const uchar* s2 = &val2.c[1];
 
  530       const uint l1 = (uint)c[0];
 
  531       const uint l2 = (uint)val2.c[0];
 
  532       assert(l1 <= g_charlen && l2 <= g_charlen);
 
  533       k = g_cs->coll->strnncollsp(g_cs, s1, l1, s2, l2, 0);
 
  534     } 
else if (! c_null) {
 
  536     } 
else if (! val2.c_null) {
 
  542   if (k == 0 && numattrs >= 3) {
 
  543     if (! d_null && ! val2.d_null) {
 
  548     } 
else if (! d_null) {
 
  550     } 
else if (! val2.d_null) {
 
  556   require(n <= numattrs);
 
  565   const char* key = (j == 0 ? ib.low_key : ib.high_key);
 
  566   const uint numattrs = (j == 0 ? ib.low_key_count : ib.high_key_count);
 
  567   const Uint8 nullbits = *(
const Uint8*)key;
 
  568   require(numattrs <= g_numattrs);
 
  570     if (nullbits & (1 << g_ndbrec_b_nb_offset))
 
  573       memcpy(&b, &key[g_ndbrec_b_offset], 
sizeof(b));
 
  578     if (nullbits & (1 << g_ndbrec_c_nb_offset))
 
  581       memcpy(c, &key[g_ndbrec_c_offset], 
sizeof(c));
 
  586     if (nullbits & (1 << g_ndbrec_d_nb_offset))
 
  589       memcpy(&d, &key[g_ndbrec_d_offset], 
sizeof(d));
 
  593   m_numattrs = numattrs;
 
  604   Key& operator=(
const Key&);
 
  609 operator<<(NdbOut& out, 
const Key& key)
 
  612   if (key.m_flag != -1)
 
  613     out << 
" flag: " << key.m_flag;
 
  622 static Key* g_keys = 0;
 
  623 static uint* g_sortkeys = 0;
 
  629   delete [] g_sortkeys;
 
  638   g_keys = 
new Key [g_opts.rows];
 
  639   g_sortkeys = 
new uint [g_opts.rows];
 
  640   require(g_keys != 0 && g_sortkeys != 0);
 
  641   memset(g_sortkeys, 0xff, 
sizeof(uint) * g_opts.rows);
 
  645 cmpkeys(
const void* p1, 
const void* p2)
 
  647   const uint i1 = *(
const uint*)p1;
 
  648   const uint i2 = *(
const uint*)p2;
 
  649   require(i1 < g_opts.rows && i2 < g_opts.rows);
 
  650   const Key& key1 = g_keys[i1];
 
  651   const Key& key2 = g_keys[i2];
 
  652   const int k = key1.m_val.cmp(key2.m_val, g_opts.attrs);
 
  663   for (i = 0; i < g_opts.rows; i++)
 
  665   qsort(g_sortkeys, g_opts.rows, 
sizeof(uint), cmpkeys);
 
  669   for (i = 1; i < g_opts.rows; i++) {
 
  670     const uint i1 = g_sortkeys[i - 1];
 
  671     const uint i2 = g_sortkeys[
i];
 
  672     require(i1 < g_opts.rows && i2 < g_opts.rows);
 
  673     const Key& key1 = g_keys[i1];
 
  674     const Key& key2 = g_keys[i2];
 
  675     const int k = key1.m_val.cmp(key2.m_val, g_opts.attrs);
 
  682   ll1(
"minkey:" << g_keys[g_sortkeys[0]]);
 
  683   ll1(
"maxkey:" << g_keys[g_sortkeys[g_opts.rows - 1]]);
 
  684   ll1(
"unique:" << unique);
 
  692   uint initrows = g_opts.rows / g_opts.rpk;
 
  693   require(initrows != 0);
 
  697   while (i < initrows) {
 
  698     Key& key = g_keys[
i];
 
  699     key.m_val.make(g_numattrs, g_lim_val);
 
  704   while (i < g_opts.rows) {
 
  706     double a = (double)(1 + urandom(g_opts.rpkvar * g_opts.rpkvar));
 
  707     double b = a / (double)g_opts.rpkvar;
 
  708     double c = b * (
double)g_opts.rpk;
 
  709     const uint n = (uint)(c + 0.5);
 
  711     const uint k = urandom(initrows);
 
  713     while (i < g_opts.rows && j < n) {
 
  714       g_keys[
i].m_val.copy(g_keys[k].m_val);
 
  722   while (i < g_opts.rows) {
 
  723     uint j = urandom(g_opts.rows);
 
  726       tmp.m_val.copy(g_keys[i].m_val);
 
  727       g_keys[
i].m_val.copy(g_keys[j].m_val);
 
  728       g_keys[j].m_val.copy(tmp.m_val);
 
  748   val.m_numattrs = g_numattrs;
 
  749   char* a_addr = (
char*)&a;
 
  750   char* b_addr = (
char*)&val.b;
 
  751   char* c_addr = (
char*)val.c;
 
  752   char* d_addr = (
char*)&val.d;
 
  757   chkdb(g_scan_op->
getValue(no++, a_addr) != 0);
 
  758   chkdb((b_ra = g_scan_op->
getValue(no++, b_addr)) != 0);
 
  759   chkdb((c_ra = g_scan_op->
getValue(no++, c_addr)) != 0);
 
  760   chkdb((d_ra = g_scan_op->
getValue(no++, d_addr)) != 0);
 
  764   for (i = 0; i < g_opts.rows; i++) {
 
  765     Key& key = g_keys[
i];
 
  771     chkdb((ret = g_scan_op->
nextResult()) == 0 || ret == 1);
 
  774     val.b_null = b_ra->isNULL();
 
  775     val.c_null = c_ra->isNULL();
 
  776     val.d_null = d_ra->isNULL();
 
  777     require(val.b_null == 0 || (g_b_nullable && val.b_null == 1));
 
  778     require(val.c_null == 0 || (g_c_nullable && val.c_null == 1));
 
  779     require(val.d_null == 0 || (g_d_nullable && val.d_null == 1));
 
  781     chkrc(i < g_opts.rows);
 
  782     Key& key = g_keys[
i];
 
  783     chkrc(key.m_val.cmp(val) == 0);
 
  784     chkrc(key.m_flag == 
false);
 
  791   for (i = 0; i < g_opts.rows; i++) {
 
  792     Key& key = g_keys[
i];
 
  793     chkrc(key.m_flag == 
true);
 
  796   assert(count == g_opts.rows);
 
  797   ll3(
"verifydata: " << g_opts.rows << 
" rows");
 
  802 loaddata(
bool update)
 
  804   ll1(
"loaddata: update: " << update);
 
  805   const uint batch = 512;
 
  808   while (i < g_opts.rows) {
 
  815     const Val& val = g_keys[
i].m_val;
 
  816     const char* a_addr = (
const char*)&a;
 
  817     const char* b_addr = ! val.b_null ? (
const char*)&val.b : 0;
 
  818     const char* c_addr = ! val.c_null ? (
const char*)val.c : 0;
 
  819     const char* d_addr = ! val.d_null ? (
const char*)&val.d : 0;
 
  821     chkdb(g_op->
equal(no++, a_addr) == 0);
 
  822     chkdb(g_op->
setValue(no++, b_addr) == 0);
 
  823     chkdb(g_op->
setValue(no++, c_addr) == 0);
 
  824     chkdb(g_op->
setValue(no++, d_addr) == 0);
 
  825     if (i++ % batch == 0) {
 
  839   chkrc(verifydata() == 0);
 
  841   for (uint i = 0; i < g_opts.rows; i++)
 
  842     ll3(
"load " << i << 
": " << g_keys[i]);
 
  843   ll0(
"loaddata: " << g_opts.rows << 
" rows");
 
  879   bool isempty() 
const;
 
  880   void copy(
const Bnd& bnd2); 
 
  881   Bnd& make(uint minattrs);
 
  882   Bnd& make(uint minattrs, 
const Val& theval);
 
  883   int cmp(
const Key& key) 
const;
 
  884   int cmp(
const Bnd& bnd2);
 
  885   int type(uint colno) 
const; 
 
  889   Bnd& operator=(
const Bnd&);
 
  894 operator<<(NdbOut& out, 
const Bnd& bnd)
 
  898   else if (bnd.m_lohi == 1)
 
  901     out << bnd.m_lohi << 
"?";
 
  905   else if (bnd.m_side == -1)
 
  907   else if (bnd.m_side == +1)
 
  921   return m_val.m_numattrs == 0;
 
  925 Bnd::copy(
const Bnd& bnd2)
 
  927   m_val.copy(bnd2.m_val);
 
  928   m_side = bnd2.m_side;
 
  932 Bnd::make(uint minattrs)
 
  934   require(minattrs <= g_opts.attrs);
 
  935   require(m_lohi == 0 || m_lohi == 1);
 
  936   uint numattrs = minattrs + urandom(g_numattrs - minattrs + 1);
 
  937   m_val.make(numattrs, g_lim_bnd);
 
  938   m_side = m_val.m_numattrs == 0 ? 0 : urandom(2) == 0 ? -1 : +1;
 
  943 Bnd::make(uint minattrs, 
const Val& theval)
 
  945   uint numattrs = minattrs + urandom(g_numattrs - minattrs);
 
  947   m_val.m_numattrs = numattrs;
 
  948   m_side = m_val.m_numattrs == 0 ? 0 : urandom(2) == 0 ? -1 : +1;
 
  953 Bnd::cmp(
const Key& key)
 const 
  958     int k = key.m_val.cmp(m_val, m_val.m_numattrs);
 
  971     assert(m_val.m_numattrs == 0);
 
  973   ll3(
"bnd: " << *
this << 
" cmp key: " << key
 
  974       << 
" ret: " << ret << 
" place: " << place);
 
  979 Bnd::cmp(
const Bnd& bnd2)
 
  983   const Bnd& bnd1 = *
this;
 
  984   const Val& val1 = bnd1.m_val;
 
  985   const Val& val2 = bnd2.m_val;
 
  986   const uint numattrs1 = val1.m_numattrs;
 
  987   const uint numattrs2 = val2.m_numattrs;
 
  988   const uint n = (numattrs1 < numattrs2 ? numattrs1 : numattrs2);
 
  990     int k = val1.cmp(val2, n);
 
  996     if (numattrs1 < numattrs2) {
 
  998       ret = (+1) * bnd1.m_side;
 
 1001     if (numattrs1 > numattrs2) {
 
 1003       ret = (-1) * bnd1.m_side;
 
 1006     if (bnd1.m_side < bnd2.m_side) {
 
 1011     if (bnd1.m_side > bnd2.m_side) {
 
 1019   ll3(
"bnd: " << *
this << 
" cmp bnd: " << bnd2
 
 1020       << 
" ret: " << ret << 
" place: " << place);
 
 1025 Bnd::type(uint colno)
 const 
 1028   require(colno < m_val.m_numattrs && (m_side == -1 || m_side == +1));
 
 1029   require(m_lohi == 0 || m_lohi == 1);
 
 1031     if (colno + 1 < m_val.m_numattrs)
 
 1033     else if (m_side == -1)
 
 1038     if (colno + 1 < m_val.m_numattrs)
 
 1040     else if (m_side == +1)
 
 1053   const uint numattrs = (j == 0 ? ib.low_key_count : ib.high_key_count);
 
 1054   const bool inclusive = (j == 0 ? ib.low_inclusive : ib.high_inclusive);
 
 1055   if (numattrs == 0) {
 
 1058     m_side = (j == 0 ? (inclusive ? -1 : +1) : (inclusive ? +1 : -1));
 
 1068   double rpk[g_numattrs];
 
 1070   char rule[NdbIndexStat::RuleBufferBytes];
 
 1075 operator<<(NdbOut& out, 
const Stval& st)
 
 1077   out << 
"rir_v2: " << st.rir_v2;
 
 1078   out << 
" rir_v4: " << st.rir;
 
 1080   for (uint k = 0; k < g_opts.attrs; k++) {
 
 1086   out << 
" " << (st.empty ? 
"E" : 
"N");
 
 1087   out << 
" " << st.rule;
 
 1095   for (uint k = 0; k < g_numattrs; k++)
 
 1112   uint minattrs() 
const;
 
 1113   uint maxattrs() 
const;
 
 1115   bool isempty() 
const;
 
 1116   void copy(
const Rng& rng2);
 
 1117   int cmp(
const Key& key) 
const; 
 
 1118   uint rowcount() 
const;
 
 1122   Rng& operator=(
const Rng&);
 
 1127 operator<<(NdbOut& out, 
const Rng& rng)
 
 1129   out << rng.m_bnd[0] << 
" " << rng.m_bnd[1];
 
 1130   if (rng.m_rowcount != -1)
 
 1131     out << 
" rows: " << rng.m_rowcount;
 
 1137   m_bnd[0].m_lohi = 0;
 
 1138   m_bnd[1].m_lohi = 1;
 
 1143 Rng::minattrs()
 const 
 1145   return min(m_bnd[0].m_val.m_numattrs, m_bnd[1].m_val.m_numattrs);
 
 1149 Rng::maxattrs()
 const 
 1151   return max(m_bnd[0].m_val.m_numattrs, m_bnd[1].m_val.m_numattrs);
 
 1158     minattrs() == maxattrs() &&
 
 1159     m_bnd[0].m_val.cmp(m_bnd[1].m_val, minattrs()) == 0 &&
 
 1160     m_bnd[0].m_side < m_bnd[1].m_side;
 
 1164 Rng::isempty()
 const 
 1166   return m_bnd[0].isempty() && m_bnd[1].isempty();
 
 1170 Rng::copy(
const Rng& rng2)
 
 1172   m_bnd[0].copy(rng2.m_bnd[0]);
 
 1173   m_bnd[1].copy(rng2.m_bnd[1]);
 
 1174   m_rowcount = rng2.m_rowcount;
 
 1178 Rng::cmp(
const Key& key)
 const 
 1184     k = m_bnd[0].cmp(key);
 
 1190     k = m_bnd[1].cmp(key);
 
 1199   ll3(
"rng: " << *
this << 
" cmp key: " << key
 
 1200       << 
" ret: " << ret << 
" place: " << place);
 
 1205 Rng::rowcount()
 const 
 1207   ll3(
"rowcount: " << *
this);
 
 1211   for (i = 0; i <= 1; i++) {
 
 1212     ll3(
"search i=" << i);
 
 1214     int hi = (int)g_opts.rows;
 
 1219       require(lo < j && j < hi);
 
 1220       ret = cmp(g_keys[g_sortkeys[j]]);
 
 1232     } 
while (hi - lo > 1);
 
 1242   const bool verify = (urandom(10) == 0);
 
 1243   const int lo = max(lim[0], 0);
 
 1244   const int hi = min(lim[1], (
int)g_opts.rows - 1);
 
 1247     for (i = 0; i < (int)g_opts.rows; i++) {
 
 1248       int k = cmp(g_keys[g_sortkeys[i]]);
 
 1252         require(lo <= i && i <= hi);
 
 1262   require(hi - lo + 1 >= 0);
 
 1263   uint count = hi - lo + 1;
 
 1264   ll3(
"rowcount: " << count << 
" lim: " << lim[0] << 
" " << lim[1]);
 
 1271   for (uint j = 0; j <= 1; j++) {
 
 1272     Bnd& bnd = m_bnd[j];
 
 1277 static Rng* g_rnglist = 0;
 
 1282   delete [] g_rnglist;
 
 1290   g_rnglist = 
new Rng [g_opts.ops];
 
 1291   require(g_rnglist != 0);
 
 1298   const uint mintries = 20;
 
 1299   const uint maxtries = 80;
 
 1300   const uint fudgefac = 10;
 
 1302   for (uint i = 0; i < g_opts.ops; i++) {
 
 1303     const bool eqpart = (urandom(100) < g_opts.eqscans);
 
 1304     const bool eqfull = eqpart && (urandom(100) < g_opts.eqscans);
 
 1307     for (j = 0; j < maxtries; j++) {
 
 1310         rng2.m_bnd[0].make(0);
 
 1311         rng2.m_bnd[1].make(0);
 
 1313         const uint mincnt = eqfull ? g_opts.attrs : 1;
 
 1314         rng2.m_bnd[0].make(mincnt);
 
 1315         rng2.m_bnd[1].copy(rng2.m_bnd[0]);
 
 1316         rng2.m_bnd[0].m_side = -1;
 
 1317         rng2.m_bnd[1].m_side = +1;
 
 1318         require(rng2.iseq());
 
 1320       rng2.m_rowcount = (Int32)rng2.rowcount();
 
 1325         if (rng.m_rowcount == -1) {
 
 1329         require(rng.m_rowcount != -1);
 
 1331         if (rng2.isempty()) {
 
 1332           if (urandom(fudgefac) != 0)
 
 1339         if (rng2.m_rowcount == 0) {
 
 1344         require((uint)rng2.m_rowcount <= g_opts.rows);
 
 1345         if (100 * (uint)rng2.m_rowcount <= g_opts.scanpct * g_opts.rows) {
 
 1346           if (urandom(fudgefac) != 0) {
 
 1352         if (rng2.m_rowcount < rng.m_rowcount) {
 
 1353           if (urandom(fudgefac) != 0) {
 
 1361         if (action == 2 || j >= mintries)
 
 1365     g_rnglist[
i].copy(rng);
 
 1366     ll2(
"rng " << i << 
": " << rng << 
" tries: " << j);
 
 1373 setbounds(
const Rng& rng)
 
 1376   ll3(
"setbounds: " << rng);
 
 1378   const Bnd (&bnd)[2] = rng.m_bnd;
 
 1379   for (i = 0; i < g_numattrs; i++) {
 
 1380     const Uint32 no = 
i; 
 
 1382     int type[2] = { -1, -1 };
 
 1385     for (j = 0; j <= 1; j++) {
 
 1386       if (no < bnd[j].m_val.m_numattrs)
 
 1387         type[j] = bnd[j].type(no);
 
 1389     for (j = 0; j <= 1; j++) {
 
 1393       if (no + 1 < bnd[j].m_val.m_numattrs)
 
 1395       const Val& val = bnd[j].m_val;
 
 1396       const void* addr = 0;
 
 1398         addr = ! val.b_null ? (
const void*)&val.b : 0;
 
 1400         addr = ! val.c_null ? (
const void*)val.c : 0;
 
 1402         addr = ! val.d_null ? (
const void*)&val.d : 0;
 
 1405       ll3(
"setBound attr:" << no << 
" type:" << t << 
" val: " << val);
 
 1406       chkdb(g_rangescan_op->
setBound(no, t, addr) == 0);
 
 1413 scanrange(
const Rng& rng)
 
 1415   ll3(
"scanrange: " << rng);
 
 1419   chkrc(setbounds(rng) == 0);
 
 1421   char* a_addr = (
char*)&a;
 
 1423   chkdb(g_rangescan_op->
getValue(no++, a_addr) != 0);
 
 1427   for (i = 0; i < g_opts.rows; i++) {
 
 1428     Key& key = g_keys[
i];
 
 1434     chkdb((ret = g_rangescan_op->
nextResult()) == 0 || ret == 1);
 
 1438     chkrc(i < g_opts.rows);
 
 1439     Key& key = g_keys[
i];
 
 1440     ll3(
"scan: " << key);
 
 1441     int k = rng.cmp(key);
 
 1443     chkrc(key.m_flag == 
false);
 
 1451   for (i = 0; i < g_opts.rows; i++) {
 
 1452     Key& key = g_keys[
i];
 
 1453     int k = rng.cmp(key);
 
 1455       chkrc(key.m_flag == 
false);
 
 1457       chkrc(key.m_flag == 
true);
 
 1460   require((uint)rng.m_rowcount == count);
 
 1468   for (uint i = 0; i < g_opts.ops; i++) {
 
 1469     const Rng& rng = g_rnglist[
i];
 
 1470     chkrc(scanrange(rng) == 0);
 
 1481   require(g_is != 0 && g_ind != 0 && g_tab != 0);
 
 1482   chkdb(g_is->set_index(*g_ind, *g_tab) == 0);
 
 1490   if (urandom(2) == 0) {
 
 1492     chkdb(g_dic->updateIndexStat(*g_ind, *g_tab) == 0);
 
 1495     chkdb(g_is->update_stat(g_ndb_sys) == 0);
 
 1506   chkdb(g_is->read_head(g_ndb_sys) == 0);
 
 1507   g_is->get_head(head);
 
 1508   chkrc(head.m_found == 
true);
 
 1509   chkrc(head.m_sampleVersion != 0);
 
 1511       << 
" sampleVersion: " << head.m_sampleVersion
 
 1512       << 
" sampleCount: " << head.m_sampleCount);
 
 1515   chkdb(g_is->read_stat(g_ndb_sys) == 0);
 
 1517   g_is->get_cache_info(infoQuery, NdbIndexStat::CacheQuery);
 
 1518   ll1(
"readstat: cache bytes: " << infoQuery.m_totalBytes);
 
 1527   ll1(
"startlistener");
 
 1528   chkdb(g_is->create_listener(g_ndb_sys) == 0);
 
 1529   chkdb(g_is->execute_listener(g_ndb_sys) == 0);
 
 1538   chkdb((ret = g_is->poll_listener(g_ndb_sys, 10000)) != -1);
 
 1541   chkdb((ret = g_is->next_listener(g_ndb_sys)) != -1);
 
 1543   chkdb((ret = g_is->next_listener(g_ndb_sys)) != -1);
 
 1551   ll1(
"stoplistener");
 
 1552   chkdb(g_is->drop_listener(g_ndb_sys) != -1);
 
 1565   uint unq[g_numattrs];
 
 1567   for (uint k = 0; k < g_opts.attrs; k++)
 
 1570   for (uint i = 0; i < g_opts.rows; i++) {
 
 1571     const Key& key = g_keys[g_sortkeys[
i]];
 
 1572     int res = rng.cmp(key);
 
 1577       for (uint k = 0; k < g_opts.attrs; k++)
 
 1581       int res = prevkey.m_val.cmp(key.m_val, g_opts.attrs, &num_eq);
 
 1583         require(num_eq == g_opts.attrs);
 
 1586         require(num_eq < g_opts.attrs);
 
 1589         for (uint k = num_eq + 1; k < g_opts.attrs; k++)
 
 1593     prevkey.m_val.copy(key.m_val);
 
 1595   require(rng.m_rowcount != -1);
 
 1596   require((uint)rng.m_rowcount == rir);
 
 1598   Stval& st = rng.m_st_scan;
 
 1600   st.rir = rir == 0 ? 1.0 : (double)rir;
 
 1601   for (uint k = 0; k < g_opts.attrs; k++) {
 
 1605       require(rir >= unq[k]);
 
 1606       require(unq[k] != 0);
 
 1607       st.rpk[k] = (double)rir / (
double)unq[k];
 
 1610   st.empty = (rir == 0);
 
 1611   ll2(
"queryscan: " << st);
 
 1621 initialiseIndexBound(
const Rng& rng, 
 
 1625   ll3(
"initialiseIndexBound: " << rng);
 
 1627   const Bnd (&bnd)[2] = rng.m_bnd;
 
 1628   Uint32 colsInBound[2]= {0, 0};
 
 1629   bool boundInclusive[2]= {
false, 
false};
 
 1631   memset(&ib, 0xf1, 
sizeof(ib));
 
 1632   memset(low_key, 0xf2, 
sizeof(*low_key));
 
 1633   memset(high_key, 0xf3, 
sizeof(*high_key));
 
 1636   low_key->m_null_bm = 0;
 
 1637   high_key->m_null_bm = 0;
 
 1639   for (i = 0; i < g_numattrs; i++) {
 
 1640     const Uint32 no = 
i; 
 
 1642     int type[2] = { -1, -1 };
 
 1645     for (j = 0; j <= 1; j++) {
 
 1646       if (no < bnd[j].m_val.m_numattrs)
 
 1647         type[j] = bnd[j].type(no);
 
 1649     for (j = 0; j <= 1; j++) {
 
 1651       my_record* keyBuf= (j==0) ? low_key : high_key;
 
 1657       if (no + 1 >= bnd[j].m_val.m_numattrs)
 
 1660         boundInclusive[j]= !(t & 1);
 
 1662       const Val& val = bnd[j].m_val;
 
 1669           keyBuf->m_null_bm |= ((val.b_null?1:0) << g_ndbrec_b_nb_offset);
 
 1674           memcpy(&keyBuf->m_c[0], (
const void*)&val.c, 1+ g_charlen);
 
 1677           keyBuf->m_null_bm |= ((val.c_null?1:0) << g_ndbrec_c_nb_offset);
 
 1685           keyBuf->m_null_bm |= ((val.d_null?1:0) << g_ndbrec_d_nb_offset);
 
 1689       ll3(
"initialiseIndexBound attr:" << no << 
" type:" << t << 
" val: " << val);
 
 1694   ib.low_key = (
char*)low_key;
 
 1695   ib.low_key_count= colsInBound[0];
 
 1696   ib.low_inclusive= boundInclusive[0];
 
 1697   ib.high_key = (
char*)high_key;
 
 1698   ib.high_key_count= colsInBound[1];
 
 1699   ib.high_inclusive= boundInclusive[1];
 
 1702   ll3(
" indexBound low_key_count=" << ib.low_key_count << 
 
 1703       " low_inc=" << ib.low_inclusive <<
 
 1704       " high_key_count=" << ib.high_key_count <<
 
 1705       " high_inc=" << ib.high_inclusive);
 
 1706   ll3(
" low bound b=" << *((Uint32*) &ib.low_key[g_ndbrec_b_offset]) <<
 
 1707       " d=" << *((Uint16*) &ib.low_key[g_ndbrec_d_offset]) <<
 
 1708       " first byte=" << ib.low_key[0]);
 
 1709   ll3(
" high bound b=" << *((Uint32*) &ib.high_key[g_ndbrec_b_offset]) <<
 
 1710       " d=" << *((Uint16*) &ib.high_key[g_ndbrec_d_offset]) <<
 
 1711       " first byte=" << ib.high_key[0]);  
 
 1717     require(rng.m_bnd[0].cmp(bnd[0]) == 0);
 
 1718     require(rng.m_bnd[1].cmp(bnd[1]) == 0);
 
 1724 querystat_v2(
Rng& rng)
 
 1726   ll3(
"querystat_v2");
 
 1734   chkrc(initialiseIndexBound(rng, ib, &low_key, &high_key) == 0);
 
 1736   Uint64 count = ~(Uint64)0;
 
 1737   chkdb(g_is->records_in_range(g_ind, 
 
 1749   Stval& st = rng.m_st_stat;
 
 1750   chkrc(count < (1 << 30));
 
 1752   ll2(
"querystat_v2: " << st.rir_v2 << 
" rows");
 
 1762   Uint8 bound_lo_buffer[NdbIndexStat::BoundBufferBytes];
 
 1763   Uint8 bound_hi_buffer[NdbIndexStat::BoundBufferBytes];
 
 1772   chkrc(initialiseIndexBound(rng, ib, &low_key, &high_key) == 0);
 
 1773   chkrc(g_is->convert_range(range, g_ind_rec, &ib) == 0);
 
 1776   Uint8 stat_buffer[NdbIndexStat::StatBufferBytes];
 
 1778   chkdb(g_is->query_stat(range, stat) == 0);
 
 1781   Stval& st = rng.m_st_stat;
 
 1782   g_is->get_rir(stat, &st.rir);
 
 1783   for (uint k = 0; k < g_opts.attrs; k++) {
 
 1784     g_is->get_rpk(stat, k, &st.rpk[k]);
 
 1786   g_is->get_empty(stat, &st.empty);
 
 1787   g_is->get_rule(stat, st.rule);
 
 1789   ll2(
"querystat: " << st);
 
 1797   for (uint i = 0; i < g_opts.ops; i++) {
 
 1798     Rng& rng = g_rnglist[
i];
 
 1799     ll1(
"rng " << i << 
": " << rng);
 
 1803     chkrc(querystat_v2(rng) == 0);
 
 1804     chkrc(querystat(rng) == 0);
 
 1805     const Stval& st1 = rng.m_st_scan;
 
 1806     const Stval& st2 = rng.m_st_stat;
 
 1808     chkrc(st2.rir_v2 != 0 || st1.rir_v2 == 0);
 
 1817   void add(
double x2);
 
 1818   void add(
const Stats& sum2);
 
 1822 operator<<(NdbOut& out, 
const Stats& st)
 
 1824   out << 
"count: " << st.getCount()
 
 1825       << 
" min: " << st.getMin()
 
 1826       << 
" max: " << st.getMax()
 
 1827       << 
" mean: " << st.getMean()
 
 1828       << 
" stddev: " << st.getStddev();
 
 1837 Stats::add(
double x2)
 
 1843 Stats::add(
const Stats& st2)
 
 1853   Stats rpk[g_numattrs];
 
 1855   void add(
const Sterr& st2);
 
 1859 operator<<(NdbOut& out, 
const Sterr& st)
 
 1861   out << 
"rir_v2: " << st.rir_v2 << endl;
 
 1862   out << 
"rir_v4: " << st.rir;
 
 1863   for (uint k = 0; k < g_opts.attrs; k++) {
 
 1864     out << endl << 
"rpk[" << k << 
"]: " << st.rpk[k];
 
 1874 Sterr::add(
const Sterr& st2)
 
 1876   rir_v2.add(st2.rir_v2);
 
 1878   for (uint k = 0; k < g_opts.attrs; k++) {
 
 1879     rpk[k].add(st2.rpk[k]);
 
 1884 sumrange(
const Rng& rng, 
Sterr& st)
 
 1886   const Stval& st1 = rng.m_st_scan;
 
 1887   const Stval& st2 = rng.m_st_stat;
 
 1891     double rows = (double)g_opts.rows;
 
 1892     double x1 = (
double)st1.rir_v2;
 
 1893     double x2 = (double)st2.rir_v2;
 
 1894     double x3 = 100.0 * (x2 - x1) / rows;
 
 1900     double rows = (double)g_opts.rows;
 
 1901     double x1 = st1.rir;
 
 1902     double x2 = st2.rir;
 
 1903     double x3 = 100.0 * (x2 - x1) / rows;
 
 1908   for (uint k = 0; k < g_opts.attrs; k++) {
 
 1909     double x1 = st1.rpk[k];
 
 1910     double x2 = st2.rpk[k];
 
 1911     double x3 = (x2 - x1);
 
 1917 sumranges(
Sterr& st)
 
 1919   for (uint i = 0; i < g_opts.ops; i++) {
 
 1920     const Rng& rng = g_rnglist[
i];
 
 1927 static Sterr g_sterr;
 
 1934   if (g_opts.loops != 1) {
 
 1935     ll0(
"=== loop " << g_loop << 
" summary ===");
 
 1946   if (g_opts.dump == 0)
 
 1950                          "%s.key.%d", g_opts.dump, g_loop);
 
 1952     chker((f = fopen(file, 
"w")) != 0);
 
 1954     for (uint k = 0; k < g_opts.attrs; k++) {
 
 1956         fprintf(f, 
",b_null,b");
 
 1958         fprintf(f, 
",c_null,c");
 
 1960         fprintf(f, 
",d_null,d");
 
 1965     for (uint i = 0; i < g_opts.rows; i++) {
 
 1966       const Key& key = g_keys[g_sortkeys[
i]];
 
 1967       const Val& val = key.m_val;
 
 1968       fprintf(f, 
"%u", i);
 
 1969       for (uint k = 0; k < g_opts.attrs; k++) {
 
 1971           fprintf(f, 
",%d,", val.b_null);
 
 1973             fprintf(f, 
"%u", val.b);
 
 1974         } 
else if (k == 1) {
 
 1975           fprintf(f, 
",%d,", val.c_null);
 
 1977             fprintf(f, 
"%.*s", val.c[0], &val.c[1]);
 
 1978         } 
else if (k == 2) {
 
 1979           fprintf(f, 
",%d,", val.d_null);
 
 1981             fprintf(f, 
"%u", val.d);
 
 1988     chker(fclose(f) == 0);
 
 1992                          "%s.range.%d", g_opts.dump, g_loop);
 
 1994     chker((f = fopen(file, 
"w")) != 0);
 
 1996     for (uint j = 0; j <= 1; j++) {
 
 1997       const char* suf = (j == 0 ? 
"_lo" : 
"_hi");
 
 1998       fprintf(f, 
",attrs%s", suf);
 
 1999       for (uint k = 0; k < g_opts.attrs; k++) {
 
 2001           fprintf(f, 
",b_null%s,b%s", suf, suf);
 
 2003           fprintf(f, 
",c_null%s,c%s", suf, suf);
 
 2005           fprintf(f, 
",d_null%s,d%s", suf, suf);
 
 2009       fprintf(f, 
",side%s", suf);
 
 2012     for (uint i = 0; i < g_opts.ops; i++) {
 
 2013       const Rng& rng = g_rnglist[
i];
 
 2014       fprintf(f, 
"%u", i);
 
 2015       for (uint j = 0; j <= 1; j++) {
 
 2016         const Bnd& bnd = rng.m_bnd[j];
 
 2017         const Val& val = bnd.m_val;
 
 2018         fprintf(f, 
",%u", val.m_numattrs);
 
 2019         for (uint k = 0; k < g_opts.attrs; k++) {
 
 2020           if (k >= val.m_numattrs)
 
 2023             fprintf(f, 
",%d,", val.b_null);
 
 2025               fprintf(f, 
"%u", val.b);
 
 2026           } 
else if (k == 1) {
 
 2027             fprintf(f, 
",%d,", val.c_null);
 
 2029               fprintf(f, 
"%.*s", val.c[0], &val.c[1]);
 
 2030           } 
else if (k == 2) {
 
 2031             fprintf(f, 
",%d,", val.d_null);
 
 2033               fprintf(f, 
"%u", val.d);
 
 2038         fprintf(f, 
",%d", bnd.m_side);
 
 2042     chker(fclose(f) == 0);
 
 2046                          "%s.stat.%d", g_opts.dump, g_loop);
 
 2048     chker((f = fopen(file, 
"w")) != 0);
 
 2050     for (uint j = 0; j <= 1; j++) {
 
 2051       const char* suf = (j == 0 ? 
"_scan" : 
"_stat");
 
 2052       fprintf(f, 
",rir_v2%s", suf);
 
 2053       fprintf(f, 
",rir%s", suf);
 
 2054       for (uint k = 0; k < g_opts.attrs; k++) {
 
 2055         fprintf(f, 
",rpk_%u%s", k, suf);
 
 2057       fprintf(f, 
",empty%s", suf);
 
 2059         fprintf(f, 
",rule%s", suf);
 
 2062     for (uint i = 0; i < g_opts.ops; i++) {
 
 2063       const Rng& rng = g_rnglist[
i];
 
 2064       fprintf(f, 
"%u", i);
 
 2065       for (uint j = 0; j <= 1; j++) {
 
 2066         const Stval& st = (j == 0 ? rng.m_st_scan : rng.m_st_stat);
 
 2067         fprintf(f, 
",%u", st.rir_v2);
 
 2068         fprintf(f, 
",%.2f", st.rir);
 
 2069         for (uint k = 0; k < g_opts.attrs; k++) {
 
 2070           fprintf(f, 
",%.2f", st.rpk[k]);
 
 2072         fprintf(f, 
",%d", st.empty);
 
 2074           fprintf(f, 
",%s", st.rule);
 
 2078     chker(fclose(f) == 0);
 
 2086   ll0(
"=== summary ===");
 
 2093   ll1(
"sizeof Val: " << 
sizeof(
Val));
 
 2094   ll1(
"sizeof Key: " << 
sizeof(
Key));
 
 2095   ll1(
"sizeof Bnd: " << 
sizeof(
Bnd));
 
 2096   ll1(
"sizeof Rng: " << 
sizeof(
Rng));
 
 2098   uint seed = g_opts.seed;
 
 2101       seed = 2 + (ushort)getpid();
 
 2103     ll0(
"random seed is " << seed);
 
 2106     ll0(
"random seed is " << 
"loop number");
 
 2108   g_cs = get_charset_by_name(g_csname, MYF(0));
 
 2110     g_cs = get_charset_by_csname(g_csname, MY_CS_PRIMARY, MYF(0));
 
 2115   chkrc(createtable() == 0);
 
 2116   chkrc(createindex() == 0);
 
 2117   chkrc(createNdbRecords() == 0);
 
 2118   chkrc(definestat() == 0);
 
 2119   chkrc(startlistener() == 0);
 
 2121   for (g_loop = 0; g_opts.loops == 0 || g_loop < g_opts.loops; g_loop++) {
 
 2122     ll0(
"=== loop " << g_loop << 
" ===");
 
 2123     uint seed = g_opts.seed;
 
 2129     chkrc(loaddata(g_loop != 0) == 0);
 
 2131     chkrc(scanranges() == 0);
 
 2132     chkrc(updatestat() == 0);
 
 2133     chkrc(runlistener() == 0);
 
 2134     chkrc(readstat() == 0);
 
 2135     chkrc(queryranges() == 0);
 
 2137     chkrc(loopdumps() == 0);
 
 2141   chkrc(stoplistener() == 0);
 
 2142   if (!g_opts.keeptable)
 
 2143     chkrc(droptable() == 0);
 
 2153   require(g_ncc != 0);
 
 2154   chkdb(g_ncc->
connect(30) == 0);
 
 2155   g_ndb = 
new Ndb(g_ncc, 
"TEST_DB");
 
 2156   require(g_ndb != 0);
 
 2157   chkdb(g_ndb->init() == 0 && g_ndb->waitUntilReady(30) == 0);
 
 2158   g_ndb_sys = 
new Ndb(g_ncc, 
"mysql");
 
 2159   require(g_ndb_sys != 0);
 
 2160   chkdb(g_ndb_sys->init() == 0 && g_ndb_sys->waitUntilReady(30) == 0);
 
 2178   NDB_STD_OPTS(
"testIndexStat"),
 
 2179   { 
"loglevel", NDB_OPT_NOSHORT,
 
 2180     "Logging level in this program 0-3 (default 0)",
 
 2181     (uchar **)&g_opts.loglevel, (uchar **)&g_opts.loglevel, 0,
 
 2182     GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
 2183   { 
"seed", NDB_OPT_NOSHORT, 
"Random seed (default 0=random, 1=loop number)",
 
 2184     (uchar **)&g_opts.seed, (uchar **)&g_opts.seed, 0,
 
 2185     GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
 2186   { 
"loops", NDB_OPT_NOSHORT, 
"Number of test loops (default 1, 0=forever)",
 
 2187     (uchar **)&g_opts.loops, (uchar **)&g_opts.loops, 0,
 
 2188     GET_INT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0 },
 
 2189   { 
"rows", NDB_OPT_NOSHORT, 
"Number of rows (default 10000)",
 
 2190     (uchar **)&g_opts.rows, (uchar **)&g_opts.rows, 0,
 
 2191     GET_UINT, REQUIRED_ARG, 100000, 0, 0, 0, 0, 0 },
 
 2192   { 
"ops", NDB_OPT_NOSHORT,
"Number of index scans per loop (default 100)",
 
 2193     (uchar **)&g_opts.ops, (uchar **)&g_opts.ops, 0,
 
 2194     GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0 },
 
 2195   { 
"nullkeys", NDB_OPT_NOSHORT, 
"Pct nulls in each key attribute (default 10)",
 
 2196     (uchar **)&g_opts.nullkeys, (uchar **)&g_opts.nullkeys, 0,
 
 2197     GET_UINT, REQUIRED_ARG, 10, 0, 0, 0, 0, 0 },
 
 2198   { 
"rpk", NDB_OPT_NOSHORT, 
"Avg records per full key (default 10)",
 
 2199     (uchar **)&g_opts.rpk, (uchar **)&g_opts.rpk, 0,
 
 2200     GET_UINT, REQUIRED_ARG, 10, 0, 0, 0, 0, 0 },
 
 2201   { 
"rpkvar", NDB_OPT_NOSHORT, 
"Vary rpk by factor (default 10, none 1)",
 
 2202     (uchar **)&g_opts.rpkvar, (uchar **)&g_opts.rpkvar, 0,
 
 2203     GET_UINT, REQUIRED_ARG, 10, 0, 0, 0, 0, 0 },
 
 2204   { 
"scanpct", NDB_OPT_NOSHORT,
 
 2205     "Preferred max pct of total rows per scan (default 10)",
 
 2206     (uchar **)&g_opts.scanpct, (uchar **)&g_opts.scanpct, 0,
 
 2207     GET_UINT, REQUIRED_ARG, 5, 0, 0, 0, 0, 0 },
 
 2208   { 
"eqscans", NDB_OPT_NOSHORT,
 
 2209     "Pct scans for partial/full equality (default 30)",
 
 2210     (uchar **)&g_opts.eqscans, (uchar **)&g_opts.eqscans, 0,
 
 2211     GET_UINT, REQUIRED_ARG, 50, 0, 0, 0, 0, 0 },
 
 2212   { 
"keeptable", NDB_OPT_NOSHORT,
 
 2213     "Do not drop table at exit",
 
 2214     (uchar **)&g_opts.keeptable, (uchar **)&g_opts.keeptable, 0,
 
 2215     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2216   { 
"abort", NDB_OPT_NOSHORT, 
"Dump core on any error",
 
 2217     (uchar **)&g_opts.abort, (uchar **)&g_opts.abort, 0,
 
 2218     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2219   { 
"dump", NDB_OPT_NOSHORT, 
"Write CSV files name.* of keys,ranges,stats",
 
 2220     (uchar **)&g_opts.dump, (uchar **)&g_opts.dump, 0,
 
 2221     GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
 2224     GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
 
 2228 load_default_groups[] = { 
"mysql_cluster", 0 };
 
 2233   ndb_short_usage_sub(NULL);
 
 2239   ndbout << my_progname << 
": ordered index stats test" << endl;
 
 2240   ndb_usage(short_usage_sub, load_default_groups, my_long_options);
 
 2246   chkrc(g_opts.rows != 0);
 
 2247   chkrc(g_opts.nullkeys <= 100);
 
 2248   chkrc(g_opts.rpk != 0);
 
 2249   g_opts.rpk = min(g_opts.rpk, g_opts.rows);
 
 2250   chkrc(g_opts.rpkvar != 0);
 
 2251   chkrc(g_opts.scanpct <= 100);
 
 2252   chkrc(g_opts.eqscans <= 100);
 
 2254   g_lim_val.all_nullable = 
false;
 
 2255   g_lim_bnd.all_nullable = 
true;
 
 2256   g_lim_val.b_min = g_opts.rows;
 
 2257   g_lim_val.b_max = 2 * g_opts.rows;
 
 2258   g_lim_bnd.b_min = 90 * g_lim_val.b_min / 100;
 
 2259   g_lim_bnd.b_max = 110 * g_lim_val.b_max / 100;
 
 2260   g_lim_val.c_char = 
"bcd";
 
 2261   g_lim_bnd.c_char = 
"abcde";
 
 2262   g_lim_val.d_min = 100;
 
 2263   g_lim_val.d_max = 200;
 
 2264   g_lim_bnd.d_min = 0;
 
 2265   g_lim_bnd.d_max = 300;
 
 2271 docreate_stat_tables()
 
 2273   if (g_is->check_systables(g_ndb_sys) == 0)
 
 2275   ll1(
"check_systables: " << g_is->getNdbError());
 
 2277   ll0(
"create stat tables");
 
 2278   chkdb(g_is->create_systables(g_ndb_sys) == 0);
 
 2279   g_has_created_stat_tables = 
true;
 
 2285 dodrop_stat_tables()
 
 2287   if (g_has_created_stat_tables == 
false)
 
 2290   ll0(
"drop stat tables");
 
 2291   chkdb(g_is->drop_systables(g_ndb_sys) == 0);
 
 2296 docreate_stat_events()
 
 2298   if (g_is->check_sysevents(g_ndb_sys) == 0)
 
 2300   ll1(
"check_sysevents: " << g_is->getNdbError());
 
 2302   ll0(
"create stat events");
 
 2303   chkdb(g_is->create_sysevents(g_ndb_sys) == 0);
 
 2304   g_has_created_stat_events = 
true;
 
 2309 dodrop_stat_events()
 
 2311   if (g_has_created_stat_events == 
false)
 
 2314   ll0(
"drop stat events");
 
 2315   chkdb(g_is->drop_sysevents(g_ndb_sys) == 0);
 
 2320 docreate_sys_objects()
 
 2322   require(g_is != 0 && g_ndb_sys != 0);
 
 2323   chkrc(docreate_stat_tables() == 0);
 
 2324   chkrc(docreate_stat_events() == 0);
 
 2329 dodrop_sys_objects()
 
 2331   require(g_is != 0 && g_ndb_sys != 0);
 
 2332   chkrc(dodrop_stat_events() == 0);
 
 2333   chkrc(dodrop_stat_tables() == 0);
 
 2338 main(
int argc, 
char** argv)
 
 2341   my_progname = strchr(argv[0], 
'/') ? strrchr(argv[0], 
'/') + 1 : argv[0];
 
 2343   ndbout << my_progname;
 
 2344   for (i = 1; i < (uint)argc; i++)
 
 2345     ndbout << 
" " << argv[i];
 
 2348   ndb_opt_set_usage_funcs(short_usage_sub, usage);
 
 2349   ret = handle_options(&argc, &argv, my_long_options, ndb_std_get_one_option);
 
 2350   if (ret != 0 || argc != 0) {
 
 2352     return NDBT_ProgramExit(NDBT_WRONGARGS);
 
 2354   if (checkoptions() == -1) {
 
 2355     ll0(
"invalid args");
 
 2356     return NDBT_ProgramExit(NDBT_WRONGARGS);
 
 2358   if (doconnect() == -1) {
 
 2359     ll0(
"connect failed");
 
 2360     return NDBT_ProgramExit(NDBT_FAILED);
 
 2362   if (docreate_sys_objects() == -1) {
 
 2363     ll0(
"failed to check or create stat tables and events");
 
 2366   if (runtest() == -1) {
 
 2370   if (dodrop_sys_objects() == -1) {
 
 2371     ll0(
"failed to drop created stat tables or events");
 
 2375   return NDBT_ProgramExit(NDBT_OK);
 
 2377   (void)dodrop_sys_objects();
 
 2379   return NDBT_ProgramExit(NDBT_FAILED);