Drizzled Public API Documentation

drizzledump.cc
1 /* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
2  * Copyright (C) 2010 Vijay Samuel
3  * Copyright (C) 2010 Andrew Hutchings
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
17 
18 /* drizzledump.cc - Dump a tables contents and format to an ASCII file
19 
20  * Derived from mysqldump, which originally came from:
21  **
22  ** The author's original notes follow :-
23  **
24  ** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
25  ** DATE: December 3, 1994
26  ** WARRANTY: None, expressed, impressed, implied
27  ** or other
28  ** STATUS: Public domain
29 
30  * and more work by Monty, Jani & Sinisa
31  * and all the MySQL developers over the years.
32 */
33 
34 #include "client/client_priv.h"
35 #include <string>
36 #include <iostream>
37 #include <stdarg.h>
38 #include <boost/unordered_set.hpp>
39 #include <algorithm>
40 #include <fstream>
41 #include <drizzled/gettext.h>
42 #include <drizzled/configmake.h>
43 #include <drizzled/error.h>
44 #include <boost/program_options.hpp>
45 #include <boost/regex.hpp>
46 #include <boost/date_time/posix_time/posix_time.hpp>
47 
48 #include "client/drizzledump_data.h"
49 #include "client/drizzledump_mysql.h"
50 #include "client/drizzledump_drizzle.h"
51 
52 #include "user_detect.h"
53 
54 using namespace std;
55 using namespace drizzled;
56 namespace po= boost::program_options;
57 
58 /* Exit codes */
59 
60 #define EX_USAGE 1
61 #define EX_DRIZZLEERR 2
62 #define EX_EOF 5 /* ferror for output file was got */
63 
64 bool verbose= false;
65 static bool use_drizzle_protocol= false;
66 bool ignore_errors= false;
67 static bool flush_logs= false;
68 static bool create_options= true;
69 static bool opt_quoted= false;
70 bool opt_databases= false;
71 bool opt_alldbs= false;
72 static bool opt_lock_all_tables= false;
73 static bool opt_dump_date= true;
74 bool opt_autocommit= false;
75 static bool opt_single_transaction= false;
76 static bool opt_comments;
77 static bool opt_compact;
78 bool opt_ignore= false;
79 bool opt_drop_database;
80 bool opt_no_create_info;
81 bool opt_no_data= false;
82 bool opt_create_db= false;
83 bool opt_disable_keys= true;
84 bool extended_insert= true;
85 bool opt_replace_into= false;
86 bool opt_drop= true;
87 bool opt_data_is_mangled= false;
88 uint32_t show_progress_size= 0;
89 static string insert_pat;
90 static uint32_t opt_drizzle_port= 0;
91 static int first_error= 0;
92 static string extended_row;
93 FILE *md_result_file= 0;
94 FILE *stderror_file= 0;
95 std::vector<DrizzleDumpDatabase*> database_store;
96 DrizzleDumpConnection* db_connection;
97 DrizzleDumpConnection* destination_connection;
98 
99 enum destinations {
100  DESTINATION_DB,
101  DESTINATION_FILES,
102  DESTINATION_STDOUT
103 };
104 
105 int opt_destination= DESTINATION_STDOUT;
106 std::string opt_destination_host;
107 uint16_t opt_destination_port;
108 std::string opt_destination_user;
109 std::string opt_destination_password;
110 std::string opt_destination_database;
111 
112 const string progname= "drizzledump";
113 
114 string password,
115  enclosed,
116  escaped,
117  current_host,
118  path,
119  current_user,
120  opt_password,
121  opt_protocol,
122  where;
123 
124 boost::unordered_set<string> ignore_table;
125 
126 void maybe_exit(int error);
127 static void die(int error, const char* reason, ...);
128 static void write_header(char *db_name);
129 static int dump_selected_tables(const string &db, const vector<string> &table_names);
130 static int dump_databases(const vector<string> &db_names);
131 static int dump_all_databases(void);
132 int get_server_type();
133 void dump_all_tables(void);
134 void generate_dump(void);
135 void generate_dump_db(void);
136 
137 void dump_all_tables(void)
138 {
139  std::vector<DrizzleDumpDatabase*>::iterator i;
140  for (i= database_store.begin(); i != database_store.end(); ++i)
141  {
142  if ((not (*i)->populateTables()) && (not ignore_errors))
143  maybe_exit(EX_DRIZZLEERR);
144  }
145 }
146 
147 void generate_dump(void)
148 {
149  std::vector<DrizzleDumpDatabase*>::iterator i;
150 
151  if (path.empty())
152  {
153  cout << endl << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;"
154  << endl << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
155  }
156 
157  if (opt_autocommit)
158  cout << "SET AUTOCOMMIT=0;" << endl;
159 
160  for (i= database_store.begin(); i != database_store.end(); ++i)
161  {
162  DrizzleDumpDatabase *database= *i;
163  cout << *database;
164  }
165 
166  if (path.empty())
167  {
168  cout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;"
169  << endl << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
170  }
171 }
172 
173 void generate_dump_db(void)
174 {
175  std::vector<DrizzleDumpDatabase*>::iterator i;
176  DrizzleStringBuf sbuf(1024);
177  try
178  {
179  destination_connection= new DrizzleDumpConnection(opt_destination_host,
180  opt_destination_port, opt_destination_user, opt_destination_password,
181  false);
182  }
183  catch (std::exception&)
184  {
185  cerr << "Could not connect to destination database server" << endl;
186  maybe_exit(EX_DRIZZLEERR);
187  }
188  sbuf.setConnection(destination_connection);
189  std::ostream sout(&sbuf);
190  sout.exceptions(ios_base::badbit);
191 
192  if (path.empty())
193  {
194  sout << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;" << endl;
195  sout << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
196  }
197 
198  if (opt_autocommit)
199  cout << "SET AUTOCOMMIT=0;" << endl;
200 
201  for (i= database_store.begin(); i != database_store.end(); ++i)
202  {
203  try
204  {
205  DrizzleDumpDatabase *database= *i;
206  sout << *database;
207  }
208  catch (std::exception&)
209  {
210  std::cout << _("Error inserting into destination database") << std::endl;
211  if (not ignore_errors)
212  maybe_exit(EX_DRIZZLEERR);
213  }
214  }
215 
216  if (path.empty())
217  {
218  sout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;" << endl;
219  sout << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
220  }
221 }
222 
223 /*
224  exit with message if ferror(file)
225 
226  SYNOPSIS
227  check_io()
228  file - checked file
229 */
230 
231 static void check_io(FILE *file)
232 {
233  if (ferror(file))
234  die(EX_EOF, _("Got errno %d on write"), errno);
235 }
236 
237 static void write_header(char *db_name)
238 {
239  if ((not opt_compact) and (opt_comments))
240  {
241  cout << "-- drizzledump " << VERSION << " libdrizzle "
242  << drizzle_version() << ", for " << HOST_VENDOR << "-" << HOST_OS
243  << " (" << HOST_CPU << ")" << endl << "--" << endl;
244  cout << "-- Host: " << current_host << " Database: " << db_name << endl;
245  cout << "-- ------------------------------------------------------" << endl;
246  cout << "-- Server version\t" << db_connection->getServerVersion();
247  if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
248  cout << " (MySQL server)";
249  else if (db_connection->getServerType() == ServerDetect::SERVER_DRIZZLE_FOUND)
250  cout << " (Drizzle server)";
251  cout << endl << endl;
252  }
253 
254 } /* write_header */
255 
256 
257 static void write_footer(FILE *sql_file)
258 {
259  if (! opt_compact)
260  {
261  if (opt_comments)
262  {
263  if (opt_dump_date)
264  {
265  boost::posix_time::ptime time(boost::posix_time::second_clock::local_time());
266  fprintf(sql_file, "-- Dump completed on %s\n",
267  boost::posix_time::to_simple_string(time).c_str());
268  }
269  else
270  fprintf(sql_file, "-- Dump completed\n");
271  }
272  check_io(sql_file);
273  }
274 } /* write_footer */
275 
276 static int get_options(void)
277 {
278  if (opt_single_transaction && opt_lock_all_tables)
279  {
280  fprintf(stderr, _("%s: You can't use --single-transaction and "
281  "--lock-all-tables at the same time.\n"), progname.c_str());
282  return(EX_USAGE);
283  }
284  if ((opt_databases || opt_alldbs) && ! path.empty())
285  {
286  fprintf(stderr,
287  _("%s: --databases or --all-databases can't be used with --tab.\n"),
288  progname.c_str());
289  return(EX_USAGE);
290  }
291 
292  if (tty_password)
293  opt_password=client_get_tty_password(NULL);
294  return(0);
295 } /* get_options */
296 
297 
298 /*
299  Prints out an error message and kills the process.
300 
301  SYNOPSIS
302  die()
303  error_num - process return value
304  fmt_reason - a format string for use by vsnprintf.
305  ... - variable arguments for above fmt_reason string
306 
307  DESCRIPTION
308  This call prints out the formatted error message to stderr and then
309  terminates the process.
310 */
311 static void die(int error_num, const char* fmt_reason, ...)
312 {
313  char buffer[1000];
314  va_list args;
315  va_start(args,fmt_reason);
316  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
317  va_end(args);
318 
319  fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
320  fflush(stderr);
321 
322  ignore_errors= 0; /* force the exit */
323  maybe_exit(error_num);
324 }
325 
326 static void free_resources(void)
327 {
328  if (md_result_file && md_result_file != stdout)
329  fclose(md_result_file);
330  opt_password.erase();
331 }
332 
333 
334 void maybe_exit(int error)
335 {
336  if (!first_error)
337  first_error= error;
338  if (ignore_errors)
339  return;
340  delete db_connection;
341  delete destination_connection;
342  free_resources();
343  exit(error);
344 }
345 
346 static int dump_all_databases()
347 {
348  drizzle_row_t row;
349  drizzle_result_st *tableres;
350  int result=0;
351  std::string query;
352  DrizzleDumpDatabase *database;
353 
354  if (verbose)
355  std::cerr << _("-- Retrieving database structures...") << std::endl;
356 
357  /* Blocking the MySQL privilege tables too because we can't import them due to bug#646187 */
358  if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
359  query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')";
360  else
361  query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM DATA_DICTIONARY.SCHEMAS WHERE SCHEMA_NAME NOT IN ('information_schema','data_dictionary')";
362 
363  tableres= db_connection->query(query);
364  while ((row= drizzle_row_next(tableres)))
365  {
366  std::string database_name(row[0]);
367  if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
368  database= new DrizzleDumpDatabaseMySQL(database_name, db_connection);
369  else
370  database= new DrizzleDumpDatabaseDrizzle(database_name, db_connection);
371 
372  database->setCollate(row[1]);
373  database_store.push_back(database);
374  }
375  db_connection->freeResult(tableres);
376  return result;
377 }
378 /* dump_all_databases */
379 
380 
381 static int dump_databases(const vector<string> &db_names)
382 {
383  int result=0;
384  string temp;
385  DrizzleDumpDatabase *database;
386 
387  for (vector<string>::const_iterator it= db_names.begin(); it != db_names.end(); ++it)
388  {
389  temp= *it;
390  if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
391  database= new DrizzleDumpDatabaseMySQL(temp, db_connection);
392  else
393  database= new DrizzleDumpDatabaseDrizzle(temp, db_connection);
394  database_store.push_back(database);
395  }
396  return(result);
397 } /* dump_databases */
398 
399 static int dump_selected_tables(const string &db, const vector<string> &table_names)
400 {
401  DrizzleDumpDatabase *database;
402 
403  if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
404  database= new DrizzleDumpDatabaseMySQL(db, db_connection);
405  else
406  database= new DrizzleDumpDatabaseDrizzle(db, db_connection);
407 
408  if (not database->populateTables(table_names))
409  {
410  delete database;
411  if (not ignore_errors)
412  maybe_exit(EX_DRIZZLEERR);
413  }
414 
415  database_store.push_back(database);
416 
417  return 0;
418 } /* dump_selected_tables */
419 
420 static int do_flush_tables_read_lock()
421 {
422  /*
423  We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
424  will wait but will not stall the whole mysqld, and when the long update is
425  done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
426  FLUSH TABLES is to lower the probability of a stage where both drizzled
427  and most client connections are stalled. Of course, if a second long
428  update starts between the two FLUSHes, we have that bad stall.
429  */
430 
431  db_connection->queryNoResult("FLUSH TABLES");
432  db_connection->queryNoResult("FLUSH TABLES WITH READ LOCK");
433 
434  return 0;
435 }
436 
437 static int start_transaction()
438 {
439  db_connection->queryNoResult("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ");
440  db_connection->queryNoResult("START TRANSACTION WITH CONSISTENT SNAPSHOT");
441 
442  if (db_connection->getServerType() == ServerDetect::SERVER_DRIZZLE_FOUND)
443  {
444  drizzle_result_st *result;
445  drizzle_row_t row;
446  std::string query("SELECT COMMIT_ID, ID FROM DATA_DICTIONARY.SYS_REPLICATION_LOG WHERE COMMIT_ID=(SELECT MAX(COMMIT_ID) FROM DATA_DICTIONARY.SYS_REPLICATION_LOG)");
447  result= db_connection->query(query);
448  if ((row= drizzle_row_next(result)))
449  {
450  cout << "-- SYS_REPLICATION_LOG: COMMIT_ID = " << row[0] << ", ID = " << row[1] << endl << endl;
451  }
452  db_connection->freeResult(result);
453  }
454 
455  return 0;
456 }
457 
458 int main(int argc, char **argv)
459 {
460 try
461 {
462  int exit_code;
463 
464 #if defined(ENABLE_NLS)
465 # if defined(HAVE_LOCALE_H)
466  setlocale(LC_ALL, "");
467 # endif
468  bindtextdomain("drizzle", LOCALEDIR);
469  textdomain("drizzle");
470 #endif
471 
472  po::options_description commandline_options(_("Options used only in command line"));
473  commandline_options.add_options()
474  ("all-databases,A", po::value<bool>(&opt_alldbs)->default_value(false)->zero_tokens(),
475  _("Dump all the databases. This will be same as --databases with all databases selected."))
476  ("flush-logs,F", po::value<bool>(&flush_logs)->default_value(false)->zero_tokens(),
477  _("Flush logs file in server before starting dump. Note that if you dump many databases at once (using the option --databases= or --all-databases), the logs will be flushed for each database dumped. The exception is when using --lock-all-tables in this case the logs will be flushed only once, corresponding to the moment all tables are locked. So if you want your dump and the log flush to happen at the same exact moment you should use --lock-all-tables or --flush-logs"))
478  ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
479  _("Continue even if we get an sql-error."))
480  ("help,?", _("Display this help message and exit."))
481  ("lock-all-tables,x", po::value<bool>(&opt_lock_all_tables)->default_value(false)->zero_tokens(),
482  _("Locks all tables across all databases. This is achieved by taking a global read lock for the duration of the whole dump. Automatically turns --single-transaction off."))
483  ("single-transaction", po::value<bool>(&opt_single_transaction)->default_value(false)->zero_tokens(),
484  _("Creates a consistent snapshot by dumping all tables in a single transaction. Works ONLY for tables stored in storage engines which support multiversioning (currently only InnoDB does); the dump is NOT guaranteed to be consistent for other storage engines. While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents), no other connection should use the following statements: ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not isolated from them."))
485  ("skip-opt",
486  _("Disable --opt. Disables --add-drop-table, --add-locks, --create-options, ---extended-insert and --disable-keys."))
487  ("tables", _("Overrides option --databases (-B)."))
488  ("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(10000),
489  _("Number of rows before each output progress report (requires --verbose)."))
490  ("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
491  _("Print info about the various stages."))
492  ("version,V", _("Output version information and exit."))
493  ("skip-comments", _("Turn off Comments"))
494  ("skip-create", _("Turn off create-options"))
495  ("skip-extended-insert", _("Turn off extended-insert"))
496  ("skip-dump-date", _( "Turn off dump date at the end of the output"))
497  ("no-defaults", _("Do not read from the configuration files"))
498  ;
499 
500  po::options_description dump_options(_("Options specific to the drizzle client"));
501  dump_options.add_options()
502  ("add-drop-database", po::value<bool>(&opt_drop_database)->default_value(false)->zero_tokens(),
503  _("Add a 'DROP DATABASE' before each create."))
504  ("skip-drop-table", _("Do not add a 'drop table' before each create."))
505  ("compact", po::value<bool>(&opt_compact)->default_value(false)->zero_tokens(),
506  _("Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs. Enables option --skip-disable-keys"))
507  ("databases,B", po::value<bool>(&opt_databases)->default_value(false)->zero_tokens(),
508  _("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."))
509  ("skip-disable-keys,K",
510  _("'ALTER TABLE tb_name DISABLE KEYS;' and 'ALTER TABLE tb_name ENABLE KEYS;' will not be put in the output."))
511  ("ignore-table", po::value<string>(),
512  _("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"))
513  ("insert-ignore", po::value<bool>(&opt_ignore)->default_value(false)->zero_tokens(),
514  _("Insert rows with INSERT IGNORE."))
515  ("no-autocommit", po::value<bool>(&opt_autocommit)->default_value(false)->zero_tokens(),
516  _("Wrap a table's data in START TRANSACTION/COMMIT statements."))
517  ("no-create-db,n", po::value<bool>(&opt_create_db)->default_value(false)->zero_tokens(),
518  _("'CREATE DATABASE IF NOT EXISTS db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given."))
519  ("no-data,d", po::value<bool>(&opt_no_data)->default_value(false)->zero_tokens(),
520  _("No row information."))
521  ("replace", po::value<bool>(&opt_replace_into)->default_value(false)->zero_tokens(),
522  _("Use REPLACE INTO instead of INSERT INTO."))
523  ("destination-type", po::value<string>()->default_value("stdout"),
524  _("Where to send output to (stdout|database"))
525  ("destination-host", po::value<string>(&opt_destination_host)->default_value("localhost"),
526  _("Hostname for destination db server (requires --destination-type=database)"))
527  ("destination-port", po::value<uint16_t>(&opt_destination_port)->default_value(4427),
528  _("Port number for destination db server (requires --destination-type=database)"))
529  ("destination-user", po::value<string>(&opt_destination_user),
530  _("User name for destination db server (resquires --destination-type=database)"))
531  ("destination-password", po::value<string>(&opt_destination_password),
532  _("Password for destination db server (requires --destination-type=database)"))
533  ("destination-database", po::value<string>(&opt_destination_database),
534  _("The database in the destination db server (requires --destination-type=database, not for use with --all-databases)"))
535  ("my-data-is-mangled", po::value<bool>(&opt_data_is_mangled)->default_value(false)->zero_tokens(),
536  _("Do not make a UTF8 connection to MySQL, use if you have UTF8 data in a non-UTF8 table"))
537  ;
538 
539  po::options_description client_options(_("Options specific to the client"));
540  client_options.add_options()
541  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
542  _("Connect to host."))
543  ("password,P", po::value<string>(&password)->default_value(PASSWORD_SENTINEL),
544  _("Password to use when connecting to server. If password is not given it's solicited on the tty."))
545  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
546  _("Port number to use for connection."))
547  ("user,u", po::value<string>(&current_user)->default_value(UserDetect().getUser()),
548  _("User for login if not current user."))
549  ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
550  _("The protocol of connection (mysql or drizzle)."))
551  ;
552 
553  po::options_description hidden_options(_("Hidden Options"));
554  hidden_options.add_options()
555  ("database-used", po::value<vector<string> >(), _("Used to select the database"))
556  ("Table-used", po::value<vector<string> >(), _("Used to select the tables"))
557  ;
558 
559  po::options_description all_options(_("Allowed Options + Hidden Options"));
560  all_options.add(commandline_options).add(dump_options).add(client_options).add(hidden_options);
561 
562  po::options_description long_options(_("Allowed Options"));
563  long_options.add(commandline_options).add(dump_options).add(client_options);
564 
565  std::string system_config_dir_dump(SYSCONFDIR);
566  system_config_dir_dump.append("/drizzle/drizzledump.cnf");
567 
568  std::string system_config_dir_client(SYSCONFDIR);
569  system_config_dir_client.append("/drizzle/client.cnf");
570 
571  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
572 
573  if (user_config_dir.compare(0, 2, "~/") == 0)
574  {
575  char *homedir;
576  homedir= getenv("HOME");
577  if (homedir != NULL)
578  user_config_dir.replace(0, 1, homedir);
579  }
580 
581  po::positional_options_description p;
582  p.add("database-used", 1);
583  p.add("Table-used",-1);
584 
585  md_result_file= stdout;
586 
587  po::variables_map vm;
588 
589  // Disable allow_guessing
590  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
591 
592  po::store(po::command_line_parser(argc, argv).style(style).
593  options(all_options).positional(p).
594  extra_parser(parse_password_arg).run(), vm);
595 
596  if (! vm.count("no-defaults"))
597  {
598  std::string user_config_dir_dump(user_config_dir);
599  user_config_dir_dump.append("/drizzle/drizzledump.cnf");
600 
601  std::string user_config_dir_client(user_config_dir);
602  user_config_dir_client.append("/drizzle/client.cnf");
603 
604  ifstream user_dump_ifs(user_config_dir_dump.c_str());
605  po::store(parse_config_file(user_dump_ifs, dump_options), vm);
606 
607  ifstream user_client_ifs(user_config_dir_client.c_str());
608  po::store(parse_config_file(user_client_ifs, client_options), vm);
609 
610  ifstream system_dump_ifs(system_config_dir_dump.c_str());
611  po::store(parse_config_file(system_dump_ifs, dump_options), vm);
612 
613  ifstream system_client_ifs(system_config_dir_client.c_str());
614  po::store(parse_config_file(system_client_ifs, client_options), vm);
615  }
616 
617  po::notify(vm);
618 
619  if ((not vm.count("database-used") && not vm.count("Table-used")
620  && not opt_alldbs && path.empty())
621  || (vm.count("help")) || vm.count("version"))
622  {
623  printf(_("Drizzledump %s build %s, for %s-%s (%s)\n"),
624  drizzle_version(), VERSION, HOST_VENDOR, HOST_OS, HOST_CPU);
625  if (vm.count("version"))
626  exit(0);
627  puts("");
628  puts(_("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"));
629  puts(_("Dumps definitions and data from a Drizzle database server"));
630  printf(_("Usage: %s [OPTIONS] database [tables]\n"), progname.c_str());
631  printf(_("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n"),
632  progname.c_str());
633  printf(_("OR %s [OPTIONS] --all-databases [OPTIONS]\n"), progname.c_str());
634  cout << long_options;
635  if (vm.count("help"))
636  exit(0);
637  else
638  exit(1);
639  }
640 
641  /* Inverted Booleans */
642 
643  opt_drop= not vm.count("skip-drop-table");
644  opt_comments= not vm.count("skip-comments");
645  extended_insert= not vm.count("skip-extended-insert");
646  opt_dump_date= not vm.count("skip-dump-date");
647  opt_disable_keys= not vm.count("skip-disable-keys");
648  opt_quoted= not vm.count("skip-quote-names");
649 
650  if (vm.count("protocol"))
651  {
652  boost::to_lower(opt_protocol);
653  if (not opt_protocol.compare("mysql"))
654  use_drizzle_protocol=false;
655  else if (not opt_protocol.compare("drizzle"))
656  use_drizzle_protocol=true;
657  else
658  {
659  cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
660  exit(-1);
661  }
662  }
663 
664  if (vm.count("port"))
665  {
666  /* If the port number is > 65535 it is not a valid port
667  * This also helps with potential data loss casting unsigned long to a
668  * uint32_t.
669  */
670  if (opt_drizzle_port > 65535)
671  {
672  fprintf(stderr, _("Value supplied for port is not valid.\n"));
673  exit(-1);
674  }
675  }
676 
677  if (vm.count("password"))
678  {
679  if (!opt_password.empty())
680  opt_password.erase();
681  if (password == PASSWORD_SENTINEL)
682  {
683  opt_password= "";
684  }
685  else
686  {
687  opt_password= password;
688  tty_password= false;
689  }
690  }
691  else
692  {
693  tty_password= true;
694  }
695 
696  if (! path.empty())
697  {
698  opt_disable_keys= 0;
699  }
700 
701  if (vm.count("skip-opt"))
702  {
703  extended_insert= opt_drop= create_options= 0;
704  opt_disable_keys= 0;
705  }
706 
707  if (opt_compact)
708  {
709  opt_comments= opt_drop= opt_disable_keys= 0;
710  }
711 
712  if (vm.count("opt"))
713  {
714  extended_insert= opt_drop= create_options= 1;
715  opt_disable_keys= 1;
716  }
717 
718  if (vm.count("tables"))
719  {
720  opt_databases= false;
721  }
722 
723  if (vm.count("ignore-table"))
724  {
725  if (!strchr(vm["ignore-table"].as<string>().c_str(), '.'))
726  {
727  fprintf(stderr, _("Illegal use of option --ignore-table=<database>.<table>\n"));
728  exit(EXIT_ARGUMENT_INVALID);
729  }
730  string tmpptr(vm["ignore-table"].as<string>());
731  ignore_table.insert(tmpptr);
732  }
733 
734  if (vm.count("skip-create"))
735  {
736  opt_create_db= opt_no_create_info= create_options= false;
737  }
738 
739  exit_code= get_options();
740  if (exit_code)
741  {
742  free_resources();
743  exit(exit_code);
744  }
745  try
746  {
747  db_connection = new DrizzleDumpConnection(current_host, opt_drizzle_port,
748  current_user, opt_password, use_drizzle_protocol);
749  }
750  catch (std::exception&)
751  {
752  maybe_exit(EX_DRIZZLEERR);
753  }
754 
755  if ((db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND) and (not opt_data_is_mangled))
756  db_connection->queryNoResult("SET NAMES 'utf8'");
757 
758  if (vm.count("destination-type"))
759  {
760  string tmp_destination(vm["destination-type"].as<string>());
761  if (tmp_destination.compare("database") == 0)
762  opt_destination= DESTINATION_DB;
763  else if (tmp_destination.compare("stdout") == 0)
764  opt_destination= DESTINATION_STDOUT;
765  else
766  exit(EXIT_ARGUMENT_INVALID);
767  }
768 
769 
770  if (path.empty() && vm.count("database-used"))
771  {
772  string database_used= *vm["database-used"].as< vector<string> >().begin();
773  write_header((char *)database_used.c_str());
774  }
775 
776  if ((opt_lock_all_tables) && do_flush_tables_read_lock())
777  goto err;
778  if (opt_single_transaction && start_transaction())
779  goto err;
780  if (opt_lock_all_tables)
781  db_connection->queryNoResult("FLUSH LOGS");
782 
783  if (opt_alldbs)
784  {
785  dump_all_databases();
786  dump_all_tables();
787  }
788  if (vm.count("database-used") && vm.count("Table-used") && not opt_databases)
789  {
790  string database_used= *vm["database-used"].as< vector<string> >().begin();
791  /* Only one database and selected table(s) */
792  dump_selected_tables(database_used, vm["Table-used"].as< vector<string> >());
793  }
794 
795  if (vm.count("Table-used") && opt_databases)
796  {
797  vector<string> database_used= vm["database-used"].as< vector<string> >();
798  vector<string> table_used= vm["Table-used"].as< vector<string> >();
799 
800  for (vector<string>::iterator it= table_used.begin();
801  it != table_used.end();
802  ++it)
803  {
804  database_used.insert(database_used.end(), *it);
805  }
806 
807  dump_databases(database_used);
808  dump_all_tables();
809  }
810 
811  if (vm.count("database-used") && not vm.count("Table-used"))
812  {
813  dump_databases(vm["database-used"].as< vector<string> >());
814  dump_all_tables();
815  }
816 
817  if (opt_destination == DESTINATION_STDOUT)
818  generate_dump();
819  else
820  generate_dump_db();
821 
822  /* ensure dumped data flushed */
823  if (md_result_file && fflush(md_result_file))
824  {
825  if (!first_error)
826  first_error= EX_DRIZZLEERR;
827  goto err;
828  }
829 
830  /*
831  No reason to explicitely COMMIT the transaction, neither to explicitely
832  UNLOCK TABLES: these will be automatically be done by the server when we
833  disconnect now. Saves some code here, some network trips, adds nothing to
834  server.
835  */
836 err:
837  delete db_connection;
838  delete destination_connection;
839  if (path.empty())
840  write_footer(md_result_file);
841  free_resources();
842 
843  if (stderror_file)
844  fclose(stderror_file);
845 }
846 
847  catch(exception &err)
848  {
849  cerr << err.what() << endl;
850  }
851 
852  return(first_error);
853 } /* main */