~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump_mysql.cc

  • Committer: Stewart Smith
  • Date: 2008-11-21 16:06:07 UTC
  • mto: This revision was merged to the branch mainline in revision 593.
  • Revision ID: stewart@flamingspork.com-20081121160607-n6gdlt013spuo54r
remove mysql_frm_type
and fix engines to return correct value from delete_table when table doesn't exist.
(it should be ENOENT).

Also fix up some tests that manipulated frm files by hand. These tests are no longer valid and will need to be rewritten in the not too distant future.

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