~drizzle-trunk/drizzle/development

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 "client_priv.h"
22
#include <drizzled/gettext.h>
23
#include <string>
24
#include <iostream>
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
25
#include <boost/regex.hpp>
1751.4.24 by Andrew Hutchings
Fix ignore tables
26
#include <boost/unordered_set.hpp>
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
27
1751.4.25 by Andrew Hutchings
Fix error handling
28
#define EX_DRIZZLEERR 2
29
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
30
extern bool opt_no_create_info;
31
extern bool opt_no_data;
32
extern bool opt_create_db;
33
extern bool opt_disable_keys;
34
extern bool extended_insert;
35
extern bool opt_replace_into;
1751.4.25 by Andrew Hutchings
Fix error handling
36
extern bool opt_drop;
37
extern bool verbose;
38
extern bool opt_databases;
39
extern bool opt_alldbs;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
40
extern uint32_t show_progress_size;
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
41
extern bool opt_ignore;
1799.7.2 by Andrew Hutchings
Clean up some drizzledump options
42
extern bool opt_compress;
43
extern bool opt_drop_database;
44
extern bool opt_autocommit;
1799.7.4 by Andrew Hutchings
Fix up some more options and the docs
45
extern bool ignore_errors;
1862.2.1 by Andrew Hutchings
Link up --destination-database
46
extern std::string opt_destination_database;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
47
1751.4.24 by Andrew Hutchings
Fix ignore tables
48
extern boost::unordered_set<std::string> ignore_table;
1751.4.25 by Andrew Hutchings
Fix error handling
49
extern void maybe_exit(int error);
1751.4.24 by Andrew Hutchings
Fix ignore tables
50
1751.4.23 by Andrew Hutchings
Fix various bugs
51
enum destinations {
52
  DESTINATION_DB,
53
  DESTINATION_FILES,
54
  DESTINATION_STDOUT
55
};
56
57
extern int opt_destination;
58
1751.4.24 by Andrew Hutchings
Fix ignore tables
59
/* returns true on keep, false on ignore */
60
bool DrizzleDumpDatabase::ignoreTable(std::string tableName)
61
{
62
  std::string dbTable(databaseName);
63
  dbTable.append(".");
64
  dbTable.append(tableName);
65
66
  boost::unordered_set<std::string>::iterator iter= ignore_table.find(dbTable);
67
  return (iter == ignore_table.end());
68
}
69
1751.4.25 by Andrew Hutchings
Fix error handling
70
void DrizzleDumpDatabase::cleanTableName(std::string &tableName)
71
{
72
  std::string replace("``");
73
  std::string find("`");
74
  size_t j = 0;
75
  for (;(j = tableName.find(find, j)) != std::string::npos;)
76
  {
77
    tableName.replace(j, find.length(), replace);
78
    j+= replace.length();
79
  }
80
81
}
82
1810.6.4 by Andrew Hutchings
Add foreign keys to Drizzle server
83
std::ostream& operator <<(std::ostream &os, const DrizzleDumpForeignKey &obj)
84
{
85
  os << "  CONSTRAINT `" << obj.constraintName << "` FOREIGN KEY ("
86
    << obj.parentColumns << ") REFERENCES `" << obj.childTable << "` ("
87
    << obj.childColumns << ")";
88
89
  if (not obj.deleteRule.empty())
90
    os << " ON DELETE " << obj.deleteRule;
91
92
  if (not obj.updateRule.empty())
93
    os << " ON UPDATE " << obj.updateRule;
94
95
  return os;
96
}
97
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
98
std::ostream& operator <<(std::ostream &os, const DrizzleDumpIndex &obj)
99
{
100
  if (obj.isPrimary)
101
  {
102
    os << "  PRIMARY KEY ";
103
  }
104
  else if (obj.isUnique)
105
  {
106
    os << "  UNIQUE KEY `" << obj.indexName << "` ";
107
  }
108
  else
109
  {
110
    os << "  KEY `" << obj.indexName << "` ";
111
  }
112
113
  os << "(";
114
  
115
  std::vector<std::string>::iterator i;
116
  std::vector<std::string> fields = obj.columns;
117
  for (i= fields.begin(); i != fields.end(); ++i)
118
  {
119
    if (i != fields.begin())
120
      os << ",";
121
    std::string field= *i;
122
    os << "`" << field << "`";
1802.2.1 by Andrew Hutchings
Fix index lengths not shown for part-indexed columns.
123
    if (obj.length > 0)
124
      os << "(" << obj.length << ")";
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
125
  }
126
127
  os << ")";
128
129
  return os;
130
}
131
132
std::ostream& operator <<(std::ostream &os, const DrizzleDumpField &obj)
133
{
134
  os << "  `" << obj.fieldName << "` ";
135
  os << obj.type;
136
  if (((obj.type.compare("VARCHAR") == 0) or
137
   (obj.type.compare("VARBINARY") == 0)) and
138
   (obj.length > 0))
139
  {
140
    os << "(" << obj.length << ")";
141
  }
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
142
  else if (((obj.type.compare("DECIMAL") == 0) or
143
    (obj.type.compare("DOUBLE") == 0)) and
144
    ((obj.decimalPrecision + obj.decimalScale) > 0))
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
145
  {
146
    os << "(" << obj.decimalPrecision << "," << obj.decimalScale << ")";
147
  }
148
  else if (obj.type.compare("ENUM") == 0)
149
  {
150
    os << "(" << obj.enumValues << ")";
151
  }
152
153
  if (not obj.isNull)
154
  {
155
    os << " NOT NULL";
156
  }
157
158
  if ((not obj.collation.empty()) and (obj.collation.compare("binary") != 0))
159
  {
160
    os << " COLLATE " << obj.collation;
161
  }
162
163
  if (obj.isAutoIncrement)
164
    os << " AUTO_INCREMENT";
165
166
  if (not obj.defaultValue.empty())
167
  {
168
    if (obj.defaultValue.compare("CURRENT_TIMESTAMP") != 0)
169
     os << " DEFAULT '" << obj.defaultValue << "'";
170
    else
171
     os << " DEFAULT CURRENT_TIMESTAMP";
172
  }
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
173
  else if ((obj.defaultIsNull))
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
174
  {
175
    os << " DEFAULT NULL";
176
  }
177
178
  return os;
179
}
180
181
std::ostream& operator <<(std::ostream &os, const DrizzleDumpDatabase &obj)
182
{
1751.4.23 by Andrew Hutchings
Fix various bugs
183
  if ((opt_destination == DESTINATION_DB) or opt_databases or opt_alldbs)
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
184
  {
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
185
    if (verbose)
186
    {
187
      std::cerr << "--" << std::endl
188
        << "-- Current Database: `" << obj.databaseName << "`" << std::endl
189
        << "--" << std::endl << std::endl;
190
    }
1751.4.23 by Andrew Hutchings
Fix various bugs
191
192
    /* Love that this variable is the opposite of its name */
193
    if (not opt_create_db)
194
    {
1799.7.2 by Andrew Hutchings
Clean up some drizzledump options
195
      if (opt_drop_database)
1862.2.1 by Andrew Hutchings
Link up --destination-database
196
      {
197
        os << "DROP DATABASE IF EXISTS `"
198
          << ((opt_destination_database.empty()) ? obj.databaseName
199
          : opt_destination_database) << "`" << std::endl;
200
      }
1799.7.2 by Andrew Hutchings
Clean up some drizzledump options
201
1862.2.1 by Andrew Hutchings
Link up --destination-database
202
      os << "CREATE DATABASE IF NOT EXISTS `"
203
        << ((opt_destination_database.empty()) ? obj.databaseName
204
        : opt_destination_database) << "`";
1751.4.23 by Andrew Hutchings
Fix various bugs
205
      if (not obj.collate.empty())
206
       os << " COLLATE = " << obj.collate;
207
208
      os << ";" << std::endl << std::endl;
209
    }
1862.2.1 by Andrew Hutchings
Link up --destination-database
210
    os << "USE `" << ((opt_destination_database.empty()) ? obj.databaseName
211
      : opt_destination_database) << "`;" << std::endl << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
212
  }
213
214
  std::vector<DrizzleDumpTable*>::iterator i;
215
  std::vector<DrizzleDumpTable*> output_tables = obj.tables;
216
  for (i= output_tables.begin(); i != output_tables.end(); ++i)
217
  {
218
    DrizzleDumpTable *table= *i;
219
    if (not opt_no_create_info)
220
      os << *table;
221
    if (not opt_no_data)
222
    {
1751.4.21 by Andrew Hutchings
Add database destination settings and connect it all up
223
      obj.dcon->setDB(obj.databaseName);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
224
      DrizzleDumpData *data= table->getData();
1751.4.25 by Andrew Hutchings
Fix error handling
225
      if (data == NULL)
226
      {
227
        std::cerr << "Error: Could not get data for table " << table->displayName << std::endl;
1799.7.4 by Andrew Hutchings
Fix up some more options and the docs
228
        if (not ignore_errors)
229
          maybe_exit(EX_DRIZZLEERR);
230
        else
231
          continue;
1751.4.25 by Andrew Hutchings
Fix error handling
232
      }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
233
      os << *data;
234
      delete data;
235
    }
236
  }
237
238
  return os;
239
}
240
241
242
std::ostream& operator <<(std::ostream &os, const DrizzleDumpData &obj)
243
{
244
  bool new_insert= true;
245
  bool first= true;
246
  uint64_t rownr= 0;
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
247
  size_t byte_counter= 0;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
248
249
  drizzle_row_t row;
250
1751.4.23 by Andrew Hutchings
Fix various bugs
251
  if (verbose)
1751.4.25 by Andrew Hutchings
Fix error handling
252
    std::cerr << _("-- Retrieving data for ") << obj.table->displayName << "..." << std::endl;
1751.4.23 by Andrew Hutchings
Fix various bugs
253
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
254
  if (drizzle_result_row_count(obj.result) < 1)
255
  {
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
256
    if (verbose)
257
    {
258
      std::cerr << "--" << std::endl
259
        << "-- No data to dump for table `" << obj.table->displayName << "`"
260
        << std::endl << "--" << std::endl << std::endl;
261
    }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
262
    return os;
263
  }
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
264
  else if (verbose)
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
265
  {
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
266
    std::cerr << "--" << std::endl
267
      << "-- Dumping data for table `" << obj.table->displayName << "`"
268
      << std::endl << "--" << std::endl << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
269
  }
270
  if (opt_disable_keys)
1751.4.25 by Andrew Hutchings
Fix error handling
271
    os << "ALTER TABLE `" << obj.table->displayName << "` DISABLE KEYS;" << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
272
1799.7.2 by Andrew Hutchings
Clean up some drizzledump options
273
  /* Another option that does the opposite of its name, makes me sad :( */
274
  if (opt_autocommit)
275
    os << "START TRANSACTION;" << std::endl;
276
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
277
  std::streampos out_position= os.tellp();
278
279
  while((row= drizzle_row_next(obj.result)))
280
  {
281
    rownr++;
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
282
    if (verbose and (rownr % show_progress_size) == 0)
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
283
    {
1802.11.1 by Andrew Hutchings
1. date regex was broken
284
      std::cerr << "-- " << rownr << _(" rows dumped for table ") << obj.table->displayName << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
285
    }
286
287
    size_t* row_sizes= drizzle_row_field_sizes(obj.result);
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
288
    for (uint32_t i= 0; i < drizzle_result_column_count(obj.result); i++)
289
      byte_counter+= row_sizes[i];
290
291
    if (not first and not new_insert)
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
292
    {
293
      if (extended_insert)
294
        os << "),(";
295
      else
296
        os << ");" << std::endl;
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
297
      byte_counter+= 3;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
298
    }
299
    else
300
      first= false;
301
302
    if (new_insert)
303
    {
304
      if (opt_replace_into)
305
        os << "REPLACE ";
306
      else
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
307
      {
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
308
        os << "INSERT ";
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
309
        if (opt_ignore)
310
          os << "IGNORE ";
311
      }
1751.4.25 by Andrew Hutchings
Fix error handling
312
      os << "INTO `" << obj.table->displayName << "` VALUES (";
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
313
      byte_counter+= 28 + obj.table->displayName.length();
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
314
      if (extended_insert)
315
        new_insert= false;
316
    }
317
    for (uint32_t i= 0; i < drizzle_result_column_count(obj.result); i++)
318
    {
319
      if (not row[i])
320
      {
321
        os << "NULL";
322
      }
323
      /* time/date conversion for MySQL connections */
324
      else if (obj.table->fields[i]->convertDateTime)
325
      {
1802.11.1 by Andrew Hutchings
1. date regex was broken
326
        os << obj.checkDateTime(row[i], i);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
327
      }
328
      else
329
      {
330
        if (obj.table->fields[i]->type.compare("INT") != 0)
331
        {
332
          /* Hex blob processing or escape text */
333
          if (((obj.table->fields[i]->type.compare("BLOB") == 0) or
334
            (obj.table->fields[i]->type.compare("VARBINARY") == 0)))
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
335
          {
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
336
            os << obj.convertHex((unsigned char*)row[i], row_sizes[i]);
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
337
            byte_counter+= row_sizes[i];
338
          }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
339
          else
1810.1.1 by Andrew Hutchings
Add table comments
340
            os << "'" << DrizzleDumpData::escape(row[i], row_sizes[i]) << "'";
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
341
          byte_counter+= 3;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
342
        }
343
        else
344
          os << row[i];
345
      }
346
      if (i != obj.table->fields.size() - 1)
347
        os << ",";
348
    }
349
    /* Break insert up if it is too long */
1865.2.1 by Andrew Hutchings
Fix drizzledump --skip-extended-insert
350
    if ((extended_insert and
351
      (byte_counter >= DRIZZLE_MAX_LINE_LENGTH)) or (not extended_insert))
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
352
    {
353
      os << ");" << std::endl;
354
      new_insert= true;
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
355
      byte_counter= 0;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
356
    }
357
  }
1865.2.2 by Andrew Hutchings
Fix possibility of double ");" at end of data dump
358
  if (not new_insert)
359
    os << ");" << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
360
1799.7.2 by Andrew Hutchings
Clean up some drizzledump options
361
  if (opt_autocommit)
362
    os << "COMMIT;" << std::endl;
363
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
364
  if (opt_disable_keys)
365
    os << "ALTER TABLE `" << obj.table->tableName << "` ENABLE KEYS;" << std::endl;
366
367
  os << std::endl;
368
369
  return os;
370
}
371
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
372
std::string DrizzleDumpData::convertHex(const unsigned char* from, size_t from_size) const
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
373
{
374
  std::ostringstream output;
375
  if (from_size > 0)
376
    output << "0x";
377
  while (from_size > 0)
378
  {
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
379
    /* Would be nice if std::hex liked uint8_t, ah well */
380
    output << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << (unsigned short)(*from);
1831.1.1 by Andrew Hutchings
Fix new warnings in GCC 4.5
381
    (void) *from++;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
382
    from_size--;
383
  }
384
385
  return output.str();
386
}
387
388
/* Ripped out of libdrizzle, hopefully a little safer */
1810.1.1 by Andrew Hutchings
Add table comments
389
std::string DrizzleDumpData::escape(const char* from, size_t from_size)
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
390
{
391
  std::string output;
392
393
  while (from_size > 0)
394
  {
395
    if (!(*from & 0x80))
396
    {
397
      switch (*from)
398
      {
399
         case 0:
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
400
           output.append("\\0");
401
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
402
         case '\n':
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
403
           output.append("\\n");
404
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
405
         case '\r':
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
406
           output.append("\\r");
407
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
408
         case '\\':
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
409
           output.append("\\\\");
410
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
411
         case '\'':
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
412
           output.append("\\'");
413
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
414
         case '"':
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
415
           output.append("\\\"");
416
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
417
         case '\032':
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
418
           output.append("\\Z");
419
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
420
         default:
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
421
           output.push_back(*from);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
422
           break;
423
       }
424
    }
1855.2.1 by Andrew Hutchings
The escape function is a clone of libdrizzle's but C++'ified. Unfortunately libdrizzle's is broken. Fixed it here, will fix it in libdrizzle at a later date.
425
    else
426
      output.push_back(*from);
1831.1.1 by Andrew Hutchings
Fix new warnings in GCC 4.5
427
    (void) *from++;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
428
    from_size--;
429
  }
430
431
  return output;
432
}
433
434
std::ostream& operator <<(std::ostream &os, const DrizzleDumpTable &obj)
435
{
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
436
  if (verbose)
437
  {
438
    std::cerr << "--" << std::endl
439
      << "-- Table structure for table `" << obj.displayName << "`" << std::endl
440
      << "--" << std::endl << std::endl;
441
  }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
442
443
  if (opt_drop)
1751.4.25 by Andrew Hutchings
Fix error handling
444
    os << "DROP TABLE IF EXISTS `" << obj.displayName <<  "`;" << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
445
1751.4.25 by Andrew Hutchings
Fix error handling
446
  os << "CREATE TABLE `" << obj.displayName << "` (" << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
447
  std::vector<DrizzleDumpField*>::iterator i;
448
  std::vector<DrizzleDumpField*> output_fields = obj.fields;
449
  for (i= output_fields.begin(); i != output_fields.end(); ++i)
450
  {
451
    if (i != output_fields.begin())
452
      os << "," << std::endl;
453
    DrizzleDumpField *field= *i;
454
    os << *field;
455
  }
456
457
  std::vector<DrizzleDumpIndex*>::iterator j;
458
  std::vector<DrizzleDumpIndex*> output_indexes = obj.indexes;
459
  for (j= output_indexes.begin(); j != output_indexes.end(); ++j)
460
  {
1810.6.4 by Andrew Hutchings
Add foreign keys to Drizzle server
461
    os << "," << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
462
    DrizzleDumpIndex *index= *j;
463
    os << *index;
464
  }
1810.6.4 by Andrew Hutchings
Add foreign keys to Drizzle server
465
466
  std::vector<DrizzleDumpForeignKey*>::iterator k;
467
  std::vector<DrizzleDumpForeignKey*> output_fkeys = obj.fkeys;
468
  for (k= output_fkeys.begin(); k != output_fkeys.end(); ++k)
469
  {
470
    os << "," << std::endl;
471
    DrizzleDumpForeignKey *fkey= *k;
472
    os << *fkey;
473
  }
474
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
475
  os << std::endl;
476
  os << ") ENGINE=" << obj.engineName << " ";
1802.5.1 by Andrew Hutchings
Adds auto_increment to data_dictionary.tables and drizzledump (when connecting to a Drizzle server)
477
  if (obj.autoIncrement > 0)
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
478
  {
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
479
    os << "AUTO_INCREMENT=" << obj.autoIncrement << " ";
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
480
  }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
481
1810.1.1 by Andrew Hutchings
Add table comments
482
  os << "COLLATE = " << obj.collate;
483
484
  if (not obj.comment.empty())
485
  {
486
    os << " COMMENT = '" << obj.comment << "'";
487
  }
488
489
  os << ";" << std::endl << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
490
491
  return os;
492
}
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
493
494
DrizzleDumpConnection::DrizzleDumpConnection(std::string &host, uint16_t port, 
495
  std::string &username, std::string &password, bool drizzle_protocol) :
496
  hostName(host),
497
  drizzleProtocol(drizzle_protocol)
498
{
499
  drizzle_return_t ret;
500
501
  if (host.empty())
502
    host= "localhost";
503
504
  std::string protocol= (drizzle_protocol) ? "Drizzle" : "MySQL";
1751.4.23 by Andrew Hutchings
Fix various bugs
505
  if (verbose)
506
  {
507
    std::cerr << _("-- Connecting to ") << host  << _(" using protocol ")
508
      << protocol << "..." << std::endl;
509
  }
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
510
  drizzle_create(&drizzle);
511
  drizzle_con_create(&drizzle, &connection);
512
  drizzle_con_set_tcp(&connection, (char *)host.c_str(), port);
513
  drizzle_con_set_auth(&connection, (char *)username.c_str(),
514
    (char *)password.c_str());
515
  drizzle_con_add_options(&connection, 
516
    drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
517
  ret= drizzle_con_connect(&connection);
518
  if (ret != DRIZZLE_RETURN_OK)
519
  {
520
    errorHandler(NULL, ret, "when trying to connect");
1802.6.1 by Andrew Hutchings
Add better error handling and exception handling for database connect
521
    throw 1;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
522
  }
523
524
  boost::match_flag_type flags = boost::match_default; 
525
526
  boost::regex mysql_regex("(5\\.[0-9]+\\.[0-9]+)");
527
  boost::regex drizzle_regex("(20[0-9]{2}\\.(0[1-9]|1[012])\\.[0-9]+)");
528
529
  std::string version(getServerVersion());
530
531
  if (regex_search(version, mysql_regex, flags))
532
    serverType= SERVER_MYSQL_FOUND;
1751.4.21 by Andrew Hutchings
Add database destination settings and connect it all up
533
  else if (regex_search(version, drizzle_regex, flags))
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
534
    serverType= SERVER_DRIZZLE_FOUND;
1751.4.21 by Andrew Hutchings
Add database destination settings and connect it all up
535
  else
536
    serverType= SERVER_UNKNOWN_FOUND;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
537
}
538
539
drizzle_result_st* DrizzleDumpConnection::query(std::string &str_query)
540
{
541
  drizzle_return_t ret;
542
  drizzle_result_st* result= new drizzle_result_st;
543
  if (drizzle_query_str(&connection, result, str_query.c_str(), &ret) == NULL ||
544
      ret != DRIZZLE_RETURN_OK)
545
  {
546
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
547
    {
548
      std::cerr << _("Error executing query: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
549
        drizzle_result_error(result) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
550
      drizzle_result_free(result);
551
    }
552
    else
553
    {
554
      std::cerr << _("Error executing query: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
555
        drizzle_con_error(&connection) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
556
    }
557
    return NULL;
558
  }
559
560
  if (drizzle_result_buffer(result) != DRIZZLE_RETURN_OK)
561
  {
562
    std::cerr << _("Could not buffer result: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
563
        drizzle_con_error(&connection) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
564
    return NULL;
565
  }
566
  return result;
567
}
568
569
void DrizzleDumpConnection::freeResult(drizzle_result_st* result)
570
{
571
  drizzle_result_free(result);
572
  delete result;
573
}
574
575
bool DrizzleDumpConnection::queryNoResult(std::string &str_query)
576
{
577
  drizzle_return_t ret;
578
  drizzle_result_st result;
579
580
  if (drizzle_query_str(&connection, &result, str_query.c_str(), &ret) == NULL ||
581
      ret != DRIZZLE_RETURN_OK)
582
  {
583
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
584
    {
585
      std::cerr << _("Error executing query: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
586
        drizzle_result_error(&result) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
587
      drizzle_result_free(&result);
588
    }
589
    else
590
    {
591
      std::cerr << _("Error executing query: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
592
        drizzle_con_error(&connection) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
593
    }
594
    return false;
595
  }
596
597
  drizzle_result_free(&result);
598
  return true;
599
}
600
601
bool DrizzleDumpConnection::setDB(std::string databaseName)
602
{
603
  drizzle_return_t ret;
604
  drizzle_result_st result;
605
  if (drizzle_select_db(&connection, &result, databaseName.c_str(), &ret) == 
606
    NULL || ret != DRIZZLE_RETURN_OK)
607
  {
1751.4.25 by Andrew Hutchings
Fix error handling
608
    std::cerr << _("Error: Could not set db '") << databaseName << "'" << std::endl;
609
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
610
      drizzle_result_free(&result);
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
611
    return false;
612
  }
613
  drizzle_result_free(&result);
614
  return true;
615
}
616
1799.7.2 by Andrew Hutchings
Clean up some drizzledump options
617
void DrizzleDumpConnection::errorHandler(drizzle_result_st *res,
618
  drizzle_return_t ret, const char *when)
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
619
{
1802.6.1 by Andrew Hutchings
Add better error handling and exception handling for database connect
620
  if (res == NULL)
621
  {
622
    std::cerr << _("Got error: ") << drizzle_con_error(&connection) << " "
623
      << when << std::endl;
624
  }
625
  else if (ret == DRIZZLE_RETURN_ERROR_CODE)
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
626
  {
627
    std::cerr << _("Got error: ") << drizzle_result_error(res)
628
      << " (" << drizzle_result_error_code(res) << ") " << when << std::endl;
629
    drizzle_result_free(res);
630
  }
631
  else
632
  {
633
    std::cerr << _("Got error: ") << ret << " " << when << std::endl;
634
  }
635
636
  return;
637
}
638
639
DrizzleDumpConnection::~DrizzleDumpConnection()
640
{
1751.4.23 by Andrew Hutchings
Fix various bugs
641
  if (verbose)
642
    std::cerr << _("-- Disconnecting from ") << hostName << "..." << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
643
  drizzle_con_free(&connection);
644
  drizzle_free(&drizzle);
645
}