~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
          }
1882.2.1 by Andrew Hutchings
MySQL can contain '' as an ENUM value which is not valid in Drizzle. Convert this to NULL.
339
          else if ((obj.table->fields[i]->type.compare("ENUM") == 0) and
340
            (strcmp(row[i], "") == 0))
341
          {
342
            os << "NULL";
343
          }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
344
          else
1810.1.1 by Andrew Hutchings
Add table comments
345
            os << "'" << DrizzleDumpData::escape(row[i], row_sizes[i]) << "'";
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
346
          byte_counter+= 3;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
347
        }
348
        else
349
          os << row[i];
350
      }
351
      if (i != obj.table->fields.size() - 1)
352
        os << ",";
353
    }
354
    /* Break insert up if it is too long */
1865.2.1 by Andrew Hutchings
Fix drizzledump --skip-extended-insert
355
    if ((extended_insert and
356
      (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
357
    {
358
      os << ");" << std::endl;
359
      new_insert= true;
1855.1.1 by Andrew Hutchings
Fix several bugs dumping tables with many rows
360
      byte_counter= 0;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
361
    }
362
  }
1865.2.2 by Andrew Hutchings
Fix possibility of double ");" at end of data dump
363
  if (not new_insert)
364
    os << ");" << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
365
1799.7.2 by Andrew Hutchings
Clean up some drizzledump options
366
  if (opt_autocommit)
367
    os << "COMMIT;" << std::endl;
368
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
369
  if (opt_disable_keys)
370
    os << "ALTER TABLE `" << obj.table->tableName << "` ENABLE KEYS;" << std::endl;
371
372
  os << std::endl;
373
374
  return os;
375
}
376
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
377
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
378
{
379
  std::ostringstream output;
380
  if (from_size > 0)
381
    output << "0x";
1897.3.1 by Andrew Hutchings
drizzledump MySQL migration fixes:
382
  else
383
    output << "''";
384
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
385
  while (from_size > 0)
386
  {
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
387
    /* Would be nice if std::hex liked uint8_t, ah well */
388
    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
389
    (void) *from++;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
390
    from_size--;
391
  }
392
393
  return output.str();
394
}
395
396
/* Ripped out of libdrizzle, hopefully a little safer */
1810.1.1 by Andrew Hutchings
Add table comments
397
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
398
{
399
  std::string output;
400
401
  while (from_size > 0)
402
  {
403
    if (!(*from & 0x80))
404
    {
405
      switch (*from)
406
      {
407
         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.
408
           output.append("\\0");
409
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
410
         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.
411
           output.append("\\n");
412
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
413
         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.
414
           output.append("\\r");
415
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
416
         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.
417
           output.append("\\\\");
418
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
419
         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.
420
           output.append("\\'");
421
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
422
         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.
423
           output.append("\\\"");
424
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
425
         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.
426
           output.append("\\Z");
427
           break;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
428
         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.
429
           output.push_back(*from);
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
430
           break;
431
       }
432
    }
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.
433
    else
434
      output.push_back(*from);
1831.1.1 by Andrew Hutchings
Fix new warnings in GCC 4.5
435
    (void) *from++;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
436
    from_size--;
437
  }
438
439
  return output;
440
}
441
442
std::ostream& operator <<(std::ostream &os, const DrizzleDumpTable &obj)
443
{
1751.4.26 by Andrew Hutchings
Fix up for the drizzledump test cases
444
  if (verbose)
445
  {
446
    std::cerr << "--" << std::endl
447
      << "-- Table structure for table `" << obj.displayName << "`" << std::endl
448
      << "--" << std::endl << std::endl;
449
  }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
450
451
  if (opt_drop)
1751.4.25 by Andrew Hutchings
Fix error handling
452
    os << "DROP TABLE IF EXISTS `" << obj.displayName <<  "`;" << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
453
1751.4.25 by Andrew Hutchings
Fix error handling
454
  os << "CREATE TABLE `" << obj.displayName << "` (" << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
455
  std::vector<DrizzleDumpField*>::iterator i;
456
  std::vector<DrizzleDumpField*> output_fields = obj.fields;
457
  for (i= output_fields.begin(); i != output_fields.end(); ++i)
458
  {
459
    if (i != output_fields.begin())
460
      os << "," << std::endl;
461
    DrizzleDumpField *field= *i;
462
    os << *field;
463
  }
464
465
  std::vector<DrizzleDumpIndex*>::iterator j;
466
  std::vector<DrizzleDumpIndex*> output_indexes = obj.indexes;
467
  for (j= output_indexes.begin(); j != output_indexes.end(); ++j)
468
  {
1810.6.4 by Andrew Hutchings
Add foreign keys to Drizzle server
469
    os << "," << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
470
    DrizzleDumpIndex *index= *j;
471
    os << *index;
472
  }
1810.6.4 by Andrew Hutchings
Add foreign keys to Drizzle server
473
474
  std::vector<DrizzleDumpForeignKey*>::iterator k;
475
  std::vector<DrizzleDumpForeignKey*> output_fkeys = obj.fkeys;
476
  for (k= output_fkeys.begin(); k != output_fkeys.end(); ++k)
477
  {
478
    os << "," << std::endl;
479
    DrizzleDumpForeignKey *fkey= *k;
480
    os << *fkey;
481
  }
482
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
483
  os << std::endl;
1880.2.1 by Andrew Hutchings
Add quoting to the end of the table definition
484
  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)
485
  if (obj.autoIncrement > 0)
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
486
  {
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
487
    os << "AUTO_INCREMENT=" << obj.autoIncrement << " ";
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
488
  }
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
489
1880.2.1 by Andrew Hutchings
Add quoting to the end of the table definition
490
  os << "COLLATE='" << obj.collate << "'";
1810.1.1 by Andrew Hutchings
Add table comments
491
492
  if (not obj.comment.empty())
493
  {
1880.2.1 by Andrew Hutchings
Add quoting to the end of the table definition
494
    os << " COMMENT='" << obj.comment << "'";
1810.1.1 by Andrew Hutchings
Add table comments
495
  }
496
497
  os << ";" << std::endl << std::endl;
1751.4.19 by Andrew Hutchings
Put drizzle and mysql processes in seperate classes/files
498
499
  return os;
500
}
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
501
502
DrizzleDumpConnection::DrizzleDumpConnection(std::string &host, uint16_t port, 
503
  std::string &username, std::string &password, bool drizzle_protocol) :
504
  hostName(host),
505
  drizzleProtocol(drizzle_protocol)
506
{
507
  drizzle_return_t ret;
508
509
  if (host.empty())
510
    host= "localhost";
511
512
  std::string protocol= (drizzle_protocol) ? "Drizzle" : "MySQL";
1751.4.23 by Andrew Hutchings
Fix various bugs
513
  if (verbose)
514
  {
515
    std::cerr << _("-- Connecting to ") << host  << _(" using protocol ")
516
      << protocol << "..." << std::endl;
517
  }
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
518
  drizzle_create(&drizzle);
519
  drizzle_con_create(&drizzle, &connection);
520
  drizzle_con_set_tcp(&connection, (char *)host.c_str(), port);
521
  drizzle_con_set_auth(&connection, (char *)username.c_str(),
522
    (char *)password.c_str());
523
  drizzle_con_add_options(&connection, 
524
    drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
525
  ret= drizzle_con_connect(&connection);
526
  if (ret != DRIZZLE_RETURN_OK)
527
  {
528
    errorHandler(NULL, ret, "when trying to connect");
1802.6.1 by Andrew Hutchings
Add better error handling and exception handling for database connect
529
    throw 1;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
530
  }
531
532
  boost::match_flag_type flags = boost::match_default; 
533
534
  boost::regex mysql_regex("(5\\.[0-9]+\\.[0-9]+)");
535
  boost::regex drizzle_regex("(20[0-9]{2}\\.(0[1-9]|1[012])\\.[0-9]+)");
536
537
  std::string version(getServerVersion());
538
539
  if (regex_search(version, mysql_regex, flags))
540
    serverType= SERVER_MYSQL_FOUND;
1751.4.21 by Andrew Hutchings
Add database destination settings and connect it all up
541
  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
542
    serverType= SERVER_DRIZZLE_FOUND;
1751.4.21 by Andrew Hutchings
Add database destination settings and connect it all up
543
  else
544
    serverType= SERVER_UNKNOWN_FOUND;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
545
}
546
547
drizzle_result_st* DrizzleDumpConnection::query(std::string &str_query)
548
{
549
  drizzle_return_t ret;
550
  drizzle_result_st* result= new drizzle_result_st;
551
  if (drizzle_query_str(&connection, result, str_query.c_str(), &ret) == NULL ||
552
      ret != DRIZZLE_RETURN_OK)
553
  {
554
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
555
    {
556
      std::cerr << _("Error executing query: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
557
        drizzle_result_error(result) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
558
      drizzle_result_free(result);
559
    }
560
    else
561
    {
562
      std::cerr << _("Error executing query: ") <<
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
    }
565
    return NULL;
566
  }
567
568
  if (drizzle_result_buffer(result) != DRIZZLE_RETURN_OK)
569
  {
570
    std::cerr << _("Could not buffer result: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
571
        drizzle_con_error(&connection) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
572
    return NULL;
573
  }
574
  return result;
575
}
576
577
void DrizzleDumpConnection::freeResult(drizzle_result_st* result)
578
{
579
  drizzle_result_free(result);
580
  delete result;
581
}
582
583
bool DrizzleDumpConnection::queryNoResult(std::string &str_query)
584
{
585
  drizzle_return_t ret;
586
  drizzle_result_st result;
587
588
  if (drizzle_query_str(&connection, &result, str_query.c_str(), &ret) == NULL ||
589
      ret != DRIZZLE_RETURN_OK)
590
  {
591
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
592
    {
593
      std::cerr << _("Error executing query: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
594
        drizzle_result_error(&result) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
595
      drizzle_result_free(&result);
596
    }
597
    else
598
    {
599
      std::cerr << _("Error executing query: ") <<
1751.4.23 by Andrew Hutchings
Fix various bugs
600
        drizzle_con_error(&connection) << std::endl;
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
601
    }
602
    return false;
603
  }
604
605
  drizzle_result_free(&result);
606
  return true;
607
}
608
609
bool DrizzleDumpConnection::setDB(std::string databaseName)
610
{
611
  drizzle_return_t ret;
612
  drizzle_result_st result;
613
  if (drizzle_select_db(&connection, &result, databaseName.c_str(), &ret) == 
614
    NULL || ret != DRIZZLE_RETURN_OK)
615
  {
1751.4.25 by Andrew Hutchings
Fix error handling
616
    std::cerr << _("Error: Could not set db '") << databaseName << "'" << std::endl;
617
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
618
      drizzle_result_free(&result);
1751.4.20 by Andrew Hutchings
Add database connection class and the start of a database output ostream
619
    return false;
620
  }
621
  drizzle_result_free(&result);
622
  return true;
623
}
624
1799.7.2 by Andrew Hutchings
Clean up some drizzledump options
625
void DrizzleDumpConnection::errorHandler(drizzle_result_st *res,
626
  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
627
{
1802.6.1 by Andrew Hutchings
Add better error handling and exception handling for database connect
628
  if (res == NULL)
629
  {
630
    std::cerr << _("Got error: ") << drizzle_con_error(&connection) << " "
631
      << when << std::endl;
632
  }
633
  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
634
  {
635
    std::cerr << _("Got error: ") << drizzle_result_error(res)
636
      << " (" << drizzle_result_error_code(res) << ") " << when << std::endl;
637
    drizzle_result_free(res);
638
  }
639
  else
640
  {
641
    std::cerr << _("Got error: ") << ret << " " << when << std::endl;
642
  }
643
644
  return;
645
}
646
647
DrizzleDumpConnection::~DrizzleDumpConnection()
648
{
1751.4.23 by Andrew Hutchings
Fix various bugs
649
  if (verbose)
650
    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
651
  drizzle_con_free(&connection);
652
  drizzle_free(&drizzle);
653
}