~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Andrew Hutchings
  • Date: 2010-09-22 19:58:16 UTC
  • mto: (1792.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1793.
  • Revision ID: andrew@linuxjedi.co.uk-20100922195816-uc3aud8va2sxponn
Put drizzle and mysql processes in seperate classes/files

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
#include <boost/program_options.hpp>
45
45
#include <boost/regex.hpp>
46
46
#include <boost/date_time/posix_time/posix_time.hpp>
47
 
#include "drizzledump.h"
 
47
#include "drizzledump_data.h"
 
48
#include "drizzledump_mysql.h"
 
49
#include "drizzledump_drizzle.h"
48
50
 
49
51
using namespace std;
50
52
using namespace drizzled;
70
72
 
71
73
/* Size of buffer for dump's select query */
72
74
#define QUERY_LENGTH 1536
73
 
#define DRIZZLE_MAX_LINE_LENGTH 1024*1024L-1025
74
75
 
75
76
/* ignore table flags */
76
77
#define IGNORE_NONE 0x00 /* no ignore */
78
79
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
79
80
 
80
81
static bool  verbose= false;
81
 
static bool opt_no_create_info;
82
 
static bool opt_no_data= false;
83
82
static bool use_drizzle_protocol= false;
84
83
static bool quick= true;
85
 
static bool extended_insert= true;
86
84
static bool ignore_errors= false;
87
85
static bool flush_logs= false;
88
 
static bool opt_drop= true; 
89
86
static bool opt_keywords= false;
90
87
static bool opt_compress= false;
91
88
static bool opt_delayed= false; 
93
90
static bool opt_quoted= false;
94
91
static bool opt_databases= false; 
95
92
static bool opt_alldbs= false; 
96
 
static bool opt_create_db= false;
97
93
static bool opt_lock_all_tables= false;
98
94
static bool opt_set_charset= false; 
99
95
static bool opt_dump_date= true;
100
96
static bool opt_autocommit= false; 
101
 
static bool opt_disable_keys= true;
102
97
static bool opt_single_transaction= false; 
103
98
static bool opt_comments;
104
99
static bool opt_compact;
107
102
static bool opt_ignore= false;
108
103
static bool opt_complete_insert= false;
109
104
static bool opt_drop_database;
110
 
static bool opt_replace_into= false;
111
105
static bool opt_alltspcs= false;
112
 
static uint32_t show_progress_size= 0;
 
106
bool opt_no_create_info;
 
107
bool opt_no_data= false;
 
108
bool opt_create_db= false;
 
109
bool opt_disable_keys= true;
 
110
bool extended_insert= true;
 
111
bool opt_replace_into= false;
 
112
bool opt_drop= true; 
 
113
uint32_t show_progress_size= 0;
113
114
//static uint64_t total_rows= 0;
114
115
static drizzle_st drizzle;
115
 
static drizzle_con_st dcon;
 
116
 drizzle_con_st dcon;
116
117
static string insert_pat;
117
118
//static char *order_by= NULL;
118
119
static uint32_t opt_drizzle_port= 0;
122
123
FILE *stderror_file= 0;
123
124
std::vector<DrizzleDumpDatabase*> database_store;
124
125
 
 
126
enum server_type {
 
127
  SERVER_MYSQL_FOUND,
 
128
  SERVER_DRIZZLE_FOUND,
 
129
  SERVER_UNKNOWN_FOUND
 
130
};
 
131
 
 
132
int connected_server_type= SERVER_UNKNOWN_FOUND;
 
133
 
125
134
const string progname= "drizzledump";
126
135
 
127
136
string password,
153
162
void dump_all_tables(void);
154
163
void generate_dump(void);
155
164
 
156
 
enum server_type {
157
 
  SERVER_MYSQL_FOUND,
158
 
  SERVER_DRIZZLE_FOUND,
159
 
  SERVER_UNKNOWN_FOUND
160
 
};
161
 
 
162
 
int connected_server_type= SERVER_UNKNOWN_FOUND;
163
 
 
164
 
bool DrizzleDumpDatabase::populateTables(drizzle_con_st &connection)
165
 
{
166
 
  drizzle_result_st result;
167
 
  drizzle_row_t row;
168
 
  drizzle_return_t ret;
169
 
  std::string query;
170
 
 
171
 
  if (drizzle_select_db(&connection, &result, databaseName.c_str(), &ret) == 
172
 
    NULL || ret != DRIZZLE_RETURN_OK)
173
 
  {
174
 
    errmsg << _("Could not set db '") << databaseName << "'";
175
 
    return false;
176
 
  }
177
 
  drizzle_result_free(&result);
178
 
 
179
 
  if (connected_server_type == SERVER_MYSQL_FOUND)
180
 
    query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='";
181
 
  else
182
 
    query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='";
183
 
 
184
 
  query.append(databaseName);
185
 
  query.append("' ORDER BY TABLE_NAME");
186
 
 
187
 
  if (drizzle_query_str(&connection, &result, query.c_str(), &ret) == NULL ||
188
 
      ret != DRIZZLE_RETURN_OK)
189
 
  {
190
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
191
 
    {
192
 
      errmsg << _("Could not get tables list due to error: ") <<
193
 
        drizzle_result_error(&result);
194
 
      drizzle_result_free(&result);
195
 
    }
196
 
    else
197
 
    {
198
 
      errmsg << _("Could not get tables list due to error: ") <<
199
 
        drizzle_con_error(&connection);
200
 
    }
201
 
    return false;
202
 
  }
203
 
 
204
 
  if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
205
 
  {
206
 
    errmsg << _("Could not get tables list due to error: ") <<
207
 
        drizzle_con_error(&connection);
208
 
    return false;
209
 
  }
210
 
 
211
 
  while ((row= drizzle_row_next(&result)))
212
 
  {
213
 
    std::string tableName(row[0]);
214
 
    DrizzleDumpTable *table = new DrizzleDumpTable(tableName);
215
 
    table->setCollate(row[1]);
216
 
    table->setEngine(row[2]);
217
 
    if (connected_server_type == SERVER_MYSQL_FOUND)
218
 
    {
219
 
      if (row[3])
220
 
        table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]);
221
 
      else
222
 
        table->autoIncrement= 0;
223
 
    }
224
 
 
225
 
    table->database= this;
226
 
    table->populateFields(connection);
227
 
    table->populateIndexes(connection);
228
 
    tables.push_back(table);
229
 
  }
230
 
 
231
 
  drizzle_result_free(&result);
232
 
 
233
 
  return true;
234
 
}
235
 
 
236
 
bool DrizzleDumpTable::populateFields(drizzle_con_st &connection)
237
 
{
238
 
  drizzle_result_st result;
239
 
  drizzle_row_t row;
240
 
  drizzle_return_t ret;
241
 
  std::string query;
242
 
 
243
 
  if (connected_server_type == SERVER_MYSQL_FOUND)
244
 
    query="SELECT COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT, 'NO', IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME, EXTRA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='";
245
 
  else
246
 
    query= "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_DEFAULT, COLUMN_DEFAULT_IS_NULL, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME, IS_AUTO_INCREMENT, ENUM_VALUES FROM DATA_DICTIONARY.COLUMNS WHERE TABLE_SCHEMA='";
247
 
  query.append(database->databaseName);
248
 
  query.append("' AND TABLE_NAME='");
249
 
  query.append(tableName);
250
 
  query.append("' ORDER BY ORDINAL_POSITION");
251
 
 
252
 
  if (drizzle_query_str(&connection, &result, query.c_str(), &ret) == NULL ||
253
 
      ret != DRIZZLE_RETURN_OK)
254
 
  {
255
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
256
 
    {
257
 
      errmsg << _("Could not get tables list due to error: ") <<
258
 
        drizzle_result_error(&result);
259
 
      drizzle_result_free(&result);
260
 
    }
261
 
    else
262
 
    {
263
 
      errmsg << _("Could not get tables list due to error: ") <<
264
 
        drizzle_con_error(&connection);
265
 
    }
266
 
    return false;
267
 
  }
268
 
 
269
 
  if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
270
 
  {
271
 
    errmsg << _("Could not get tables list due to error: ") <<
272
 
        drizzle_con_error(&connection);
273
 
    return false;
274
 
  }
275
 
  while ((row= drizzle_row_next(&result)))
276
 
  {
277
 
    std::string fieldName(row[0]);
278
 
    DrizzleDumpField *field = new DrizzleDumpField(fieldName);
279
 
    /* Stop valgrind warning */
280
 
    field->convertDateTime= false;
281
 
    /* Also sets collation */
282
 
    field->setType(row[1], row[8]);
283
 
    if (row[2])
284
 
    {
285
 
      if (field->convertDateTime)
286
 
      {
287
 
        field->dateTimeConvert(row[2]);
288
 
      }
289
 
      else
290
 
        field->defaultValue= row[2];
291
 
    }
292
 
    else
293
 
     field->defaultValue= "";
294
 
 
295
 
    field->isNull= (strcmp(row[4], "YES") == 0) ? true : false;
296
 
    if (connected_server_type == SERVER_MYSQL_FOUND)
297
 
    {
298
 
      field->isAutoIncrement= (strcmp(row[9], "auto_increment") == 0) ? true : false;
299
 
      field->defaultIsNull= field->isNull;
300
 
    }
301
 
    else
302
 
    {
303
 
      field->isAutoIncrement= (strcmp(row[9], "YES") == 0) ? true : false;
304
 
      field->defaultIsNull= (strcmp(row[3], "YES") == 0) ? true : false;
305
 
      field->enumValues= (row[10]) ? row[10] : "";
306
 
    }
307
 
    field->length= (row[5]) ? boost::lexical_cast<uint32_t>(row[5]) : 0;
308
 
    field->decimalPrecision= (row[6]) ? boost::lexical_cast<uint32_t>(row[6]) : 0;
309
 
    field->decimalScale= (row[7]) ? boost::lexical_cast<uint32_t>(row[7]) : 0;
310
 
 
311
 
 
312
 
    fields.push_back(field);
313
 
  }
314
 
 
315
 
  drizzle_result_free(&result);
316
 
  return true;
317
 
}
318
 
 
319
 
void DrizzleDumpField::dateTimeConvert(const char* oldDefault)
320
 
{
321
 
  boost::match_flag_type flags = boost::match_default;
322
 
 
323
 
  if (strcmp(oldDefault, "CURRENT_TIMESTAMP") == 0)
324
 
  {
325
 
    defaultValue= oldDefault;
326
 
    return;
327
 
  }
328
 
 
329
 
  if (type.compare("INT") == 0)
330
 
  {
331
 
    /* We were a TIME, now we are an INT */
332
 
    std::string ts(oldDefault);
333
 
    boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts));
334
 
    defaultValue= boost::lexical_cast<string>(td.total_seconds());
335
 
    return;
336
 
  }
337
 
 
338
 
  boost::regex date_regex("([0-9]{3}[1-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))");
339
 
 
340
 
  if (regex_search(oldDefault, date_regex, flags))
341
 
  {
342
 
    defaultValue= oldDefault;
343
 
  }
344
 
  else
345
 
  {
346
 
    defaultIsNull= true;
347
 
    defaultValue="";
348
 
  }
349
 
 
350
 
}
351
 
 
352
 
bool DrizzleDumpTable::populateIndexes(drizzle_con_st &connection)
353
 
{
354
 
  drizzle_result_st result;
355
 
  drizzle_row_t row;
356
 
  drizzle_return_t ret;
357
 
  std::string query;
358
 
  std::string lastKey;
359
 
  bool firstIndex= true;
360
 
  DrizzleDumpIndex *index;
361
 
 
362
 
  if (connected_server_type == SERVER_MYSQL_FOUND)
363
 
    query="SHOW INDEXES FROM ";
364
 
  else
365
 
    query= "SELECT INDEX_NAME, COLUMN_NAME, IS_USED_IN_PRIMARY, IS_UNIQUE FROM DATA_DICTIONARY.INDEX_PARTS WHERE TABLE_NAME='";
366
 
  query.append(tableName);
367
 
  if (connected_server_type == SERVER_DRIZZLE_FOUND)
368
 
    query.append("'");
369
 
 
370
 
  if (drizzle_query_str(&connection, &result, query.c_str(), &ret) == NULL ||
371
 
      ret != DRIZZLE_RETURN_OK)
372
 
  {
373
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
374
 
    {
375
 
      errmsg << _("Could not get tables list due to error: ") <<
376
 
        drizzle_result_error(&result);
377
 
      drizzle_result_free(&result);
378
 
    }
379
 
    else
380
 
    {
381
 
      errmsg << _("Could not get tables list due to error: ") <<
382
 
        drizzle_con_error(&connection);
383
 
    }
384
 
    return false;
385
 
  }
386
 
 
387
 
  if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
388
 
  {
389
 
    errmsg << _("Could not get tables list due to error: ") <<
390
 
        drizzle_con_error(&connection);
391
 
    return false;
392
 
  }
393
 
  while ((row= drizzle_row_next(&result)))
394
 
  {
395
 
    std::string indexName((connected_server_type == SERVER_MYSQL_FOUND) ? row[2] : row[0]);
396
 
    if (indexName.compare(lastKey) != 0)
397
 
    {
398
 
      if ((connected_server_type == SERVER_MYSQL_FOUND) and
399
 
        (strcmp(row[10], "FULLTEXT") == 0))
400
 
        continue;
401
 
 
402
 
      if (!firstIndex)
403
 
        indexes.push_back(index);
404
 
      index = new DrizzleDumpIndex(indexName);
405
 
      if (connected_server_type == SERVER_MYSQL_FOUND)
406
 
      {
407
 
        index->isPrimary= (strcmp(row[2], "PRIMARY") == 0);
408
 
        index->isUnique= (strcmp(row[1], "0") == 0);
409
 
        index->isHash= (strcmp(row[10], "HASH") == 0);
410
 
      }
411
 
      else
412
 
      {
413
 
        index->isPrimary= (strcmp(row[0], "PRIMARY") == 0);
414
 
        index->isUnique= (strcmp(row[3], "YES") == 0);
415
 
        index->isHash= 0;
416
 
      }
417
 
      lastKey= (connected_server_type == SERVER_MYSQL_FOUND) ? row[2] : row[0];
418
 
      firstIndex= false;
419
 
    }
420
 
    index->columns.push_back((connected_server_type == SERVER_MYSQL_FOUND) ? row[4] : row[1]);
421
 
  }
422
 
  if (!firstIndex)
423
 
    indexes.push_back(index);
424
 
 
425
 
  drizzle_result_free(&result);
426
 
  return true;
427
 
}
428
 
 
429
 
void DrizzleDumpField::setType(const char* raw_type, const char* raw_collation)
430
 
{
431
 
  std::string old_type(raw_type);
432
 
  std::string extra;
433
 
  size_t pos;
434
 
  
435
 
  if ((pos= old_type.find("(")) != string::npos)
436
 
  {
437
 
    extra= old_type.substr(pos);
438
 
    old_type.erase(pos,string::npos);
439
 
  }
440
 
 
441
 
  if (connected_server_type == SERVER_DRIZZLE_FOUND)
442
 
  {
443
 
    collation= raw_collation;
444
 
    if (strcmp(raw_type, "BLOB") == 0)
445
 
    {
446
 
      if (strcmp(raw_collation, "binary") != 0)
447
 
        type= "TEXT";
448
 
      else
449
 
        type= raw_type;
450
 
      return;
451
 
    }
452
 
 
453
 
    if (strcmp(raw_type, "VARCHAR") == 0)
454
 
    {
455
 
      if (strcmp(raw_collation, "binary") != 0)
456
 
        type= "VARCHAR";
457
 
      else
458
 
        type= "VARBINARY";
459
 
      return;
460
 
    }
461
 
 
462
 
    if (strcmp(raw_type, "INTEGER") == 0)
463
 
    {
464
 
      type= "INT";
465
 
      return;
466
 
    }
467
 
 
468
 
    type= raw_type;
469
 
    return;
470
 
  }
471
 
 
472
 
  if (connected_server_type == SERVER_MYSQL_FOUND)
473
 
  {
474
 
    std::transform(old_type.begin(), old_type.end(), old_type.begin(), ::toupper);
475
 
    if ((old_type.find("CHAR") != string::npos) or 
476
 
      (old_type.find("TEXT") != string::npos))
477
 
      setCollate(raw_collation);
478
 
 
479
 
    if ((old_type.compare("INT") == 0) and 
480
 
      ((extra.find("unsigned") != string::npos)))
481
 
    {
482
 
      type= "BIGINT";
483
 
      return;
484
 
    }
485
 
    
486
 
    if ((old_type.compare("TINYINT") == 0) or
487
 
      (old_type.compare("SMALLINT") == 0) or
488
 
      (old_type.compare("MEDIUMINT") == 0))
489
 
    {
490
 
      type= "INT";
491
 
      return;
492
 
    }
493
 
 
494
 
    if ((old_type.compare("TINYBLOB") == 0) or
495
 
      (old_type.compare("MEDIUMBLOB") == 0) or
496
 
      (old_type.compare("LONGBLOB") == 0))
497
 
    {
498
 
      type= "BLOB";
499
 
      return;
500
 
    }
501
 
 
502
 
    if ((old_type.compare("TINYTEXT") == 0) or
503
 
      (old_type.compare("MEDIUMTEXT") == 0) or
504
 
      (old_type.compare("LONGTEXT") == 0))
505
 
    {
506
 
      type= "TEXT";
507
 
      return;
508
 
    }
509
 
 
510
 
    if (old_type.compare("CHAR") == 0)
511
 
    {
512
 
      type= "VARCHAR";
513
 
      return;
514
 
    }
515
 
 
516
 
    if (old_type.compare("BINARY") == 0)
517
 
    {
518
 
      type= "VARBINARY";
519
 
      return;
520
 
    }
521
 
 
522
 
    if (old_type.compare("ENUM") == 0)
523
 
    {
524
 
      type= old_type;
525
 
      /* Strip out the braces, we add them again during output */
526
 
      enumValues= extra.substr(1, extra.length()-2);
527
 
      return;
528
 
    }
529
 
 
530
 
    if ((old_type.find("TIME") != string::npos) or
531
 
      (old_type.find("DATE") != string::npos))
532
 
    {
533
 
      /* Intended to catch TIME/DATE/TIMESTAMP/DATETIME 
534
 
         We may have a default TIME/DATE which needs converting */
535
 
      convertDateTime= true;
536
 
    }
537
 
 
538
 
    if (old_type.compare("TIME") == 0)
539
 
    {
540
 
      type= "INT";
541
 
      return;
542
 
    }
543
 
 
544
 
    if (old_type.compare("FLOAT") == 0)
545
 
    {
546
 
      type= "DOUBLE";
547
 
      return;
548
 
    }
549
 
 
550
 
    type= old_type;
551
 
    return;
552
 
  }
553
 
}
554
 
 
555
 
void DrizzleDumpTable::setEngine(const char* newEngine)
556
 
{
557
 
  if (strcmp(newEngine, "MyISAM") == 0)
558
 
    engineName= "InnoDB";
559
 
  else
560
 
    engineName= newEngine; 
561
 
}
562
 
 
563
 
void DrizzleDumpDatabase::setCollate(const char* newCollate)
564
 
{
565
 
  if (newCollate)
566
 
  {
567
 
    std::string tmpCollate(newCollate);
568
 
    if (tmpCollate.find("utf8") != string::npos)
569
 
    {
570
 
      collate= tmpCollate;
571
 
      return;
572
 
    }
573
 
  }
574
 
  collate= "utf8_general_ci";
575
 
}
576
 
 
577
 
void DrizzleDumpTable::setCollate(const char* newCollate)
578
 
{
579
 
  if (newCollate)
580
 
  {
581
 
    std::string tmpCollate(newCollate);
582
 
    if (tmpCollate.find("utf8") != string::npos)
583
 
    {
584
 
      collate= tmpCollate;
585
 
      return;
586
 
    }
587
 
  }
588
 
 
589
 
  collate= "utf8_general_ci";
590
 
}
591
 
 
592
 
void DrizzleDumpField::setCollate(const char* newCollate)
593
 
{
594
 
  if (newCollate)
595
 
  {
596
 
    std::string tmpCollate(newCollate);
597
 
    if (tmpCollate.find("utf8") != string::npos)
598
 
    {
599
 
      collation= tmpCollate;
600
 
      return;
601
 
    }
602
 
  }
603
 
  collation= "utf8_general_ci";
604
 
}
605
 
 
606
 
ostream& operator <<(ostream &os,const DrizzleDumpIndex &obj)
607
 
{
608
 
  if (obj.isPrimary)
609
 
  {
610
 
    os << "  PRIMARY KEY ";
611
 
  }
612
 
  else if (obj.isUnique)
613
 
  {
614
 
    os << "  UNIQUE KEY `" << obj.indexName << "` ";
615
 
  }
616
 
  else
617
 
  {
618
 
    os << "  KEY `" << obj.indexName << "` ";
619
 
  }
620
 
 
621
 
  os << "(";
622
 
  
623
 
  std::vector<std::string>::iterator i;
624
 
  std::vector<std::string> fields = obj.columns;
625
 
  for (i= fields.begin(); i != fields.end(); ++i)
626
 
  {
627
 
    if (i != fields.begin())
628
 
      os << ",";
629
 
    std::string field= *i;
630
 
    os << "`" << field << "`";
631
 
  }
632
 
 
633
 
  os << ")";
634
 
 
635
 
  return os;
636
 
}
637
 
 
638
 
ostream& operator <<(ostream &os, const DrizzleDumpField &obj)
639
 
{
640
 
  os << "  `" << obj.fieldName << "` ";
641
 
  os << obj.type;
642
 
  if (((obj.type.compare("VARCHAR") == 0) or
643
 
   (obj.type.compare("VARBINARY") == 0)) and
644
 
   (obj.length > 0))
645
 
  {
646
 
    os << "(" << obj.length << ")";
647
 
  }
648
 
  else if ((obj.type.compare("DECIMAL") == 0) or
649
 
    (obj.type.compare("DOUBLE") == 0))
650
 
  {
651
 
    os << "(" << obj.decimalPrecision << "," << obj.decimalScale << ")";
652
 
  }
653
 
  else if (obj.type.compare("ENUM") == 0)
654
 
  {
655
 
    os << "(" << obj.enumValues << ")";
656
 
  }
657
 
 
658
 
  if (not obj.isNull)
659
 
  {
660
 
    os << " NOT NULL";
661
 
  }
662
 
 
663
 
  if ((not obj.collation.empty()) and (obj.collation.compare("binary") != 0))
664
 
  {
665
 
    os << " COLLATE " << obj.collation;
666
 
  }
667
 
 
668
 
  if (obj.isAutoIncrement)
669
 
    os << " AUTO_INCREMENT";
670
 
 
671
 
  if (not obj.defaultValue.empty())
672
 
  {
673
 
    if (obj.defaultValue.compare("CURRENT_TIMESTAMP") != 0)
674
 
     os << " DEFAULT '" << obj.defaultValue << "'";
675
 
    else
676
 
     os << " DEFAULT CURRENT_TIMESTAMP";
677
 
  }
678
 
  else if ((obj.collation.empty()) and (obj.defaultIsNull))
679
 
  {
680
 
    os << " DEFAULT NULL";
681
 
  }
682
 
 
683
 
  return os;
684
 
}
685
 
 
686
 
ostream& operator <<(ostream &os,const DrizzleDumpDatabase &obj)
687
 
{
688
 
  os << "--" << endl
689
 
     << "-- Current Database: `" << obj.databaseName << "`" << endl
690
 
     << "--" << endl << endl;
691
 
 
692
 
  /* Love that this variable is the opposite of its name */
693
 
  if (not opt_create_db)
694
 
  {
695
 
    os << "CREATE DATABASE IF NOT EXISTS `" << obj.databaseName
696
 
      << "` COLLATE = " << obj.collate << ";" << endl << endl;
697
 
  }
698
 
 
699
 
  os << "USE `" << obj.databaseName << "`;" << endl << endl;
700
 
 
701
 
  std::vector<DrizzleDumpTable*>::iterator i;
702
 
  std::vector<DrizzleDumpTable*> output_tables = obj.tables;
703
 
  for (i= output_tables.begin(); i != output_tables.end(); ++i)
704
 
  {
705
 
    DrizzleDumpTable *table= *i;
706
 
    if (not opt_no_create_info)
707
 
      os << *table;
708
 
    if (not opt_no_data)
709
 
    {
710
 
      DrizzleDumpData *data= new DrizzleDumpData(dcon, table);
711
 
      os << *data;
712
 
      delete data;
713
 
    }
714
 
  }
715
 
 
716
 
  return os;
717
 
}
718
 
 
719
 
DrizzleDumpData::DrizzleDumpData(drizzle_con_st &conn, DrizzleDumpTable *dataTable) :
720
 
 table(dataTable),
721
 
 connection(&conn)
722
 
{
723
 
  drizzle_return_t ret;
724
 
  std::string query;
725
 
  query= "SELECT * FROM `";
726
 
  query.append(table->tableName);
727
 
  query.append("`");
728
 
  result= new drizzle_result_st;
729
 
 
730
 
  if (drizzle_query_str(connection, result, query.c_str(), &ret) == NULL ||
731
 
      ret != DRIZZLE_RETURN_OK)
732
 
  {
733
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
734
 
    {
735
 
      errmsg << _("Could not get tables list due to error: ") <<
736
 
        drizzle_result_error(result);
737
 
      drizzle_result_free(result);
738
 
    }
739
 
    else
740
 
    {
741
 
      errmsg << _("Could not get tables list due to error: ") <<
742
 
        drizzle_con_error(connection);
743
 
    }
744
 
    return;
745
 
  }
746
 
 
747
 
  if (drizzle_result_buffer(result) != DRIZZLE_RETURN_OK)
748
 
  {
749
 
    errmsg << _("Could not get tables list due to error: ") <<
750
 
        drizzle_con_error(connection);
751
 
    return;
752
 
  }
753
 
}
754
 
DrizzleDumpData::~DrizzleDumpData()
755
 
{
756
 
  drizzle_result_free(result);
757
 
  if (result) delete result;
758
 
}
759
 
ostream& operator <<(ostream &os,const DrizzleDumpData &obj)
760
 
{
761
 
  bool new_insert= true;
762
 
  bool first= true;
763
 
  uint64_t rownr= 0;
764
 
 
765
 
  drizzle_row_t row;
766
 
 
767
 
  if (drizzle_result_row_count(obj.result) < 1)
768
 
  {
769
 
    os << "--" << endl
770
 
       << "-- No data to dump for table `" << obj.table->tableName << "`" << endl
771
 
       << "--" << endl << endl;
772
 
    return os;
773
 
  }
774
 
  else
775
 
  {
776
 
    os << "--" << endl
777
 
       << "-- Dumping data for table `" << obj.table->tableName << "`" << endl
778
 
       << "--" << endl << endl;
779
 
  }
780
 
  if (opt_disable_keys)
781
 
    os << "ALTER TABLE `" << obj.table->tableName << "` DISABLE KEYS;" << endl;
782
 
 
783
 
  streampos out_position= os.tellp();
784
 
 
785
 
  while((row= drizzle_row_next(obj.result)))
786
 
  {
787
 
    rownr++;
788
 
    if ((rownr % show_progress_size) == 0)
789
 
    {
790
 
      cerr << "-- %" << rownr << _(" rows dumped for table ") << obj.table->tableName << endl;
791
 
    }
792
 
 
793
 
    size_t* row_sizes= drizzle_row_field_sizes(obj.result);
794
 
    if (not first)
795
 
    {
796
 
      if (extended_insert)
797
 
        os << "),(";
798
 
      else
799
 
        os << ");" << endl;
800
 
    }
801
 
    else
802
 
      first= false;
803
 
 
804
 
    if (new_insert)
805
 
    {
806
 
      if (opt_replace_into)
807
 
        os << "REPLACE ";
808
 
      else
809
 
        os << "INSERT ";
810
 
      os << "INTO `" << obj.table->tableName << "` VALUES (";
811
 
      if (extended_insert)
812
 
        new_insert= false;
813
 
    }
814
 
    for (uint32_t i= 0; i < drizzle_result_column_count(obj.result); i++)
815
 
    {
816
 
      if (not row[i])
817
 
      {
818
 
        os << "NULL";
819
 
      }
820
 
      /* time/date conversion for MySQL connections */
821
 
      else if ((connected_server_type == SERVER_MYSQL_FOUND) and
822
 
        (obj.table->fields[i]->convertDateTime))
823
 
      {
824
 
        if (obj.table->fields[i]->type.compare("INT") == 0)
825
 
          os << obj.convertTime(row[i]);
826
 
        else
827
 
          os << obj.convertDate(row[i]);
828
 
      }
829
 
      else
830
 
      {
831
 
        if (obj.table->fields[i]->type.compare("INT") != 0)
832
 
        {
833
 
          /* Hex blob processing or escape text */
834
 
          if (opt_hex_blob and
835
 
            ((obj.table->fields[i]->type.compare("BLOB") == 0) or
836
 
            (obj.table->fields[i]->type.compare("VARBINARY") == 0)))
837
 
            os << obj.convertHex(row[i], row_sizes[i]);
838
 
          else
839
 
            os << "'" << obj.escape(row[i], row_sizes[i]) << "'";
840
 
        }
841
 
        else
842
 
          os << row[i];
843
 
      }
844
 
      if (i != obj.table->fields.size() - 1)
845
 
        os << ",";
846
 
    }
847
 
    /* Break insert up if it is too long */
848
 
    if (extended_insert and
849
 
      ((os.tellp() - out_position) >= DRIZZLE_MAX_LINE_LENGTH))
850
 
    {
851
 
      os << ");" << endl;
852
 
      new_insert= true;
853
 
      out_position= os.tellp();
854
 
    }
855
 
  }
856
 
  os << ");" << endl;
857
 
 
858
 
  if (opt_disable_keys)
859
 
    os << "ALTER TABLE `" << obj.table->tableName << "` ENABLE KEYS;" << endl;
860
 
 
861
 
  os << endl;
862
 
 
863
 
  return os;
864
 
}
865
 
 
866
 
long DrizzleDumpData::convertTime(const char* oldTime) const
867
 
{
868
 
  std::string ts(oldTime);
869
 
  boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts));
870
 
  long seconds= td.total_seconds();
871
 
  return seconds;
872
 
}
873
 
 
874
 
std::string DrizzleDumpData::convertDate(const char* oldDate) const
875
 
{
876
 
  boost::match_flag_type flags = boost::match_default;
877
 
  std::string output;
878
 
  boost::regex date_regex("([0-9]{3}[1-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))");
879
 
 
880
 
  if (regex_search(oldDate, date_regex, flags))
881
 
  {
882
 
    output.push_back('\'');
883
 
    output.append(oldDate);
884
 
    output.push_back('\'');
885
 
  }
886
 
  else
887
 
    output= "NULL";
888
 
 
889
 
  return output;
890
 
}
891
 
 
892
 
std::string DrizzleDumpData::convertHex(const char* from, size_t from_size) const
893
 
{
894
 
  ostringstream output;
895
 
  if (from_size > 0)
896
 
    output << "0x";
897
 
  while (from_size > 0)
898
 
  {
899
 
    output << uppercase << hex << setw(2) << setfill('0') << int(*from);
900
 
    *from++;
901
 
    from_size--;
902
 
  }
903
 
 
904
 
  return output.str();
905
 
}
906
 
 
907
 
/* Ripped out of libdrizzle, hopefully a little safer */
908
 
std::string DrizzleDumpData::escape(const char* from, size_t from_size) const
909
 
{
910
 
  std::string output;
911
 
 
912
 
  while (from_size > 0)
913
 
  {
914
 
    if (!(*from & 0x80))
915
 
    {
916
 
      switch (*from)
917
 
      {
918
 
         case 0:
919
 
         case '\n':
920
 
         case '\r':
921
 
         case '\\':
922
 
         case '\'':
923
 
         case '"':
924
 
         case '\032':
925
 
           output.push_back('\\');
926
 
         default:
927
 
           break;
928
 
       }
929
 
    }
930
 
    output.push_back(*from);
931
 
    *from++;
932
 
    from_size--;
933
 
  }
934
 
 
935
 
  return output;
936
 
}
937
 
 
938
 
ostream& operator <<(ostream &os,const DrizzleDumpTable &obj)
939
 
{
940
 
  os << "--" << endl
941
 
     << "-- Table structure for table `" << obj.tableName << "`" << endl
942
 
     << "--" << endl << endl;
943
 
 
944
 
  if (opt_drop)
945
 
    os << "DROP TABLE IF EXISTS `" << obj.tableName <<  "`;" << endl;
946
 
 
947
 
  os << "CREATE TABLE `" << obj.tableName << "` (" << endl;
948
 
  std::vector<DrizzleDumpField*>::iterator i;
949
 
  std::vector<DrizzleDumpField*> output_fields = obj.fields;
950
 
  for (i= output_fields.begin(); i != output_fields.end(); ++i)
951
 
  {
952
 
    if (i != output_fields.begin())
953
 
      os << "," << endl;
954
 
    DrizzleDumpField *field= *i;
955
 
    os << *field;
956
 
  }
957
 
 
958
 
  std::vector<DrizzleDumpIndex*>::iterator j;
959
 
  std::vector<DrizzleDumpIndex*> output_indexes = obj.indexes;
960
 
  for (j= output_indexes.begin(); j != output_indexes.end(); ++j)
961
 
  {
962
 
    os << "," << endl;;
963
 
    DrizzleDumpIndex *index= *j;
964
 
    os << *index;
965
 
  }
966
 
  os << endl;
967
 
  os << ") ENGINE=" << obj.engineName << " ";
968
 
  if ((connected_server_type == SERVER_MYSQL_FOUND) and (obj.autoIncrement > 0))
969
 
    os << "AUTO_INCREMENT=" << obj.autoIncrement << " ";
970
 
 
971
 
  os << "COLLATE = " << obj.collate << ";" << endl << endl;
972
 
 
973
 
  return os;
974
 
}
975
 
 
976
165
void dump_all_tables(void)
977
166
{
978
167
  std::vector<DrizzleDumpDatabase*>::iterator i;
979
168
  for (i= database_store.begin(); i != database_store.end(); ++i)
980
169
  {
981
 
    (*i)->populateTables(dcon);
 
170
    (*i)->populateTables();
982
171
  }
983
172
}
984
173
 
1344
533
  drizzle_result_st tableres;
1345
534
  int result=0;
1346
535
  std::string query;
 
536
  DrizzleDumpDatabase *database;
1347
537
 
1348
538
  if (connected_server_type == SERVER_MYSQL_FOUND)
1349
539
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema')";
1355
545
  while ((row= drizzle_row_next(&tableres)))
1356
546
  {
1357
547
    std::string database_name(row[0]);
1358
 
    DrizzleDumpDatabase *database= new DrizzleDumpDatabase(database_name);
 
548
    if (connected_server_type == SERVER_MYSQL_FOUND)
 
549
      database= new DrizzleDumpDatabaseMySQL(database_name);
 
550
    else
 
551
      database= new DrizzleDumpDatabaseDrizzle(database_name);
 
552
 
1359
553
    database->setCollate(row[1]);
1360
554
    database_store.push_back(database);
1361
555
  }
1369
563
{
1370
564
  int result=0;
1371
565
  string temp;
 
566
  DrizzleDumpDatabase *database;
 
567
 
1372
568
  for (vector<string>::const_iterator it= db_names.begin(); it != db_names.end(); ++it)
1373
569
  {
1374
570
    temp= *it;
1375
 
    DrizzleDumpDatabase *database= new DrizzleDumpDatabase(temp);
 
571
    if (connected_server_type == SERVER_MYSQL_FOUND)
 
572
      database= new DrizzleDumpDatabaseMySQL(temp);
 
573
    else
 
574
      database= new DrizzleDumpDatabaseDrizzle(temp);
1376
575
    database_store.push_back(database);
1377
576
  }
1378
577
  return(result);
1380
579
 
1381
580
static int dump_selected_tables(const string &db, const vector<string> &table_names)
1382
581
{
1383
 
  DrizzleDumpDatabase *database= new DrizzleDumpDatabase(db);
 
582
  DrizzleDumpDatabase *database;
 
583
  DrizzleDumpTable *table;
 
584
 
 
585
  if (connected_server_type == SERVER_MYSQL_FOUND)
 
586
    database= new DrizzleDumpDatabaseMySQL(db);
 
587
  else
 
588
    database= new DrizzleDumpDatabaseDrizzle(db);
 
589
 
1384
590
  database_store.push_back(database); 
1385
591
 
1386
592
  for (vector<string>::const_iterator it= table_names.begin(); it != table_names.end(); ++it)
1387
593
  {
1388
594
    string temp= *it;
1389
 
    DrizzleDumpTable *table= new DrizzleDumpTable(temp);
 
595
    if (connected_server_type == SERVER_MYSQL_FOUND)
 
596
      table= new DrizzleDumpTableMySQL(temp);
 
597
    else
 
598
      table= new DrizzleDumpTableDrizzle(temp);
1390
599
    database->tables.push_back(table);
1391
600
  }
1392
601
  database_store.push_back(database);