~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Monty Taylor
  • Date: 2010-07-19 05:06:59 UTC
  • mto: (1662.1.2 rollup)
  • mto: This revision was merged to the branch mainline in revision 1663.
  • Revision ID: mordred@inaugust.com-20100719050659-if3thz0k66m1jkaf
Backed out two bits that snuck in to the merge.

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