~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Patrick Crews
  • Date: 2010-09-14 20:21:03 UTC
  • mto: (1771.1.1 pcrews)
  • mto: This revision was merged to the branch mainline in revision 1772.
  • Revision ID: gleebix@gmail.com-20100914202103-1db2n0bshzafep19
Moved transaction_log tests into updated non-publisher-based tree

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
2
2
 * Copyright (C) 2010 Vijay Samuel
3
 
 * Copyright (C) 2010 Andrew Hutchings
4
3
 
5
4
  This program is free software; you can redistribute it and/or modify
6
5
  it under the terms of the GNU General Public License as published by
13
12
 
14
13
  You should have received a copy of the GNU General Public License
15
14
  along with this program; if not, write to the Free Software
16
 
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
15
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
17
16
 
18
17
/* drizzledump.cc  - Dump a tables contents and format to an ASCII file
19
18
 
34
33
#include "client_priv.h"
35
34
#include <string>
36
35
#include <iostream>
 
36
#include "drizzled/internal/my_sys.h"
 
37
#include "drizzled/internal/m_string.h"
 
38
#include "drizzled/charset_info.h"
37
39
#include <stdarg.h>
38
40
#include <boost/unordered_set.hpp>
39
41
#include <algorithm>
42
44
#include <drizzled/configmake.h>
43
45
#include <drizzled/error.h>
44
46
#include <boost/program_options.hpp>
45
 
#include <boost/regex.hpp>
46
 
#include <boost/date_time/posix_time/posix_time.hpp>
47
 
#include "drizzledump_data.h"
48
 
#include "drizzledump_mysql.h"
49
 
#include "drizzledump_drizzle.h"
50
47
 
51
48
using namespace std;
52
49
using namespace drizzled;
72
69
 
73
70
/* Size of buffer for dump's select query */
74
71
#define QUERY_LENGTH 1536
 
72
#define DRIZZLE_MAX_LINE_LENGTH 1024*1024L-1025
75
73
 
76
74
/* ignore table flags */
77
75
#define IGNORE_NONE 0x00 /* no ignore */
78
76
#define IGNORE_DATA 0x01 /* don't dump data for this table */
79
77
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
80
78
 
81
 
bool opt_alltspcs= false;
82
 
bool opt_complete_insert= false;
83
 
bool  verbose= false;
 
79
static void add_load_option(string &str, const char *option,
 
80
                            const string &option_value);
 
81
 
 
82
static void field_escape(string &in, const string &from);
 
83
static bool  verbose= false;
 
84
static bool opt_no_create_info;
 
85
static bool opt_no_data= false;
84
86
static bool use_drizzle_protocol= false;
85
 
bool ignore_errors= false;
 
87
static bool quick= true;
 
88
static bool extended_insert= true;
 
89
static bool ignore_errors= false;
86
90
static bool flush_logs= false;
 
91
static bool opt_drop= true; 
 
92
static bool opt_keywords= false;
 
93
static bool opt_compress= false;
 
94
static bool opt_delayed= false; 
87
95
static bool create_options= true; 
88
96
static bool opt_quoted= false;
89
 
bool opt_databases= false; 
90
 
bool opt_alldbs= false; 
 
97
static bool opt_databases= false; 
 
98
static bool opt_alldbs= false; 
 
99
static bool opt_create_db= false;
91
100
static bool opt_lock_all_tables= false;
 
101
static bool opt_set_charset= false; 
92
102
static bool opt_dump_date= true;
93
 
bool opt_autocommit= false; 
 
103
static bool opt_autocommit= false; 
 
104
static bool opt_disable_keys= true;
 
105
static bool opt_xml;
94
106
static bool opt_single_transaction= false; 
95
107
static bool opt_comments;
96
108
static bool opt_compact;
97
 
bool opt_ignore= false;
98
 
bool opt_drop_database;
99
 
bool opt_no_create_info;
100
 
bool opt_no_data= false;
101
 
bool opt_create_db= false;
102
 
bool opt_disable_keys= true;
103
 
bool extended_insert= true;
104
 
bool opt_replace_into= false;
105
 
bool opt_drop= true; 
106
 
bool opt_data_is_mangled= false;
107
 
uint32_t show_progress_size= 0;
 
109
static bool opt_hex_blob= false;
 
110
static bool opt_order_by_primary=false; 
 
111
static bool opt_ignore= false;
 
112
static bool opt_complete_insert= false;
 
113
static bool opt_drop_database;
 
114
static bool opt_replace_into= false;
 
115
static bool opt_alltspcs= false;
 
116
static uint32_t show_progress_size= 0;
 
117
static uint64_t total_rows= 0;
 
118
static drizzle_st drizzle;
 
119
static drizzle_con_st dcon;
108
120
static string insert_pat;
 
121
static char *order_by= NULL;
109
122
static uint32_t opt_drizzle_port= 0;
110
123
static int first_error= 0;
111
124
static string extended_row;
112
125
FILE *md_result_file= 0;
113
126
FILE *stderror_file= 0;
114
 
std::vector<DrizzleDumpDatabase*> database_store;
115
 
DrizzleDumpConnection* db_connection;
116
 
DrizzleDumpConnection* destination_connection;
117
 
 
118
 
enum destinations {
119
 
  DESTINATION_DB,
120
 
  DESTINATION_FILES,
121
 
  DESTINATION_STDOUT
122
 
};
123
 
 
124
 
int opt_destination= DESTINATION_STDOUT;
125
 
std::string opt_destination_host;
126
 
uint16_t opt_destination_port;
127
 
std::string opt_destination_user;
128
 
std::string opt_destination_password;
129
 
std::string opt_destination_database;
130
127
 
131
128
const string progname= "drizzledump";
132
129
 
134
131
  enclosed,
135
132
  escaped,
136
133
  current_host,
 
134
  opt_enclosed,
 
135
  fields_terminated,
137
136
  path,
 
137
  lines_terminated,
138
138
  current_user,
139
139
  opt_password,
140
140
  opt_protocol,
141
141
  where;
142
142
 
 
143
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
 
144
 
143
145
boost::unordered_set<string> ignore_table;
144
146
 
145
 
void maybe_exit(int error);
 
147
static void maybe_exit(int error);
146
148
static void die(int error, const char* reason, ...);
147
 
static void write_header(char *db_name);
 
149
static void maybe_die(int error, const char* reason, ...);
 
150
static void write_header(FILE *sql_file, char *db_name);
 
151
static void print_value(FILE *file, drizzle_result_st *result,
 
152
                        drizzle_row_t row, const char *prefix, const char *name,
 
153
                        int string_value);
 
154
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row,
 
155
                                   const char* name);
148
156
static int dump_selected_tables(const string &db, const vector<string> &table_names);
 
157
static int dump_all_tables_in_db(char *db);
 
158
static int init_dumping_tables(char *);
 
159
static int init_dumping(char *, int init_func(char*));
149
160
static int dump_databases(const vector<string> &db_names);
150
161
static int dump_all_databases(void);
151
 
int get_server_type();
152
 
void dump_all_tables(void);
153
 
void generate_dump(void);
154
 
void generate_dump_db(void);
155
 
 
156
 
void dump_all_tables(void)
157
 
{
158
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
159
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
160
 
  {
161
 
    if ((not (*i)->populateTables()) && (not ignore_errors))
162
 
      maybe_exit(EX_DRIZZLEERR);
163
 
  }
164
 
}
165
 
 
166
 
void generate_dump(void)
167
 
{
168
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
169
 
 
170
 
  if (path.empty())
171
 
  {
172
 
    cout << endl << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;"
173
 
      << endl << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
174
 
  }
175
 
 
176
 
  if (opt_autocommit)
177
 
    cout << "SET AUTOCOMMIT=0;" << endl;
178
 
 
179
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
180
 
  {
181
 
    DrizzleDumpDatabase *database= *i;
182
 
    cout << *database;
183
 
  }
184
 
 
185
 
  if (path.empty())
186
 
  {
187
 
    cout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;"
188
 
      << endl << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
189
 
  }
190
 
}
191
 
 
192
 
void generate_dump_db(void)
193
 
{
194
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
195
 
  DrizzleStringBuf sbuf(1024);
196
 
  try
197
 
  {
198
 
    destination_connection= new DrizzleDumpConnection(opt_destination_host,
199
 
      opt_destination_port, opt_destination_user, opt_destination_password,
200
 
      false);
201
 
  }
202
 
  catch (std::exception&)
203
 
  {
204
 
    cerr << "Could not connect to destination database server" << endl;
205
 
    maybe_exit(EX_DRIZZLEERR);
206
 
  }
207
 
  sbuf.setConnection(destination_connection);
208
 
  std::ostream sout(&sbuf);
209
 
  sout.exceptions(ios_base::badbit);
210
 
 
211
 
  if (path.empty())
212
 
  {
213
 
    sout << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;" << endl;
214
 
    sout << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
215
 
  }
216
 
 
217
 
  if (opt_autocommit)
218
 
    cout << "SET AUTOCOMMIT=0;" << endl;
219
 
 
220
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
221
 
  {
222
 
    try
223
 
    {
224
 
      DrizzleDumpDatabase *database= *i;
225
 
      sout << *database;
226
 
    }
227
 
    catch (std::exception&)
228
 
    {
229
 
      std::cout << _("Error inserting into destination database") << std::endl;
230
 
      if (not ignore_errors)
231
 
        maybe_exit(EX_DRIZZLEERR);
232
 
    }
233
 
  }
234
 
 
235
 
  if (path.empty())
236
 
  {
237
 
    sout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;" << endl;
238
 
    sout << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
239
 
  }
 
162
static char *quote_name(const char *name, char *buff, bool force);
 
163
char check_if_ignore_table(const char *table_name, char *table_type);
 
164
static char *primary_key_fields(const char *table_name);
 
165
 
 
166
/*
 
167
  Print the supplied message if in verbose mode
 
168
 
 
169
  SYNOPSIS
 
170
  verbose_msg()
 
171
  fmt   format specifier
 
172
  ...   variable number of parameters
 
173
*/
 
174
 
 
175
static void verbose_msg(const char *fmt, ...)
 
176
{
 
177
  va_list args;
 
178
 
 
179
 
 
180
  if (!verbose)
 
181
    return;
 
182
 
 
183
  va_start(args, fmt);
 
184
  vfprintf(stderr, fmt, args);
 
185
  va_end(args);
240
186
}
241
187
 
242
188
/*
253
199
    die(EX_EOF, _("Got errno %d on write"), errno);
254
200
}
255
201
 
256
 
static void write_header(char *db_name)
 
202
static void write_header(FILE *sql_file, char *db_name)
257
203
{
258
 
  if ((not opt_compact) and (opt_comments))
 
204
  if (opt_xml)
259
205
  {
260
 
    cout << "-- drizzledump " << VERSION << " libdrizzle "
261
 
      << drizzle_version() << ", for " << HOST_VENDOR << "-" << HOST_OS
262
 
      << " (" << HOST_CPU << ")" << endl << "--" << endl;
263
 
    cout << "-- Host: " << current_host << "    Database: " << db_name << endl;
264
 
    cout << "-- ------------------------------------------------------" << endl;
265
 
    cout << "-- Server version\t" << db_connection->getServerVersion();
266
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
267
 
      cout << " (MySQL server)";
268
 
    else if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_DRIZZLE_FOUND)
269
 
      cout << " (Drizzle server)";
270
 
    cout << endl << endl;
 
206
    fputs("<?xml version=\"1.0\"?>\n", sql_file);
 
207
    /*
 
208
      Schema reference.  Allows use of xsi:nil for NULL values and
 
209
xsi:type to define an element's data type.
 
210
    */
 
211
    fputs("<drizzledump ", sql_file);
 
212
    fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
 
213
          sql_file);
 
214
    fputs(">\n", sql_file);
 
215
    check_io(sql_file);
 
216
  }
 
217
  else if (! opt_compact)
 
218
  { 
 
219
    if (opt_comments)
 
220
    {
 
221
      fprintf(sql_file,
 
222
              "-- drizzledump %s libdrizzle %s, for %s-%s (%s)\n--\n",
 
223
              VERSION, drizzle_version(), HOST_VENDOR, HOST_OS, HOST_CPU);
 
224
      fprintf(sql_file, "-- Host: %s    Database: %s\n",
 
225
              ! current_host.empty() ? current_host.c_str() : "localhost", db_name ? db_name :
 
226
              "");
 
227
      fputs("-- ------------------------------------------------------\n",
 
228
            sql_file);
 
229
      fprintf(sql_file, "-- Server version\t%s\n",
 
230
              drizzle_con_server_version(&dcon));
 
231
    }
 
232
    if (opt_set_charset)
 
233
      fprintf(sql_file,
 
234
              "\nSET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION;\n");
 
235
 
 
236
    if (path.empty())
 
237
    {
 
238
      fprintf(md_result_file,"SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;\nSET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;\n");
 
239
    }
 
240
    check_io(sql_file);
271
241
  }
272
242
} /* write_header */
273
243
 
274
244
 
275
245
static void write_footer(FILE *sql_file)
276
246
{
277
 
  if (! opt_compact)
278
 
  {
 
247
  if (opt_xml)
 
248
  {
 
249
    fputs("</drizzledump>\n", sql_file);
 
250
    check_io(sql_file);
 
251
  }
 
252
  else if (! opt_compact)
 
253
  {
 
254
    if (path.empty())
 
255
    {
 
256
      fprintf(md_result_file,"SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;\nSET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;\n");
 
257
    }
 
258
    if (opt_set_charset)
 
259
      fprintf(sql_file, "SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION;\n");
279
260
    if (opt_comments)
280
261
    {
281
262
      if (opt_dump_date)
282
263
      {
283
 
        boost::posix_time::ptime time(boost::posix_time::second_clock::local_time());
 
264
        char time_str[20];
 
265
        internal::get_date(time_str, GETDATE_DATE_TIME, 0);
284
266
        fprintf(sql_file, "-- Dump completed on %s\n",
285
 
          boost::posix_time::to_simple_string(time).c_str());
 
267
                time_str);
286
268
      }
287
269
      else
288
270
        fprintf(sql_file, "-- Dump completed\n");
293
275
 
294
276
static int get_options(void)
295
277
{
 
278
 
 
279
  if (path.empty() && (! enclosed.empty() || ! opt_enclosed.empty() || ! escaped.empty() || ! lines_terminated.empty() ||
 
280
                ! fields_terminated.empty()))
 
281
  {
 
282
    fprintf(stderr,
 
283
            _("%s: You must use option --tab with --fields-...\n"), progname.c_str());
 
284
    return(EX_USAGE);
 
285
  }
 
286
 
296
287
  if (opt_single_transaction && opt_lock_all_tables)
297
288
  {
298
289
    fprintf(stderr, _("%s: You can't use --single-transaction and "
299
290
                      "--lock-all-tables at the same time.\n"), progname.c_str());
300
291
    return(EX_USAGE);
301
292
  }
 
293
  if (! enclosed.empty() && ! opt_enclosed.empty())
 
294
  {
 
295
    fprintf(stderr, _("%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n"), progname.c_str());
 
296
    return(EX_USAGE);
 
297
  }
302
298
  if ((opt_databases || opt_alldbs) && ! path.empty())
303
299
  {
304
300
    fprintf(stderr,
314
310
 
315
311
 
316
312
/*
 
313
 ** DB_error -- prints DRIZZLE error message and exits the program.
 
314
*/
 
315
static void DB_error(drizzle_result_st *res, drizzle_return_t ret,
 
316
                     const char *when)
 
317
{
 
318
  if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
319
  {
 
320
    maybe_die(EX_DRIZZLEERR, _("Got error: %s (%d) %s"),
 
321
              drizzle_result_error(res),
 
322
              drizzle_result_error_code(res),
 
323
              when);
 
324
    drizzle_result_free(res);
 
325
  }
 
326
  else
 
327
    maybe_die(EX_DRIZZLEERR, _("Got error: %d %s"), ret, when);
 
328
 
 
329
  return;
 
330
}
 
331
 
 
332
 
 
333
 
 
334
/*
317
335
  Prints out an error message and kills the process.
318
336
 
319
337
  SYNOPSIS
341
359
  maybe_exit(error_num);
342
360
}
343
361
 
 
362
 
 
363
/*
 
364
  Prints out an error message and maybe kills the process.
 
365
 
 
366
  SYNOPSIS
 
367
  maybe_die()
 
368
  error_num   - process return value
 
369
  fmt_reason  - a format string for use by vsnprintf.
 
370
  ...         - variable arguments for above fmt_reason string
 
371
 
 
372
  DESCRIPTION
 
373
  This call prints out the formatted error message to stderr and then
 
374
  terminates the process, unless the --force command line option is used.
 
375
 
 
376
  This call should be used for non-fatal errors (such as database
 
377
  errors) that the code may still be able to continue to the next unit
 
378
  of work.
 
379
 
 
380
*/
 
381
static void maybe_die(int error_num, const char* fmt_reason, ...)
 
382
{
 
383
  char buffer[1000];
 
384
  va_list args;
 
385
  va_start(args,fmt_reason);
 
386
  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
 
387
  va_end(args);
 
388
 
 
389
  fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
 
390
  fflush(stderr);
 
391
 
 
392
  maybe_exit(error_num);
 
393
}
 
394
 
 
395
 
 
396
 
 
397
/*
 
398
  Sends a query to server, optionally reads result, prints error message if
 
399
  some.
 
400
 
 
401
  SYNOPSIS
 
402
  drizzleclient_query_with_error_report()
 
403
  drizzle_con       connection to use
 
404
  res             if non zero, result will be put there with
 
405
  drizzleclient_store_result()
 
406
  query           query to send to server
 
407
 
 
408
  RETURN VALUES
 
409
  0               query sending and (if res!=0) result reading went ok
 
410
  1               error
 
411
*/
 
412
 
 
413
static int drizzleclient_query_with_error_report(drizzle_con_st *con,
 
414
                                                 drizzle_result_st *result,
 
415
                                                 const char *query_str,
 
416
                                                 bool no_buffer)
 
417
{
 
418
  drizzle_return_t ret;
 
419
 
 
420
  if (drizzle_query_str(con, result, query_str, &ret) == NULL ||
 
421
      ret != DRIZZLE_RETURN_OK)
 
422
  {
 
423
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
424
    {
 
425
      maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
426
                query_str, drizzle_result_error(result),
 
427
                drizzle_result_error_code(result));
 
428
      drizzle_result_free(result);
 
429
    }
 
430
    else
 
431
    {
 
432
      maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
433
                query_str, drizzle_con_error(con), ret);
 
434
    }
 
435
    return 1;
 
436
  }
 
437
 
 
438
  if (no_buffer)
 
439
    ret= drizzle_column_buffer(result);
 
440
  else
 
441
    ret= drizzle_result_buffer(result);
 
442
  if (ret != DRIZZLE_RETURN_OK)
 
443
  {
 
444
    drizzle_result_free(result);
 
445
    maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
446
              query_str, drizzle_con_error(con), ret);
 
447
    return 1;
 
448
  }
 
449
 
 
450
  return 0;
 
451
}
 
452
 
 
453
/*
 
454
  Open a new .sql file to dump the table or view into
 
455
 
 
456
  SYNOPSIS
 
457
  open_sql_file_for_table
 
458
  name      name of the table or view
 
459
 
 
460
  RETURN VALUES
 
461
  0        Failed to open file
 
462
  > 0      Handle of the open file
 
463
*/
 
464
static FILE* open_sql_file_for_table(const char* table)
 
465
{
 
466
  FILE* res;
 
467
  char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
468
  internal::convert_dirname(tmp_path,(char *)path.c_str(),NULL);
 
469
  res= fopen(internal::fn_format(filename, table, tmp_path, ".sql", 4), "w");
 
470
 
 
471
  return res;
 
472
}
 
473
 
 
474
 
344
475
static void free_resources(void)
345
476
{
346
477
  if (md_result_file && md_result_file != stdout)
347
478
    fclose(md_result_file);
348
479
  opt_password.erase();
 
480
  internal::my_end();
349
481
}
350
482
 
351
483
 
352
 
void maybe_exit(int error)
 
484
static void maybe_exit(int error)
353
485
{
354
486
  if (!first_error)
355
487
    first_error= error;
356
488
  if (ignore_errors)
357
489
    return;
358
 
  delete db_connection;
359
 
  delete destination_connection;
 
490
  drizzle_con_free(&dcon);
 
491
  drizzle_free(&drizzle);
360
492
  free_resources();
361
493
  exit(error);
362
494
}
363
495
 
 
496
 
 
497
/*
 
498
  db_connect -- connects to the host and selects DB.
 
499
*/
 
500
 
 
501
static int connect_to_db(string host, string user,string passwd)
 
502
{
 
503
  drizzle_return_t ret;
 
504
 
 
505
  verbose_msg(_("-- Connecting to %s, using protocol %s...\n"), ! host.empty() ? (char *)host.c_str() : "localhost", opt_protocol.c_str());
 
506
  drizzle_create(&drizzle);
 
507
  drizzle_con_create(&drizzle, &dcon);
 
508
  drizzle_con_set_tcp(&dcon, (char *)host.c_str(), opt_drizzle_port);
 
509
  drizzle_con_set_auth(&dcon, (char *)user.c_str(), (char *)passwd.c_str());
 
510
  drizzle_con_add_options(&dcon, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
511
  ret= drizzle_con_connect(&dcon);
 
512
  if (ret != DRIZZLE_RETURN_OK)
 
513
  {
 
514
    DB_error(NULL, ret, "when trying to connect");
 
515
    return(1);
 
516
  }
 
517
 
 
518
  return(0);
 
519
} /* connect_to_db */
 
520
 
 
521
 
 
522
/*
 
523
 ** dbDisconnect -- disconnects from the host.
 
524
*/
 
525
static void dbDisconnect(string &host)
 
526
{
 
527
  verbose_msg(_("-- Disconnecting from %s...\n"), ! host.empty() ? host.c_str() : "localhost");
 
528
  drizzle_con_free(&dcon);
 
529
  drizzle_free(&drizzle);
 
530
} /* dbDisconnect */
 
531
 
 
532
 
 
533
static void unescape(FILE *file,char *pos,uint32_t length)
 
534
{
 
535
  char *tmp;
 
536
 
 
537
  if (!(tmp=(char*) malloc(length*2+1)))
 
538
    die(EX_DRIZZLEERR, _("Couldn't allocate memory"));
 
539
 
 
540
  drizzle_escape_string(tmp, pos, length);
 
541
  fputc('\'', file);
 
542
  fputs(tmp, file);
 
543
  fputc('\'', file);
 
544
  check_io(file);
 
545
  free(tmp);
 
546
  return;
 
547
} /* unescape */
 
548
 
 
549
 
 
550
static bool test_if_special_chars(const char *str)
 
551
{
 
552
  for ( ; *str ; str++)
 
553
    if (!my_isvar(charset_info,*str) && *str != '$')
 
554
      return 1;
 
555
  return 0;
 
556
} /* test_if_special_chars */
 
557
 
 
558
 
 
559
 
 
560
/*
 
561
  quote_name(name, buff, force)
 
562
 
 
563
  Quotes char string, taking into account compatible mode
 
564
 
 
565
  Args
 
566
 
 
567
  name                 Unquoted string containing that which will be quoted
 
568
  buff                 The buffer that contains the quoted value, also returned
 
569
  force                Flag to make it ignore 'test_if_special_chars'
 
570
 
 
571
  Returns
 
572
 
 
573
  buff                 quoted string
 
574
 
 
575
*/
 
576
static char *quote_name(const char *name, char *buff, bool force)
 
577
{
 
578
  char *to= buff;
 
579
  char qtype= '`';
 
580
 
 
581
  if (!force && !opt_quoted && !test_if_special_chars(name))
 
582
    return (char*) name;
 
583
  *to++= qtype;
 
584
  while (*name)
 
585
  {
 
586
    if (*name == qtype)
 
587
      *to++= qtype;
 
588
    *to++= *name++;
 
589
  }
 
590
  to[0]= qtype;
 
591
  to[1]= 0;
 
592
  return buff;
 
593
} /* quote_name */
 
594
 
 
595
 
 
596
/*
 
597
  Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
 
598
 
 
599
  SYNOPSIS
 
600
  quote_for_like()
 
601
  name     name of the table
 
602
  buff     quoted name of the table
 
603
 
 
604
  DESCRIPTION
 
605
  Quote \, _, ' and % characters
 
606
 
 
607
Note: Because DRIZZLE uses the C escape syntax in strings
 
608
(for example, '\n' to represent newline), you must double
 
609
any '\' that you use in your LIKE  strings. For example, to
 
610
search for '\n', specify it as '\\n'. To search for '\', specify
 
611
it as '\\\\' (the backslashes are stripped once by the parser
 
612
and another time when the pattern match is done, leaving a
 
613
single backslash to be matched).
 
614
 
 
615
Example: "t\1" => "t\\\\1"
 
616
 
 
617
*/
 
618
static char *quote_for_like(const char *name, char *buff)
 
619
{
 
620
  char *to= buff;
 
621
  *to++= '\'';
 
622
  while (*name)
 
623
  {
 
624
    if (*name == '\\')
 
625
    {
 
626
      *to++='\\';
 
627
      *to++='\\';
 
628
      *to++='\\';
 
629
    }
 
630
    else if (*name == '\'' || *name == '_'  || *name == '%')
 
631
      *to++= '\\';
 
632
    *to++= *name++;
 
633
  }
 
634
  to[0]= '\'';
 
635
  to[1]= 0;
 
636
  return buff;
 
637
}
 
638
 
 
639
 
 
640
/*
 
641
  Quote and print a string.
 
642
 
 
643
  SYNOPSIS
 
644
  print_quoted_xml()
 
645
  xml_file    - output file
 
646
  str         - string to print
 
647
  len         - its length
 
648
 
 
649
  DESCRIPTION
 
650
  Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
 
651
*/
 
652
 
 
653
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
 
654
{
 
655
  const char *end;
 
656
 
 
657
  for (end= str + len; str != end; str++)
 
658
  {
 
659
    switch (*str) {
 
660
    case '<':
 
661
      fputs("&lt;", xml_file);
 
662
      break;
 
663
    case '>':
 
664
      fputs("&gt;", xml_file);
 
665
      break;
 
666
    case '&':
 
667
      fputs("&amp;", xml_file);
 
668
      break;
 
669
      case '\"':
 
670
        fputs("&quot;", xml_file);
 
671
      break;
 
672
    default:
 
673
      fputc(*str, xml_file);
 
674
      break;
 
675
    }
 
676
  }
 
677
  check_io(xml_file);
 
678
}
 
679
 
 
680
 
 
681
/*
 
682
  Print xml tag. Optionally add attribute(s).
 
683
 
 
684
  SYNOPSIS
 
685
  print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
 
686
  ..., attribute_name_n, attribute_value_n, NULL)
 
687
  xml_file              - output file
 
688
  sbeg                  - line beginning
 
689
  line_end              - line ending
 
690
  tag_name              - XML tag name.
 
691
  first_attribute_name  - tag and first attribute
 
692
  first_attribute_value - (Implied) value of first attribute
 
693
  attribute_name_n      - attribute n
 
694
  attribute_value_n     - value of attribute n
 
695
 
 
696
  DESCRIPTION
 
697
  Print XML tag with any number of attribute="value" pairs to the xml_file.
 
698
 
 
699
  Format is:
 
700
  sbeg<tag_name first_attribute_name="first_attribute_value" ...
 
701
  attribute_name_n="attribute_value_n">send
 
702
  NOTE
 
703
  Additional arguments must be present in attribute/value pairs.
 
704
  The last argument should be the null character pointer.
 
705
  All attribute_value arguments MUST be NULL terminated strings.
 
706
  All attribute_value arguments will be quoted before output.
 
707
*/
 
708
 
 
709
static void print_xml_tag(FILE * xml_file, const char* sbeg,
 
710
                          const char* line_end,
 
711
                          const char* tag_name,
 
712
                          const char* first_attribute_name, ...)
 
713
{
 
714
  va_list arg_list;
 
715
  const char *attribute_name, *attribute_value;
 
716
 
 
717
  fputs(sbeg, xml_file);
 
718
  fputc('<', xml_file);
 
719
  fputs(tag_name, xml_file);
 
720
 
 
721
  va_start(arg_list, first_attribute_name);
 
722
  attribute_name= first_attribute_name;
 
723
  while (attribute_name != NULL)
 
724
  {
 
725
    attribute_value= va_arg(arg_list, char *);
 
726
    assert(attribute_value != NULL);
 
727
 
 
728
    fputc(' ', xml_file);
 
729
    fputs(attribute_name, xml_file);
 
730
    fputc('\"', xml_file);
 
731
 
 
732
    print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
 
733
    fputc('\"', xml_file);
 
734
 
 
735
    attribute_name= va_arg(arg_list, char *);
 
736
  }
 
737
  va_end(arg_list);
 
738
 
 
739
  fputc('>', xml_file);
 
740
  fputs(line_end, xml_file);
 
741
  check_io(xml_file);
 
742
}
 
743
 
 
744
 
 
745
/*
 
746
  Print xml tag with for a field that is null
 
747
 
 
748
  SYNOPSIS
 
749
  print_xml_null_tag()
 
750
  xml_file    - output file
 
751
  sbeg        - line beginning
 
752
  stag_atr    - tag and attribute
 
753
  sval        - value of attribute
 
754
  line_end        - line ending
 
755
 
 
756
  DESCRIPTION
 
757
  Print tag with one attribute to the xml_file. Format is:
 
758
  <stag_atr="sval" xsi:nil="true"/>
 
759
  NOTE
 
760
  sval MUST be a NULL terminated string.
 
761
  sval string will be qouted before output.
 
762
*/
 
763
 
 
764
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
 
765
                               const char* stag_atr, const char* sval,
 
766
                               const char* line_end)
 
767
{
 
768
  fputs(sbeg, xml_file);
 
769
  fputs("<", xml_file);
 
770
  fputs(stag_atr, xml_file);
 
771
  fputs("\"", xml_file);
 
772
  print_quoted_xml(xml_file, sval, strlen(sval));
 
773
  fputs("\" xsi:nil=\"true\" />", xml_file);
 
774
  fputs(line_end, xml_file);
 
775
  check_io(xml_file);
 
776
}
 
777
 
 
778
 
 
779
/*
 
780
  Print xml tag with many attributes.
 
781
 
 
782
  SYNOPSIS
 
783
  print_xml_row()
 
784
  xml_file    - output file
 
785
  row_name    - xml tag name
 
786
  tableRes    - query result
 
787
  row         - result row
 
788
 
 
789
  DESCRIPTION
 
790
  Print tag with many attribute to the xml_file. Format is:
 
791
  \t\t<row_name Atr1="Val1" Atr2="Val2"... />
 
792
  NOTE
 
793
  All atributes and values will be quoted before output.
 
794
*/
 
795
 
 
796
static void print_xml_row(FILE *xml_file, const char *row_name,
 
797
                          drizzle_result_st *tableRes, drizzle_row_t *row)
 
798
{
 
799
  uint32_t i;
 
800
  drizzle_column_st *column;
 
801
  size_t *lengths= drizzle_row_field_sizes(tableRes);
 
802
 
 
803
  fprintf(xml_file, "\t\t<%s", row_name);
 
804
  check_io(xml_file);
 
805
  drizzle_column_seek(tableRes, 0);
 
806
  for (i= 0; (column= drizzle_column_next(tableRes)); i++)
 
807
  {
 
808
    if ((*row)[i])
 
809
    {
 
810
      fputc(' ', xml_file);
 
811
      print_quoted_xml(xml_file, drizzle_column_name(column),
 
812
                       strlen(drizzle_column_name(column)));
 
813
      fputs("=\"", xml_file);
 
814
      print_quoted_xml(xml_file, (*row)[i], lengths[i]);
 
815
      fputc('"', xml_file);
 
816
      check_io(xml_file);
 
817
    }
 
818
  }
 
819
  fputs(" />\n", xml_file);
 
820
  check_io(xml_file);
 
821
}
 
822
 
 
823
 
 
824
/*
 
825
  Print hex value for blob data.
 
826
 
 
827
  SYNOPSIS
 
828
  print_blob_as_hex()
 
829
  output_file         - output file
 
830
  str                 - string to print
 
831
  len                 - its length
 
832
 
 
833
  DESCRIPTION
 
834
  Print hex value for blob data.
 
835
*/
 
836
 
 
837
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
 
838
{
 
839
  /* sakaik got the idea to to provide blob's in hex notation. */
 
840
  const char *ptr= str, *end= ptr + len;
 
841
  for (; ptr < end ; ptr++)
 
842
    fprintf(output_file, "%02X", *((unsigned char *)ptr));
 
843
  check_io(output_file);
 
844
}
 
845
 
 
846
/*
 
847
  get_table_structure -- retrievs database structure, prints out corresponding
 
848
  CREATE statement and fills out insert_pat if the table is the type we will
 
849
  be dumping.
 
850
 
 
851
  ARGS
 
852
  table       - table name
 
853
  db          - db name
 
854
  table_type  - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
 
855
  ignore_flag - what we must particularly ignore - see IGNORE_ defines above
 
856
  num_fields  - number of fields in the table
 
857
 
 
858
  RETURN
 
859
  true if success, false if error
 
860
*/
 
861
 
 
862
static bool get_table_structure(char *table, char *db, char *table_type,
 
863
                                char *ignore_flag, uint64_t *num_fields)
 
864
{
 
865
  bool    init=0, delayed, write_data, complete_insert;
 
866
  char       *result_table, *opt_quoted_table;
 
867
  const char *insert_option;
 
868
  char       name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE+3];
 
869
  char       table_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+3];
 
870
  char       table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3];
 
871
  char       query_buff[QUERY_LENGTH];
 
872
  FILE       *sql_file= md_result_file;
 
873
  drizzle_result_st result;
 
874
  drizzle_row_t  row;
 
875
 
 
876
  *ignore_flag= check_if_ignore_table(table, table_type);
 
877
 
 
878
  delayed= opt_delayed;
 
879
  if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
 
880
  {
 
881
    delayed= 0;
 
882
    verbose_msg(_("-- Warning: Unable to use delayed inserts for table '%s' "
 
883
                  "because it's of type %s\n"), table, table_type);
 
884
  }
 
885
 
 
886
  complete_insert= 0;
 
887
  if ((write_data= !(*ignore_flag & IGNORE_DATA)))
 
888
  {
 
889
    complete_insert= opt_complete_insert;
 
890
    insert_pat.clear();
 
891
  }
 
892
 
 
893
  insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
 
894
                  delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
 
895
 
 
896
  verbose_msg(_("-- Retrieving table structure for table %s...\n"), table);
 
897
 
 
898
  result_table=     quote_name(table, table_buff, 1);
 
899
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
900
 
 
901
  if (opt_order_by_primary)
 
902
  {
 
903
    free(order_by);
 
904
    order_by= primary_key_fields(result_table);
 
905
  }
 
906
 
 
907
  if (! opt_xml)
 
908
  { 
 
909
    /* using SHOW CREATE statement */
 
910
    if (! opt_no_create_info)
 
911
    { 
 
912
      /* Make an sql-file, if path was given iow. option -T was given */
 
913
      char buff[20+FN_REFLEN];
 
914
      const drizzle_column_st *column;
 
915
 
 
916
      snprintf(buff, sizeof(buff), "show create table %s", result_table);
 
917
 
 
918
      if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
919
        return false;
 
920
 
 
921
      if (! path.empty())
 
922
      {
 
923
        if (!(sql_file= open_sql_file_for_table(table)))
 
924
        {
 
925
          drizzle_result_free(&result);
 
926
          return false;
 
927
        }
 
928
 
 
929
        write_header(sql_file, db);
 
930
      }
 
931
      if (!opt_xml && opt_comments)
 
932
      {
 
933
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
934
                result_table);
 
935
        check_io(sql_file);
 
936
      }
 
937
      if (opt_drop)
 
938
      { 
 
939
        /*
 
940
          Even if the "table" is a view, we do a DROP TABLE here.
 
941
        */
 
942
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
 
943
        check_io(sql_file);
 
944
      }
 
945
 
 
946
      column= drizzle_column_index(&result, 0);
 
947
 
 
948
      row= drizzle_row_next(&result);
 
949
 
 
950
      fprintf(sql_file, "%s;\n", row[1]);
 
951
 
 
952
      check_io(sql_file);
 
953
      drizzle_result_free(&result);
 
954
    }
 
955
 
 
956
    snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
957
             result_table);
 
958
 
 
959
    if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
 
960
    {
 
961
      if (! path.empty())
 
962
        fclose(sql_file);
 
963
      return false;
 
964
    }
 
965
 
 
966
    /*
 
967
      If write_data is true, then we build up insert statements for
 
968
      the table's data. Note: in subsequent lines of code, this test
 
969
      will have to be performed each time we are appending to
 
970
      insert_pat.
 
971
    */
 
972
    if (write_data)
 
973
    {
 
974
      if (opt_replace_into)
 
975
        insert_pat.append("REPLACE ");
 
976
      else
 
977
        insert_pat.append("INSERT ");
 
978
      insert_pat.append(insert_option);
 
979
      insert_pat.append("INTO ");
 
980
      insert_pat.append(opt_quoted_table);
 
981
      if (complete_insert)
 
982
      {
 
983
        insert_pat.append(" (");
 
984
      }
 
985
      else
 
986
      {
 
987
        insert_pat.append(" VALUES ");
 
988
        if (!extended_insert)
 
989
          insert_pat.append("(");
 
990
      }
 
991
    }
 
992
 
 
993
    while ((row= drizzle_row_next(&result)))
 
994
    {
 
995
      if (complete_insert)
 
996
      {
 
997
        if (init)
 
998
        {
 
999
          insert_pat.append(", ");
 
1000
        }
 
1001
        init=1;
 
1002
        insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
1003
      }
 
1004
    }
 
1005
    *num_fields= drizzle_result_row_count(&result);
 
1006
    drizzle_result_free(&result);
 
1007
  }
 
1008
  else
 
1009
  {
 
1010
    verbose_msg(_("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n"),
 
1011
                progname.c_str(), drizzle_con_error(&dcon));
 
1012
 
 
1013
    snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
1014
             result_table);
 
1015
    if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
 
1016
      return false;
 
1017
 
 
1018
    /* Make an sql-file, if path was given iow. option -T was given */
 
1019
    if (! opt_no_create_info)
 
1020
    {
 
1021
      if (! path.empty())
 
1022
      {
 
1023
        if (!(sql_file= open_sql_file_for_table(table)))
 
1024
        {
 
1025
          drizzle_result_free(&result);
 
1026
          return false;
 
1027
        }
 
1028
        write_header(sql_file, db);
 
1029
      }
 
1030
      if (!opt_xml && opt_comments)
 
1031
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
1032
                result_table);
 
1033
      if (opt_drop)
 
1034
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
 
1035
      if (!opt_xml)
 
1036
        fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
 
1037
      else
 
1038
        print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
 
1039
                      NULL);
 
1040
      check_io(sql_file);
 
1041
    }
 
1042
 
 
1043
    if (write_data)
 
1044
    {
 
1045
      if (opt_replace_into)
 
1046
        insert_pat.append("REPLACE ");
 
1047
      else
 
1048
        insert_pat.append("INSERT ");
 
1049
      insert_pat.append(insert_option);
 
1050
      insert_pat.append("INTO ");
 
1051
      insert_pat.append(result_table);
 
1052
      if (complete_insert)
 
1053
        insert_pat.append(" (");
 
1054
      else
 
1055
      {
 
1056
        insert_pat.append(" VALUES ");
 
1057
        if (!extended_insert)
 
1058
          insert_pat.append("(");
 
1059
      }
 
1060
    }
 
1061
 
 
1062
    while ((row= drizzle_row_next(&result)))
 
1063
    {
 
1064
      size_t *lengths= drizzle_row_field_sizes(&result);
 
1065
      if (init)
 
1066
      {
 
1067
        if (!opt_xml && !opt_no_create_info)
 
1068
        {
 
1069
          fputs(",\n",sql_file);
 
1070
          check_io(sql_file);
 
1071
        }
 
1072
        if (complete_insert)
 
1073
          insert_pat.append(", ");
 
1074
      }
 
1075
      init=1;
 
1076
      if (complete_insert)
 
1077
        insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
1078
      if (!opt_no_create_info)
 
1079
      {
 
1080
        if (opt_xml)
 
1081
        {
 
1082
          print_xml_row(sql_file, "field", &result, &row);
 
1083
          continue;
 
1084
        }
 
1085
 
 
1086
        if (opt_keywords)
 
1087
          fprintf(sql_file, "  %s.%s %s", result_table,
 
1088
                  quote_name(row[SHOW_FIELDNAME],name_buff, 0),
 
1089
                  row[SHOW_TYPE]);
 
1090
        else
 
1091
          fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
 
1092
                                                  name_buff, 0),
 
1093
                  row[SHOW_TYPE]);
 
1094
        if (row[SHOW_DEFAULT])
 
1095
        {
 
1096
          fputs(" DEFAULT ", sql_file);
 
1097
          unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
 
1098
        }
 
1099
        if (!row[SHOW_NULL][0])
 
1100
          fputs(" NOT NULL", sql_file);
 
1101
        if (row[SHOW_EXTRA][0])
 
1102
          fprintf(sql_file, " %s",row[SHOW_EXTRA]);
 
1103
        check_io(sql_file);
 
1104
      }
 
1105
    }
 
1106
    *num_fields= drizzle_result_row_count(&result);
 
1107
    drizzle_result_free(&result);
 
1108
 
 
1109
    if (!opt_no_create_info)
 
1110
    {
 
1111
      /* Make an sql-file, if path was given iow. option -T was given */
 
1112
      char buff[20+FN_REFLEN];
 
1113
      uint32_t keynr,primary_key;
 
1114
      snprintf(buff, sizeof(buff), "show keys from %s", result_table);
 
1115
      if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
1116
      {
 
1117
        fprintf(stderr, _("%s: Can't get keys for table %s\n"),
 
1118
                progname.c_str(), result_table);
 
1119
        if (! path.empty())
 
1120
          fclose(sql_file);
 
1121
        return false;
 
1122
      }
 
1123
 
 
1124
      /* Find first which key is primary key */
 
1125
      keynr=0;
 
1126
      primary_key=INT_MAX;
 
1127
      while ((row= drizzle_row_next(&result)))
 
1128
      {
 
1129
        if (atoi(row[3]) == 1)
 
1130
        {
 
1131
          keynr++;
 
1132
#ifdef FORCE_PRIMARY_KEY
 
1133
          if (atoi(row[1]) == 0 && primary_key == INT_MAX)
 
1134
            primary_key=keynr;
 
1135
#endif
 
1136
          if (!strcmp(row[2],"PRIMARY"))
 
1137
          {
 
1138
            primary_key=keynr;
 
1139
            break;
 
1140
          }
 
1141
        }
 
1142
      }
 
1143
      drizzle_row_seek(&result,0);
 
1144
      keynr=0;
 
1145
      while ((row= drizzle_row_next(&result)))
 
1146
      {
 
1147
        if (opt_xml)
 
1148
        {
 
1149
          print_xml_row(sql_file, "key", &result, &row);
 
1150
          continue;
 
1151
        }
 
1152
 
 
1153
        if (atoi(row[3]) == 1)
 
1154
        {
 
1155
          if (keynr++)
 
1156
            putc(')', sql_file);
 
1157
          if (atoi(row[1]))       /* Test if duplicate key */
 
1158
            /* Duplicate allowed */
 
1159
            fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff,0));
 
1160
          else if (keynr == primary_key)
 
1161
            fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
 
1162
          else
 
1163
            fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff,
 
1164
                                                            0));
 
1165
        }
 
1166
        else
 
1167
          putc(',', sql_file);
 
1168
        fputs(quote_name(row[4], name_buff, 0), sql_file);
 
1169
        if (row[7])
 
1170
          fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
 
1171
        check_io(sql_file);
 
1172
      }
 
1173
      drizzle_result_free(&result);
 
1174
      if (!opt_xml)
 
1175
      {
 
1176
        if (keynr)
 
1177
          putc(')', sql_file);
 
1178
        fputs("\n)",sql_file);
 
1179
        check_io(sql_file);
 
1180
      }
 
1181
      /* Get DRIZZLE specific create options */
 
1182
      if (create_options)
 
1183
      {
 
1184
        char show_name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+2+24];
 
1185
 
 
1186
        /* Check memory for quote_for_like() */
 
1187
        snprintf(buff, sizeof(buff), "show table status like %s",
 
1188
                 quote_for_like(table, show_name_buff));
 
1189
 
 
1190
        if (!drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
1191
        {
 
1192
          if (!(row= drizzle_row_next(&result)))
 
1193
          {
 
1194
            fprintf(stderr,
 
1195
                    _("Error: Couldn't read status information for table %s\n"),
 
1196
                    result_table);
 
1197
          }
 
1198
          else
 
1199
          {
 
1200
            if (opt_xml)
 
1201
              print_xml_row(sql_file, "options", &result, &row);
 
1202
            else
 
1203
            {
 
1204
              fputs("/*!",sql_file);
 
1205
              print_value(sql_file,&result,row,"engine=","Engine",0);
 
1206
              print_value(sql_file,&result,row,"","Create_options",0);
 
1207
              print_value(sql_file,&result,row,"comment=","Comment",1);
 
1208
 
 
1209
              fputs(" */",sql_file);
 
1210
              check_io(sql_file);
 
1211
            }
 
1212
          }
 
1213
          drizzle_result_free(&result);
 
1214
        }
 
1215
      }
 
1216
      if (!opt_xml)
 
1217
        fputs(";\n", sql_file);
 
1218
      else
 
1219
        fputs("\t</table_structure>\n", sql_file);
 
1220
      check_io(sql_file);
 
1221
    }
 
1222
  }
 
1223
  if (complete_insert) {
 
1224
    insert_pat.append(") VALUES ");
 
1225
    if (!extended_insert)
 
1226
      insert_pat.append("(");
 
1227
  }
 
1228
  if (sql_file != md_result_file)
 
1229
  {
 
1230
    fputs("\n", sql_file);
 
1231
    write_footer(sql_file);
 
1232
    fclose(sql_file);
 
1233
  }
 
1234
  return true;
 
1235
} /* get_table_structure */
 
1236
 
 
1237
static void add_load_option(string &str, const char *option,
 
1238
                            const string &option_value)
 
1239
{
 
1240
  if (option_value.empty())
 
1241
  {
 
1242
    /* Null value means we don't add this option. */
 
1243
    return;
 
1244
  }
 
1245
 
 
1246
  str.append(option);
 
1247
 
 
1248
  if (option_value.compare(0, 2, "0x") == 0)
 
1249
  {
 
1250
    /* It's a hex constant, don't escape */
 
1251
    str.append(option_value);
 
1252
  }
 
1253
  else
 
1254
  {
 
1255
    /* char constant; escape */
 
1256
    field_escape(str, option_value);
 
1257
  }
 
1258
}
 
1259
 
 
1260
 
 
1261
/*
 
1262
  Allow the user to specify field terminator strings like:
 
1263
  "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
 
1264
  This is done by doubling ' and add a end -\ if needed to avoid
 
1265
  syntax errors from the SQL parser.
 
1266
*/
 
1267
 
 
1268
static void field_escape(string &in, const string &from)
 
1269
{
 
1270
  uint32_t end_backslashes= 0;
 
1271
 
 
1272
  in.append("'");
 
1273
 
 
1274
  string::const_iterator it= from.begin();
 
1275
  while (it != from.end())
 
1276
  {
 
1277
    in.push_back(*it);
 
1278
 
 
1279
    if (*it == '\\')
 
1280
      end_backslashes^= 1;    /* find odd number of backslashes */
 
1281
    else
 
1282
    {
 
1283
      if (*it == '\'' && !end_backslashes)
 
1284
      {
 
1285
        /* We want a duplicate of "'" for DRIZZLE */
 
1286
        in.push_back('\'');
 
1287
      }
 
1288
      end_backslashes=0;
 
1289
    }
 
1290
    ++it;
 
1291
  }
 
1292
  /* Add missing backslashes if user has specified odd number of backs.*/
 
1293
  if (end_backslashes)
 
1294
    in.append("\\");
 
1295
 
 
1296
  in.append("'");
 
1297
}
 
1298
 
 
1299
 
 
1300
 
 
1301
/*
 
1302
 
 
1303
  SYNOPSIS
 
1304
  dump_table()
 
1305
 
 
1306
  dump_table saves database contents as a series of INSERT statements.
 
1307
 
 
1308
  ARGS
 
1309
  table - table name
 
1310
  db    - db name
 
1311
 
 
1312
  RETURNS
 
1313
  void
 
1314
*/
 
1315
 
 
1316
 
 
1317
static void dump_table(char *table, char *db)
 
1318
{
 
1319
  char ignore_flag;
 
1320
  char table_buff[DRIZZLE_MAX_TABLE_SIZE+3];
 
1321
  string query_string;
 
1322
  char table_type[DRIZZLE_MAX_TABLE_SIZE];
 
1323
  char *result_table, table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3], *opt_quoted_table;
 
1324
  int error= 0;
 
1325
  uint32_t rownr, row_break, total_length, init_length;
 
1326
  uint64_t num_fields= 0;
 
1327
  drizzle_return_t ret;
 
1328
  drizzle_result_st result;
 
1329
  drizzle_column_st *column;
 
1330
  drizzle_row_t row;
 
1331
 
 
1332
 
 
1333
  /*
 
1334
    Make sure you get the create table info before the following check for
 
1335
    --no-data flag below. Otherwise, the create table info won't be printed.
 
1336
  */
 
1337
  if (!get_table_structure(table, db, table_type, &ignore_flag, &num_fields))
 
1338
  {
 
1339
    maybe_die(EX_TABLE_STATUS, _("Error retrieving table structure for table: \"%s\""), table);
 
1340
    return;
 
1341
  }
 
1342
 
 
1343
  /* Check --no-data flag */
 
1344
  if (opt_no_data)
 
1345
  {
 
1346
    verbose_msg(_("-- Skipping dump data for table '%s', --no-data was used\n"),
 
1347
                table);
 
1348
    return;
 
1349
  }
 
1350
 
 
1351
  /*
 
1352
    If the table type is a merge table or any type that has to be
 
1353
    _completely_ ignored and no data dumped
 
1354
  */
 
1355
  if (ignore_flag & IGNORE_DATA)
 
1356
  {
 
1357
    verbose_msg(_("-- Warning: Skipping data for table '%s' because " \
 
1358
                  "it's of type %s\n"), table, table_type);
 
1359
    return;
 
1360
  }
 
1361
  /* Check that there are any fields in the table */
 
1362
  if (num_fields == 0)
 
1363
  {
 
1364
    verbose_msg(_("-- Skipping dump data for table '%s', it has no fields\n"),
 
1365
                table);
 
1366
    return;
 
1367
  }
 
1368
 
 
1369
  result_table= quote_name(table,table_buff, 1);
 
1370
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
1371
 
 
1372
  verbose_msg(_("-- Sending SELECT query...\n"));
 
1373
 
 
1374
  query_string.clear();
 
1375
  query_string.reserve(1024);
 
1376
 
 
1377
  if (! path.empty())
 
1378
  {
 
1379
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
1380
 
 
1381
    /*
 
1382
      Convert the path to native os format
 
1383
      and resolve to the full filepath.
 
1384
    */
 
1385
    internal::convert_dirname(tmp_path,(char *)path.c_str(),NULL);
 
1386
    internal::my_load_path(tmp_path, tmp_path, NULL);
 
1387
    internal::fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
 
1388
 
 
1389
    /* Must delete the file that 'INTO OUTFILE' will write to */
 
1390
    internal::my_delete(filename, MYF(0));
 
1391
 
 
1392
    /* now build the query string */
 
1393
 
 
1394
    query_string.append( "SELECT * INTO OUTFILE '");
 
1395
    query_string.append( filename);
 
1396
    query_string.append( "'");
 
1397
 
 
1398
    if (! fields_terminated.empty() || ! enclosed.empty() || ! opt_enclosed.empty() || ! escaped.empty())
 
1399
      query_string.append( " FIELDS");
 
1400
 
 
1401
    add_load_option(query_string, " TERMINATED BY ", fields_terminated);
 
1402
    add_load_option(query_string, " ENCLOSED BY ", enclosed);
 
1403
    add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
 
1404
    add_load_option(query_string, " ESCAPED BY ", escaped);
 
1405
    add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
 
1406
 
 
1407
    query_string.append(" FROM ");
 
1408
    query_string.append(result_table);
 
1409
 
 
1410
    if (! where.empty())
 
1411
    {
 
1412
      query_string.append(" WHERE ");
 
1413
      query_string.append(where);
 
1414
    }
 
1415
 
 
1416
    if (order_by)
 
1417
    {
 
1418
      query_string.append(" ORDER BY ");
 
1419
      query_string.append(order_by);
 
1420
    }
 
1421
 
 
1422
    if (drizzle_query(&dcon, &result, query_string.c_str(),
 
1423
                      query_string.length(), &ret) == NULL ||
 
1424
        ret != DRIZZLE_RETURN_OK)
 
1425
    {
 
1426
      DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
 
1427
 
 
1428
      return;
 
1429
    }
 
1430
    drizzle_result_free(&result);
 
1431
  }
 
1432
 
 
1433
  else
 
1434
  {
 
1435
    if (!opt_xml && opt_comments)
 
1436
    {
 
1437
      fprintf(md_result_file,_("\n--\n-- Dumping data for table %s\n--\n"),
 
1438
              result_table);
 
1439
      check_io(md_result_file);
 
1440
    }
 
1441
 
 
1442
    query_string.append( "SELECT * FROM ");
 
1443
    query_string.append( result_table);
 
1444
 
 
1445
    if (! where.empty())
 
1446
    {
 
1447
      if (!opt_xml && opt_comments)
 
1448
      {
 
1449
        fprintf(md_result_file, "-- WHERE:  %s\n", where.c_str());
 
1450
        check_io(md_result_file);
 
1451
      }
 
1452
 
 
1453
      query_string.append( " WHERE ");
 
1454
      query_string.append( (char *)where.c_str());
 
1455
    }
 
1456
    if (order_by)
 
1457
    {
 
1458
      if (!opt_xml && opt_comments)
 
1459
      {
 
1460
        fprintf(md_result_file, "-- ORDER BY:  %s\n", order_by);
 
1461
        check_io(md_result_file);
 
1462
      }
 
1463
      query_string.append( " ORDER BY ");
 
1464
      query_string.append( order_by);
 
1465
    }
 
1466
 
 
1467
    if (!opt_xml && !opt_compact)
 
1468
    {
 
1469
      fputs("\n", md_result_file);
 
1470
      check_io(md_result_file);
 
1471
    }
 
1472
    if (drizzleclient_query_with_error_report(&dcon, &result,
 
1473
                                              query_string.c_str(), quick))
 
1474
    {
 
1475
      goto err;
 
1476
    }
 
1477
 
 
1478
    verbose_msg(_("-- Retrieving rows...\n"));
 
1479
    if (drizzle_result_column_count(&result) != num_fields)
 
1480
    {
 
1481
      fprintf(stderr,_("%s: Error in field count for table: %s !  Aborting.\n"),
 
1482
              progname.c_str(), result_table);
 
1483
      error= EX_CONSCHECK;
 
1484
      drizzle_result_free(&result);
 
1485
      goto err;
 
1486
    }
 
1487
 
 
1488
    /* Moved disable keys to after lock per bug 15977 */
 
1489
    if (opt_disable_keys)
 
1490
    {
 
1491
      fprintf(md_result_file, "ALTER TABLE %s DISABLE KEYS;\n",
 
1492
              opt_quoted_table);
 
1493
      check_io(md_result_file);
 
1494
    }
 
1495
    
 
1496
    total_length= DRIZZLE_MAX_LINE_LENGTH;                /* Force row break */
 
1497
    row_break=0;
 
1498
    rownr=0;
 
1499
    init_length=(uint32_t) insert_pat.length()+4;
 
1500
    if (opt_xml)
 
1501
      print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
 
1502
                    NULL);
 
1503
    if (opt_autocommit)
 
1504
    {
 
1505
      fprintf(md_result_file, "set autocommit=0;\n");
 
1506
      check_io(md_result_file);
 
1507
    }
 
1508
 
 
1509
    row= NULL;
 
1510
 
 
1511
    while (1)
 
1512
    {
 
1513
      uint32_t i;
 
1514
      size_t *lengths;
 
1515
 
 
1516
      if (quick)
 
1517
      {
 
1518
        if (row)
 
1519
          drizzle_row_free(&result, row);
 
1520
 
 
1521
        row= drizzle_row_buffer(&result, &ret);
 
1522
        if (ret != DRIZZLE_RETURN_OK)
 
1523
        {
 
1524
          fprintf(stderr,
 
1525
                  _("%s: Error reading rows for table: %s (%d:%s) ! Aborting.\n"),
 
1526
                  progname.c_str(), result_table, ret, drizzle_con_error(&dcon));
 
1527
          drizzle_result_free(&result);
 
1528
          goto err;
 
1529
        }
 
1530
      }
 
1531
      else
 
1532
        row= drizzle_row_next(&result);
 
1533
 
 
1534
      if (row == NULL)
 
1535
        break;
 
1536
 
 
1537
      lengths= drizzle_row_field_sizes(&result);
 
1538
 
 
1539
      rownr++;
 
1540
      if ((rownr % show_progress_size) == 0)
 
1541
      {
 
1542
        verbose_msg(_("-- %"PRIu32" of ~%"PRIu64" rows dumped for table %s\n"), rownr, total_rows, opt_quoted_table);
 
1543
      }
 
1544
      if (!extended_insert && !opt_xml)
 
1545
      {
 
1546
        fputs(insert_pat.c_str(),md_result_file);
 
1547
        check_io(md_result_file);
 
1548
      }
 
1549
      drizzle_column_seek(&result,0);
 
1550
 
 
1551
      if (opt_xml)
 
1552
      {
 
1553
        fputs("\t<row>\n", md_result_file);
 
1554
        check_io(md_result_file);
 
1555
      }
 
1556
 
 
1557
      for (i= 0; i < drizzle_result_column_count(&result); i++)
 
1558
      {
 
1559
        int is_blob;
 
1560
        uint32_t length= lengths[i];
 
1561
 
 
1562
        if (!(column= drizzle_column_next(&result)))
 
1563
          die(EX_CONSCHECK,
 
1564
              _("Not enough fields from table %s! Aborting.\n"),
 
1565
              result_table);
 
1566
 
 
1567
        /*
 
1568
          63 is my_charset_bin. If charsetnr is not 63,
 
1569
          we have not a BLOB but a TEXT column.
 
1570
          we'll dump in hex only BLOB columns.
 
1571
        */
 
1572
        is_blob= (opt_hex_blob && drizzle_column_charset(column) == 63 &&
 
1573
                  (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_VARCHAR ||
 
1574
                   drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_BLOB)) ? 1 : 0;
 
1575
        if (extended_insert && !opt_xml)
 
1576
        {
 
1577
          if (i == 0)
 
1578
          {
 
1579
            extended_row.clear();
 
1580
            extended_row.append("(");
 
1581
          }
 
1582
          else
 
1583
            extended_row.append(",");
 
1584
 
 
1585
          if (row[i])
 
1586
          {
 
1587
            if (length)
 
1588
            {
 
1589
              if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
 
1590
              {
 
1591
                /*
 
1592
                  "length * 2 + 2" is OK for both HEX and non-HEX modes:
 
1593
                  - In HEX mode we need exactly 2 bytes per character
 
1594
                  plus 2 bytes for '0x' prefix.
 
1595
                  - In non-HEX mode we need up to 2 bytes per character,
 
1596
                  plus 2 bytes for leading and trailing '\'' characters.
 
1597
                  Also we need to reserve 1 byte for terminating '\0'.
 
1598
                */
 
1599
                char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
 
1600
                memset(tmp_str, '\0', length * 2 + 2 + 1);
 
1601
                if (opt_hex_blob && is_blob)
 
1602
                {
 
1603
                  extended_row.append("0x");
 
1604
                  drizzle_hex_string(tmp_str, row[i], length);
 
1605
                  extended_row.append(tmp_str);
 
1606
                }
 
1607
                else
 
1608
                {
 
1609
                  extended_row.append("'");
 
1610
                  drizzle_escape_string(tmp_str, row[i],length);
 
1611
                  extended_row.append(tmp_str);
 
1612
                  extended_row.append("'");
 
1613
                }
 
1614
                free(tmp_str);
 
1615
              }
 
1616
              else
 
1617
              {
 
1618
                /* change any strings ("inf", "-inf", "nan") into NULL */
 
1619
                char *ptr= row[i];
 
1620
                if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
 
1621
                                                       my_isalpha(charset_info, ptr[1])))
 
1622
                  extended_row.append( "NULL");
 
1623
                else
 
1624
                {
 
1625
                  extended_row.append( ptr);
 
1626
                }
 
1627
              }
 
1628
            }
 
1629
            else
 
1630
              extended_row.append("''");
 
1631
          }
 
1632
          else
 
1633
            extended_row.append("NULL");
 
1634
        }
 
1635
        else
 
1636
        {
 
1637
          if (i && !opt_xml)
 
1638
          {
 
1639
            fputc(',', md_result_file);
 
1640
            check_io(md_result_file);
 
1641
          }
 
1642
          if (row[i])
 
1643
          {
 
1644
            if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
 
1645
            {
 
1646
              if (opt_xml)
 
1647
              {
 
1648
                if (opt_hex_blob && is_blob && length)
 
1649
                {
 
1650
                  /* Define xsi:type="xs:hexBinary" for hex encoded data */
 
1651
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
1652
                                drizzle_column_name(column), "xsi:type=", "xs:hexBinary", NULL);
 
1653
                  print_blob_as_hex(md_result_file, row[i], length);
 
1654
                }
 
1655
                else
 
1656
                {
 
1657
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
1658
                                drizzle_column_name(column), NULL);
 
1659
                  print_quoted_xml(md_result_file, row[i], length);
 
1660
                }
 
1661
                fputs("</field>\n", md_result_file);
 
1662
              }
 
1663
              else if (opt_hex_blob && is_blob && length)
 
1664
              {
 
1665
                fputs("0x", md_result_file);
 
1666
                print_blob_as_hex(md_result_file, row[i], length);
 
1667
              }
 
1668
              else
 
1669
                unescape(md_result_file, row[i], length);
 
1670
            }
 
1671
            else
 
1672
            {
 
1673
              /* change any strings ("inf", "-inf", "nan") into NULL */
 
1674
              char *ptr= row[i];
 
1675
              if (opt_xml)
 
1676
              {
 
1677
                print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
1678
                              drizzle_column_name(column), NULL);
 
1679
                fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
 
1680
                      md_result_file);
 
1681
                fputs("</field>\n", md_result_file);
 
1682
              }
 
1683
              else if (my_isalpha(charset_info, *ptr) ||
 
1684
                       (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
 
1685
                fputs("NULL", md_result_file);
 
1686
              else
 
1687
                fputs(ptr, md_result_file);
 
1688
            }
 
1689
          }
 
1690
          else
 
1691
          {
 
1692
            /* The field value is NULL */
 
1693
            if (!opt_xml)
 
1694
              fputs("NULL", md_result_file);
 
1695
            else
 
1696
              print_xml_null_tag(md_result_file, "\t\t", "field name=",
 
1697
                                 drizzle_column_name(column), "\n");
 
1698
          }
 
1699
          check_io(md_result_file);
 
1700
        }
 
1701
      }
 
1702
 
 
1703
      if (opt_xml)
 
1704
      {
 
1705
        fputs("\t</row>\n", md_result_file);
 
1706
        check_io(md_result_file);
 
1707
      }
 
1708
 
 
1709
      if (extended_insert)
 
1710
      {
 
1711
        uint32_t row_length;
 
1712
        extended_row.append(")");
 
1713
        row_length= 2 + extended_row.length();
 
1714
        if (total_length + row_length < DRIZZLE_MAX_LINE_LENGTH)
 
1715
        {
 
1716
          total_length+= row_length;
 
1717
          fputc(',',md_result_file);            /* Always row break */
 
1718
          fputs(extended_row.c_str(),md_result_file);
 
1719
        }
 
1720
        else
 
1721
        {
 
1722
          if (row_break)
 
1723
            fputs(";\n", md_result_file);
 
1724
          row_break=1;                          /* This is first row */
 
1725
 
 
1726
          fputs(insert_pat.c_str(),md_result_file);
 
1727
          fputs(extended_row.c_str(),md_result_file);
 
1728
          total_length= row_length+init_length;
 
1729
        }
 
1730
        check_io(md_result_file);
 
1731
      }
 
1732
      else if (!opt_xml)
 
1733
      {
 
1734
        fputs(");\n", md_result_file);
 
1735
        check_io(md_result_file);
 
1736
      }
 
1737
    }
 
1738
 
 
1739
    /* XML - close table tag and supress regular output */
 
1740
    if (opt_xml)
 
1741
      fputs("\t</table_data>\n", md_result_file);
 
1742
    else if (extended_insert && row_break)
 
1743
      fputs(";\n", md_result_file);             /* If not empty table */
 
1744
    fflush(md_result_file);
 
1745
    check_io(md_result_file);
 
1746
 
 
1747
    /* Moved enable keys to before unlock per bug 15977 */
 
1748
    if (opt_disable_keys)
 
1749
    {
 
1750
      fprintf(md_result_file,"ALTER TABLE %s ENABLE KEYS;\n",
 
1751
              opt_quoted_table);
 
1752
      check_io(md_result_file);
 
1753
    }
 
1754
    if (opt_autocommit)
 
1755
    {
 
1756
      fprintf(md_result_file, "commit;\n");
 
1757
      check_io(md_result_file);
 
1758
    }
 
1759
    drizzle_result_free(&result);
 
1760
  }
 
1761
  return;
 
1762
 
 
1763
err:
 
1764
  maybe_exit(error);
 
1765
  return;
 
1766
} /* dump_table */
 
1767
 
 
1768
 
 
1769
static char *getTableName(int reset)
 
1770
{
 
1771
  static drizzle_result_st result;
 
1772
  static bool have_result= false;
 
1773
  drizzle_row_t row;
 
1774
 
 
1775
  if (!have_result)
 
1776
  {
 
1777
    if (drizzleclient_query_with_error_report(&dcon, &result, "SHOW TABLES", false))
 
1778
      return NULL;
 
1779
    have_result= true;
 
1780
  }
 
1781
 
 
1782
  if ((row= drizzle_row_next(&result)))
 
1783
    return row[0];
 
1784
 
 
1785
  if (reset)
 
1786
    drizzle_row_seek(&result, 0);
 
1787
  else
 
1788
  {
 
1789
    drizzle_result_free(&result);
 
1790
    have_result= false;
 
1791
  }
 
1792
  return NULL;
 
1793
} /* getTableName */
 
1794
 
 
1795
 
364
1796
static int dump_all_databases()
365
1797
{
366
1798
  drizzle_row_t row;
367
 
  drizzle_result_st *tableres;
 
1799
  drizzle_result_st tableres;
368
1800
  int result=0;
369
 
  std::string query;
370
 
  DrizzleDumpDatabase *database;
371
 
 
372
 
  if (verbose)
373
 
    std::cerr << _("-- Retrieving database structures...") << std::endl;
374
 
 
375
 
  /* Blocking the MySQL privilege tables too because we can't import them due to bug#646187 */
376
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
377
 
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')";
378
 
  else
379
 
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM DATA_DICTIONARY.SCHEMAS WHERE SCHEMA_NAME NOT IN ('information_schema','data_dictionary')";
380
 
 
381
 
  tableres= db_connection->query(query);
382
 
  while ((row= drizzle_row_next(tableres)))
 
1801
 
 
1802
  if (drizzleclient_query_with_error_report(&dcon, &tableres, "SHOW DATABASES", false))
 
1803
    return 1;
 
1804
  while ((row= drizzle_row_next(&tableres)))
383
1805
  {
384
 
    std::string database_name(row[0]);
385
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
386
 
      database= new DrizzleDumpDatabaseMySQL(database_name, db_connection);
387
 
    else
388
 
      database= new DrizzleDumpDatabaseDrizzle(database_name, db_connection);
389
 
 
390
 
    database->setCollate(row[1]);
391
 
    database_store.push_back(database);
 
1806
    if (dump_all_tables_in_db(row[0]))
 
1807
      result=1;
392
1808
  }
393
 
  db_connection->freeResult(tableres);
 
1809
  drizzle_result_free(&tableres);
394
1810
  return result;
395
1811
}
396
1812
/* dump_all_databases */
400
1816
{
401
1817
  int result=0;
402
1818
  string temp;
403
 
  DrizzleDumpDatabase *database;
404
 
 
405
1819
  for (vector<string>::const_iterator it= db_names.begin(); it != db_names.end(); ++it)
406
1820
  {
407
1821
    temp= *it;
408
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
409
 
      database= new DrizzleDumpDatabaseMySQL(temp, db_connection);
410
 
    else
411
 
      database= new DrizzleDumpDatabaseDrizzle(temp, db_connection);
412
 
    database_store.push_back(database);
 
1822
    if (dump_all_tables_in_db((char *)temp.c_str()))
 
1823
      result=1;
413
1824
  }
414
1825
  return(result);
415
1826
} /* dump_databases */
416
1827
 
 
1828
 
 
1829
/*
 
1830
  Table Specific database initalization.
 
1831
 
 
1832
  SYNOPSIS
 
1833
  init_dumping_tables
 
1834
  qdatabase      quoted name of the database
 
1835
 
 
1836
  RETURN VALUES
 
1837
  0        Success.
 
1838
  1        Failure.
 
1839
*/
 
1840
 
 
1841
int init_dumping_tables(char *qdatabase)
 
1842
{
 
1843
  if (!opt_create_db)
 
1844
  {
 
1845
    char qbuf[256];
 
1846
    drizzle_row_t row;
 
1847
    drizzle_result_st result;
 
1848
    drizzle_return_t ret;
 
1849
 
 
1850
    snprintf(qbuf, sizeof(qbuf),
 
1851
             "SHOW CREATE DATABASE IF NOT EXISTS %s",
 
1852
             qdatabase);
 
1853
 
 
1854
    if (drizzle_query_str(&dcon, &result, qbuf, &ret) == NULL ||
 
1855
        ret != DRIZZLE_RETURN_OK)
 
1856
    {
 
1857
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
1858
        drizzle_result_free(&result);
 
1859
 
 
1860
      /* Old server version, dump generic CREATE DATABASE */
 
1861
      if (opt_drop_database)
 
1862
        fprintf(md_result_file,
 
1863
                "\nDROP DATABASE IF EXISTS %s;\n",
 
1864
                qdatabase);
 
1865
      fprintf(md_result_file,
 
1866
              "\nCREATE DATABASE IF NOT EXISTS %s;\n",
 
1867
              qdatabase);
 
1868
    }
 
1869
    else
 
1870
    {
 
1871
      if (drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
 
1872
      {
 
1873
        if (opt_drop_database)
 
1874
          fprintf(md_result_file,
 
1875
                  "\nDROP DATABASE IF EXISTS %s;\n",
 
1876
                  qdatabase);
 
1877
        row = drizzle_row_next(&result);
 
1878
        if (row != NULL && row[1])
 
1879
        {
 
1880
          fprintf(md_result_file,"\n%s;\n",row[1]);
 
1881
        }
 
1882
      }
 
1883
      drizzle_result_free(&result);
 
1884
    }
 
1885
  }
 
1886
  return(0);
 
1887
} /* init_dumping_tables */
 
1888
 
 
1889
 
 
1890
static int init_dumping(char *database, int init_func(char*))
 
1891
{
 
1892
  drizzle_result_st result;
 
1893
  drizzle_return_t ret;
 
1894
  char qbuf[512];
 
1895
  
 
1896
  /* If this DB contains non-standard tables we don't want it */
 
1897
 
 
1898
  snprintf(qbuf, sizeof(qbuf), "SELECT TABLE_NAME FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='%s' AND TABLE_TYPE != 'STANDARD'", database);
 
1899
  
 
1900
  if (drizzle_query_str(&dcon, &result, qbuf, &ret) != NULL)
 
1901
  {
 
1902
    drizzle_result_buffer(&result);
 
1903
    if (drizzle_result_row_count(&result) > 0)
 
1904
    {
 
1905
      drizzle_result_free(&result);
 
1906
      return 1;
 
1907
    }
 
1908
  }
 
1909
 
 
1910
  drizzle_result_free(&result);
 
1911
 
 
1912
  if (drizzle_select_db(&dcon, &result, database, &ret) == NULL ||
 
1913
      ret != DRIZZLE_RETURN_OK)
 
1914
  {
 
1915
    DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
 
1916
    return 1;                   /* If --force */
 
1917
  }
 
1918
  drizzle_result_free(&result);
 
1919
 
 
1920
  if (path.empty() && !opt_xml)
 
1921
  {
 
1922
    if (opt_databases || opt_alldbs)
 
1923
    {
 
1924
      /*
 
1925
        length of table name * 2 (if name contains quotes), 2 quotes and 0
 
1926
      */
 
1927
      char quoted_database_buf[DRIZZLE_MAX_DB_SIZE*2+3];
 
1928
      char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
 
1929
      if (opt_comments)
 
1930
      {
 
1931
        fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
 
1932
        check_io(md_result_file);
 
1933
      }
 
1934
 
 
1935
      /* Call the view or table specific function */
 
1936
      init_func(qdatabase);
 
1937
 
 
1938
      fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
 
1939
      check_io(md_result_file);
 
1940
    }
 
1941
  }
 
1942
  if (extended_insert)
 
1943
    extended_row.clear();
 
1944
  return 0;
 
1945
} /* init_dumping */
 
1946
 
 
1947
 
 
1948
/* Return 1 if we should copy the table */
 
1949
 
 
1950
static bool include_table(const char *hash_key, size_t key_size)
 
1951
{
 
1952
  string match(hash_key, key_size);
 
1953
  boost::unordered_set<string>::iterator iter= ignore_table.find(match);
 
1954
  return (iter == ignore_table.end());
 
1955
}
 
1956
 
 
1957
 
 
1958
static int dump_all_tables_in_db(char *database)
 
1959
{
 
1960
  char *table;
 
1961
  char hash_key[DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2];  /* "db.tablename" */
 
1962
  char *afterdot;
 
1963
  drizzle_result_st result;
 
1964
  drizzle_return_t ret;
 
1965
 
 
1966
  memset(hash_key, 0, DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2);
 
1967
  afterdot= strcpy(hash_key, database) + strlen(database);
 
1968
  *afterdot++= '.';
 
1969
 
 
1970
  if (init_dumping(database, init_dumping_tables))
 
1971
    return(1);
 
1972
  if (opt_xml)
 
1973
    print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NULL);
 
1974
  if (flush_logs)
 
1975
  {
 
1976
    if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
 
1977
        ret != DRIZZLE_RETURN_OK)
 
1978
    {
 
1979
      DB_error(&result, ret, _("when doing refresh"));
 
1980
      /* We shall continue here, if --force was given */
 
1981
    }
 
1982
    else
 
1983
      drizzle_result_free(&result);
 
1984
  }
 
1985
  while ((table= getTableName(0)))
 
1986
  {
 
1987
    char *end= strcpy(afterdot, table) + strlen(table);
 
1988
    if (include_table(hash_key, end - hash_key))
 
1989
    {
 
1990
      dump_table(table,database);
 
1991
      free(order_by);
 
1992
      order_by= 0;
 
1993
    }
 
1994
  }
 
1995
  if (opt_xml)
 
1996
  {
 
1997
    fputs("</database>\n", md_result_file);
 
1998
    check_io(md_result_file);
 
1999
  }
 
2000
 
 
2001
  return 0;
 
2002
} /* dump_all_tables_in_db */
 
2003
 
 
2004
 
 
2005
/*
 
2006
  get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
 
2007
  table name from the server for the table name given on the command line.
 
2008
  we do this because the table name given on the command line may be a
 
2009
  different case (e.g.  T1 vs t1)
 
2010
 
 
2011
  RETURN
 
2012
  pointer to the table name
 
2013
  0 if error
 
2014
*/
 
2015
 
 
2016
static char *get_actual_table_name(const char *old_table_name,
 
2017
                                   drizzled::memory::Root *root)
 
2018
{
 
2019
  char *name= 0;
 
2020
  drizzle_result_st result;
 
2021
  drizzle_row_t  row;
 
2022
  char query[50 + 2*DRIZZLE_MAX_TABLE_SIZE];
 
2023
  char show_name_buff[FN_REFLEN];
 
2024
  uint64_t num_rows;
 
2025
 
 
2026
 
 
2027
  /* Check memory for quote_for_like() */
 
2028
  assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
 
2029
  snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
 
2030
           quote_for_like(old_table_name, show_name_buff));
 
2031
 
 
2032
  if (drizzleclient_query_with_error_report(&dcon, &result, query, false))
 
2033
    return NULL;
 
2034
 
 
2035
  num_rows= drizzle_result_row_count(&result);
 
2036
  if (num_rows > 0)
 
2037
  {
 
2038
    size_t *lengths;
 
2039
    /*
 
2040
      Return first row
 
2041
      TODO-> Return all matching rows
 
2042
    */
 
2043
    row= drizzle_row_next(&result);
 
2044
    lengths= drizzle_row_field_sizes(&result);
 
2045
    name= root->strmake_root(row[0], lengths[0]);
 
2046
  }
 
2047
  drizzle_result_free(&result);
 
2048
 
 
2049
  return(name);
 
2050
}
 
2051
 
 
2052
 
417
2053
static int dump_selected_tables(const string &db, const vector<string> &table_names)
418
2054
{
419
 
  DrizzleDumpDatabase *database;
420
 
 
421
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
422
 
    database= new DrizzleDumpDatabaseMySQL(db, db_connection);
423
 
  else
424
 
    database= new DrizzleDumpDatabaseDrizzle(db, db_connection);
425
 
 
426
 
  if (not database->populateTables(table_names))
427
 
  {
428
 
    delete database;
429
 
    if (not ignore_errors)
430
 
      maybe_exit(EX_DRIZZLEERR);
431
 
  }
432
 
 
433
 
  database_store.push_back(database); 
434
 
 
 
2055
  drizzled::memory::Root root;
 
2056
  char **dump_tables, **pos, **end;
 
2057
  drizzle_result_st result;
 
2058
  drizzle_return_t ret;
 
2059
 
 
2060
 
 
2061
  if (init_dumping((char *)db.c_str(), init_dumping_tables))
 
2062
    return(1);
 
2063
 
 
2064
  root.init_alloc_root(8192);
 
2065
  if (!(dump_tables= pos= (char**) root.alloc_root(table_names.size() * sizeof(char *))))
 
2066
    die(EX_EOM, _("alloc_root failure."));
 
2067
 
 
2068
  for (vector<string>::const_iterator it= table_names.begin(); it != table_names.end(); ++it)
 
2069
  {
 
2070
    string temp= *it;
 
2071
    /* the table name passed on commandline may be wrong case */
 
2072
    if ((*pos= get_actual_table_name(temp.c_str(), &root)))
 
2073
    {
 
2074
      pos++;
 
2075
    }
 
2076
    else
 
2077
    {
 
2078
      if (!ignore_errors)
 
2079
      {
 
2080
        root.free_root(MYF(0));
 
2081
      }
 
2082
      maybe_die(EX_ILLEGAL_TABLE, _("Couldn't find table: \"%s\""),(char *) temp.c_str());
 
2083
      /* We shall countinue here, if --force was given */
 
2084
    }
 
2085
  }
 
2086
  end= pos;
 
2087
 
 
2088
  if (flush_logs)
 
2089
  {
 
2090
    if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
 
2091
        ret != DRIZZLE_RETURN_OK)
 
2092
    {
 
2093
      if (!ignore_errors)
 
2094
        root.free_root(MYF(0));
 
2095
      DB_error(&result, ret, _("when doing refresh"));
 
2096
      /* We shall countinue here, if --force was given */
 
2097
    }
 
2098
    else
 
2099
      drizzle_result_free(&result);
 
2100
  }
 
2101
  if (opt_xml)
 
2102
    print_xml_tag(md_result_file, "", "\n", "database", "name=", (char *)db.c_str(), NULL);
 
2103
 
 
2104
  /* Dump each selected table */
 
2105
  for (pos= dump_tables; pos < end; pos++)
 
2106
    dump_table(*pos, (char *)db.c_str());
 
2107
 
 
2108
  root.free_root(MYF(0));
 
2109
  free(order_by);
 
2110
  order_by= 0;
 
2111
  if (opt_xml)
 
2112
  {
 
2113
    fputs("</database>\n", md_result_file);
 
2114
    check_io(md_result_file);
 
2115
  }
435
2116
  return 0;
436
2117
} /* dump_selected_tables */
437
2118
 
438
 
static int do_flush_tables_read_lock()
 
2119
static int do_flush_tables_read_lock(drizzle_con_st *drizzle_con)
439
2120
{
440
2121
  /*
441
2122
    We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
445
2126
    and most client connections are stalled. Of course, if a second long
446
2127
    update starts between the two FLUSHes, we have that bad stall.
447
2128
  */
448
 
 
449
 
   db_connection->queryNoResult("FLUSH TABLES");
450
 
   db_connection->queryNoResult("FLUSH TABLES WITH READ LOCK");
451
 
 
452
 
  return 0;
453
 
}
454
 
 
455
 
static int do_unlock_tables()
456
 
{
457
 
  db_connection->queryNoResult("UNLOCK TABLES");
458
 
  return 0;
459
 
}
460
 
 
461
 
static int start_transaction()
462
 
{
463
 
  db_connection->queryNoResult("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ");
464
 
  db_connection->queryNoResult("START TRANSACTION WITH CONSISTENT SNAPSHOT");
465
 
  return 0;
 
2129
  return
 
2130
    ( drizzleclient_query_with_error_report(drizzle_con, 0, "FLUSH TABLES", false) ||
 
2131
      drizzleclient_query_with_error_report(drizzle_con, 0,
 
2132
                                            "FLUSH TABLES WITH READ LOCK", false) );
 
2133
}
 
2134
 
 
2135
static int do_unlock_tables(drizzle_con_st *drizzle_con)
 
2136
{
 
2137
  return drizzleclient_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES", false);
 
2138
}
 
2139
 
 
2140
static int start_transaction(drizzle_con_st *drizzle_con)
 
2141
{
 
2142
  return (drizzleclient_query_with_error_report(drizzle_con, 0,
 
2143
                                                "SET SESSION TRANSACTION ISOLATION "
 
2144
                                                "LEVEL REPEATABLE READ", false) ||
 
2145
          drizzleclient_query_with_error_report(drizzle_con, 0,
 
2146
                                                "START TRANSACTION "
 
2147
                                                "WITH CONSISTENT SNAPSHOT", false));
 
2148
}
 
2149
 
 
2150
 
 
2151
/* Print a value with a prefix on file */
 
2152
static void print_value(FILE *file, drizzle_result_st  *result, drizzle_row_t row,
 
2153
                        const char *prefix, const char *name,
 
2154
                        int string_value)
 
2155
{
 
2156
  drizzle_column_st *column;
 
2157
  drizzle_column_seek(result, 0);
 
2158
 
 
2159
  for ( ; (column= drizzle_column_next(result)) ; row++)
 
2160
  {
 
2161
    if (!strcmp(drizzle_column_name(column),name))
 
2162
    {
 
2163
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
2164
      {
 
2165
        fputc(' ',file);
 
2166
        fputs(prefix, file);
 
2167
        if (string_value)
 
2168
          unescape(file,row[0],(uint32_t) strlen(row[0]));
 
2169
        else
 
2170
          fputs(row[0], file);
 
2171
        check_io(file);
 
2172
        return;
 
2173
      }
 
2174
    }
 
2175
  }
 
2176
  return;                                       /* This shouldn't happen */
 
2177
} /* print_value */
 
2178
 
 
2179
/**
 
2180
 * Fetches a row from a result based on a field name
 
2181
 * Returns const char* of the data in that row or NULL if not found
 
2182
 */
 
2183
 
 
2184
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row, const char *name)
 
2185
{
 
2186
  drizzle_column_st *column;
 
2187
  drizzle_column_seek(result, 0);
 
2188
 
 
2189
  for ( ; (column= drizzle_column_next(result)) ; row++)
 
2190
  {
 
2191
    if (!strcmp(drizzle_column_name(column),name))
 
2192
    {
 
2193
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
2194
      {
 
2195
        drizzle_column_seek(result, 0);
 
2196
        return row[0];
 
2197
      }
 
2198
    }
 
2199
  }
 
2200
  drizzle_column_seek(result, 0);
 
2201
  return NULL;
 
2202
}
 
2203
 
 
2204
 
 
2205
/*
 
2206
  SYNOPSIS
 
2207
 
 
2208
  Check if we the table is one of the table types that should be ignored:
 
2209
  MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
 
2210
  If the table should be altogether ignored, it returns a true, false if it
 
2211
  should not be ignored. If the user has selected to use INSERT DELAYED, it
 
2212
  sets the value of the bool pointer supports_delayed_inserts to 0 if not
 
2213
  supported, 1 if it is supported.
 
2214
 
 
2215
  ARGS
 
2216
 
 
2217
  check_if_ignore_table()
 
2218
  table_name                  Table name to check
 
2219
  table_type                  Type of table
 
2220
 
 
2221
  GLOBAL VARIABLES
 
2222
  drizzle                       Drizzle connection
 
2223
  verbose                     Write warning messages
 
2224
 
 
2225
  RETURN
 
2226
  char (bit value)            See IGNORE_ values at top
 
2227
*/
 
2228
 
 
2229
char check_if_ignore_table(const char *table_name, char *table_type)
 
2230
{
 
2231
  char result= IGNORE_NONE;
 
2232
  char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
 
2233
  const char *number_of_rows= NULL;
 
2234
  drizzle_result_st res;
 
2235
  drizzle_row_t row;
 
2236
 
 
2237
  /* Check memory for quote_for_like() */
 
2238
  assert(2*sizeof(table_name) < sizeof(show_name_buff));
 
2239
  snprintf(buff, sizeof(buff), "show table status like %s",
 
2240
           quote_for_like(table_name, show_name_buff));
 
2241
  if (drizzleclient_query_with_error_report(&dcon, &res, buff, false))
 
2242
  {
 
2243
    return result;
 
2244
  }
 
2245
  if (!(row= drizzle_row_next(&res)))
 
2246
  {
 
2247
    fprintf(stderr,
 
2248
            _("Error: Couldn't read status information for table %s\n"),
 
2249
            table_name);
 
2250
    drizzle_result_free(&res);
 
2251
    return(result);                         /* assume table is ok */
 
2252
  }
 
2253
  else
 
2254
  {
 
2255
    if ((number_of_rows= fetch_named_row(&res, row, "Rows")) != NULL)
 
2256
    {
 
2257
      total_rows= strtoul(number_of_rows, NULL, 10);
 
2258
    }
 
2259
  }
 
2260
  /*
 
2261
    If the table type matches any of these, we do support delayed inserts.
 
2262
    Note-> we do not want to skip dumping this table if if is not one of
 
2263
    these types, but we do want to use delayed inserts in the dump if
 
2264
    the table type is _NOT_ one of these types
 
2265
  */
 
2266
  {
 
2267
    strncpy(table_type, row[1], DRIZZLE_MAX_TABLE_SIZE-1);
 
2268
    if (opt_delayed)
 
2269
    {
 
2270
      if (strcmp(table_type,"MyISAM") &&
 
2271
          strcmp(table_type,"ARCHIVE") &&
 
2272
          strcmp(table_type,"HEAP") &&
 
2273
          strcmp(table_type,"MEMORY"))
 
2274
        result= IGNORE_INSERT_DELAYED;
 
2275
    }
 
2276
  }
 
2277
  drizzle_result_free(&res);
 
2278
  return(result);
 
2279
}
 
2280
 
 
2281
 
 
2282
/*
 
2283
  Get string of comma-separated primary key field names
 
2284
 
 
2285
  SYNOPSIS
 
2286
  char *primary_key_fields(const char *table_name)
 
2287
  RETURNS     pointer to allocated buffer (must be freed by caller)
 
2288
  table_name  quoted table name
 
2289
 
 
2290
  DESCRIPTION
 
2291
  Use SHOW KEYS FROM table_name, allocate a buffer to hold the
 
2292
  field names, and then build that string and return the pointer
 
2293
  to that buffer.
 
2294
 
 
2295
  Returns NULL if there is no PRIMARY or UNIQUE key on the table,
 
2296
  or if there is some failure.  It is better to continue to dump
 
2297
  the table unsorted, rather than exit without dumping the data.
 
2298
*/
 
2299
 
 
2300
static char *primary_key_fields(const char *table_name)
 
2301
{
 
2302
  drizzle_result_st res;
 
2303
  drizzle_return_t ret;
 
2304
  drizzle_row_t  row;
 
2305
  /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
 
2306
  char show_keys_buff[15 + DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
 
2307
  uint32_t result_length= 0;
 
2308
  char *result= 0;
 
2309
  char buff[DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
 
2310
  char *quoted_field;
 
2311
 
 
2312
  snprintf(show_keys_buff, sizeof(show_keys_buff),
 
2313
           "SHOW KEYS FROM %s", table_name);
 
2314
  if (drizzle_query_str(&dcon, &res, show_keys_buff, &ret) == NULL ||
 
2315
      ret != DRIZZLE_RETURN_OK)
 
2316
  {
 
2317
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
2318
    {
 
2319
      fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
2320
                        " records are NOT sorted (%s)\n"),
 
2321
              table_name, drizzle_result_error(&res));
 
2322
      drizzle_result_free(&res);
 
2323
    }
 
2324
    else
 
2325
    {
 
2326
      fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
2327
                        " records are NOT sorted (%s)\n"),
 
2328
              table_name, drizzle_con_error(&dcon));
 
2329
    }
 
2330
 
 
2331
    return result;
 
2332
  }
 
2333
 
 
2334
  if (drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
2335
  {
 
2336
    fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
2337
                      " records are NOT sorted (%s)\n"),
 
2338
            table_name, drizzle_con_error(&dcon));
 
2339
    return result;
 
2340
  }
 
2341
 
 
2342
  /*
 
2343
   * Figure out the length of the ORDER BY clause result.
 
2344
   * Note that SHOW KEYS is ordered:  a PRIMARY key is always the first
 
2345
   * row, and UNIQUE keys come before others.  So we only need to check
 
2346
   * the first key, not all keys.
 
2347
 */
 
2348
  if ((row= drizzle_row_next(&res)) && atoi(row[1]) == 0)
 
2349
  {
 
2350
    /* Key is unique */
 
2351
    do
 
2352
    {
 
2353
      quoted_field= quote_name(row[4], buff, 0);
 
2354
      result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
 
2355
    } while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1);
 
2356
  }
 
2357
 
 
2358
  /* Build the ORDER BY clause result */
 
2359
  if (result_length)
 
2360
  {
 
2361
    char *end;
 
2362
    /* result (terminating \0 is already in result_length) */
 
2363
 
 
2364
    size_t result_length_alloc= result_length + 10;
 
2365
    result= (char *)malloc(result_length_alloc);
 
2366
    if (!result)
 
2367
    {
 
2368
      fprintf(stderr, _("Error: Not enough memory to store ORDER BY clause\n"));
 
2369
      drizzle_result_free(&res);
 
2370
      return result;
 
2371
    }
 
2372
    drizzle_row_seek(&res, 0);
 
2373
    row= drizzle_row_next(&res);
 
2374
    quoted_field= quote_name(row[4], buff, 0);
 
2375
    end= strcpy(result, quoted_field) + strlen(quoted_field);
 
2376
    result_length_alloc -= strlen(quoted_field);
 
2377
    while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1)
 
2378
    {
 
2379
      quoted_field= quote_name(row[4], buff, 0);
 
2380
      end+= snprintf(end, result_length_alloc, ",%s",quoted_field);
 
2381
      result_length_alloc -= strlen(quoted_field);
 
2382
    }
 
2383
  }
 
2384
 
 
2385
  drizzle_result_free(&res);
 
2386
  return result;
466
2387
}
467
2388
 
468
2389
int main(int argc, char **argv)
470
2391
try
471
2392
{
472
2393
  int exit_code;
473
 
 
474
 
#if defined(ENABLE_NLS)
475
 
# if defined(HAVE_LOCALE_H)
476
 
  setlocale(LC_ALL, "");
477
 
# endif
478
 
  bindtextdomain("drizzle7", LOCALEDIR);
479
 
  textdomain("drizzle7");
480
 
#endif
481
 
 
482
 
  po::options_description commandline_options(_("Options used only in command line"));
 
2394
  drizzle_result_st result;
 
2395
 
 
2396
  po::options_description commandline_options(N_("Options used only in command line"));
483
2397
  commandline_options.add_options()
484
2398
  ("all-databases,A", po::value<bool>(&opt_alldbs)->default_value(false)->zero_tokens(),
485
 
  _("Dump all the databases. This will be same as --databases with all databases selected."))
 
2399
  N_("Dump all the databases. This will be same as --databases with all databases selected."))
486
2400
  ("all-tablespaces,Y", po::value<bool>(&opt_alltspcs)->default_value(false)->zero_tokens(),
487
 
  _("Dump all the tablespaces."))
 
2401
  N_("Dump all the tablespaces."))
488
2402
  ("complete-insert,c", po::value<bool>(&opt_complete_insert)->default_value(false)->zero_tokens(),
489
 
  _("Use complete insert statements."))
 
2403
  N_("Use complete insert statements."))
 
2404
  ("compress,C", po::value<bool>(&opt_compress)->default_value(false)->zero_tokens(),
 
2405
  N_("Use compression in server/client protocol."))
490
2406
  ("flush-logs,F", po::value<bool>(&flush_logs)->default_value(false)->zero_tokens(),
491
 
  _("Flush logs file in server before starting dump. Note that if you dump many databases at once (using the option --databases= or --all-databases), the logs will be flushed for each database dumped. The exception is when using --lock-all-tables in this case the logs will be flushed only once, corresponding to the moment all tables are locked. So if you want your dump and the log flush to happen at the same exact moment you should use --lock-all-tables or --flush-logs"))
 
2407
  N_("Flush logs file in server before starting dump. Note that if you dump many databases at once (using the option --databases= or --all-databases), the logs will be flushed for each database dumped. The exception is when using --lock-all-tables in this case the logs will be flushed only once, corresponding to the moment all tables are locked. So if you want your dump and the log flush to happen at the same exact moment you should use --lock-all-tables or --flush-logs"))
492
2408
  ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
493
 
  _("Continue even if we get an sql-error."))
494
 
  ("help,?", _("Display this help message and exit."))
 
2409
  N_("Continue even if we get an sql-error."))
 
2410
  ("help,?", N_("Display this help message and exit."))
495
2411
  ("lock-all-tables,x", po::value<bool>(&opt_lock_all_tables)->default_value(false)->zero_tokens(),
496
 
  _("Locks all tables across all databases. This is achieved by taking a global read lock for the duration of the whole dump. Automatically turns --single-transaction off."))
 
2412
  N_("Locks all tables across all databases. This is achieved by taking a global read lock for the duration of the whole dump. Automatically turns --single-transaction and --lock-tables off."))
 
2413
  ("order-by-primary", po::value<bool>(&opt_order_by_primary)->default_value(false)->zero_tokens(),
 
2414
  N_("Sorts each table's rows by primary key, or first unique key, if such a key exists.  Useful when dumping a MyISAM table to be loaded into an InnoDB table, but will make the dump itself take considerably longer."))
497
2415
  ("single-transaction", po::value<bool>(&opt_single_transaction)->default_value(false)->zero_tokens(),
498
 
  _("Creates a consistent snapshot by dumping all tables in a single transaction. Works ONLY for tables stored in storage engines which support multiversioning (currently only InnoDB does); the dump is NOT guaranteed to be consistent for other storage engines. While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents), no other connection should use the following statements: ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not isolated from them."))
 
2416
  N_("Creates a consistent snapshot by dumping all tables in a single transaction. Works ONLY for tables stored in storage engines which support multiversioning (currently only InnoDB does); the dump is NOT guaranteed to be consistent for other storage engines. While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents), no other connection should use the following statements: ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not isolated from them. Option automatically turns off --lock-tables."))
 
2417
  ("opt", N_("Same as --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys. Enabled by default, disable with --skip-opt.")) 
499
2418
  ("skip-opt", 
500
 
  _("Disable --opt. Disables --add-drop-table, --add-locks, --create-options, ---extended-insert and --disable-keys."))    
501
 
  ("tables", _("Overrides option --databases (-B)."))
 
2419
  N_("Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys."))    
 
2420
  ("tables", N_("Overrides option --databases (-B)."))
502
2421
  ("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(10000),
503
 
  _("Number of rows before each output progress report (requires --verbose)."))
 
2422
  N_("Number of rows before each output progress report (requires --verbose)."))
504
2423
  ("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
505
 
  _("Print info about the various stages."))
506
 
  ("version,V", _("Output version information and exit."))
507
 
  ("skip-comments", _("Turn off Comments"))
508
 
  ("skip-create", _("Turn off create-options"))
509
 
  ("skip-extended-insert", _("Turn off extended-insert"))
510
 
  ("skip-dump-date", _( "Turn off dump date at the end of the output"))
511
 
  ("no-defaults", _("Do not read from the configuration files"))
 
2424
  N_("Print info about the various stages."))
 
2425
  ("version,V", N_("Output version information and exit."))
 
2426
  ("xml,X", N_("Dump a database as well formed XML."))
 
2427
  ("skip-comments", N_("Turn off Comments"))
 
2428
  ("skip-create", N_("Turn off create-options"))
 
2429
  ("skip-extended-insert", N_("Turn off extended-insert"))
 
2430
  ("skip-dump-date",N_( "Turn off dump-date"))
 
2431
  ("no-defaults", N_("Do not read from the configuration files"))
512
2432
  ;
513
2433
 
514
 
  po::options_description dump_options(_("Options specific to the drizzle client"));
 
2434
  po::options_description dump_options(N_("Options specific to the drizzle client"));
515
2435
  dump_options.add_options()
516
2436
  ("add-drop-database", po::value<bool>(&opt_drop_database)->default_value(false)->zero_tokens(),
517
 
  _("Add a 'DROP DATABASE' before each create."))
518
 
  ("skip-drop-table", _("Do not add a 'drop table' before each create."))
 
2437
  N_("Add a 'DROP DATABASE' before each create."))
 
2438
  ("add-drop-table", po::value<bool>(&opt_drop)->default_value(true)->zero_tokens(),
 
2439
  N_("Add a 'drop table' before each create."))
 
2440
  ("allow-keywords", po::value<bool>(&opt_keywords)->default_value(false)->zero_tokens(),
 
2441
  N_("Allow creation of column names that are keywords."))
 
2442
  ("comments,i", po::value<bool>(&opt_comments)->default_value(true)->zero_tokens(),
 
2443
  N_("Write additional information."))
519
2444
  ("compact", po::value<bool>(&opt_compact)->default_value(false)->zero_tokens(),
520
 
  _("Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs.  Enables options --skip-add-drop-table --no-set-names --skip-disable-keys"))
 
2445
  N_("Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs.  Enables options --skip-add-drop-table --no-set-names --skip-disable-keys --skip-add-locks"))
 
2446
  ("create-options", po::value<bool>(&create_options)->default_value(true)->zero_tokens(),
 
2447
  N_("Include all DRIZZLE specific create options."))
 
2448
  ("dump-date", po::value<bool>(&opt_dump_date)->default_value(true)->zero_tokens(),
 
2449
  N_("Put a dump date to the end of the output."))
521
2450
  ("databases,B", po::value<bool>(&opt_databases)->default_value(false)->zero_tokens(),
522
 
  _("To dump several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames. 'USE db_name;' will be included in the output."))
523
 
  ("skip-disable-keys,K",
524
 
  _("'ALTER TABLE tb_name DISABLE KEYS;' and 'ALTER TABLE tb_name ENABLE KEYS;' will not be put in the output."))
 
2451
  N_("To dump several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames. 'USE db_name;' will be included in the output."))
 
2452
  ("delayed-insert", po::value<bool>(&opt_delayed)->default_value(false)->zero_tokens(),
 
2453
  N_("Insert rows with INSERT DELAYED;"))
 
2454
  ("disable-keys,K", po::value<bool>(&opt_disable_keys)->default_value(true)->zero_tokens(),
 
2455
  N_("'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will be put in the output."))
 
2456
  ("extended-insert,e", po::value<bool>(&extended_insert)->default_value(true)->zero_tokens(),
 
2457
  N_("Allows utilization of the new, much faster INSERT syntax."))
 
2458
  ("fields-terminated-by", po::value<string>(&fields_terminated)->default_value(""),
 
2459
  N_("Fields in the textfile are terminated by ..."))
 
2460
  ("fields-enclosed-by", po::value<string>(&enclosed)->default_value(""),
 
2461
  N_("Fields in the importfile are enclosed by ..."))
 
2462
  ("fields-optionally-enclosed-by", po::value<string>(&opt_enclosed)->default_value(""),
 
2463
  N_("Fields in the i.file are opt. enclosed by ..."))
 
2464
  ("fields-escaped-by", po::value<string>(&escaped)->default_value(""),
 
2465
  N_("Fields in the i.file are escaped by ..."))
 
2466
  ("hex-blob", po::value<bool>(&opt_hex_blob)->default_value(false)->zero_tokens(),
 
2467
  "Dump binary strings (BINARY, VARBINARY, BLOB) in hexadecimal format.")
525
2468
  ("ignore-table", po::value<string>(),
526
 
  _("Do not dump the specified table. To specify more than one table to ignore, use the directive multiple times, once for each table.  Each table must be specified with both database and table names, e.g. --ignore-table=database.table"))
 
2469
  N_("Do not dump the specified table. To specify more than one table to ignore, use the directive multiple times, once for each table.  Each table must be specified with both database and table names, e.g. --ignore-table=database.table"))
527
2470
  ("insert-ignore", po::value<bool>(&opt_ignore)->default_value(false)->zero_tokens(),
528
 
  _("Insert rows with INSERT IGNORE."))
 
2471
  N_("Insert rows with INSERT IGNORE."))
 
2472
  ("lines-terminated-by", po::value<string>(&lines_terminated)->default_value(""),
 
2473
  N_("Lines in the i.file are terminated by ..."))
529
2474
  ("no-autocommit", po::value<bool>(&opt_autocommit)->default_value(false)->zero_tokens(),
530
 
  _("Wrap a table's data in START TRANSACTION/COMMIT statements."))
 
2475
  N_("Wrap tables with autocommit/commit statements."))
531
2476
  ("no-create-db,n", po::value<bool>(&opt_create_db)->default_value(false)->zero_tokens(),
532
 
  _("'CREATE DATABASE IF NOT EXISTS db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given."))
 
2477
  N_("'CREATE DATABASE IF NOT EXISTS db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given."))
 
2478
  ("no-create-info,t", po::value<bool>(&opt_no_create_info)->default_value(false)->zero_tokens(),
 
2479
  N_("Don't write table creation info."))
533
2480
  ("no-data,d", po::value<bool>(&opt_no_data)->default_value(false)->zero_tokens(),
534
 
  _("No row information."))
 
2481
  N_("No row information."))
 
2482
  ("no-set-names,N", N_("Deprecated. Use --skip-set-charset instead."))
 
2483
  ("set-charset", po::value<bool>(&opt_set_charset)->default_value(false)->zero_tokens(),
 
2484
  N_("Enable set-name"))
 
2485
  ("quick,q", po::value<bool>(&quick)->default_value(true)->zero_tokens(),
 
2486
  N_("Don't buffer query, dump directly to stdout."))
 
2487
  ("quote-names,Q", po::value<bool>(&opt_quoted)->default_value(true)->zero_tokens(),
 
2488
  N_("Quote table and column names with backticks (`)."))
535
2489
  ("replace", po::value<bool>(&opt_replace_into)->default_value(false)->zero_tokens(),
536
 
  _("Use REPLACE INTO instead of INSERT INTO."))
537
 
  ("destination-type", po::value<string>()->default_value("stdout"),
538
 
  _("Where to send output to (stdout|database"))
539
 
  ("destination-host", po::value<string>(&opt_destination_host)->default_value("localhost"),
540
 
  _("Hostname for destination db server (requires --destination-type=database)"))
541
 
  ("destination-port", po::value<uint16_t>(&opt_destination_port)->default_value(4427),
542
 
  _("Port number for destination db server (requires --destination-type=database)"))
543
 
  ("destination-user", po::value<string>(&opt_destination_user),
544
 
  _("User name for destination db server (resquires --destination-type=database)"))
545
 
  ("destination-password", po::value<string>(&opt_destination_password),
546
 
  _("Password for destination db server (requires --destination-type=database)"))
547
 
  ("destination-database", po::value<string>(&opt_destination_database),
548
 
  _("The database in the destination db server (requires --destination-type=database, not for use with --all-databases)"))
549
 
  ("my-data-is-mangled", po::value<bool>(&opt_data_is_mangled)->default_value(false)->zero_tokens(),
550
 
  _("Do not make a UTF8 connection to MySQL, use if you have UTF8 data in a non-UTF8 table"))
 
2490
  N_("Use REPLACE INTO instead of INSERT INTO."))
 
2491
  ("result-file,r", po::value<string>(),
 
2492
  N_("Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed)."))
 
2493
  ("tab,T", po::value<string>(&path)->default_value(""),
 
2494
  N_("Creates tab separated textfile for each table to given path. (creates .sql and .txt files). NOTE: This only works if drizzledump is run on the same machine as the drizzled daemon."))
 
2495
  ("where,w", po::value<string>(&where)->default_value(""),
 
2496
  N_("Dump only selected records; QUOTES mandatory!"))
551
2497
  ;
552
2498
 
553
 
  po::options_description client_options(_("Options specific to the client"));
 
2499
  po::options_description client_options(N_("Options specific to the client"));
554
2500
  client_options.add_options()
555
2501
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
556
 
  _("Connect to host."))
 
2502
  N_("Connect to host."))
557
2503
  ("password,P", po::value<string>(&password)->default_value(PASSWORD_SENTINEL),
558
 
  _("Password to use when connecting to server. If password is not given it's solicited on the tty."))
 
2504
  N_("Password to use when connecting to server. If password is not given it's solicited on the tty."))
559
2505
  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
560
 
  _("Port number to use for connection."))
 
2506
  N_("Port number to use for connection."))
561
2507
  ("user,u", po::value<string>(&current_user)->default_value(""),
562
 
  _("User for login if not current user."))
 
2508
  N_("User for login if not current user."))
563
2509
  ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
564
 
  _("The protocol of connection (mysql or drizzle)."))
 
2510
  N_("The protocol of connection (mysql or drizzle)."))
565
2511
  ;
566
2512
 
567
 
  po::options_description hidden_options(_("Hidden Options"));
 
2513
  po::options_description hidden_options(N_("Hidden Options"));
568
2514
  hidden_options.add_options()
569
 
  ("database-used", po::value<vector<string> >(), _("Used to select the database"))
570
 
  ("Table-used", po::value<vector<string> >(), _("Used to select the tables"))
 
2515
  ("database-used", po::value<vector<string> >(), N_("Used to select the database"))
 
2516
  ("Table-used", po::value<vector<string> >(), N_("Used to select the tables"))
571
2517
  ;
572
2518
 
573
 
  po::options_description all_options(_("Allowed Options + Hidden Options"));
 
2519
  po::options_description all_options(N_("Allowed Options + Hidden Options"));
574
2520
  all_options.add(commandline_options).add(dump_options).add(client_options).add(hidden_options);
575
2521
 
576
 
  po::options_description long_options(_("Allowed Options"));
 
2522
  po::options_description long_options(N_("Allowed Options"));
577
2523
  long_options.add(commandline_options).add(dump_options).add(client_options);
578
2524
 
579
2525
  std::string system_config_dir_dump(SYSCONFDIR); 
584
2530
 
585
2531
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
586
2532
 
587
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
588
 
  {
589
 
    char *homedir;
590
 
    homedir= getenv("HOME");
591
 
    if (homedir != NULL)
592
 
      user_config_dir.replace(0, 1, homedir);
593
 
  }
594
 
 
595
2533
  po::positional_options_description p;
596
2534
  p.add("database-used", 1);
597
2535
  p.add("Table-used",-1);
600
2538
 
601
2539
  po::variables_map vm;
602
2540
 
603
 
  // Disable allow_guessing
604
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
605
 
 
606
 
  po::store(po::command_line_parser(argc, argv).style(style).
607
 
            options(all_options).positional(p).
608
 
            extra_parser(parse_password_arg).run(), vm);
 
2541
  po::store(po::command_line_parser(argc, argv).options(all_options).
 
2542
            positional(p).extra_parser(parse_password_arg).run(), vm);
609
2543
 
610
2544
  if (! vm.count("no-defaults"))
611
2545
  {
652
2586
      exit(1);
653
2587
  }
654
2588
 
655
 
  /* Inverted Booleans */
656
 
 
657
 
  opt_drop= (vm.count("skip-drop-table")) ? false : true;
658
 
  opt_comments= (vm.count("skip-comments")) ? false : true;
659
 
  extended_insert= (vm.count("skip-extended-insert")) ? false : true;
660
 
  opt_dump_date= (vm.count("skip-dump-date")) ? false : true;
661
 
  opt_disable_keys= (vm.count("skip-disable-keys")) ? false : true;
662
 
  opt_quoted= (vm.count("skip-quote-names")) ? false : true;
663
 
 
664
2589
  if (vm.count("protocol"))
665
2590
  {
666
2591
    std::transform(opt_protocol.begin(), opt_protocol.end(),
709
2634
      tty_password= true;
710
2635
  }
711
2636
 
 
2637
  if (vm.count("result-file"))
 
2638
  {
 
2639
    if (!(md_result_file= fopen(vm["result-file"].as<string>().c_str(), "w")))
 
2640
      exit(1);
 
2641
  }
 
2642
 
 
2643
  if (vm.count("no-set-names"))
 
2644
  {
 
2645
    opt_set_charset= 0;
 
2646
  }
 
2647
 
712
2648
  if (! path.empty())
713
2649
  { 
714
2650
    opt_disable_keys= 0;
715
 
  }
716
 
 
 
2651
 
 
2652
    if (vm["tab"].as<string>().length() >= FN_REFLEN)
 
2653
    {
 
2654
      /*
 
2655
        This check is made because the some the file functions below
 
2656
        have FN_REFLEN sized stack allocated buffers and will cause
 
2657
        a crash even if the input destination buffer is large enough
 
2658
        to hold the output.
 
2659
      */
 
2660
      fprintf(stderr, _("Input filename too long: %s"), vm["tab"].as<string>().c_str());
 
2661
      exit(EXIT_ARGUMENT_INVALID);
 
2662
    }
 
2663
  }
 
2664
 
 
2665
  if (vm.count("xml"))
 
2666
  { 
 
2667
    opt_xml= 1;
 
2668
    extended_insert= opt_drop= opt_disable_keys= opt_autocommit= opt_create_db= 0;
 
2669
  }
 
2670
  
717
2671
  if (vm.count("skip-opt"))
718
2672
  {
719
 
    extended_insert= opt_drop= create_options= 0;
720
 
    opt_disable_keys= 0;
 
2673
    extended_insert= opt_drop= quick= create_options= 0;
 
2674
    opt_disable_keys= opt_set_charset= 0;
721
2675
  }
722
2676
 
723
2677
  if (opt_compact)
724
2678
  { 
725
2679
    opt_comments= opt_drop= opt_disable_keys= 0;
 
2680
    opt_set_charset= 0;
726
2681
  }
727
2682
 
728
2683
  if (vm.count("opt"))
729
2684
  {
730
 
    extended_insert= opt_drop= create_options= 1;
731
 
    opt_disable_keys= 1;
 
2685
    extended_insert= opt_drop= quick= create_options= 1;
 
2686
    opt_disable_keys= opt_set_charset= 1;
732
2687
  }
733
2688
 
734
2689
  if (vm.count("tables"))
746
2701
    string tmpptr(vm["ignore-table"].as<string>());
747
2702
    ignore_table.insert(tmpptr); 
748
2703
  }
749
 
 
 
2704
  
750
2705
  if (vm.count("skip-create"))
751
2706
  {
752
2707
    opt_create_db= opt_no_create_info= create_options= false;
753
2708
  }
754
 
 
 
2709
 
 
2710
  if (vm.count("skip-comments"))
 
2711
  {
 
2712
    opt_comments= false; 
 
2713
  }
 
2714
 
 
2715
  if (vm.count("skip-extended-insert"))
 
2716
  {
 
2717
    extended_insert= false; 
 
2718
  }
 
2719
 
 
2720
  if (vm.count("skip-dump-date"))
 
2721
  {
 
2722
    opt_dump_date= false; 
 
2723
  } 
 
2724
 
755
2725
  exit_code= get_options();
756
2726
  if (exit_code)
757
2727
  {
758
2728
    free_resources();
759
2729
    exit(exit_code);
760
2730
  }
761
 
  try
762
 
  {
763
 
    db_connection = new DrizzleDumpConnection(current_host, opt_drizzle_port,
764
 
      current_user, opt_password, use_drizzle_protocol);
765
 
  }
766
 
  catch (std::exception&)
767
 
  {
768
 
    maybe_exit(EX_DRIZZLEERR);
769
 
  }
770
 
 
771
 
  if ((db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND) and (not opt_data_is_mangled))
772
 
    db_connection->queryNoResult("SET NAMES 'utf8'");
773
 
 
774
 
  if (vm.count("destination-type"))
775
 
  {
776
 
    string tmp_destination(vm["destination-type"].as<string>());
777
 
    if (tmp_destination.compare("database") == 0)
778
 
      opt_destination= DESTINATION_DB;
779
 
    else if (tmp_destination.compare("stdout") == 0)
780
 
      opt_destination= DESTINATION_STDOUT;
781
 
    else
782
 
      exit(EXIT_ARGUMENT_INVALID);
783
 
  }
784
 
 
785
 
 
 
2731
 
 
2732
  if (connect_to_db(current_host, current_user, opt_password))
 
2733
  {
 
2734
    free_resources();
 
2735
    exit(EX_DRIZZLEERR);
 
2736
  }
786
2737
  if (path.empty() && vm.count("database-used"))
787
2738
  {
788
2739
    string database_used= *vm["database-used"].as< vector<string> >().begin();
789
 
    write_header((char *)database_used.c_str());
 
2740
    write_header(md_result_file, (char *)database_used.c_str());
790
2741
  }
791
2742
 
792
 
  if ((opt_lock_all_tables) && do_flush_tables_read_lock())
 
2743
  if ((opt_lock_all_tables) && do_flush_tables_read_lock(&dcon))
793
2744
    goto err;
794
 
  if (opt_single_transaction && start_transaction())
 
2745
  if (opt_single_transaction && start_transaction(&dcon))
795
2746
    goto err;
796
2747
  if (opt_lock_all_tables)
797
 
    db_connection->queryNoResult("FLUSH LOGS");
798
 
  if (opt_single_transaction && do_unlock_tables()) /* unlock but no commit! */
 
2748
  {
 
2749
    if (drizzleclient_query_with_error_report(&dcon, &result, "FLUSH LOGS", false))
 
2750
      goto err;
 
2751
    drizzle_result_free(&result);
 
2752
    flush_logs= 0; /* not anymore; that would not be sensible */
 
2753
  }
 
2754
  if (opt_single_transaction && do_unlock_tables(&dcon)) /* unlock but no commit! */
799
2755
    goto err;
800
2756
 
801
2757
  if (opt_alldbs)
802
2758
  {
803
2759
    dump_all_databases();
804
 
    dump_all_tables();
805
2760
  }
806
2761
  if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
807
2762
  {
810
2765
    dump_selected_tables(database_used, vm["Table-used"].as< vector<string> >());
811
2766
  }
812
2767
 
813
 
  if (vm.count("Table-used") and opt_databases)
 
2768
  if (vm.count("Table-used") && opt_databases)
814
2769
  {
815
2770
    vector<string> database_used= vm["database-used"].as< vector<string> >();
816
2771
    vector<string> table_used= vm["Table-used"].as< vector<string> >();
821
2776
    {
822
2777
      database_used.insert(database_used.end(), *it);
823
2778
    }
824
 
 
825
2779
    dump_databases(database_used);
826
 
    dump_all_tables();
827
2780
  }
828
 
 
 
2781
  
829
2782
  if (vm.count("database-used") && ! vm.count("Table-used"))
830
2783
  {
831
2784
    dump_databases(vm["database-used"].as< vector<string> >());
832
 
    dump_all_tables();
833
2785
  }
834
2786
 
835
 
  if (opt_destination == DESTINATION_STDOUT)
836
 
    generate_dump();
837
 
  else
838
 
    generate_dump_db();
839
 
 
840
2787
  /* ensure dumped data flushed */
841
2788
  if (md_result_file && fflush(md_result_file))
842
2789
  {
852
2799
    server.
853
2800
  */
854
2801
err:
855
 
  delete db_connection;
856
 
  delete destination_connection;
 
2802
  dbDisconnect(current_host);
857
2803
  if (path.empty())
858
2804
    write_footer(md_result_file);
859
2805
  free_resources();