153
162
void dump_all_tables(void);
154
163
void generate_dump(void);
158
SERVER_DRIZZLE_FOUND,
162
int connected_server_type= SERVER_UNKNOWN_FOUND;
164
bool DrizzleDumpDatabase::populateTables(drizzle_con_st &connection)
166
drizzle_result_st result;
168
drizzle_return_t ret;
171
if (drizzle_select_db(&connection, &result, databaseName.c_str(), &ret) ==
172
NULL || ret != DRIZZLE_RETURN_OK)
174
errmsg << _("Could not set db '") << databaseName << "'";
177
drizzle_result_free(&result);
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='";
182
query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='";
184
query.append(databaseName);
185
query.append("' ORDER BY TABLE_NAME");
187
if (drizzle_query_str(&connection, &result, query.c_str(), &ret) == NULL ||
188
ret != DRIZZLE_RETURN_OK)
190
if (ret == DRIZZLE_RETURN_ERROR_CODE)
192
errmsg << _("Could not get tables list due to error: ") <<
193
drizzle_result_error(&result);
194
drizzle_result_free(&result);
198
errmsg << _("Could not get tables list due to error: ") <<
199
drizzle_con_error(&connection);
204
if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
206
errmsg << _("Could not get tables list due to error: ") <<
207
drizzle_con_error(&connection);
211
while ((row= drizzle_row_next(&result)))
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)
220
table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]);
222
table->autoIncrement= 0;
225
table->database= this;
226
table->populateFields(connection);
227
table->populateIndexes(connection);
228
tables.push_back(table);
231
drizzle_result_free(&result);
236
bool DrizzleDumpTable::populateFields(drizzle_con_st &connection)
238
drizzle_result_st result;
240
drizzle_return_t ret;
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='";
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");
252
if (drizzle_query_str(&connection, &result, query.c_str(), &ret) == NULL ||
253
ret != DRIZZLE_RETURN_OK)
255
if (ret == DRIZZLE_RETURN_ERROR_CODE)
257
errmsg << _("Could not get tables list due to error: ") <<
258
drizzle_result_error(&result);
259
drizzle_result_free(&result);
263
errmsg << _("Could not get tables list due to error: ") <<
264
drizzle_con_error(&connection);
269
if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
271
errmsg << _("Could not get tables list due to error: ") <<
272
drizzle_con_error(&connection);
275
while ((row= drizzle_row_next(&result)))
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]);
285
if (field->convertDateTime)
287
field->dateTimeConvert(row[2]);
290
field->defaultValue= row[2];
293
field->defaultValue= "";
295
field->isNull= (strcmp(row[4], "YES") == 0) ? true : false;
296
if (connected_server_type == SERVER_MYSQL_FOUND)
298
field->isAutoIncrement= (strcmp(row[9], "auto_increment") == 0) ? true : false;
299
field->defaultIsNull= field->isNull;
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] : "";
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;
312
fields.push_back(field);
315
drizzle_result_free(&result);
319
void DrizzleDumpField::dateTimeConvert(const char* oldDefault)
321
boost::match_flag_type flags = boost::match_default;
323
if (strcmp(oldDefault, "CURRENT_TIMESTAMP") == 0)
325
defaultValue= oldDefault;
329
if (type.compare("INT") == 0)
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());
338
boost::regex date_regex("([0-9]{3}[1-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))");
340
if (regex_search(oldDefault, date_regex, flags))
342
defaultValue= oldDefault;
352
bool DrizzleDumpTable::populateIndexes(drizzle_con_st &connection)
354
drizzle_result_st result;
356
drizzle_return_t ret;
359
bool firstIndex= true;
360
DrizzleDumpIndex *index;
362
if (connected_server_type == SERVER_MYSQL_FOUND)
363
query="SHOW INDEXES FROM ";
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)
370
if (drizzle_query_str(&connection, &result, query.c_str(), &ret) == NULL ||
371
ret != DRIZZLE_RETURN_OK)
373
if (ret == DRIZZLE_RETURN_ERROR_CODE)
375
errmsg << _("Could not get tables list due to error: ") <<
376
drizzle_result_error(&result);
377
drizzle_result_free(&result);
381
errmsg << _("Could not get tables list due to error: ") <<
382
drizzle_con_error(&connection);
387
if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
389
errmsg << _("Could not get tables list due to error: ") <<
390
drizzle_con_error(&connection);
393
while ((row= drizzle_row_next(&result)))
395
std::string indexName((connected_server_type == SERVER_MYSQL_FOUND) ? row[2] : row[0]);
396
if (indexName.compare(lastKey) != 0)
398
if ((connected_server_type == SERVER_MYSQL_FOUND) and
399
(strcmp(row[10], "FULLTEXT") == 0))
403
indexes.push_back(index);
404
index = new DrizzleDumpIndex(indexName);
405
if (connected_server_type == SERVER_MYSQL_FOUND)
407
index->isPrimary= (strcmp(row[2], "PRIMARY") == 0);
408
index->isUnique= (strcmp(row[1], "0") == 0);
409
index->isHash= (strcmp(row[10], "HASH") == 0);
413
index->isPrimary= (strcmp(row[0], "PRIMARY") == 0);
414
index->isUnique= (strcmp(row[3], "YES") == 0);
417
lastKey= (connected_server_type == SERVER_MYSQL_FOUND) ? row[2] : row[0];
420
index->columns.push_back((connected_server_type == SERVER_MYSQL_FOUND) ? row[4] : row[1]);
423
indexes.push_back(index);
425
drizzle_result_free(&result);
429
void DrizzleDumpField::setType(const char* raw_type, const char* raw_collation)
431
std::string old_type(raw_type);
435
if ((pos= old_type.find("(")) != string::npos)
437
extra= old_type.substr(pos);
438
old_type.erase(pos,string::npos);
441
if (connected_server_type == SERVER_DRIZZLE_FOUND)
443
collation= raw_collation;
444
if (strcmp(raw_type, "BLOB") == 0)
446
if (strcmp(raw_collation, "binary") != 0)
453
if (strcmp(raw_type, "VARCHAR") == 0)
455
if (strcmp(raw_collation, "binary") != 0)
462
if (strcmp(raw_type, "INTEGER") == 0)
472
if (connected_server_type == SERVER_MYSQL_FOUND)
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);
479
if ((old_type.compare("INT") == 0) and
480
((extra.find("unsigned") != string::npos)))
486
if ((old_type.compare("TINYINT") == 0) or
487
(old_type.compare("SMALLINT") == 0) or
488
(old_type.compare("MEDIUMINT") == 0))
494
if ((old_type.compare("TINYBLOB") == 0) or
495
(old_type.compare("MEDIUMBLOB") == 0) or
496
(old_type.compare("LONGBLOB") == 0))
502
if ((old_type.compare("TINYTEXT") == 0) or
503
(old_type.compare("MEDIUMTEXT") == 0) or
504
(old_type.compare("LONGTEXT") == 0))
510
if (old_type.compare("CHAR") == 0)
516
if (old_type.compare("BINARY") == 0)
522
if (old_type.compare("ENUM") == 0)
525
/* Strip out the braces, we add them again during output */
526
enumValues= extra.substr(1, extra.length()-2);
530
if ((old_type.find("TIME") != string::npos) or
531
(old_type.find("DATE") != string::npos))
533
/* Intended to catch TIME/DATE/TIMESTAMP/DATETIME
534
We may have a default TIME/DATE which needs converting */
535
convertDateTime= true;
538
if (old_type.compare("TIME") == 0)
544
if (old_type.compare("FLOAT") == 0)
555
void DrizzleDumpTable::setEngine(const char* newEngine)
557
if (strcmp(newEngine, "MyISAM") == 0)
558
engineName= "InnoDB";
560
engineName= newEngine;
563
void DrizzleDumpDatabase::setCollate(const char* newCollate)
567
std::string tmpCollate(newCollate);
568
if (tmpCollate.find("utf8") != string::npos)
574
collate= "utf8_general_ci";
577
void DrizzleDumpTable::setCollate(const char* newCollate)
581
std::string tmpCollate(newCollate);
582
if (tmpCollate.find("utf8") != string::npos)
589
collate= "utf8_general_ci";
592
void DrizzleDumpField::setCollate(const char* newCollate)
596
std::string tmpCollate(newCollate);
597
if (tmpCollate.find("utf8") != string::npos)
599
collation= tmpCollate;
603
collation= "utf8_general_ci";
606
ostream& operator <<(ostream &os,const DrizzleDumpIndex &obj)
610
os << " PRIMARY KEY ";
612
else if (obj.isUnique)
614
os << " UNIQUE KEY `" << obj.indexName << "` ";
618
os << " KEY `" << obj.indexName << "` ";
623
std::vector<std::string>::iterator i;
624
std::vector<std::string> fields = obj.columns;
625
for (i= fields.begin(); i != fields.end(); ++i)
627
if (i != fields.begin())
629
std::string field= *i;
630
os << "`" << field << "`";
638
ostream& operator <<(ostream &os, const DrizzleDumpField &obj)
640
os << " `" << obj.fieldName << "` ";
642
if (((obj.type.compare("VARCHAR") == 0) or
643
(obj.type.compare("VARBINARY") == 0)) and
646
os << "(" << obj.length << ")";
648
else if ((obj.type.compare("DECIMAL") == 0) or
649
(obj.type.compare("DOUBLE") == 0))
651
os << "(" << obj.decimalPrecision << "," << obj.decimalScale << ")";
653
else if (obj.type.compare("ENUM") == 0)
655
os << "(" << obj.enumValues << ")";
663
if ((not obj.collation.empty()) and (obj.collation.compare("binary") != 0))
665
os << " COLLATE " << obj.collation;
668
if (obj.isAutoIncrement)
669
os << " AUTO_INCREMENT";
671
if (not obj.defaultValue.empty())
673
if (obj.defaultValue.compare("CURRENT_TIMESTAMP") != 0)
674
os << " DEFAULT '" << obj.defaultValue << "'";
676
os << " DEFAULT CURRENT_TIMESTAMP";
678
else if ((obj.collation.empty()) and (obj.defaultIsNull))
680
os << " DEFAULT NULL";
686
ostream& operator <<(ostream &os,const DrizzleDumpDatabase &obj)
689
<< "-- Current Database: `" << obj.databaseName << "`" << endl
690
<< "--" << endl << endl;
692
/* Love that this variable is the opposite of its name */
693
if (not opt_create_db)
695
os << "CREATE DATABASE IF NOT EXISTS `" << obj.databaseName
696
<< "` COLLATE = " << obj.collate << ";" << endl << endl;
699
os << "USE `" << obj.databaseName << "`;" << endl << endl;
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)
705
DrizzleDumpTable *table= *i;
706
if (not opt_no_create_info)
710
DrizzleDumpData *data= new DrizzleDumpData(dcon, table);
719
DrizzleDumpData::DrizzleDumpData(drizzle_con_st &conn, DrizzleDumpTable *dataTable) :
723
drizzle_return_t ret;
725
query= "SELECT * FROM `";
726
query.append(table->tableName);
728
result= new drizzle_result_st;
730
if (drizzle_query_str(connection, result, query.c_str(), &ret) == NULL ||
731
ret != DRIZZLE_RETURN_OK)
733
if (ret == DRIZZLE_RETURN_ERROR_CODE)
735
errmsg << _("Could not get tables list due to error: ") <<
736
drizzle_result_error(result);
737
drizzle_result_free(result);
741
errmsg << _("Could not get tables list due to error: ") <<
742
drizzle_con_error(connection);
747
if (drizzle_result_buffer(result) != DRIZZLE_RETURN_OK)
749
errmsg << _("Could not get tables list due to error: ") <<
750
drizzle_con_error(connection);
754
DrizzleDumpData::~DrizzleDumpData()
756
drizzle_result_free(result);
757
if (result) delete result;
759
ostream& operator <<(ostream &os,const DrizzleDumpData &obj)
761
bool new_insert= true;
767
if (drizzle_result_row_count(obj.result) < 1)
770
<< "-- No data to dump for table `" << obj.table->tableName << "`" << endl
771
<< "--" << endl << endl;
777
<< "-- Dumping data for table `" << obj.table->tableName << "`" << endl
778
<< "--" << endl << endl;
780
if (opt_disable_keys)
781
os << "ALTER TABLE `" << obj.table->tableName << "` DISABLE KEYS;" << endl;
783
streampos out_position= os.tellp();
785
while((row= drizzle_row_next(obj.result)))
788
if ((rownr % show_progress_size) == 0)
790
cerr << "-- %" << rownr << _(" rows dumped for table ") << obj.table->tableName << endl;
793
size_t* row_sizes= drizzle_row_field_sizes(obj.result);
806
if (opt_replace_into)
810
os << "INTO `" << obj.table->tableName << "` VALUES (";
814
for (uint32_t i= 0; i < drizzle_result_column_count(obj.result); i++)
820
/* time/date conversion for MySQL connections */
821
else if ((connected_server_type == SERVER_MYSQL_FOUND) and
822
(obj.table->fields[i]->convertDateTime))
824
if (obj.table->fields[i]->type.compare("INT") == 0)
825
os << obj.convertTime(row[i]);
827
os << obj.convertDate(row[i]);
831
if (obj.table->fields[i]->type.compare("INT") != 0)
833
/* Hex blob processing or escape text */
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]);
839
os << "'" << obj.escape(row[i], row_sizes[i]) << "'";
844
if (i != obj.table->fields.size() - 1)
847
/* Break insert up if it is too long */
848
if (extended_insert and
849
((os.tellp() - out_position) >= DRIZZLE_MAX_LINE_LENGTH))
853
out_position= os.tellp();
858
if (opt_disable_keys)
859
os << "ALTER TABLE `" << obj.table->tableName << "` ENABLE KEYS;" << endl;
866
long DrizzleDumpData::convertTime(const char* oldTime) const
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();
874
std::string DrizzleDumpData::convertDate(const char* oldDate) const
876
boost::match_flag_type flags = boost::match_default;
878
boost::regex date_regex("([0-9]{3}[1-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))");
880
if (regex_search(oldDate, date_regex, flags))
882
output.push_back('\'');
883
output.append(oldDate);
884
output.push_back('\'');
892
std::string DrizzleDumpData::convertHex(const char* from, size_t from_size) const
894
ostringstream output;
897
while (from_size > 0)
899
output << uppercase << hex << setw(2) << setfill('0') << int(*from);
907
/* Ripped out of libdrizzle, hopefully a little safer */
908
std::string DrizzleDumpData::escape(const char* from, size_t from_size) const
912
while (from_size > 0)
925
output.push_back('\\');
930
output.push_back(*from);
938
ostream& operator <<(ostream &os,const DrizzleDumpTable &obj)
941
<< "-- Table structure for table `" << obj.tableName << "`" << endl
942
<< "--" << endl << endl;
945
os << "DROP TABLE IF EXISTS `" << obj.tableName << "`;" << endl;
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)
952
if (i != output_fields.begin())
954
DrizzleDumpField *field= *i;
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)
963
DrizzleDumpIndex *index= *j;
967
os << ") ENGINE=" << obj.engineName << " ";
968
if ((connected_server_type == SERVER_MYSQL_FOUND) and (obj.autoIncrement > 0))
969
os << "AUTO_INCREMENT=" << obj.autoIncrement << " ";
971
os << "COLLATE = " << obj.collate << ";" << endl << endl;
976
165
void dump_all_tables(void)
978
167
std::vector<DrizzleDumpDatabase*>::iterator i;
979
168
for (i= database_store.begin(); i != database_store.end(); ++i)
981
(*i)->populateTables(dcon);
170
(*i)->populateTables();