select_all.cpp 8.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


18 19
#include <ndb_global.h>

20 21 22 23 24 25 26 27 28
#include <NdbOut.hpp>

#include <NdbApi.hpp>
#include <NdbMain.h>
#include <NDBT.hpp> 
#include <NdbSleep.h>
#include <getarg.h>
#include <NdbScanFilter.hpp>
 
29 30 31
#ifndef DBUG_OFF
const char *debug_option= 0;
#endif
32 33 34

int scanReadRecords(Ndb*, 
		    const NdbDictionary::Table*, 
joreland@mysql.com's avatar
joreland@mysql.com committed
35
		    const NdbDictionary::Index*,
36 37 38 39
		    int parallel,
		    int lockType,
		    bool headers,
		    bool useHexFormat,
joreland@mysql.com's avatar
joreland@mysql.com committed
40 41
		    char delim,
		    bool orderby);
42 43

int main(int argc, const char** argv){
44
  ndb_init();
45 46 47 48 49 50 51 52
  int _parallelism = 240;
  const char* _delimiter = "\t";
  int _header = true;
  int _useHexFormat = false;
  const char* _tabname = NULL;
  const char* _dbname = "TEST_DB";
  int _help = 0;
  int _lock = 0;
joreland@mysql.com's avatar
joreland@mysql.com committed
53
  int _order = 0;
54 55 56 57 58 59 60 61 62 63 64

  struct getargs args[] = {
    { "database", 'd', arg_string, &_dbname, "dbname", 
      "Name of database table is in"},
    { "parallelism", 'p', arg_integer, &_parallelism, "parallelism", 
      "parallelism" },
    { "header", 'h', arg_flag, &_header, "Print header", "header" },
    { "useHexFormat", 'x', arg_flag, &_useHexFormat, 
      "Output numbers in hexadecimal format", "useHexFormat" },
    { "delimiter", 'd', arg_string, &_delimiter, "Column delimiter", 
      "delimiter" },
65 66 67 68
#ifndef DBUG_OFF
    { "debug", 0, arg_string, &debug_option,
      "Specify debug options e.g. d:t:i:o,out.trace", "options" },
#endif
69 70
    { "usage", '?', arg_flag, &_help, "Print help", "" },
    { "lock", 'l', arg_integer, &_lock, 
joreland@mysql.com's avatar
joreland@mysql.com committed
71 72
      "Read(0), Read-hold(1), Exclusive(2)", "lock"},
    { "order", 'o', arg_flag, &_order, "Sort resultset according to index", ""}
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
  };
  int num_args = sizeof(args) / sizeof(args[0]);
  int optind = 0;
  char desc[] = 
    "tabname\n"\
    "This program reads all records from one table in NDB Cluster\n"\
    "and print them to stdout.  This is performed using a scan read.\n"\
    "(It only print error messages if it encounters a permanent error.)\n"\
    "It can also be used to dump the content of a table to file \n"\
    "  ex: select_all --no-header --delimiter=';' T4 > T4.data\n";
  
  if(getarg(args, num_args, argc, argv, &optind) || 
     argv[optind] == NULL || _help) {
    arg_printusage(args, num_args, argv[0], desc);
    return NDBT_ProgramExit(NDBT_WRONGARGS);
  }
  _tabname = argv[optind];

91 92 93 94 95
#ifndef DBUG_OFF
  if (debug_option)
    DBUG_PUSH(debug_option);
#endif

96 97 98 99 100 101 102 103 104 105 106 107 108 109
  // Connect to Ndb
  Ndb MyNdb(_dbname);

  if(MyNdb.init() != 0){
    ERR(MyNdb.getNdbError());
    return NDBT_ProgramExit(NDBT_FAILED);
  }

  // Connect to Ndb and wait for it to become ready
  while(MyNdb.waitUntilReady() != 0)
    ndbout << "Waiting for ndb to become ready..." << endl;
   
  // Check if table exists in db
  const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname);
joreland@mysql.com's avatar
joreland@mysql.com committed
110 111 112 113 114
  const NdbDictionary::Index * pIdx = 0;
  if(optind+1 < argc){
    pIdx = MyNdb.getDictionary()->getIndex(argv[optind+1], _tabname);
  }

115 116 117 118 119 120 121
  if(pTab == NULL){
    ndbout << " Table " << _tabname << " does not exist!" << endl;
    return NDBT_ProgramExit(NDBT_WRONGARGS);
  }

  if (scanReadRecords(&MyNdb, 
		      pTab, 
joreland@mysql.com's avatar
joreland@mysql.com committed
122
		      pIdx,
123 124 125 126
		      _parallelism, 
		      _lock,
		      _header, 
		      _useHexFormat, 
joreland@mysql.com's avatar
joreland@mysql.com committed
127
		      (char)*_delimiter, _order) != 0){
128 129 130 131 132 133 134 135 136
    return NDBT_ProgramExit(NDBT_FAILED);
  }

  return NDBT_ProgramExit(NDBT_OK);

}

int scanReadRecords(Ndb* pNdb, 
		    const NdbDictionary::Table* pTab, 
joreland@mysql.com's avatar
joreland@mysql.com committed
137
		    const NdbDictionary::Index* pIdx,
138 139 140 141
		    int parallel,
		    int _lock,
		    bool headers,
		    bool useHexFormat,
joreland@mysql.com's avatar
joreland@mysql.com committed
142
		    char delimiter, bool order){
143 144 145 146 147

  int                  retryAttempt = 0;
  const int            retryMax = 100;
  int                  check;
  NdbConnection	       *pTrans;
joreland@mysql.com's avatar
joreland@mysql.com committed
148 149
  NdbScanOperation	       *pOp;
  NdbIndexScanOperation * pIOp;
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

  NDBT_ResultRow * row = new NDBT_ResultRow(*pTab, delimiter);

  while (true){

    if (retryAttempt >= retryMax){
      ndbout << "ERROR: has retried this operation " << retryAttempt 
	     << " times, failing!" << endl;
      return -1;
    }

    pTrans = pNdb->startTransaction();
    if (pTrans == NULL) {
      const NdbError err = pNdb->getNdbError();

      if (err.status == NdbError::TemporaryError){
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      return -1;
    }

joreland@mysql.com's avatar
joreland@mysql.com committed
174 175 176 177
    
    pOp = (!pIdx) ? pTrans->getNdbScanOperation(pTab->getName()) : 
      pIOp=pTrans->getNdbIndexScanOperation(pIdx->getName(), pTab->getName());
    
178 179 180 181 182 183
    if (pOp == NULL) {
      ERR(pTrans->getNdbError());
      pNdb->closeTransaction(pTrans);
      return -1;
    }

joreland@mysql.com's avatar
joreland@mysql.com committed
184 185
    NdbResultSet * rs;
    switch(_lock + (3 * order)){
186
    case 1:
joreland@mysql.com's avatar
joreland@mysql.com committed
187
      rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallel);
188 189
      break;
    case 2:
joreland@mysql.com's avatar
joreland@mysql.com committed
190 191 192 193 194
      rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel);
      break;
    case 3:
      rs = pIOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel, 
			    true);
195
      break;
joreland@mysql.com's avatar
joreland@mysql.com committed
196 197 198 199 200 201 202
    case 4:
      rs = pIOp->readTuples(NdbScanOperation::LM_Read, 0, parallel, true);
      break;
    case 5:
      rs = pIOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel, true);
      break;
    case 0:
203
    default:
joreland@mysql.com's avatar
joreland@mysql.com committed
204 205
      rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel);
      break;
206
    }
joreland@mysql.com's avatar
joreland@mysql.com committed
207
    if( rs == 0 ){
208 209 210 211
      ERR(pTrans->getNdbError());
      pNdb->closeTransaction(pTrans);
      return -1;
    }
joreland@mysql.com's avatar
joreland@mysql.com committed
212
    
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
    if(0){
      NdbScanFilter sf(pOp);
#if 0
      sf.begin(NdbScanFilter::AND);
      sf.le(0, (Uint32)10);
      
      sf.end();
#elif 0
      sf.begin(NdbScanFilter::OR);
      sf.begin(NdbScanFilter::AND);
      sf.ge(0, (Uint32)10);
      sf.lt(0, (Uint32)20);
      sf.end();
      sf.begin(NdbScanFilter::AND);
      sf.ge(0, (Uint32)30);
      sf.lt(0, (Uint32)40);
      sf.end();
      sf.end();
#elif 1
      sf.begin(NdbScanFilter::AND);
      sf.begin(NdbScanFilter::OR);
      sf.begin(NdbScanFilter::AND);
      sf.ge(0, (Uint32)10);
      sf.lt(0, (Uint32)20);
      sf.end();
      sf.begin(NdbScanFilter::AND);
      sf.ge(0, (Uint32)30);
      sf.lt(0, (Uint32)40);
      sf.end();
      sf.end();
      sf.begin(NdbScanFilter::OR);
      sf.begin(NdbScanFilter::AND);
      sf.ge(0, (Uint32)0);
      sf.lt(0, (Uint32)50);
      sf.end();
      sf.begin(NdbScanFilter::AND);
      sf.ge(0, (Uint32)100);
      sf.lt(0, (Uint32)200);
      sf.end();
      sf.end();
      sf.end();
#endif
    } else {
      check = pOp->interpret_exit_ok();
      if( check == -1 ) {
	ERR(pTrans->getNdbError());
	pNdb->closeTransaction(pTrans);
	return -1;
      }
    }
    
    for(int a = 0; a<pTab->getNoOfColumns(); a++){
      if((row->attributeStore(a) = 
	  pOp->getValue(pTab->getColumn(a)->getName())) == 0) {
	ERR(pTrans->getNdbError());
	pNdb->closeTransaction(pTrans);
	return -1;
      }
    }

joreland@mysql.com's avatar
joreland@mysql.com committed
273
    check = pTrans->execute(NoCommit);   
274 275
    if( check == -1 ) {
      const NdbError err = pTrans->getNdbError();
joreland@mysql.com's avatar
joreland@mysql.com committed
276
      
277 278 279 280 281 282 283 284 285 286 287 288 289
      if (err.status == NdbError::TemporaryError){
	pNdb->closeTransaction(pTrans);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      pNdb->closeTransaction(pTrans);
      return -1;
    }

    if (headers)
      row->header(ndbout) << endl;
joreland@mysql.com's avatar
joreland@mysql.com committed
290
    
291 292
    int eof;
    int rows = 0;
joreland@mysql.com's avatar
joreland@mysql.com committed
293 294
    eof = rs->nextResult();
    
295 296 297 298 299 300 301 302 303
    while(eof == 0){
      rows++;

      if (useHexFormat) {
	ndbout.setHexFormat(1) << (*row) << endl;
      } else {
	ndbout << (*row) << endl;
      }

joreland@mysql.com's avatar
joreland@mysql.com committed
304
      eof = rs->nextResult();
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
    }
    if (eof == -1) {
      const NdbError err = pTrans->getNdbError();

      if (err.status == NdbError::TemporaryError){
	pNdb->closeTransaction(pTrans);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      pNdb->closeTransaction(pTrans);
      return -1;
    }

    pNdb->closeTransaction(pTrans);

    ndbout << rows << " rows returned" << endl;

    return 0;
  }
  return -1;
}