22 #include "client/drizzledump_data.h"
23 #include "client/client_priv.h"
25 #include <drizzled/gettext.h>
28 #include <boost/unordered_set.hpp>
29 #include <boost/lexical_cast.hpp>
31 #define EX_DRIZZLEERR 2
33 extern bool opt_no_create_info;
34 extern bool opt_no_data;
35 extern bool opt_create_db;
36 extern bool opt_disable_keys;
37 extern bool extended_insert;
38 extern bool opt_replace_into;
41 extern bool opt_databases;
42 extern bool opt_alldbs;
43 extern uint32_t show_progress_size;
44 extern bool opt_ignore;
45 extern bool opt_compress;
46 extern bool opt_drop_database;
47 extern bool opt_autocommit;
48 extern bool ignore_errors;
49 extern std::string opt_destination_database;
51 extern boost::unordered_set<std::string> ignore_table;
52 extern void maybe_exit(
int error);
60 extern int opt_destination;
63 bool DrizzleDumpDatabase::ignoreTable(std::string tableName)
65 return ignore_table.find(databaseName +
"." + tableName) == ignore_table.end();
68 void DrizzleDumpDatabase::cleanTableName(std::string &tableName)
70 std::string replace(
"``");
71 std::string find(
"`");
73 for (;(j = tableName.find(find, j)) != std::string::npos;)
75 tableName.replace(j, find.length(), replace);
83 os <<
" CONSTRAINT `" << obj.constraintName <<
"` FOREIGN KEY ("
84 << obj.parentColumns <<
") REFERENCES `" << obj.childTable <<
"` ("
85 << obj.childColumns <<
")";
87 if (not obj.deleteRule.empty())
88 os <<
" ON DELETE " << obj.deleteRule;
90 if (not obj.updateRule.empty())
91 os <<
" ON UPDATE " << obj.updateRule;
100 os <<
" PRIMARY KEY ";
102 else if (obj.isUnique)
104 os <<
" UNIQUE KEY `" << obj.indexName <<
"` ";
108 os <<
" KEY `" << obj.indexName <<
"` ";
113 std::vector<DrizzleDumpIndex::columnData>::iterator i;
114 std::vector<DrizzleDumpIndex::columnData> fields = obj.columns;
115 for (i= fields.begin(); i != fields.end(); ++i)
117 if (i != fields.begin())
119 os <<
"`" << (*i).first <<
"`";
121 os <<
"(" << (*i).second <<
")";
131 os <<
" `" << obj.fieldName <<
"` ";
133 if (((obj.type.compare(
"VARCHAR") == 0) or
134 (obj.type.compare(
"VARBINARY") == 0)) and
137 os <<
"(" << obj.length <<
")";
139 else if (((obj.type.compare(
"DECIMAL") == 0) or
140 (obj.type.compare(
"DOUBLE") == 0)) and
141 ((obj.decimalPrecision + obj.decimalScale) > 0))
143 os <<
"(" << obj.decimalPrecision <<
"," << obj.decimalScale <<
")";
145 else if (obj.type.compare(
"ENUM") == 0)
147 os <<
"(" << obj.enumValues <<
")";
155 if ((not obj.collation.empty()) and (obj.collation.compare(
"binary") != 0))
157 os <<
" COLLATE " << obj.collation;
160 if (obj.isAutoIncrement)
161 os <<
" AUTO_INCREMENT";
163 if (not obj.defaultValue.empty())
165 if (obj.defaultValue.compare(
"CURRENT_TIMESTAMP") != 0)
167 if (obj.defaultValue.compare(0, 2,
"b'") == 0)
169 os <<
" DEFAULT " << obj.defaultValue;
173 os <<
" DEFAULT '" << obj.defaultValue <<
"'";
178 os <<
" DEFAULT CURRENT_TIMESTAMP";
181 else if ((obj.defaultIsNull))
183 os <<
" DEFAULT NULL";
186 if (not obj.comment.empty())
188 os <<
" COMMENT '" << DrizzleDumpData::escape(obj.comment.c_str(), obj.comment.length()) <<
"'";
196 if ((opt_destination == DESTINATION_DB) or opt_databases or opt_alldbs)
200 std::cerr <<
"--" << std::endl
201 <<
"-- Current Database: `" << obj.databaseName <<
"`" << std::endl
202 <<
"--" << std::endl << std::endl;
206 if (not opt_create_db)
208 if (opt_drop_database)
210 os <<
"DROP DATABASE IF EXISTS `"
211 << ((opt_destination_database.empty()) ? obj.databaseName
212 : opt_destination_database) <<
"`" << std::endl;
215 os <<
"CREATE DATABASE IF NOT EXISTS `"
216 << ((opt_destination_database.empty()) ? obj.databaseName
217 : opt_destination_database) <<
"`";
218 if (not obj.collate.empty())
219 os <<
" COLLATE = " << obj.collate;
221 os <<
";" << std::endl << std::endl;
223 os <<
"USE `" << ((opt_destination_database.empty()) ? obj.databaseName
224 : opt_destination_database) <<
"`;" << std::endl << std::endl;
227 std::vector<DrizzleDumpTable*>::iterator i;
228 std::vector<DrizzleDumpTable*> output_tables = obj.tables;
229 for (i= output_tables.begin(); i != output_tables.end(); ++i)
232 if (not opt_no_create_info)
236 obj.dcon->setDB(obj.databaseName);
240 std::cerr <<
"Error: Could not get data for table " << table->displayName << std::endl;
241 if (not ignore_errors)
242 maybe_exit(EX_DRIZZLEERR);
255 std::ostream& operator <<(std::ostream &os,
const DrizzleDumpData &obj)
257 bool new_insert=
true;
260 size_t byte_counter= 0;
265 std::cerr << _(
"-- Retrieving data for ") << obj.table->displayName <<
"..." << std::endl;
267 if (drizzle_result_row_count(obj.result) < 1)
271 std::cerr <<
"--" << std::endl
272 <<
"-- No data to dump for table `" << obj.table->displayName <<
"`"
273 << std::endl <<
"--" << std::endl << std::endl;
279 std::cerr <<
"--" << std::endl
280 <<
"-- Dumping data for table `" << obj.table->displayName <<
"`"
281 << std::endl <<
"--" << std::endl << std::endl;
283 if (opt_disable_keys)
284 os <<
"ALTER TABLE `" << obj.table->displayName <<
"` DISABLE KEYS;" << std::endl;
288 os <<
"START TRANSACTION;" << std::endl;
290 while((row= drizzle_row_next(obj.result)))
293 if (verbose and (rownr % show_progress_size) == 0)
295 std::cerr <<
"-- " << rownr << _(
" rows dumped for table ") << obj.table->displayName << std::endl;
298 size_t* row_sizes= drizzle_row_field_sizes(obj.result);
299 for (uint32_t i= 0; i < drizzle_result_column_count(obj.result); i++)
300 byte_counter+= row_sizes[i];
302 if (not first and not new_insert)
307 os <<
");" << std::endl;
315 if (opt_replace_into)
323 os <<
"INTO `" << obj.table->displayName <<
"` VALUES (";
324 byte_counter+= 28 + obj.table->displayName.length();
328 for (uint32_t i= 0; i < drizzle_result_column_count(obj.result); i++)
333 if (i != obj.table->fields.size() - 1)
338 if ((obj.table->fields[i]->rangeCheck) and
339 (obj.table->fields[i]->type.compare(
"BIGINT") == 0) and
340 (boost::lexical_cast<uint64_t>(row[i]) > INT64_MAX))
342 std::cerr <<
"Error: Data for column " << obj.table->fields[i]->fieldName <<
" is greater than max BIGINT, cannot migrate automatically" << std::endl;
343 if (not ignore_errors)
344 maybe_exit(EX_DRIZZLEERR);
350 else if (obj.table->fields[i]->convertDateTime)
352 os << obj.checkDateTime(row[i], i);
356 if ((obj.table->fields[i]->type.compare(
"INT") != 0) and
357 (obj.table->fields[i]->type.compare(
"BIGINT") != 0))
360 if (((obj.table->fields[i]->type.compare(
"BLOB") == 0) or
361 (obj.table->fields[i]->type.compare(
"VARBINARY") == 0)))
363 os << obj.convertHex((
unsigned char*)row[i], row_sizes[i]);
364 byte_counter+= row_sizes[i];
366 else if ((obj.table->fields[i]->type.compare(
"ENUM") == 0) and
367 (strcmp(row[i],
"") == 0))
371 else if (obj.table->fields[i]->type.compare(
"BOOLEAN") == 0)
373 if (strncmp(row[i],
"1", 1) == 0)
379 os <<
"'" << DrizzleDumpData::escape(row[i], row_sizes[i]) <<
"'";
385 if (i != obj.table->fields.size() - 1)
389 if ((extended_insert and
390 (byte_counter >= DRIZZLE_MAX_LINE_LENGTH)) or (not extended_insert))
392 os <<
");" << std::endl;
398 os <<
");" << std::endl;
401 os <<
"COMMIT;" << std::endl;
403 if (opt_disable_keys)
404 os <<
"ALTER TABLE `" << obj.table->tableName <<
"` ENABLE KEYS;" << std::endl;
411 std::string DrizzleDumpData::convertHex(
const unsigned char* from,
size_t from_size)
const
413 std::ostringstream output;
419 while (from_size > 0)
422 output << std::uppercase << std::hex << std::setw(2) << std::setfill(
'0') << (
unsigned short)(*from);
431 std::string DrizzleDumpData::escape(
const char* from,
size_t from_size)
435 while (from_size > 0)
442 output.append(
"\\0");
445 output.append(
"\\n");
448 output.append(
"\\r");
451 output.append(
"\\\\");
454 output.append(
"\\'");
457 output.append(
"\\\"");
460 output.append(
"\\Z");
463 output.push_back(*from);
468 output.push_back(*from);
480 std::cerr <<
"--" << std::endl
481 <<
"-- Table structure for table `" << obj.displayName <<
"`" << std::endl
482 <<
"--" << std::endl << std::endl;
486 os <<
"DROP TABLE IF EXISTS `" << obj.displayName <<
"`;" << std::endl;
488 os <<
"CREATE TABLE `" << obj.displayName <<
"` (" << std::endl;
489 std::vector<DrizzleDumpField*>::iterator i;
490 std::vector<DrizzleDumpField*> output_fields = obj.fields;
491 for (i= output_fields.begin(); i != output_fields.end(); ++i)
493 if (i != output_fields.begin())
494 os <<
"," << std::endl;
499 std::vector<DrizzleDumpIndex*>::iterator j;
500 std::vector<DrizzleDumpIndex*> output_indexes = obj.indexes;
501 for (j= output_indexes.begin(); j != output_indexes.end(); ++j)
503 os <<
"," << std::endl;
508 std::vector<DrizzleDumpForeignKey*>::iterator k;
509 std::vector<DrizzleDumpForeignKey*> output_fkeys = obj.fkeys;
510 for (k= output_fkeys.begin(); k != output_fkeys.end(); ++k)
512 os <<
"," << std::endl;
518 os <<
") ENGINE='" << obj.engineName <<
"' ";
519 if (obj.autoIncrement > 0)
521 os <<
"AUTO_INCREMENT=" << obj.autoIncrement <<
" ";
524 os <<
"COLLATE='" << obj.collate <<
"'";
526 if (not obj.comment.empty())
528 os <<
" COMMENT='" << obj.comment <<
"'";
531 if (not obj.replicate)
533 os <<
" REPLICATE=FALSE";
536 os <<
";" << std::endl << std::endl;
541 DrizzleDumpConnection::DrizzleDumpConnection(std::string &host, uint16_t port,
542 std::string &username, std::string &password,
bool drizzle_protocol) :
544 drizzleProtocol(drizzle_protocol)
551 std::string protocol= (drizzle_protocol) ?
"Drizzle" :
"MySQL";
554 std::cerr << _(
"-- Connecting to ") << host << _(
" using protocol ")
555 << protocol <<
"..." << std::endl;
558 drizzle= drizzle_create();
562 std::cerr <<
"drizzle_create() failed" << std::endl;
565 connection= drizzle_con_create(drizzle);
566 drizzle_con_set_tcp(connection, (
char *)host.c_str(), port);
567 drizzle_con_set_auth(connection, (
char *)username.c_str(), (
char *)password.c_str());
568 drizzle_con_add_options(connection, drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
570 drizzle_return_t ret= drizzle_con_connect(connection);
571 if (ret != DRIZZLE_RETURN_OK)
573 errorHandler(NULL, ret,
"when trying to connect");
574 throw std::exception();
579 serverType= server_detect.getServerType();
580 serverVersion= server_detect.getServerVersion();
583 drizzle_result_st* DrizzleDumpConnection::query(std::string &str_query)
585 drizzle_return_t ret;
586 drizzle_result_st* result=
new drizzle_result_st;
587 if (drizzle_query_str(connection, result, str_query.c_str(), &ret) == NULL or
588 ret != DRIZZLE_RETURN_OK)
590 if (ret == DRIZZLE_RETURN_ERROR_CODE)
592 std::cerr << _(
"Error executing query: ") <<
593 drizzle_result_error(result) << std::endl;
594 drizzle_result_free(result);
598 std::cerr << _(
"Error executing query: ") << drizzle_con_error(connection) << std::endl;
603 if (drizzle_result_buffer(result) != DRIZZLE_RETURN_OK)
605 std::cerr << _(
"Could not buffer result: ") << drizzle_con_error(connection) << std::endl;
611 void DrizzleDumpConnection::freeResult(drizzle_result_st* result)
613 drizzle_result_free(result);
617 bool DrizzleDumpConnection::queryNoResult(std::string &str_query)
619 drizzle_return_t ret;
620 drizzle_result_st result;
622 if (drizzle_query_str(connection, &result, str_query.c_str(), &ret) == NULL or
623 ret != DRIZZLE_RETURN_OK)
625 if (ret == DRIZZLE_RETURN_ERROR_CODE)
627 std::cerr << _(
"Error executing query: ") <<
628 drizzle_result_error(&result) << std::endl;
629 drizzle_result_free(&result);
633 std::cerr << _(
"Error executing query: ") << drizzle_con_error(connection) << std::endl;
638 drizzle_result_free(&result);
642 bool DrizzleDumpConnection::setDB(std::string databaseName)
644 drizzle_return_t ret;
645 drizzle_result_st result;
647 if (drizzle_select_db(connection, &result, databaseName.c_str(), &ret) == NULL or
648 ret != DRIZZLE_RETURN_OK)
650 std::cerr << _(
"Error: Could not set db '") << databaseName <<
"'" << std::endl;
651 if (ret == DRIZZLE_RETURN_ERROR_CODE)
653 drizzle_result_free(&result);
658 drizzle_result_free(&result);
663 void DrizzleDumpConnection::errorHandler(drizzle_result_st *res,
664 drizzle_return_t ret,
const char *when)
668 std::cerr << _(
"Got error: ") << drizzle_con_error(connection) <<
" " << when << std::endl;
670 else if (ret == DRIZZLE_RETURN_ERROR_CODE)
672 std::cerr << _(
"Got error: ") << drizzle_result_error(res)
673 <<
" (" << drizzle_result_error_code(res) <<
") " << when << std::endl;
674 drizzle_result_free(res);
678 std::cerr << _(
"Got error: ") << ret <<
" " << when << std::endl;
684 DrizzleDumpConnection::~DrizzleDumpConnection()
688 std::cerr << _(
"-- Disconnecting from ") << hostName <<
"..." << std::endl;
691 drizzle_con_free(connection);
692 drizzle_free(drizzle);