~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: lbieber
  • Date: 2010-09-24 22:32:14 UTC
  • mfrom: (1792.1.3 build)
  • Revision ID: lbieber@orisndriz08-20100924223214-fy0e0bfu7yy5zeup
Merge Paul - fix bug 641033 - fix basic_create_select test
Merge Paul - fix bug 641035 - basic_index_lookup and basic_pkey_index_reverse_scan don't always use index
Merge Brian - Adding have_linux to disabled pbxt tests.
Merge Andrew - drizzledump mysql migration tool

Show diffs side-by-side

added added

removed removed

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