1 /* Copyright (c) 2003-2007 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
17 #include <ndb_global.h>
27 int scanReadRecords(Ndb
*,
28 const NdbDictionary::Table
*,
29 const NdbDictionary::Index
*,
40 static const char* _dbname
= "TEST_DB";
41 static const char* _delimiter
= "\t";
42 static int _header
, _parallelism
, _useHexFormat
, _lock
,
45 const char *load_default_groups
[]= { "mysql_cluster",0 };
48 static int _dumpDisk
= 0;
49 static int use_rowid
= 0;
50 static int nodata
= 0;
51 static int use_gci
= 0;
53 static struct my_option my_long_options
[] =
55 NDB_STD_OPTS("ndb_desc"),
56 { "database", 'd', "Name of database table is in",
57 (uchar
**) &_dbname
, (uchar
**) &_dbname
, 0,
58 GET_STR
, REQUIRED_ARG
, 0, 0, 0, 0, 0, 0 },
59 { "parallelism", 'p', "parallelism",
60 (uchar
**) &_parallelism
, (uchar
**) &_parallelism
, 0,
61 GET_INT
, REQUIRED_ARG
, 0, 0, 0, 0, 0, 0 },
62 { "lock", 'l', "Read(0), Read-hold(1), Exclusive(2)",
63 (uchar
**) &_lock
, (uchar
**) &_lock
, 0,
64 GET_INT
, REQUIRED_ARG
, 0, 0, 0, 0, 0, 0 },
65 { "order", 'o', "Sort resultset according to index",
66 (uchar
**) &_order
, (uchar
**) &_order
, 0,
67 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
68 { "descending", 'z', "Sort descending (requires order flag)",
69 (uchar
**) &_descending
, (uchar
**) &_descending
, 0,
70 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
71 { "header", 'h', "Print header",
72 (uchar
**) &_header
, (uchar
**) &_header
, 0,
73 GET_BOOL
, NO_ARG
, 1, 0, 0, 0, 0, 0 },
74 { "useHexFormat", 'x', "Output numbers in hexadecimal format",
75 (uchar
**) &_useHexFormat
, (uchar
**) &_useHexFormat
, 0,
76 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
77 { "delimiter", 'D', "Column delimiter",
78 (uchar
**) &_delimiter
, (uchar
**) &_delimiter
, 0,
79 GET_STR
, REQUIRED_ARG
, 0, 0, 0, 0, 0, 0 },
80 { "disk", 256, "Dump disk ref",
81 (uchar
**) &_dumpDisk
, (uchar
**) &_dumpDisk
, 0,
82 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
83 { "rowid", 256, "Dump rowid",
84 (uchar
**) &use_rowid
, (uchar
**) &use_rowid
, 0,
85 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
86 { "gci", 256, "Dump gci",
87 (uchar
**) &use_gci
, (uchar
**) &use_gci
, 0,
88 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
89 { "tupscan", 't', "Scan in tup order",
90 (uchar
**) &_tup
, (uchar
**) &_tup
, 0,
91 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
92 { "nodata", 256, "Dont print data",
93 (uchar
**) &nodata
, (uchar
**) &nodata
, 0,
94 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
95 { 0, 0, 0, 0, 0, 0, GET_NO_ARG
, NO_ARG
, 0, 0, 0, 0, 0, 0}
102 "This program reads all records from one table in NDB Cluster\n"\
103 "and print them to stdout. This is performed using a scan read.\n"\
104 "(It only print error messages if it encounters a permanent error.)\n"\
105 "It can also be used to dump the content of a table to file \n"\
106 " ex: select_all --no-header --delimiter=';' T4 > T4.data\n";
108 ndb_std_print_version();
109 print_defaults(MYSQL_CONFIG_NAME
,load_default_groups
);
111 my_print_help(my_long_options
);
112 my_print_variables(my_long_options
);
115 int main(int argc
, char** argv
){
117 load_defaults("my",load_default_groups
,&argc
,&argv
);
118 const char* _tabname
;
121 opt_debug
= "d:t:O,/tmp/ndb_select_all.trace";
123 if ((ho_error
=handle_options(&argc
, &argv
, my_long_options
,
124 ndb_std_get_one_option
)))
125 return NDBT_ProgramExit(NDBT_WRONGARGS
);
126 if ((_tabname
= argv
[0]) == 0) {
128 return NDBT_ProgramExit(NDBT_WRONGARGS
);
131 Ndb_cluster_connection
con(opt_connect_str
);
132 con
.set_name("ndb_select_all");
133 if(con
.connect(12, 5, 1) != 0)
135 ndbout
<< "Unable to connect to management server." << endl
;
136 return NDBT_ProgramExit(NDBT_FAILED
);
138 if (con
.wait_until_ready(30,0) < 0)
140 ndbout
<< "Cluster nodes not ready in 30 seconds." << endl
;
141 return NDBT_ProgramExit(NDBT_FAILED
);
144 Ndb
MyNdb(&con
, _dbname
);
145 if(MyNdb
.init() != 0){
146 ERR(MyNdb
.getNdbError());
147 return NDBT_ProgramExit(NDBT_FAILED
);
150 // Check if table exists in db
151 const NdbDictionary::Table
* pTab
= NDBT_Table::discoverTableFromDb(&MyNdb
, _tabname
);
152 const NdbDictionary::Index
* pIdx
= 0;
154 pIdx
= MyNdb
.getDictionary()->getIndex(argv
[1], _tabname
);
158 ndbout
<< " Table " << _tabname
<< " does not exist!" << endl
;
159 return NDBT_ProgramExit(NDBT_WRONGARGS
);
162 if(argc
> 1 && pIdx
== 0)
164 ndbout
<< " Index " << argv
[1] << " does not exists" << endl
;
167 if(_order
&& pIdx
== NULL
){
168 ndbout
<< " Order flag given without an index" << endl
;
169 return NDBT_ProgramExit(NDBT_WRONGARGS
);
172 if (_descending
&& ! _order
) {
173 ndbout
<< " Descending flag given without order flag" << endl
;
174 return NDBT_ProgramExit(NDBT_WRONGARGS
);
177 if (scanReadRecords(&MyNdb
,
184 (char)*_delimiter
, _order
, _descending
) != 0){
185 return NDBT_ProgramExit(NDBT_FAILED
);
188 return NDBT_ProgramExit(NDBT_OK
);
192 int scanReadRecords(Ndb
* pNdb
,
193 const NdbDictionary::Table
* pTab
,
194 const NdbDictionary::Index
* pIdx
,
199 char delimiter
, bool order
, bool descending
){
201 int retryAttempt
= 0;
202 const int retryMax
= 100;
204 NdbTransaction
*pTrans
;
205 NdbScanOperation
*pOp
;
206 NdbIndexScanOperation
* pIOp
= 0;
208 NDBT_ResultRow
* row
= new NDBT_ResultRow(*pTab
, delimiter
);
212 if (retryAttempt
>= retryMax
){
213 ndbout
<< "ERROR: has retried this operation " << retryAttempt
214 << " times, failing!" << endl
;
218 pTrans
= pNdb
->startTransaction();
219 if (pTrans
== NULL
) {
220 const NdbError err
= pNdb
->getNdbError();
222 if (err
.status
== NdbError::TemporaryError
){
223 NdbSleep_MilliSleep(50);
232 pOp
= (!pIdx
) ? pTrans
->getNdbScanOperation(pTab
->getName()) :
233 pIOp
=pTrans
->getNdbIndexScanOperation(pIdx
->getName(), pTab
->getName());
236 ERR(pTrans
->getNdbError());
237 pNdb
->closeTransaction(pTrans
);
242 unsigned scan_flags
= 0;
243 if (_tup
) scan_flags
|= NdbScanOperation::SF_TupScan
;
244 switch(_lock
+ (3 * order
)){
246 rs
= pOp
->readTuples(NdbScanOperation::LM_Read
, scan_flags
, parallel
);
249 rs
= pOp
->readTuples(NdbScanOperation::LM_Exclusive
, scan_flags
, parallel
);
252 rs
= pIOp
->readTuples(NdbScanOperation::LM_CommittedRead
, 0, parallel
,
256 rs
= pIOp
->readTuples(NdbScanOperation::LM_Read
, 0, parallel
, true, descending
);
259 rs
= pIOp
->readTuples(NdbScanOperation::LM_Exclusive
, 0, parallel
, true, descending
);
263 rs
= pOp
->readTuples(NdbScanOperation::LM_CommittedRead
, scan_flags
, parallel
);
267 ERR(pTrans
->getNdbError());
268 pNdb
->closeTransaction(pTrans
);
273 NdbScanFilter
sf(pOp
);
275 sf
.begin(NdbScanFilter::AND
);
276 sf
.le(0, (Uint32
)10);
280 sf
.begin(NdbScanFilter::OR
);
281 sf
.begin(NdbScanFilter::AND
);
282 sf
.ge(0, (Uint32
)10);
283 sf
.lt(0, (Uint32
)20);
285 sf
.begin(NdbScanFilter::AND
);
286 sf
.ge(0, (Uint32
)30);
287 sf
.lt(0, (Uint32
)40);
291 sf
.begin(NdbScanFilter::AND
);
292 sf
.begin(NdbScanFilter::OR
);
293 sf
.begin(NdbScanFilter::AND
);
294 sf
.ge(0, (Uint32
)10);
295 sf
.lt(0, (Uint32
)20);
297 sf
.begin(NdbScanFilter::AND
);
298 sf
.ge(0, (Uint32
)30);
299 sf
.lt(0, (Uint32
)40);
302 sf
.begin(NdbScanFilter::OR
);
303 sf
.begin(NdbScanFilter::AND
);
305 sf
.lt(0, (Uint32
)50);
307 sf
.begin(NdbScanFilter::AND
);
308 sf
.ge(0, (Uint32
)100);
309 sf
.lt(0, (Uint32
)200);
315 check
= pOp
->interpret_exit_ok();
317 ERR(pTrans
->getNdbError());
318 pNdb
->closeTransaction(pTrans
);
324 for(int a
= 0; a
<pTab
->getNoOfColumns(); a
++)
326 const NdbDictionary::Column
* col
= pTab
->getColumn(a
);
327 if(col
->getStorageType() == NdbDictionary::Column::StorageTypeDisk
)
331 if((row
->attributeStore(a
) = pOp
->getValue(col
)) == 0)
333 ERR(pTrans
->getNdbError());
334 pNdb
->closeTransaction(pTrans
);
339 NdbRecAttr
* disk_ref
= 0;
340 if(_dumpDisk
&& disk
)
341 disk_ref
= pOp
->getValue(NdbDictionary::Column::DISK_REF
);
343 NdbRecAttr
* rowid
= 0, *frag
= 0, *gci
= 0;
346 frag
= pOp
->getValue(NdbDictionary::Column::FRAGMENT
);
347 rowid
= pOp
->getValue(NdbDictionary::Column::ROWID
);
352 gci
= pOp
->getValue(NdbDictionary::Column::ROW_GCI
);
355 check
= pTrans
->execute(NdbTransaction::NoCommit
);
357 const NdbError err
= pTrans
->getNdbError();
359 if (err
.status
== NdbError::TemporaryError
){
360 pNdb
->closeTransaction(pTrans
);
361 NdbSleep_MilliSleep(50);
366 pNdb
->closeTransaction(pTrans
);
376 if (headers
&& !nodata
)
380 ndbout
<< "\tDISK_REF";
386 eof
= pOp
->nextResult();
392 ndbout
.setHexFormat(1);
396 ndbout
<< "[ fragment: " << frag
->u_32_value()
397 << " m_page: " << rowid
->u_32_value()
398 << " m_page_idx: " << *(Uint32
*)(rowid
->aRef() + 4) << " ]";
407 ndbout
<< gci
->u_64_value() << "\t";
416 ndbout
<< "[ m_file_no: " << *(Uint16
*)(disk_ref
->aRef()+6)
417 << " m_page: " << disk_ref
->u_32_value()
418 << " m_page_idx: " << *(Uint16
*)(disk_ref
->aRef() + 4) << " ]";
421 if (rowid
|| disk_ref
|| gci
|| !nodata
)
423 eof
= pOp
->nextResult();
426 const NdbError err
= pTrans
->getNdbError();
428 if (err
.status
== NdbError::TemporaryError
){
429 pNdb
->closeTransaction(pTrans
);
430 NdbSleep_MilliSleep(50);
435 pNdb
->closeTransaction(pTrans
);
439 pNdb
->closeTransaction(pTrans
);
441 ndbout
<< rows
<< " rows returned" << endl
;