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