MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
select_all.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 
19 #include <ndb_global.h>
20 #include <ndb_opts.h>
21 
22 #include <NdbOut.hpp>
23 
24 #include <NdbApi.hpp>
25 #include <NdbMain.h>
26 #include <NDBT.hpp>
27 #include <NdbSleep.h>
28 
29 int scanReadRecords(Ndb*,
30  const NdbDictionary::Table*,
31  const NdbDictionary::Index*,
32  int parallel,
33  int lockType,
34  bool headers,
35  bool useHexFormat,
36  char delim,
37  bool orderby,
38  bool descending);
39 
40 static const char* _dbname = "TEST_DB";
41 static const char* _delimiter = "\t";
42 static int _header, _parallelism, _useHexFormat, _lock,
43  _order, _descending;
44 
45 const char *load_default_groups[]= { "mysql_cluster",0 };
46 
47 static int _tup = 0;
48 static int _dumpDisk = 0;
49 static int use_rowid = 0;
50 static int nodata = 0;
51 static int use_gci = 0;
52 static int use_gci64 = 0;
53 static int use_author = 0;
54 
55 static struct my_option my_long_options[] =
56 {
57  NDB_STD_OPTS("ndb_select_all"),
58  { "database", 'd', "Name of database table is in",
59  (uchar**) &_dbname, (uchar**) &_dbname, 0,
60  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
61  { "parallelism", 'p', "parallelism",
62  (uchar**) &_parallelism, (uchar**) &_parallelism, 0,
63  GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
64  { "lock", 'l', "Read(0), Read-hold(1), Exclusive(2)",
65  (uchar**) &_lock, (uchar**) &_lock, 0,
66  GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
67  { "order", 'o', "Sort resultset according to index",
68  (uchar**) &_order, (uchar**) &_order, 0,
69  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
70  { "descending", 'z', "Sort descending (requires order flag)",
71  (uchar**) &_descending, (uchar**) &_descending, 0,
72  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
73  { "header", 'h', "Print header",
74  (uchar**) &_header, (uchar**) &_header, 0,
75  GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
76  { "useHexFormat", 'x', "Output numbers in hexadecimal format",
77  (uchar**) &_useHexFormat, (uchar**) &_useHexFormat, 0,
78  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
79  { "delimiter", 'D', "Column delimiter",
80  (uchar**) &_delimiter, (uchar**) &_delimiter, 0,
81  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
82  { "disk", NDB_OPT_NOSHORT, "Dump disk ref",
83  (uchar**) &_dumpDisk, (uchar**) &_dumpDisk, 0,
84  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
85  { "rowid", NDB_OPT_NOSHORT, "Dump rowid",
86  (uchar**) &use_rowid, (uchar**) &use_rowid, 0,
87  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
88  { "gci", NDB_OPT_NOSHORT, "Dump gci",
89  (uchar**) &use_gci, (uchar**) &use_gci, 0,
90  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
91  { "gci64", NDB_OPT_NOSHORT, "Dump ROW$GCI64",
92  (uchar**) &use_gci64, (uchar**) &use_gci64, 0,
93  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
94  { "author", NDB_OPT_NOSHORT, "Dump ROW$AUTHOR",
95  (uchar**) &use_author, (uchar**) &use_author, 0,
96  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
97  { "tupscan", 't', "Scan in tup order",
98  (uchar**) &_tup, (uchar**) &_tup, 0,
99  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
100  { "nodata", NDB_OPT_NOSHORT, "Dont print data",
101  (uchar**) &nodata, (uchar**) &nodata, 0,
102  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
103  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
104 };
105 
106 
107 static void short_usage_sub(void)
108 {
109  ndb_short_usage_sub(NULL);
110 }
111 
112 static void usage()
113 {
114  ndb_usage(short_usage_sub, load_default_groups, my_long_options);
115 }
116 
117 int main(int argc, char** argv){
118  NDB_INIT(argv[0]);
119  ndb_opt_set_usage_funcs(short_usage_sub, usage);
120  load_defaults("my",load_default_groups,&argc,&argv);
121  const char* _tabname;
122  int ho_error;
123 #ifndef DBUG_OFF
124  opt_debug= "d:t:O,/tmp/ndb_select_all.trace";
125 #endif
126  if ((ho_error=handle_options(&argc, &argv, my_long_options,
127  ndb_std_get_one_option)))
128  return NDBT_ProgramExit(NDBT_WRONGARGS);
129  if ((_tabname = argv[0]) == 0) {
130  usage();
131  return NDBT_ProgramExit(NDBT_WRONGARGS);
132  }
133 
134  Ndb_cluster_connection con(opt_ndb_connectstring, opt_ndb_nodeid);
135  con.set_name("ndb_select_all");
136  if(con.connect(12, 5, 1) != 0)
137  {
138  ndbout << "Unable to connect to management server." << endl;
139  return NDBT_ProgramExit(NDBT_FAILED);
140  }
141  if (con.wait_until_ready(30,0) < 0)
142  {
143  ndbout << "Cluster nodes not ready in 30 seconds." << endl;
144  return NDBT_ProgramExit(NDBT_FAILED);
145  }
146 
147  Ndb MyNdb(&con, _dbname );
148  if(MyNdb.init() != 0){
149  ERR(MyNdb.getNdbError());
150  return NDBT_ProgramExit(NDBT_FAILED);
151  }
152 
153  // Check if table exists in db
154  const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname);
155  const NdbDictionary::Index * pIdx = 0;
156  if(argc > 1){
157  pIdx = MyNdb.getDictionary()->getIndex(argv[1], _tabname);
158  }
159 
160  if(pTab == NULL){
161  ndbout << " Table " << _tabname << " does not exist!" << endl;
162  return NDBT_ProgramExit(NDBT_WRONGARGS);
163  }
164 
165  if(argc > 1 && pIdx == 0)
166  {
167  ndbout << " Index " << argv[1] << " does not exists" << endl;
168  }
169 
170  if(_order && pIdx == NULL){
171  ndbout << " Order flag given without an index" << endl;
172  return NDBT_ProgramExit(NDBT_WRONGARGS);
173  }
174 
175  if (_descending && ! _order) {
176  ndbout << " Descending flag given without order flag" << endl;
177  return NDBT_ProgramExit(NDBT_WRONGARGS);
178  }
179 
180  if (scanReadRecords(&MyNdb,
181  pTab,
182  pIdx,
183  _parallelism,
184  _lock,
185  _header,
186  _useHexFormat,
187  (char)*_delimiter, _order, _descending) != 0){
188  return NDBT_ProgramExit(NDBT_FAILED);
189  }
190 
191  return NDBT_ProgramExit(NDBT_OK);
192 
193 }
194 
195 int scanReadRecords(Ndb* pNdb,
196  const NdbDictionary::Table* pTab,
197  const NdbDictionary::Index* pIdx,
198  int parallel,
199  int _lock,
200  bool headers,
201  bool useHexFormat,
202  char delimiter, bool order, bool descending){
203 
204  int retryAttempt = 0;
205  const int retryMax = 100;
206  int check;
207  NdbTransaction *pTrans;
208  NdbScanOperation *pOp;
209  NdbIndexScanOperation * pIOp= 0;
210 
211  NDBT_ResultRow * row = new NDBT_ResultRow(*pTab, delimiter);
212 
213  while (true){
214 
215  if (retryAttempt >= retryMax){
216  ndbout << "ERROR: has retried this operation " << retryAttempt
217  << " times, failing!" << endl;
218  return -1;
219  }
220 
221  pTrans = pNdb->startTransaction();
222  if (pTrans == NULL) {
223  const NdbError err = pNdb->getNdbError();
224 
225  if (err.status == NdbError::TemporaryError){
226  NdbSleep_MilliSleep(50);
227  retryAttempt++;
228  continue;
229  }
230  ERR(err);
231  return -1;
232  }
233 
234 
235  pOp = (!pIdx) ? pTrans->getNdbScanOperation(pTab->getName()) :
236  pIOp=pTrans->getNdbIndexScanOperation(pIdx->getName(), pTab->getName());
237 
238  if (pOp == NULL) {
239  ERR(pTrans->getNdbError());
240  pNdb->closeTransaction(pTrans);
241  return -1;
242  }
243 
244  int rs;
245  unsigned scan_flags = 0;
246  if (_tup) scan_flags |= NdbScanOperation::SF_TupScan;
247  switch(_lock + (3 * order)){
248  case 1:
249  rs = pOp->readTuples(NdbScanOperation::LM_Read, scan_flags, parallel);
250  break;
251  case 2:
252  rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, scan_flags, parallel);
253  break;
254  case 3:
255  rs = pIOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel,
256  true, descending);
257  break;
258  case 4:
259  rs = pIOp->readTuples(NdbScanOperation::LM_Read, 0, parallel, true, descending);
260  break;
261  case 5:
262  rs = pIOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel, true, descending);
263  break;
264  case 0:
265  default:
266  rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, scan_flags, parallel);
267  break;
268  }
269  if( rs != 0 ){
270  ERR(pTrans->getNdbError());
271  pNdb->closeTransaction(pTrans);
272  return -1;
273  }
274 
275  if(0){
276  NdbScanFilter sf(pOp);
277 #if 0
278  sf.begin(NdbScanFilter::AND);
279  sf.le(0, (Uint32)10);
280 
281  sf.end();
282 #elif 0
283  sf.begin(NdbScanFilter::OR);
284  sf.begin(NdbScanFilter::AND);
285  sf.ge(0, (Uint32)10);
286  sf.lt(0, (Uint32)20);
287  sf.end();
288  sf.begin(NdbScanFilter::AND);
289  sf.ge(0, (Uint32)30);
290  sf.lt(0, (Uint32)40);
291  sf.end();
292  sf.end();
293 #elif 1
294  sf.begin(NdbScanFilter::AND);
295  sf.begin(NdbScanFilter::OR);
296  sf.begin(NdbScanFilter::AND);
297  sf.ge(0, (Uint32)10);
298  sf.lt(0, (Uint32)20);
299  sf.end();
300  sf.begin(NdbScanFilter::AND);
301  sf.ge(0, (Uint32)30);
302  sf.lt(0, (Uint32)40);
303  sf.end();
304  sf.end();
305  sf.begin(NdbScanFilter::OR);
306  sf.begin(NdbScanFilter::AND);
307  sf.ge(0, (Uint32)0);
308  sf.lt(0, (Uint32)50);
309  sf.end();
310  sf.begin(NdbScanFilter::AND);
311  sf.ge(0, (Uint32)100);
312  sf.lt(0, (Uint32)200);
313  sf.end();
314  sf.end();
315  sf.end();
316 #endif
317  }
318 
319  bool disk= false;
320  for(int a = 0; a<pTab->getNoOfColumns(); a++)
321  {
322  const NdbDictionary::Column* col = pTab->getColumn(a);
323  if(col->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
324  disk= true;
325 
326  if (!nodata)
327  if((row->attributeStore(a) = pOp->getValue(col)) == 0)
328  {
329  ERR(pTrans->getNdbError());
330  pNdb->closeTransaction(pTrans);
331  return -1;
332  }
333  }
334 
335  NdbRecAttr * disk_ref= 0;
336  if(_dumpDisk && disk)
337  disk_ref = pOp->getValue(NdbDictionary::Column::DISK_REF);
338 
339  NdbRecAttr * rowid= 0, *frag = 0, *gci = 0, *gci64 = 0, *author = 0;
340  if (use_rowid)
341  {
342  frag = pOp->getValue(NdbDictionary::Column::FRAGMENT);
343  rowid = pOp->getValue(NdbDictionary::Column::ROWID);
344  }
345 
346  if (use_gci)
347  {
348  gci = pOp->getValue(NdbDictionary::Column::ROW_GCI);
349  }
350 
351  if (use_gci64)
352  {
353  gci64 = pOp->getValue(NdbDictionary::Column::ROW_GCI64);
354  }
355 
356  if (use_author)
357  {
358  author = pOp->getValue(NdbDictionary::Column::ROW_AUTHOR);
359  }
360 
361  check = pTrans->execute(NdbTransaction::NoCommit);
362  if( check == -1 ) {
363  const NdbError err = pTrans->getNdbError();
364 
365  if (err.status == NdbError::TemporaryError){
366  pNdb->closeTransaction(pTrans);
367  NdbSleep_MilliSleep(50);
368  retryAttempt++;
369  continue;
370  }
371  ERR(err);
372  pNdb->closeTransaction(pTrans);
373  return -1;
374  }
375 
376  bool do_delimiter= false;
377  char delimiter_string[2];
378  delimiter_string[0]= delimiter;
379  delimiter_string[1]= '\0';
380 #define DELIMITER if (do_delimiter) ndbout << delimiter_string; else do_delimiter= true
381  if (headers)
382  {
383  if (rowid)
384  {
385  DELIMITER;
386  ndbout << "ROWID";
387  }
388 
389  if (gci)
390  {
391  DELIMITER;
392  ndbout << "GCI";
393  }
394 
395  if (!nodata)
396  {
397  DELIMITER;
398  row->header(ndbout);
399  }
400 
401  if (disk_ref)
402  {
403  DELIMITER;
404  ndbout << "DISK_REF";
405  }
406 
407  if (gci64)
408  {
409  DELIMITER;
410  ndbout << "ROW$GCI64";
411  }
412 
413  if (author)
414  {
415  DELIMITER;
416  ndbout << "ROW$AUTHOR";
417  }
418 
419  ndbout << endl;
420  }
421 #undef DELIMITER
422 
423  int eof;
424  int rows = 0;
425  eof = pOp->nextResult();
426 
427  while(eof == 0){
428  rows++;
429 
430  if (useHexFormat)
431  ndbout.setHexFormat(1);
432 
433  if (rowid)
434  {
435  ndbout << "[ fragment: " << frag->u_32_value()
436  << " m_page: " << rowid->u_32_value()
437  << " m_page_idx: " << *(Uint32*)(rowid->aRef() + 4) << " ]";
438  ndbout << "\t";
439  }
440 
441  if (gci)
442  {
443  if (gci->isNULL())
444  ndbout << "NULL\t";
445  else
446  ndbout << gci->u_64_value() << "\t";
447  }
448 
449  if (!nodata)
450  ndbout << (*row);
451 
452  if(disk_ref)
453  {
454  ndbout << "\t";
455  ndbout << "[ m_file_no: " << *(Uint16*)(disk_ref->aRef()+6)
456  << " m_page: " << disk_ref->u_32_value()
457  << " m_page_idx: " << *(Uint16*)(disk_ref->aRef() + 4) << " ]";
458  }
459 
460  if (gci64)
461  {
462  if (gci64->isNULL())
463  ndbout << "\tNULL";
464  else
465  {
466  Uint64 tmp = gci64->u_64_value();
467  ndbout << "\t" << Uint32(tmp >> 32) << "/" << Uint32(tmp);
468  }
469  }
470 
471  if (author)
472  {
473  if (author->isNULL())
474  ndbout << "\tNULL";
475  else
476  {
477  ndbout << "\t" << author->u_32_value();
478  }
479  }
480 
481 
482  if (rowid || disk_ref || gci || !nodata || gci64 || author)
483  ndbout << endl;
484  eof = pOp->nextResult();
485  }
486  if (eof == -1) {
487  const NdbError err = pTrans->getNdbError();
488 
489  if (err.status == NdbError::TemporaryError){
490  pNdb->closeTransaction(pTrans);
491  NdbSleep_MilliSleep(50);
492  retryAttempt++;
493  continue;
494  }
495  ERR(err);
496  pNdb->closeTransaction(pTrans);
497  return -1;
498  }
499 
500  pNdb->closeTransaction(pTrans);
501 
502  ndbout << rows << " rows returned" << endl;
503 
504  return 0;
505  }
506  return -1;
507 }