20 #include "client/drizzledump_data.h"
21 #include "client/drizzledump_mysql.h"
22 #include "client/client_priv.h"
25 #include <boost/regex.hpp>
26 #include <boost/date_time/posix_time/posix_time.hpp>
27 #include <drizzled/gettext.h>
30 extern bool ignore_errors;
32 bool DrizzleDumpDatabaseMySQL::populateTables()
34 drizzle_result_st *result;
38 if (not dcon->setDB(databaseName))
42 std::cerr << _(
"-- Retrieving table structures for ") << databaseName <<
"..." << std::endl;
44 query=
"SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, AUTO_INCREMENT, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE != 'VIEW' AND TABLE_SCHEMA='";
45 query.append(databaseName);
46 query.append(
"' ORDER BY TABLE_NAME");
48 result= dcon->query(query);
53 while ((row= drizzle_row_next(result)))
55 size_t* row_sizes= drizzle_row_field_sizes(result);
56 std::string tableName(row[0]);
57 std::string displayName(tableName);
58 cleanTableName(displayName);
59 if (not ignoreTable(displayName))
63 table->displayName= displayName;
64 table->setCollate(row[1]);
65 table->setEngine(row[2]);
67 table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]);
69 table->autoIncrement= 0;
71 if ((row[4]) and (strstr(row[4],
"InnoDB free") == NULL))
72 table->comment= DrizzleDumpData::escape(row[4], row_sizes[4]);
76 table->database=
this;
77 if ((not table->populateFields()) or (not table->populateIndexes()) or
78 (not table->populateFkeys()))
81 if (not ignore_errors)
86 tables.push_back(table);
89 dcon->freeResult(result);
94 bool DrizzleDumpDatabaseMySQL::populateTables(
const std::vector<std::string> &table_names)
96 drizzle_result_st *result;
100 if (not dcon->setDB(databaseName))
104 std::cerr << _(
"-- Retrieving table structures for ") << databaseName <<
"..." << std::endl;
105 for (std::vector<std::string>::const_iterator it= table_names.begin(); it != table_names.end(); ++it)
107 std::string tableName= *it;
108 std::string displayName(tableName);
109 cleanTableName(displayName);
110 if (not ignoreTable(displayName))
113 query=
"SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='";
114 query.append(databaseName);
115 query.append(
"' AND TABLE_NAME = '");
116 query.append(tableName);
119 result= dcon->query(query);
124 if ((row= drizzle_row_next(result)))
127 table->displayName= displayName;
128 table->setCollate(row[1]);
129 table->setEngine(row[2]);
131 table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]);
133 table->autoIncrement= 0;
135 table->database=
this;
136 if ((not table->populateFields()) or (not table->populateIndexes()))
139 if (not ignore_errors)
144 tables.push_back(table);
145 dcon->freeResult(result);
149 dcon->freeResult(result);
150 if (not ignore_errors)
161 bool DrizzleDumpTableMySQL::populateFields()
163 drizzle_result_st *result;
168 std::cerr << _(
"-- Retrieving fields for ") << tableName <<
"..." << std::endl;
170 query=
"SELECT COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME, EXTRA, COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='";
171 query.append(database->databaseName);
172 query.append(
"' AND TABLE_NAME='");
173 query.append(tableName);
174 query.append(
"' ORDER BY ORDINAL_POSITION");
176 result= dcon->query(query);
181 while ((row= drizzle_row_next(result)))
183 std::string fieldName(row[0]);
186 field->convertDateTime=
false;
187 field->isNull= strcmp(row[3],
"YES") == 0;
189 field->setType(row[1], row[8]);
190 if (field->type.compare(
"ENUM") == 0)
193 if ((row[2]) and (field->type.compare(
"TEXT") != 0))
195 field->defaultValue= row[2];
196 if (field->convertDateTime)
198 field->dateTimeConvert();
203 field->defaultValue=
"";
206 field->isAutoIncrement= strcmp(row[8],
"auto_increment") == 0;
207 field->defaultIsNull= field->isNull;
210 if ((strncmp(row[1],
"bit", 3) == 0) and (row[5] != NULL))
211 field->length= ((boost::lexical_cast<uint32_t>(row[5]) - 1) / 8) + 1;
213 field->length= (row[4]) ? boost::lexical_cast<uint32_t>(row[4]) : 0;
216 if (((field->type.compare(
"VARBINARY") == 0)
217 or (field->type.compare(
"VARCHAR") == 0))
218 and (field->length == 0))
223 field->decimalPrecision= (row[5]) ? boost::lexical_cast<uint32_t>(row[5]) : 0;
224 field->decimalScale= (row[6]) ? boost::lexical_cast<uint32_t>(row[6]) : 0;
225 field->comment= (row[9]) ? row[9] :
"";
226 fields.push_back(field);
229 dcon->freeResult(result);
234 void DrizzleDumpFieldMySQL::dateTimeConvert(
void)
236 boost::match_flag_type flags = boost::match_default;
238 if (strcmp(defaultValue.c_str(),
"CURRENT_TIMESTAMP") == 0)
241 if (type.compare(
"INT") == 0)
244 std::string ts(defaultValue);
245 boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts));
246 defaultValue= boost::lexical_cast<std::string>(td.total_seconds());
250 boost::regex date_regex(
"(0000|-00)");
252 if (regex_search(defaultValue, date_regex, flags))
260 bool DrizzleDumpTableMySQL::populateIndexes()
262 drizzle_result_st *result;
266 bool firstIndex=
true;
270 std::cerr << _(
"-- Retrieving indexes for ") << tableName <<
"..." << std::endl;
272 query=
"SHOW INDEXES FROM ";
273 query.append(tableName);
275 result= dcon->query(query);
280 while ((row= drizzle_row_next(result)))
282 std::string indexName(row[2]);
283 if (indexName.compare(lastKey) != 0)
285 if (strcmp(row[10],
"FULLTEXT") == 0)
289 indexes.push_back(index);
291 index->isPrimary= (strcmp(row[2],
"PRIMARY") == 0);
292 index->isUnique= (strcmp(row[1],
"0") == 0);
293 index->isHash= (strcmp(row[10],
"HASH") == 0);
297 uint32_t length= (row[7]) ? boost::lexical_cast<uint32_t>(row[7]) : 0;
298 index->columns.push_back(std::make_pair(row[4], length));
301 indexes.push_back(index);
303 dcon->freeResult(result);
307 bool DrizzleDumpTableMySQL::populateFkeys()
309 drizzle_result_st *result;
315 std::cerr << _(
"-- Retrieving foreign keys for ") << tableName <<
"..." << std::endl;
317 query=
"SHOW CREATE TABLE `";
318 query.append(database->databaseName);
320 query.append(tableName);
322 result= dcon->query(query);
327 if ((row= drizzle_row_next(result)))
329 boost::match_flag_type flags = boost::match_default;
330 boost::regex constraint_regex(
"CONSTRAINT `(.*?)` FOREIGN KEY \\((.*?)\\) REFERENCES `(.*?)` \\((.*?)\\)( ON (UPDATE|DELETE) (CASCADE|RESTRICT|SET NULL))?( ON (UPDATE|DELETE) (CASCADE|RESTRICT|SET NULL))?");
332 boost::match_results<std::string::const_iterator> constraint_results;
334 std::string search_body(row[1]);
335 std::string::const_iterator start, end;
336 start= search_body.begin();
337 end= search_body.end();
338 while (regex_search(start, end, constraint_results, constraint_regex, flags))
341 fkey->parentColumns= constraint_results[2];
342 fkey->childTable= constraint_results[3];
343 fkey->childColumns= constraint_results[4];
345 if (constraint_results[5].compare(
"") != 0)
347 if (constraint_results[6].compare(
"UPDATE") == 0)
348 fkey->updateRule= constraint_results[7];
349 else if (constraint_results[6].compare(
"DELETE") == 0)
350 fkey->deleteRule= constraint_results[7];
352 if (constraint_results[8].compare(
"") != 0)
354 if (constraint_results[9].compare(
"UPDATE") == 0)
355 fkey->updateRule= constraint_results[10];
356 else if (constraint_results[9].compare(
"DELETE") == 0)
357 fkey->deleteRule= constraint_results[10];
359 fkey->matchOption=
"";
361 fkeys.push_back(fkey);
363 start= constraint_results[0].second;
364 flags |= boost::match_prev_avail;
365 flags |= boost::match_not_bob;
368 dcon->freeResult(result);
372 void DrizzleDumpFieldMySQL::setType(
const char* raw_type,
const char* raw_collation)
374 std::string old_type(raw_type);
378 if (((pos= old_type.find(
"(")) != std::string::npos) or
379 ((pos= old_type.find(
" ")) != std::string::npos))
381 extra= old_type.substr(pos);
382 old_type.erase(pos, std::string::npos);
385 boost::to_upper(old_type);
386 if ((old_type.find(
"CHAR") != std::string::npos) or
387 (old_type.find(
"TEXT") != std::string::npos))
388 setCollate(raw_collation);
390 if ((old_type.compare(
"BIGINT") == 0) and
391 ((extra.find(
"unsigned") != std::string::npos)))
396 if ((old_type.compare(
"INT") == 0) and
397 ((extra.find(
"unsigned") != std::string::npos)))
403 if ((old_type.compare(
"TINYINT") == 0) or
404 (old_type.compare(
"SMALLINT") == 0) or
405 (old_type.compare(
"MEDIUMINT") == 0))
411 if ((old_type.compare(
"TINYBLOB") == 0) or
412 (old_type.compare(
"MEDIUMBLOB") == 0) or
413 (old_type.compare(
"LONGBLOB") == 0))
419 if ((old_type.compare(
"TINYTEXT") == 0) or
420 (old_type.compare(
"MEDIUMTEXT") == 0) or
421 (old_type.compare(
"LONGTEXT") == 0) or
422 (old_type.compare(
"SET") == 0))
428 if (old_type.compare(
"CHAR") == 0)
434 if (old_type.compare(
"BINARY") == 0)
441 if (old_type.compare(
"ENUM") == 0)
445 enumValues= extra.substr(1, extra.length()-2);
449 if ((old_type.find(
"TIME") != std::string::npos) or
450 (old_type.find(
"DATE") != std::string::npos))
454 convertDateTime=
true;
458 if ((old_type.compare(
"TIME") == 0) or (old_type.compare(
"YEAR") == 0))
464 if (old_type.compare(
"FLOAT") == 0)
470 if (old_type.compare(
"BIT") == 0)
480 void DrizzleDumpTableMySQL::setEngine(
const char* newEngine)
482 if ((strcmp(newEngine,
"MyISAM") == 0) || (strcmp(newEngine,
"MEMORY") == 0))
483 engineName=
"InnoDB";
485 engineName= newEngine;
500 void DrizzleDumpDatabaseMySQL::setCollate(
const char* newCollate)
504 std::string tmpCollate(newCollate);
505 if (tmpCollate.find(
"utf8") != std::string::npos)
511 collate=
"utf8_general_ci";
514 void DrizzleDumpTableMySQL::setCollate(
const char* newCollate)
518 std::string tmpCollate(newCollate);
519 if (tmpCollate.find(
"utf8") != std::string::npos)
526 collate=
"utf8_general_ci";
529 void DrizzleDumpFieldMySQL::setCollate(
const char* newCollate)
533 std::string tmpCollate(newCollate);
534 if (tmpCollate.find(
"utf8") != std::string::npos)
536 collation= tmpCollate;
540 collation=
"utf8_general_ci";
548 query=
"SELECT * FROM `";
549 query.append(table->displayName);
552 result= dcon->query(query);
554 throw std::exception();
557 DrizzleDumpDataMySQL::~DrizzleDumpDataMySQL()
559 drizzle_result_free(result);
563 long DrizzleDumpDataMySQL::convertTime(
const char* oldTime)
const
565 std::string ts(oldTime);
566 boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts));
567 long seconds= td.total_seconds();
571 std::string DrizzleDumpDataMySQL::convertDate(
const char* oldDate)
const
573 boost::match_flag_type flags = boost::match_default;
575 boost::regex date_regex(
"(0000|-00)");
577 if (not regex_search(oldDate, date_regex, flags))
579 output.push_back(
'\'');
580 output.append(oldDate);
581 output.push_back(
'\'');
589 std::string DrizzleDumpDataMySQL::checkDateTime(
const char* item, uint32_t field)
const
593 if (table->fields[field]->convertDateTime)
595 if (table->fields[field]->type.compare(
"INT") == 0)
596 ret= boost::lexical_cast<std::string>(convertTime(item));
598 ret= convertDate(item);