1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
1 |
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
2 |
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
|
|
3 |
*
|
|
4 |
* Copyright (C) 2010 Andrew Hutchings
|
|
5 |
*
|
|
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.
|
|
9 |
*
|
|
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.
|
|
14 |
*
|
|
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
|
|
18 |
*/
|
|
19 |
||
20 |
#include "drizzledump_data.h" |
|
21 |
#include "drizzledump_mysql.h" |
|
22 |
#include "client_priv.h" |
|
23 |
#include <string> |
|
24 |
#include <iostream> |
|
25 |
#include <boost/regex.hpp> |
|
26 |
#include <boost/date_time/posix_time/posix_time.hpp> |
|
27 |
#include <drizzled/gettext.h> |
|
28 |
||
1799.7.4
by Andrew Hutchings
Fix up some more options and the docs |
29 |
extern bool verbose; |
30 |
extern bool ignore_errors; |
|
1751.4.23
by Andrew Hutchings
Fix various bugs |
31 |
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
32 |
bool DrizzleDumpDatabaseMySQL::populateTables() |
33 |
{
|
|
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
34 |
drizzle_result_st *result; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
35 |
drizzle_row_t row; |
36 |
std::string query; |
|
37 |
||
1751.4.25
by Andrew Hutchings
Fix error handling |
38 |
if (not dcon->setDB(databaseName)) |
39 |
return false; |
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
40 |
|
1751.4.23
by Andrew Hutchings
Fix various bugs |
41 |
if (verbose) |
42 |
std::cerr << _("-- Retrieving table structures for ") << databaseName << "..." << std::endl; |
|
43 |
||
1810.1.1
by Andrew Hutchings
Add table comments |
44 |
query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, AUTO_INCREMENT, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE != 'VIEW' AND TABLE_SCHEMA='"; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
45 |
query.append(databaseName); |
46 |
query.append("' ORDER BY TABLE_NAME"); |
|
47 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
48 |
result= dcon->query(query); |
49 |
||
1751.4.25
by Andrew Hutchings
Fix error handling |
50 |
if (result == NULL) |
51 |
return false; |
|
52 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
53 |
while ((row= drizzle_row_next(result))) |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
54 |
{
|
1810.1.1
by Andrew Hutchings
Add table comments |
55 |
size_t* row_sizes= drizzle_row_field_sizes(result); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
56 |
std::string tableName(row[0]); |
1751.4.25
by Andrew Hutchings
Fix error handling |
57 |
std::string displayName(tableName); |
58 |
cleanTableName(displayName); |
|
59 |
if (not ignoreTable(displayName)) |
|
1751.4.24
by Andrew Hutchings
Fix ignore tables |
60 |
continue; |
61 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
62 |
DrizzleDumpTableMySQL *table = new DrizzleDumpTableMySQL(tableName, dcon); |
1751.4.25
by Andrew Hutchings
Fix error handling |
63 |
table->displayName= displayName; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
64 |
table->setCollate(row[1]); |
65 |
table->setEngine(row[2]); |
|
66 |
if (row[3]) |
|
67 |
table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]); |
|
68 |
else
|
|
69 |
table->autoIncrement= 0; |
|
70 |
||
1859.4.1
by Andrew Hutchings
Make foreign keys work for MySQL 5.0 |
71 |
if ((row[4]) and (strstr(row[4], "InnoDB free") == NULL)) |
1810.1.1
by Andrew Hutchings
Add table comments |
72 |
table->comment= DrizzleDumpData::escape(row[4], row_sizes[4]); |
73 |
else
|
|
74 |
table->comment= ""; |
|
75 |
||
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
76 |
table->database= this; |
1810.6.6
by Andrew Hutchings
Add foriegn key support for MySQL |
77 |
if ((not table->populateFields()) or (not table->populateIndexes()) or |
78 |
(not table->populateFkeys())) |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
79 |
{
|
80 |
delete table; |
|
1799.7.4
by Andrew Hutchings
Fix up some more options and the docs |
81 |
if (not ignore_errors) |
82 |
return false; |
|
83 |
else
|
|
84 |
continue; |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
85 |
}
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
86 |
tables.push_back(table); |
87 |
}
|
|
88 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
89 |
dcon->freeResult(result); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
90 |
|
91 |
return true; |
|
92 |
}
|
|
93 |
||
1751.4.23
by Andrew Hutchings
Fix various bugs |
94 |
bool DrizzleDumpDatabaseMySQL::populateTables(const std::vector<std::string> &table_names) |
95 |
{
|
|
96 |
drizzle_result_st *result; |
|
97 |
drizzle_row_t row; |
|
98 |
std::string query; |
|
99 |
||
1751.4.25
by Andrew Hutchings
Fix error handling |
100 |
if (not dcon->setDB(databaseName)) |
101 |
return false; |
|
1751.4.23
by Andrew Hutchings
Fix various bugs |
102 |
|
103 |
if (verbose) |
|
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) |
|
106 |
{
|
|
107 |
std::string tableName= *it; |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
108 |
std::string displayName(tableName); |
109 |
cleanTableName(displayName); |
|
110 |
if (not ignoreTable(displayName)) |
|
1751.4.24
by Andrew Hutchings
Fix ignore tables |
111 |
continue; |
112 |
||
1751.4.23
by Andrew Hutchings
Fix various bugs |
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); |
|
117 |
query.append("'"); |
|
118 |
||
119 |
result= dcon->query(query); |
|
120 |
||
1751.4.25
by Andrew Hutchings
Fix error handling |
121 |
if (result == NULL) |
122 |
return false; |
|
123 |
||
1751.4.23
by Andrew Hutchings
Fix various bugs |
124 |
if ((row= drizzle_row_next(result))) |
125 |
{
|
|
126 |
DrizzleDumpTableMySQL *table = new DrizzleDumpTableMySQL(tableName, dcon); |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
127 |
table->displayName= displayName; |
1751.4.23
by Andrew Hutchings
Fix various bugs |
128 |
table->setCollate(row[1]); |
129 |
table->setEngine(row[2]); |
|
130 |
if (row[3]) |
|
131 |
table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]); |
|
132 |
else
|
|
133 |
table->autoIncrement= 0; |
|
134 |
||
135 |
table->database= this; |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
136 |
if ((not table->populateFields()) or (not table->populateIndexes())) |
137 |
{
|
|
138 |
delete table; |
|
1799.7.5
by Andrew Hutchings
Fix test cases |
139 |
if (not ignore_errors) |
140 |
return false; |
|
141 |
else
|
|
142 |
continue; |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
143 |
}
|
1751.4.23
by Andrew Hutchings
Fix various bugs |
144 |
tables.push_back(table); |
145 |
dcon->freeResult(result); |
|
146 |
}
|
|
147 |
else
|
|
148 |
{
|
|
149 |
dcon->freeResult(result); |
|
1799.7.5
by Andrew Hutchings
Fix test cases |
150 |
if (not ignore_errors) |
151 |
return false; |
|
152 |
else
|
|
153 |
continue; |
|
1751.4.23
by Andrew Hutchings
Fix various bugs |
154 |
}
|
155 |
}
|
|
156 |
||
157 |
return true; |
|
158 |
||
159 |
}
|
|
160 |
||
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
161 |
bool DrizzleDumpTableMySQL::populateFields() |
162 |
{
|
|
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
163 |
drizzle_result_st *result; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
164 |
drizzle_row_t row; |
165 |
std::string query; |
|
166 |
||
1751.4.23
by Andrew Hutchings
Fix various bugs |
167 |
if (verbose) |
168 |
std::cerr << _("-- Retrieving fields for ") << tableName << "..." << std::endl; |
|
169 |
||
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
170 |
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='"; |
171 |
query.append(database->databaseName); |
|
172 |
query.append("' AND TABLE_NAME='"); |
|
173 |
query.append(tableName); |
|
174 |
query.append("' ORDER BY ORDINAL_POSITION"); |
|
175 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
176 |
result= dcon->query(query); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
177 |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
178 |
if (result == NULL) |
179 |
return false; |
|
180 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
181 |
while ((row= drizzle_row_next(result))) |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
182 |
{
|
183 |
std::string fieldName(row[0]); |
|
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
184 |
DrizzleDumpFieldMySQL *field = new DrizzleDumpFieldMySQL(fieldName, dcon); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
185 |
/* Stop valgrind warning */
|
186 |
field->convertDateTime= false; |
|
1897.3.1
by Andrew Hutchings
drizzledump MySQL migration fixes: |
187 |
field->isNull= (strcmp(row[3], "YES") == 0) ? true : false; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
188 |
/* Also sets collation */
|
189 |
field->setType(row[1], row[8]); |
|
1882.2.1
by Andrew Hutchings
MySQL can contain '' as an ENUM value which is not valid in Drizzle. Convert this to NULL. |
190 |
if (field->type.compare("ENUM") == 0) |
191 |
field->isNull= true; |
|
1897.3.1
by Andrew Hutchings
drizzledump MySQL migration fixes: |
192 |
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
193 |
if (row[2]) |
194 |
{
|
|
1836.1.1
by Andrew Hutchings
The MySQL date/time schema convert was not run when there was no default value |
195 |
field->defaultValue= row[2]; |
1897.3.1
by Andrew Hutchings
drizzledump MySQL migration fixes: |
196 |
if (field->convertDateTime) |
197 |
{
|
|
198 |
field->dateTimeConvert(); |
|
199 |
}
|
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
200 |
}
|
201 |
else
|
|
202 |
field->defaultValue= ""; |
|
203 |
||
204 |
field->isAutoIncrement= (strcmp(row[8], "auto_increment") == 0) ? true : false; |
|
205 |
field->defaultIsNull= field->isNull; |
|
206 |
field->length= (row[4]) ? boost::lexical_cast<uint32_t>(row[4]) : 0; |
|
1862.2.1
by Andrew Hutchings
Link up --destination-database |
207 |
if ((row[5] != NULL) and (row[6] != NULL)) |
208 |
{
|
|
209 |
field->decimalPrecision= boost::lexical_cast<uint32_t>(row[5]); |
|
210 |
field->decimalScale= boost::lexical_cast<uint32_t>(row[6]); |
|
211 |
}
|
|
212 |
else
|
|
213 |
{
|
|
214 |
field->decimalPrecision= 0; |
|
215 |
field->decimalScale= 0; |
|
216 |
}
|
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
217 |
|
218 |
fields.push_back(field); |
|
219 |
}
|
|
220 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
221 |
dcon->freeResult(result); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
222 |
return true; |
223 |
}
|
|
224 |
||
225 |
||
1836.1.1
by Andrew Hutchings
The MySQL date/time schema convert was not run when there was no default value |
226 |
void DrizzleDumpFieldMySQL::dateTimeConvert(void) |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
227 |
{
|
228 |
boost::match_flag_type flags = boost::match_default; |
|
229 |
||
1836.1.1
by Andrew Hutchings
The MySQL date/time schema convert was not run when there was no default value |
230 |
if (strcmp(defaultValue.c_str(), "CURRENT_TIMESTAMP") == 0) |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
231 |
return; |
232 |
||
233 |
if (type.compare("INT") == 0) |
|
234 |
{
|
|
235 |
/* We were a TIME, now we are an INT */
|
|
1836.1.1
by Andrew Hutchings
The MySQL date/time schema convert was not run when there was no default value |
236 |
std::string ts(defaultValue); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
237 |
boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts)); |
238 |
defaultValue= boost::lexical_cast<std::string>(td.total_seconds()); |
|
239 |
return; |
|
240 |
}
|
|
241 |
||
1802.11.1
by Andrew Hutchings
1. date regex was broken |
242 |
boost::regex date_regex("(0000|-00)"); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
243 |
|
1836.1.1
by Andrew Hutchings
The MySQL date/time schema convert was not run when there was no default value |
244 |
if (regex_search(defaultValue, date_regex, flags)) |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
245 |
{
|
246 |
defaultIsNull= true; |
|
247 |
defaultValue=""; |
|
248 |
}
|
|
249 |
}
|
|
250 |
||
251 |
||
252 |
bool DrizzleDumpTableMySQL::populateIndexes() |
|
253 |
{
|
|
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
254 |
drizzle_result_st *result; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
255 |
drizzle_row_t row; |
256 |
std::string query; |
|
257 |
std::string lastKey; |
|
258 |
bool firstIndex= true; |
|
259 |
DrizzleDumpIndex *index; |
|
260 |
||
1751.4.23
by Andrew Hutchings
Fix various bugs |
261 |
if (verbose) |
262 |
std::cerr << _("-- Retrieving indexes for ") << tableName << "..." << std::endl; |
|
263 |
||
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
264 |
query="SHOW INDEXES FROM "; |
265 |
query.append(tableName); |
|
266 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
267 |
result= dcon->query(query); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
268 |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
269 |
if (result == NULL) |
270 |
return false; |
|
271 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
272 |
while ((row= drizzle_row_next(result))) |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
273 |
{
|
274 |
std::string indexName(row[2]); |
|
275 |
if (indexName.compare(lastKey) != 0) |
|
276 |
{
|
|
277 |
if (strcmp(row[10], "FULLTEXT") == 0) |
|
278 |
continue; |
|
279 |
||
280 |
if (!firstIndex) |
|
281 |
indexes.push_back(index); |
|
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
282 |
index = new DrizzleDumpIndexMySQL(indexName, dcon); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
283 |
index->isPrimary= (strcmp(row[2], "PRIMARY") == 0); |
284 |
index->isUnique= (strcmp(row[1], "0") == 0); |
|
285 |
index->isHash= (strcmp(row[10], "HASH") == 0); |
|
1802.2.1
by Andrew Hutchings
Fix index lengths not shown for part-indexed columns. |
286 |
index->length= (row[7]) ? boost::lexical_cast<uint32_t>(row[7]) : 0; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
287 |
lastKey= row[2]; |
288 |
firstIndex= false; |
|
289 |
}
|
|
290 |
index->columns.push_back(row[4]); |
|
291 |
}
|
|
292 |
if (!firstIndex) |
|
293 |
indexes.push_back(index); |
|
294 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
295 |
dcon->freeResult(result); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
296 |
return true; |
297 |
}
|
|
298 |
||
1810.6.6
by Andrew Hutchings
Add foriegn key support for MySQL |
299 |
bool DrizzleDumpTableMySQL::populateFkeys() |
300 |
{
|
|
301 |
drizzle_result_st *result; |
|
302 |
drizzle_row_t row; |
|
303 |
std::string query; |
|
304 |
DrizzleDumpForeignKey *fkey; |
|
305 |
||
306 |
if (verbose) |
|
307 |
std::cerr << _("-- Retrieving foreign keys for ") << tableName << "..." << std::endl; |
|
308 |
||
1859.4.1
by Andrew Hutchings
Make foreign keys work for MySQL 5.0 |
309 |
query= "SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'REFERENTIAL_CONSTRAINTS'"; |
1810.6.6
by Andrew Hutchings
Add foriegn key support for MySQL |
310 |
|
311 |
result= dcon->query(query); |
|
312 |
||
313 |
if (result == NULL) |
|
314 |
return false; |
|
315 |
||
1859.4.1
by Andrew Hutchings
Make foreign keys work for MySQL 5.0 |
316 |
uint64_t search_count = drizzle_result_row_count(result); |
317 |
||
318 |
dcon->freeResult(result); |
|
319 |
||
320 |
/* MySQL 5.0 will be 0 and MySQL 5.1 will be 1 */
|
|
321 |
if (search_count > 0) |
|
322 |
{
|
|
323 |
query= "select rc.constraint_name, rc.referenced_table_name, group_concat(distinct concat('`',kc.column_name,'`')), rc.update_rule, rc.delete_rule, rc.match_option, group_concat(distinct concat('`',kt.column_name,'`')) from information_schema.referential_constraints rc join information_schema.key_column_usage kt on (rc.constraint_schema = kt.constraint_schema and rc.constraint_name = kt.constraint_name) join information_schema.key_column_usage kc on (rc.constraint_schema = kc.constraint_schema and rc.referenced_table_name = kc.table_name and rc.unique_constraint_name = kc.constraint_name) where rc.constraint_schema='"; |
|
324 |
query.append(database->databaseName); |
|
325 |
query.append("' and rc.table_name='"); |
|
326 |
query.append(tableName); |
|
327 |
query.append("' group by rc.constraint_name"); |
|
328 |
||
329 |
result= dcon->query(query); |
|
330 |
||
331 |
if (result == NULL) |
|
332 |
return false; |
|
333 |
||
334 |
while ((row= drizzle_row_next(result))) |
|
335 |
{
|
|
336 |
fkey= new DrizzleDumpForeignKey(row[0], dcon); |
|
337 |
fkey->parentColumns= row[6]; |
|
338 |
fkey->childTable= row[1]; |
|
339 |
fkey->childColumns= row[2]; |
|
340 |
fkey->updateRule= (strcmp(row[3], "RESTRICT") != 0) ? row[3] : ""; |
|
341 |
fkey->deleteRule= (strcmp(row[4], "RESTRICT") != 0) ? row[4] : ""; |
|
342 |
fkey->matchOption= (strcmp(row[5], "NONE") != 0) ? row[5] : ""; |
|
343 |
||
344 |
fkeys.push_back(fkey); |
|
345 |
}
|
|
346 |
}
|
|
347 |
else
|
|
348 |
{
|
|
349 |
query= "SHOW CREATE TABLE `"; |
|
350 |
query.append(database->databaseName); |
|
351 |
query.append("`.`"); |
|
352 |
query.append(tableName); |
|
353 |
query.append("`"); |
|
354 |
result= dcon->query(query); |
|
355 |
||
356 |
if (result == NULL) |
|
357 |
return false; |
|
358 |
||
359 |
if ((row= drizzle_row_next(result))) |
|
360 |
{
|
|
361 |
boost::match_flag_type flags = boost::match_default; |
|
362 |
boost::regex constraint_regex("CONSTRAINT `(.*)` FOREIGN KEY \\((.*)\\) REFERENCES `(.*)` \\((.*)\\)( ON (UPDATE|DELETE) (CASCADE|RESTRICT|SET NULL))?( ON (UPDATE|DELETE) (CASCADE|RESTRICT|SET NULL))?"); |
|
363 |
||
364 |
boost::match_results<std::string::const_iterator> constraint_results; |
|
365 |
||
366 |
std::string search_body(row[1]); |
|
367 |
std::string::const_iterator start, end; |
|
368 |
start= search_body.begin(); |
|
369 |
end= search_body.end(); |
|
370 |
while (regex_search(start, end, constraint_results, constraint_regex, flags)) |
|
371 |
{
|
|
372 |
fkey= new DrizzleDumpForeignKey(constraint_results[1], dcon); |
|
373 |
fkey->parentColumns= constraint_results[2]; |
|
374 |
fkey->childTable= constraint_results[3]; |
|
375 |
fkey->childColumns= constraint_results[4]; |
|
376 |
||
377 |
if (constraint_results[5].compare("") != 0) |
|
378 |
{
|
|
379 |
if (constraint_results[6].compare("UPDATE") == 0) |
|
380 |
fkey->updateRule= constraint_results[7]; |
|
381 |
else if (constraint_results[6].compare("DELETE") == 0) |
|
382 |
fkey->deleteRule= constraint_results[7]; |
|
383 |
}
|
|
384 |
if (constraint_results[8].compare("") != 0) |
|
385 |
{
|
|
386 |
if (constraint_results[9].compare("UPDATE") == 0) |
|
387 |
fkey->updateRule= constraint_results[10]; |
|
388 |
else if (constraint_results[9].compare("DELETE") == 0) |
|
389 |
fkey->deleteRule= constraint_results[10]; |
|
390 |
}
|
|
391 |
fkey->matchOption= ""; |
|
392 |
||
393 |
fkeys.push_back(fkey); |
|
394 |
||
395 |
start= constraint_results[0].second; |
|
396 |
flags |= boost::match_prev_avail; |
|
397 |
flags |= boost::match_not_bob; |
|
398 |
}
|
|
399 |
}
|
|
1810.6.6
by Andrew Hutchings
Add foriegn key support for MySQL |
400 |
}
|
401 |
dcon->freeResult(result); |
|
402 |
return true; |
|
403 |
}
|
|
404 |
||
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
405 |
void DrizzleDumpFieldMySQL::setType(const char* raw_type, const char* raw_collation) |
406 |
{
|
|
407 |
std::string old_type(raw_type); |
|
408 |
std::string extra; |
|
409 |
size_t pos; |
|
410 |
||
411 |
if ((pos= old_type.find("(")) != std::string::npos) |
|
412 |
{
|
|
413 |
extra= old_type.substr(pos); |
|
414 |
old_type.erase(pos, std::string::npos); |
|
415 |
}
|
|
416 |
||
417 |
std::transform(old_type.begin(), old_type.end(), old_type.begin(), ::toupper); |
|
418 |
if ((old_type.find("CHAR") != std::string::npos) or |
|
419 |
(old_type.find("TEXT") != std::string::npos)) |
|
420 |
setCollate(raw_collation); |
|
421 |
||
422 |
if ((old_type.compare("INT") == 0) and |
|
423 |
((extra.find("unsigned") != std::string::npos))) |
|
424 |
{
|
|
425 |
type= "BIGINT"; |
|
426 |
return; |
|
427 |
}
|
|
428 |
||
429 |
if ((old_type.compare("TINYINT") == 0) or |
|
430 |
(old_type.compare("SMALLINT") == 0) or |
|
431 |
(old_type.compare("MEDIUMINT") == 0)) |
|
432 |
{
|
|
433 |
type= "INT"; |
|
434 |
return; |
|
435 |
}
|
|
436 |
||
437 |
if ((old_type.compare("TINYBLOB") == 0) or |
|
438 |
(old_type.compare("MEDIUMBLOB") == 0) or |
|
439 |
(old_type.compare("LONGBLOB") == 0)) |
|
440 |
{
|
|
441 |
type= "BLOB"; |
|
442 |
return; |
|
443 |
}
|
|
444 |
||
445 |
if ((old_type.compare("TINYTEXT") == 0) or |
|
446 |
(old_type.compare("MEDIUMTEXT") == 0) or |
|
1751.4.21
by Andrew Hutchings
Add database destination settings and connect it all up |
447 |
(old_type.compare("LONGTEXT") == 0) or |
448 |
(old_type.compare("SET") == 0)) |
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
449 |
{
|
450 |
type= "TEXT"; |
|
451 |
return; |
|
452 |
}
|
|
453 |
||
454 |
if (old_type.compare("CHAR") == 0) |
|
455 |
{
|
|
456 |
type= "VARCHAR"; |
|
457 |
return; |
|
458 |
}
|
|
459 |
||
460 |
if (old_type.compare("BINARY") == 0) |
|
461 |
{
|
|
462 |
type= "VARBINARY"; |
|
463 |
return; |
|
464 |
}
|
|
465 |
||
466 |
if (old_type.compare("ENUM") == 0) |
|
467 |
{
|
|
468 |
type= old_type; |
|
469 |
/* Strip out the braces, we add them again during output */
|
|
470 |
enumValues= extra.substr(1, extra.length()-2); |
|
471 |
return; |
|
472 |
}
|
|
473 |
||
474 |
if ((old_type.find("TIME") != std::string::npos) or |
|
475 |
(old_type.find("DATE") != std::string::npos)) |
|
476 |
{
|
|
477 |
/* Intended to catch TIME/DATE/TIMESTAMP/DATETIME
|
|
478 |
We may have a default TIME/DATE which needs converting */
|
|
479 |
convertDateTime= true; |
|
1897.3.1
by Andrew Hutchings
drizzledump MySQL migration fixes: |
480 |
isNull= true; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
481 |
}
|
482 |
||
1802.3.1
by Andrew Hutchings
Add YEAR conversion that was previously missing from the MySQL migration code |
483 |
if ((old_type.compare("TIME") == 0) or (old_type.compare("YEAR") == 0)) |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
484 |
{
|
485 |
type= "INT"; |
|
486 |
return; |
|
487 |
}
|
|
488 |
||
489 |
if (old_type.compare("FLOAT") == 0) |
|
490 |
{
|
|
491 |
type= "DOUBLE"; |
|
492 |
return; |
|
493 |
}
|
|
494 |
||
495 |
type= old_type; |
|
496 |
return; |
|
497 |
}
|
|
498 |
||
499 |
void DrizzleDumpTableMySQL::setEngine(const char* newEngine) |
|
500 |
{
|
|
501 |
if (strcmp(newEngine, "MyISAM") == 0) |
|
502 |
engineName= "InnoDB"; |
|
503 |
else
|
|
504 |
engineName= newEngine; |
|
505 |
}
|
|
506 |
||
507 |
DrizzleDumpData* DrizzleDumpTableMySQL::getData(void) |
|
508 |
{
|
|
1751.4.25
by Andrew Hutchings
Fix error handling |
509 |
try
|
510 |
{
|
|
511 |
return new DrizzleDumpDataMySQL(this, dcon); |
|
512 |
}
|
|
513 |
catch(...) |
|
514 |
{
|
|
515 |
return NULL; |
|
516 |
}
|
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
517 |
}
|
518 |
||
519 |
void DrizzleDumpDatabaseMySQL::setCollate(const char* newCollate) |
|
520 |
{
|
|
521 |
if (newCollate) |
|
522 |
{
|
|
523 |
std::string tmpCollate(newCollate); |
|
524 |
if (tmpCollate.find("utf8") != std::string::npos) |
|
525 |
{
|
|
526 |
collate= tmpCollate; |
|
527 |
return; |
|
528 |
}
|
|
529 |
}
|
|
530 |
collate= "utf8_general_ci"; |
|
531 |
}
|
|
532 |
||
533 |
void DrizzleDumpTableMySQL::setCollate(const char* newCollate) |
|
534 |
{
|
|
535 |
if (newCollate) |
|
536 |
{
|
|
537 |
std::string tmpCollate(newCollate); |
|
538 |
if (tmpCollate.find("utf8") != std::string::npos) |
|
539 |
{
|
|
540 |
collate= tmpCollate; |
|
541 |
return; |
|
542 |
}
|
|
543 |
}
|
|
544 |
||
545 |
collate= "utf8_general_ci"; |
|
546 |
}
|
|
547 |
||
548 |
void DrizzleDumpFieldMySQL::setCollate(const char* newCollate) |
|
549 |
{
|
|
550 |
if (newCollate) |
|
551 |
{
|
|
552 |
std::string tmpCollate(newCollate); |
|
553 |
if (tmpCollate.find("utf8") != std::string::npos) |
|
554 |
{
|
|
555 |
collation= tmpCollate; |
|
556 |
return; |
|
557 |
}
|
|
558 |
}
|
|
559 |
collation= "utf8_general_ci"; |
|
560 |
}
|
|
561 |
||
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
562 |
DrizzleDumpDataMySQL::DrizzleDumpDataMySQL(DrizzleDumpTable *dataTable, |
563 |
DrizzleDumpConnection *connection) |
|
564 |
: DrizzleDumpData(dataTable, connection) |
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
565 |
{
|
566 |
std::string query; |
|
567 |
query= "SELECT * FROM `"; |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
568 |
query.append(table->displayName); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
569 |
query.append("`"); |
1751.4.20
by Andrew Hutchings
Add database connection class and the start of a database output ostream |
570 |
|
571 |
result= dcon->query(query); |
|
1751.4.25
by Andrew Hutchings
Fix error handling |
572 |
if (result == NULL) |
573 |
throw 1; |
|
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
574 |
}
|
575 |
||
576 |
DrizzleDumpDataMySQL::~DrizzleDumpDataMySQL() |
|
577 |
{
|
|
578 |
drizzle_result_free(result); |
|
1883.3.1
by Andrew Hutchings
Cleanup drizzledump and drizzle for cppcheck |
579 |
delete result; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
580 |
}
|
581 |
||
582 |
long DrizzleDumpDataMySQL::convertTime(const char* oldTime) const |
|
583 |
{
|
|
584 |
std::string ts(oldTime); |
|
585 |
boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts)); |
|
586 |
long seconds= td.total_seconds(); |
|
587 |
return seconds; |
|
588 |
}
|
|
589 |
||
590 |
std::string DrizzleDumpDataMySQL::convertDate(const char* oldDate) const |
|
591 |
{
|
|
592 |
boost::match_flag_type flags = boost::match_default; |
|
593 |
std::string output; |
|
1802.11.1
by Andrew Hutchings
1. date regex was broken |
594 |
boost::regex date_regex("(0000|-00)"); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
595 |
|
1802.11.1
by Andrew Hutchings
1. date regex was broken |
596 |
if (not regex_search(oldDate, date_regex, flags)) |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
597 |
{
|
598 |
output.push_back('\''); |
|
599 |
output.append(oldDate); |
|
600 |
output.push_back('\''); |
|
601 |
}
|
|
602 |
else
|
|
603 |
output= "NULL"; |
|
604 |
||
605 |
return output; |
|
606 |
}
|
|
607 |
||
1802.11.1
by Andrew Hutchings
1. date regex was broken |
608 |
std::string DrizzleDumpDataMySQL::checkDateTime(const char* item, uint32_t field) const |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
609 |
{
|
1802.11.1
by Andrew Hutchings
1. date regex was broken |
610 |
std::string ret; |
611 |
||
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
612 |
if (table->fields[field]->convertDateTime) |
613 |
{
|
|
614 |
if (table->fields[field]->type.compare("INT") == 0) |
|
1802.11.1
by Andrew Hutchings
1. date regex was broken |
615 |
ret= boost::lexical_cast<std::string>(convertTime(item)); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
616 |
else
|
1802.11.1
by Andrew Hutchings
1. date regex was broken |
617 |
ret= convertDate(item); |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
618 |
}
|
1802.11.1
by Andrew Hutchings
1. date regex was broken |
619 |
return ret; |
1751.4.19
by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files |
620 |
}
|
621 |