~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump_mysql.cc

  • Committer: Monty Taylor
  • Date: 2008-10-09 22:38:27 UTC
  • mto: This revision was merged to the branch mainline in revision 497.
  • Revision ID: monty@inaugust.com-20081009223827-bc9gvpiplsmvpwyq
Moved test() to its own file.
Made a new function to possibly replace int10_to_str.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
29
 
extern bool  verbose;
30
 
 
31
 
bool DrizzleDumpDatabaseMySQL::populateTables()
32
 
{
33
 
  drizzle_result_st *result;
34
 
  drizzle_row_t row;
35
 
  std::string query;
36
 
 
37
 
  if (not dcon->setDB(databaseName))
38
 
    return false;
39
 
 
40
 
  if (verbose)
41
 
    std::cerr << _("-- Retrieving table structures for ") << databaseName << "..." << std::endl;
42
 
 
43
 
  query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='";
44
 
  query.append(databaseName);
45
 
  query.append("' ORDER BY TABLE_NAME");
46
 
 
47
 
  result= dcon->query(query);
48
 
 
49
 
  if (result == NULL)
50
 
    return false;
51
 
 
52
 
  while ((row= drizzle_row_next(result)))
53
 
  {
54
 
    std::string tableName(row[0]);
55
 
    std::string displayName(tableName);
56
 
    cleanTableName(displayName);
57
 
    if (not ignoreTable(displayName))
58
 
      continue;
59
 
 
60
 
    DrizzleDumpTableMySQL *table = new DrizzleDumpTableMySQL(tableName, dcon);
61
 
    table->displayName= displayName;
62
 
    table->setCollate(row[1]);
63
 
    table->setEngine(row[2]);
64
 
    if (row[3])
65
 
      table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]);
66
 
    else
67
 
      table->autoIncrement= 0;
68
 
 
69
 
    table->database= this;
70
 
    if ((not table->populateFields()) or (not table->populateIndexes()))
71
 
    {
72
 
      delete table;
73
 
      return false;
74
 
    }
75
 
    tables.push_back(table);
76
 
  }
77
 
 
78
 
  dcon->freeResult(result);
79
 
 
80
 
  return true;
81
 
}
82
 
 
83
 
bool DrizzleDumpDatabaseMySQL::populateTables(const std::vector<std::string> &table_names)
84
 
{
85
 
  drizzle_result_st *result;
86
 
  drizzle_row_t row;
87
 
  std::string query;
88
 
 
89
 
  if (not dcon->setDB(databaseName))
90
 
    return false;
91
 
 
92
 
  if (verbose)
93
 
    std::cerr << _("-- Retrieving table structures for ") << databaseName << "..." << std::endl;
94
 
  for (std::vector<std::string>::const_iterator it= table_names.begin(); it != table_names.end(); ++it)
95
 
  {
96
 
    std::string tableName= *it;
97
 
    std::string displayName(tableName);
98
 
    cleanTableName(displayName);
99
 
    if (not ignoreTable(displayName))
100
 
      continue;
101
 
 
102
 
    query="SELECT TABLE_NAME, TABLE_COLLATION, ENGINE, AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='";
103
 
    query.append(databaseName);
104
 
    query.append("' AND TABLE_NAME = '");
105
 
    query.append(tableName);
106
 
    query.append("'");
107
 
 
108
 
    result= dcon->query(query);
109
 
 
110
 
    if (result == NULL)
111
 
      return false;
112
 
 
113
 
    if ((row= drizzle_row_next(result)))
114
 
    {
115
 
      DrizzleDumpTableMySQL *table = new DrizzleDumpTableMySQL(tableName, dcon);
116
 
      table->displayName= displayName;
117
 
      table->setCollate(row[1]);
118
 
      table->setEngine(row[2]);
119
 
      if (row[3])
120
 
        table->autoIncrement= boost::lexical_cast<uint64_t>(row[3]);
121
 
      else
122
 
        table->autoIncrement= 0;
123
 
 
124
 
      table->database= this;
125
 
      if ((not table->populateFields()) or (not table->populateIndexes()))
126
 
      {
127
 
        delete table;
128
 
        return false;
129
 
      }
130
 
      tables.push_back(table);
131
 
      dcon->freeResult(result);
132
 
    }
133
 
    else
134
 
    {
135
 
      dcon->freeResult(result);
136
 
      return false;
137
 
    }
138
 
  }
139
 
 
140
 
  return true;
141
 
 
142
 
}
143
 
 
144
 
bool DrizzleDumpTableMySQL::populateFields()
145
 
{
146
 
  drizzle_result_st *result;
147
 
  drizzle_row_t row;
148
 
  std::string query;
149
 
 
150
 
  if (verbose)
151
 
    std::cerr << _("-- Retrieving fields for ") << tableName << "..." << std::endl;
152
 
 
153
 
  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='";
154
 
  query.append(database->databaseName);
155
 
  query.append("' AND TABLE_NAME='");
156
 
  query.append(tableName);
157
 
  query.append("' ORDER BY ORDINAL_POSITION");
158
 
 
159
 
  result= dcon->query(query);
160
 
 
161
 
  if (result == NULL)
162
 
    return false;
163
 
 
164
 
  while ((row= drizzle_row_next(result)))
165
 
  {
166
 
    std::string fieldName(row[0]);
167
 
    DrizzleDumpFieldMySQL *field = new DrizzleDumpFieldMySQL(fieldName, dcon);
168
 
    /* Stop valgrind warning */
169
 
    field->convertDateTime= false;
170
 
    /* Also sets collation */
171
 
    field->setType(row[1], row[8]);
172
 
    if (row[2])
173
 
    {
174
 
      if (field->convertDateTime)
175
 
      {
176
 
        field->dateTimeConvert(row[2]);
177
 
      }
178
 
      else
179
 
        field->defaultValue= row[2];
180
 
    }
181
 
    else
182
 
     field->defaultValue= "";
183
 
 
184
 
    field->isNull= (strcmp(row[3], "YES") == 0) ? true : false;
185
 
    field->isAutoIncrement= (strcmp(row[8], "auto_increment") == 0) ? true : false;
186
 
    field->defaultIsNull= field->isNull;
187
 
    field->length= (row[4]) ? boost::lexical_cast<uint32_t>(row[4]) : 0;
188
 
    field->decimalPrecision= (row[5]) ? boost::lexical_cast<uint32_t>(row[5]) : 0;
189
 
    field->decimalScale= (row[6]) ? boost::lexical_cast<uint32_t>(row[6]) : 0;
190
 
 
191
 
 
192
 
    fields.push_back(field);
193
 
  }
194
 
 
195
 
  dcon->freeResult(result);
196
 
  return true;
197
 
}
198
 
 
199
 
 
200
 
void DrizzleDumpFieldMySQL::dateTimeConvert(const char* oldDefault)
201
 
{
202
 
  boost::match_flag_type flags = boost::match_default;
203
 
 
204
 
  if (strcmp(oldDefault, "CURRENT_TIMESTAMP") == 0)
205
 
  {
206
 
    defaultValue= oldDefault;
207
 
    return;
208
 
  }
209
 
 
210
 
  if (type.compare("INT") == 0)
211
 
  {
212
 
    /* We were a TIME, now we are an INT */
213
 
    std::string ts(oldDefault);
214
 
    boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts));
215
 
    defaultValue= boost::lexical_cast<std::string>(td.total_seconds());
216
 
    return;
217
 
  }
218
 
 
219
 
  boost::regex date_regex("([0-9]{3}[1-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))");
220
 
 
221
 
  if (regex_search(oldDefault, date_regex, flags))
222
 
  {
223
 
    defaultValue= oldDefault;
224
 
  }
225
 
  else
226
 
  {
227
 
    defaultIsNull= true;
228
 
    defaultValue="";
229
 
  }
230
 
}
231
 
 
232
 
 
233
 
bool DrizzleDumpTableMySQL::populateIndexes()
234
 
{
235
 
  drizzle_result_st *result;
236
 
  drizzle_row_t row;
237
 
  std::string query;
238
 
  std::string lastKey;
239
 
  bool firstIndex= true;
240
 
  DrizzleDumpIndex *index;
241
 
 
242
 
  if (verbose)
243
 
    std::cerr << _("-- Retrieving indexes for ") << tableName << "..." << std::endl;
244
 
 
245
 
  query="SHOW INDEXES FROM ";
246
 
  query.append(tableName);
247
 
 
248
 
  result= dcon->query(query);
249
 
 
250
 
  if (result == NULL)
251
 
    return false;
252
 
 
253
 
  while ((row= drizzle_row_next(result)))
254
 
  {
255
 
    std::string indexName(row[2]);
256
 
    if (indexName.compare(lastKey) != 0)
257
 
    {
258
 
      if (strcmp(row[10], "FULLTEXT") == 0)
259
 
        continue;
260
 
 
261
 
      if (!firstIndex)
262
 
        indexes.push_back(index);
263
 
      index = new DrizzleDumpIndexMySQL(indexName, dcon);
264
 
      index->isPrimary= (strcmp(row[2], "PRIMARY") == 0);
265
 
      index->isUnique= (strcmp(row[1], "0") == 0);
266
 
      index->isHash= (strcmp(row[10], "HASH") == 0);
267
 
      lastKey= row[2];
268
 
      firstIndex= false;
269
 
    }
270
 
    index->columns.push_back(row[4]);
271
 
  }
272
 
  if (!firstIndex)
273
 
    indexes.push_back(index);
274
 
 
275
 
  dcon->freeResult(result);
276
 
  return true;
277
 
}
278
 
 
279
 
void DrizzleDumpFieldMySQL::setType(const char* raw_type, const char* raw_collation)
280
 
{
281
 
  std::string old_type(raw_type);
282
 
  std::string extra;
283
 
  size_t pos;
284
 
  
285
 
  if ((pos= old_type.find("(")) != std::string::npos)
286
 
  {
287
 
    extra= old_type.substr(pos);
288
 
    old_type.erase(pos, std::string::npos);
289
 
  }
290
 
 
291
 
  std::transform(old_type.begin(), old_type.end(), old_type.begin(), ::toupper);
292
 
  if ((old_type.find("CHAR") != std::string::npos) or 
293
 
    (old_type.find("TEXT") != std::string::npos))
294
 
    setCollate(raw_collation);
295
 
 
296
 
  if ((old_type.compare("INT") == 0) and 
297
 
    ((extra.find("unsigned") != std::string::npos)))
298
 
  {
299
 
    type= "BIGINT";
300
 
    return;
301
 
  }
302
 
    
303
 
  if ((old_type.compare("TINYINT") == 0) or
304
 
    (old_type.compare("SMALLINT") == 0) or
305
 
    (old_type.compare("MEDIUMINT") == 0))
306
 
  {
307
 
    type= "INT";
308
 
    return;
309
 
  }
310
 
 
311
 
  if ((old_type.compare("TINYBLOB") == 0) or
312
 
    (old_type.compare("MEDIUMBLOB") == 0) or
313
 
    (old_type.compare("LONGBLOB") == 0))
314
 
  {
315
 
    type= "BLOB";
316
 
    return;
317
 
  }
318
 
 
319
 
  if ((old_type.compare("TINYTEXT") == 0) or
320
 
    (old_type.compare("MEDIUMTEXT") == 0) or
321
 
    (old_type.compare("LONGTEXT") == 0) or
322
 
    (old_type.compare("SET") == 0))
323
 
  {
324
 
    type= "TEXT";
325
 
    return;
326
 
  }
327
 
 
328
 
  if (old_type.compare("CHAR") == 0)
329
 
  {
330
 
    type= "VARCHAR";
331
 
    return;
332
 
  }
333
 
 
334
 
  if (old_type.compare("BINARY") == 0)
335
 
  {
336
 
    type= "VARBINARY";
337
 
    return;
338
 
  }
339
 
 
340
 
  if (old_type.compare("ENUM") == 0)
341
 
  {
342
 
    type= old_type;
343
 
    /* Strip out the braces, we add them again during output */
344
 
    enumValues= extra.substr(1, extra.length()-2);
345
 
    return;
346
 
  }
347
 
 
348
 
  if ((old_type.find("TIME") != std::string::npos) or
349
 
    (old_type.find("DATE") != std::string::npos))
350
 
  {
351
 
    /* Intended to catch TIME/DATE/TIMESTAMP/DATETIME 
352
 
       We may have a default TIME/DATE which needs converting */
353
 
    convertDateTime= true;
354
 
  }
355
 
 
356
 
  if (old_type.compare("TIME") == 0)
357
 
  {
358
 
    type= "INT";
359
 
    return;
360
 
  }
361
 
 
362
 
  if (old_type.compare("FLOAT") == 0)
363
 
  {
364
 
    type= "DOUBLE";
365
 
    return;
366
 
  }
367
 
 
368
 
  type= old_type;
369
 
  return;
370
 
}
371
 
 
372
 
void DrizzleDumpTableMySQL::setEngine(const char* newEngine)
373
 
{
374
 
  if (strcmp(newEngine, "MyISAM") == 0)
375
 
    engineName= "InnoDB";
376
 
  else
377
 
    engineName= newEngine; 
378
 
}
379
 
 
380
 
DrizzleDumpData* DrizzleDumpTableMySQL::getData(void)
381
 
{
382
 
  try
383
 
  {
384
 
    return new DrizzleDumpDataMySQL(this, dcon);
385
 
  }
386
 
  catch(...)
387
 
  {
388
 
    return NULL;
389
 
  }
390
 
}
391
 
 
392
 
void DrizzleDumpDatabaseMySQL::setCollate(const char* newCollate)
393
 
{
394
 
  if (newCollate)
395
 
  {
396
 
    std::string tmpCollate(newCollate);
397
 
    if (tmpCollate.find("utf8") != std::string::npos)
398
 
    {
399
 
      collate= tmpCollate;
400
 
      return;
401
 
    }
402
 
  }
403
 
  collate= "utf8_general_ci";
404
 
}
405
 
 
406
 
void DrizzleDumpTableMySQL::setCollate(const char* newCollate)
407
 
{
408
 
  if (newCollate)
409
 
  {
410
 
    std::string tmpCollate(newCollate);
411
 
    if (tmpCollate.find("utf8") != std::string::npos)
412
 
    {
413
 
      collate= tmpCollate;
414
 
      return;
415
 
    }
416
 
  }
417
 
 
418
 
  collate= "utf8_general_ci";
419
 
}
420
 
 
421
 
void DrizzleDumpFieldMySQL::setCollate(const char* newCollate)
422
 
{
423
 
  if (newCollate)
424
 
  {
425
 
    std::string tmpCollate(newCollate);
426
 
    if (tmpCollate.find("utf8") != std::string::npos)
427
 
    {
428
 
      collation= tmpCollate;
429
 
      return;
430
 
    }
431
 
  }
432
 
  collation= "utf8_general_ci";
433
 
}
434
 
 
435
 
DrizzleDumpDataMySQL::DrizzleDumpDataMySQL(DrizzleDumpTable *dataTable,
436
 
  DrizzleDumpConnection *connection)
437
 
  : DrizzleDumpData(dataTable, connection)
438
 
{
439
 
  std::string query;
440
 
  query= "SELECT * FROM `";
441
 
  query.append(table->displayName);
442
 
  query.append("`");
443
 
 
444
 
  result= dcon->query(query);
445
 
  if (result == NULL)
446
 
    throw 1;
447
 
}
448
 
 
449
 
DrizzleDumpDataMySQL::~DrizzleDumpDataMySQL()
450
 
{
451
 
  drizzle_result_free(result);
452
 
  if (result) delete result;
453
 
}
454
 
 
455
 
long DrizzleDumpDataMySQL::convertTime(const char* oldTime) const
456
 
{
457
 
  std::string ts(oldTime);
458
 
  boost::posix_time::time_duration td(boost::posix_time::duration_from_string(ts));
459
 
  long seconds= td.total_seconds();
460
 
  return seconds;
461
 
}
462
 
 
463
 
std::string DrizzleDumpDataMySQL::convertDate(const char* oldDate) const
464
 
{
465
 
  boost::match_flag_type flags = boost::match_default;
466
 
  std::string output;
467
 
  boost::regex date_regex("([0-9]{3}[1-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))");
468
 
 
469
 
  if (regex_search(oldDate, date_regex, flags))
470
 
  {
471
 
    output.push_back('\'');
472
 
    output.append(oldDate);
473
 
    output.push_back('\'');
474
 
  }
475
 
  else
476
 
    output= "NULL";
477
 
 
478
 
  return output;
479
 
}
480
 
 
481
 
std::ostream& DrizzleDumpDataMySQL::checkDateTime(std::ostream &os, const char* item, uint32_t field) const
482
 
{
483
 
  if (table->fields[field]->convertDateTime)
484
 
  {
485
 
    if (table->fields[field]->type.compare("INT") == 0)
486
 
      os << convertTime(item);
487
 
    else
488
 
      os << convertDate(item);
489
 
  }
490
 
  return os;
491
 
}
492