1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 Andrew Hutchings
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
#include "drizzledump_data.h"
21
#include "drizzledump_mysql.h"
22
#include "client_priv.h"
25
#include <boost/regex.hpp>
26
#include <boost/date_time/posix_time/posix_time.hpp>
27
#include <drizzled/gettext.h>
29
extern drizzle_con_st dcon;
32
bool DrizzleDumpDatabaseMySQL::populateTables()
34
drizzle_result_st result;
39
if (drizzle_select_db(&dcon, &result, databaseName.c_str(), &ret) ==
40
NULL || ret != DRIZZLE_RETURN_OK)
42
errmsg << _("Could not set db '") << databaseName << "'";
45
drizzle_result_free(&result);
47
query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='";
48
query.append(databaseName);
49
query.append("' ORDER BY TABLE_NAME");
51
if (drizzle_query_str(&dcon, &result, query.c_str(), &ret) == NULL ||
52
ret != DRIZZLE_RETURN_OK)
54
if (ret == DRIZZLE_RETURN_ERROR_CODE)
56
errmsg << _("Could not get tables list due to error: ") <<
57
drizzle_result_error(&result);
58
drizzle_result_free(&result);
62
errmsg << _("Could not get tables list due to error: ") <<
63
drizzle_con_error(&dcon);
68
if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
70
errmsg << _("Could not get tables list due to error: ") <<
71
drizzle_con_error(&dcon);
75
while ((row= drizzle_row_next(&result)))
77
std::string tableName(row[0]);
78
DrizzleDumpTableMySQL *table = new DrizzleDumpTableMySQL(tableName);
79
table->setCollate(row[1]);
80
table->setEngine(row[2]);
82
table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]);
84
table->autoIncrement= 0;
86
table->database= this;
87
table->populateFields();
88
table->populateIndexes();
89
tables.push_back(table);
92
drizzle_result_free(&result);
97
bool DrizzleDumpTableMySQL::populateFields()
99
drizzle_result_st result;
101
drizzle_return_t ret;
104
query="SELECT COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME, EXTRA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='";
105
query.append(database->databaseName);
106
query.append("' AND TABLE_NAME='");
107
query.append(tableName);
108
query.append("' ORDER BY ORDINAL_POSITION");
110
if (drizzle_query_str(&dcon, &result, query.c_str(), &ret) == NULL ||
111
ret != DRIZZLE_RETURN_OK)
113
if (ret == DRIZZLE_RETURN_ERROR_CODE)
115
errmsg << _("Could not get tables list due to error: ") <<
116
drizzle_result_error(&result);
117
drizzle_result_free(&result);
121
errmsg << _("Could not get tables list due to error: ") <<
122
drizzle_con_error(&dcon);
127
if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
129
errmsg << _("Could not get tables list due to error: ") <<
130
drizzle_con_error(&dcon);
133
while ((row= drizzle_row_next(&result)))
135
std::string fieldName(row[0]);
136
DrizzleDumpFieldMySQL *field = new DrizzleDumpFieldMySQL(fieldName);
137
/* Stop valgrind warning */
138
field->convertDateTime= false;
139
/* Also sets collation */
140
field->setType(row[1], row[8]);
143
if (field->convertDateTime)
145
field->dateTimeConvert(row[2]);
148
field->defaultValue= row[2];
151
field->defaultValue= "";
153
field->isNull= (strcmp(row[3], "YES") == 0) ? true : false;
154
field->isAutoIncrement= (strcmp(row[8], "auto_increment") == 0) ? true : false;
155
field->defaultIsNull= field->isNull;
156
field->length= (row[4]) ? boost::lexical_cast<uint32_t>(row[4]) : 0;
157
field->decimalPrecision= (row[5]) ? boost::lexical_cast<uint32_t>(row[5]) : 0;
158
field->decimalScale= (row[6]) ? boost::lexical_cast<uint32_t>(row[6]) : 0;
161
fields.push_back(field);
164
drizzle_result_free(&result);
169
void DrizzleDumpFieldMySQL::dateTimeConvert(const char* oldDefault)
171
boost::match_flag_type flags = boost::match_default;
173
if (strcmp(oldDefault, "CURRENT_TIMESTAMP") == 0)
175
defaultValue= oldDefault;
179
if (type.compare("INT") == 0)
181
/* We were a TIME, now we are an INT */
182
std::string ts(oldDefault);
183
boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts));
184
defaultValue= boost::lexical_cast<std::string>(td.total_seconds());
188
boost::regex date_regex("([0-9]{3}[1-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))");
190
if (regex_search(oldDefault, date_regex, flags))
192
defaultValue= oldDefault;
202
bool DrizzleDumpTableMySQL::populateIndexes()
204
drizzle_result_st result;
206
drizzle_return_t ret;
209
bool firstIndex= true;
210
DrizzleDumpIndex *index;
212
query="SHOW INDEXES FROM ";
213
query.append(tableName);
215
if (drizzle_query_str(&dcon, &result, query.c_str(), &ret) == NULL ||
216
ret != DRIZZLE_RETURN_OK)
218
if (ret == DRIZZLE_RETURN_ERROR_CODE)
220
errmsg << _("Could not get tables list due to error: ") <<
221
drizzle_result_error(&result);
222
drizzle_result_free(&result);
226
errmsg << _("Could not get tables list due to error: ") <<
227
drizzle_con_error(&dcon);
232
if (drizzle_result_buffer(&result) != DRIZZLE_RETURN_OK)
234
errmsg << _("Could not get tables list due to error: ") <<
235
drizzle_con_error(&dcon);
238
while ((row= drizzle_row_next(&result)))
240
std::string indexName(row[2]);
241
if (indexName.compare(lastKey) != 0)
243
if (strcmp(row[10], "FULLTEXT") == 0)
247
indexes.push_back(index);
248
index = new DrizzleDumpIndexMySQL(indexName);
249
index->isPrimary= (strcmp(row[2], "PRIMARY") == 0);
250
index->isUnique= (strcmp(row[1], "0") == 0);
251
index->isHash= (strcmp(row[10], "HASH") == 0);
255
index->columns.push_back(row[4]);
258
indexes.push_back(index);
260
drizzle_result_free(&result);
264
void DrizzleDumpFieldMySQL::setType(const char* raw_type, const char* raw_collation)
266
std::string old_type(raw_type);
270
if ((pos= old_type.find("(")) != std::string::npos)
272
extra= old_type.substr(pos);
273
old_type.erase(pos, std::string::npos);
276
std::transform(old_type.begin(), old_type.end(), old_type.begin(), ::toupper);
277
if ((old_type.find("CHAR") != std::string::npos) or
278
(old_type.find("TEXT") != std::string::npos))
279
setCollate(raw_collation);
281
if ((old_type.compare("INT") == 0) and
282
((extra.find("unsigned") != std::string::npos)))
288
if ((old_type.compare("TINYINT") == 0) or
289
(old_type.compare("SMALLINT") == 0) or
290
(old_type.compare("MEDIUMINT") == 0))
296
if ((old_type.compare("TINYBLOB") == 0) or
297
(old_type.compare("MEDIUMBLOB") == 0) or
298
(old_type.compare("LONGBLOB") == 0))
304
if ((old_type.compare("TINYTEXT") == 0) or
305
(old_type.compare("MEDIUMTEXT") == 0) or
306
(old_type.compare("LONGTEXT") == 0))
312
if (old_type.compare("CHAR") == 0)
318
if (old_type.compare("BINARY") == 0)
324
if (old_type.compare("ENUM") == 0)
327
/* Strip out the braces, we add them again during output */
328
enumValues= extra.substr(1, extra.length()-2);
332
if ((old_type.find("TIME") != std::string::npos) or
333
(old_type.find("DATE") != std::string::npos))
335
/* Intended to catch TIME/DATE/TIMESTAMP/DATETIME
336
We may have a default TIME/DATE which needs converting */
337
convertDateTime= true;
340
if (old_type.compare("TIME") == 0)
346
if (old_type.compare("FLOAT") == 0)
356
void DrizzleDumpTableMySQL::setEngine(const char* newEngine)
358
if (strcmp(newEngine, "MyISAM") == 0)
359
engineName= "InnoDB";
361
engineName= newEngine;
364
DrizzleDumpData* DrizzleDumpTableMySQL::getData(void)
366
return new DrizzleDumpDataMySQL(this);
369
void DrizzleDumpDatabaseMySQL::setCollate(const char* newCollate)
373
std::string tmpCollate(newCollate);
374
if (tmpCollate.find("utf8") != std::string::npos)
380
collate= "utf8_general_ci";
383
void DrizzleDumpTableMySQL::setCollate(const char* newCollate)
387
std::string tmpCollate(newCollate);
388
if (tmpCollate.find("utf8") != std::string::npos)
395
collate= "utf8_general_ci";
398
void DrizzleDumpFieldMySQL::setCollate(const char* newCollate)
402
std::string tmpCollate(newCollate);
403
if (tmpCollate.find("utf8") != std::string::npos)
405
collation= tmpCollate;
409
collation= "utf8_general_ci";
412
DrizzleDumpDataMySQL::DrizzleDumpDataMySQL(DrizzleDumpTable *dataTable) :
413
DrizzleDumpData(dataTable)
415
drizzle_return_t ret;
417
query= "SELECT * FROM `";
418
query.append(table->tableName);
420
result= new drizzle_result_st;
422
if (drizzle_query_str(&dcon, result, query.c_str(), &ret) == NULL ||
423
ret != DRIZZLE_RETURN_OK)
425
if (ret == DRIZZLE_RETURN_ERROR_CODE)
427
errmsg << _("Could not get tables list due to error: ") <<
428
drizzle_result_error(result);
429
drizzle_result_free(result);
433
errmsg << _("Could not get tables list due to error: ") <<
434
drizzle_con_error(&dcon);
439
if (drizzle_result_buffer(result) != DRIZZLE_RETURN_OK)
441
errmsg << _("Could not get tables list due to error: ") <<
442
drizzle_con_error(&dcon);
447
DrizzleDumpDataMySQL::~DrizzleDumpDataMySQL()
449
drizzle_result_free(result);
450
if (result) delete result;
453
long DrizzleDumpDataMySQL::convertTime(const char* oldTime) const
455
std::string ts(oldTime);
456
boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts));
457
long seconds= td.total_seconds();
461
std::string DrizzleDumpDataMySQL::convertDate(const char* oldDate) const
463
boost::match_flag_type flags = boost::match_default;
465
boost::regex date_regex("([0-9]{3}[1-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))");
467
if (regex_search(oldDate, date_regex, flags))
469
output.push_back('\'');
470
output.append(oldDate);
471
output.push_back('\'');
479
std::ostream& DrizzleDumpDataMySQL::checkDateTime(std::ostream &os, const char* item, uint32_t field) const
481
if (table->fields[field]->convertDateTime)
483
if (table->fields[field]->type.compare("INT") == 0)
484
os << convertTime(item);
486
os << convertDate(item);