52
56
static char *add_load_option(char *ptr,const char *object,
53
57
const char *statement);
55
static bool verbose= false, ignore_errors= false,
59
static bool verbose= false, lock_tables= false, ignore_errors= false,
56
60
opt_delete= false, opt_replace= false, silent= false,
57
61
ignore_unique= false, opt_low_priority= false,
58
use_drizzle_protocol= false, opt_local_file;
60
static uint32_t opt_use_threads;
64
static uint32_t opt_use_threads= 0, opt_local_file= 0;
65
static char *opt_password= NULL, *current_user= NULL,
66
*current_host= NULL, *current_db= NULL, *fields_terminated= NULL,
67
*lines_terminated= NULL, *enclosed= NULL, *opt_enclosed= NULL,
68
*escaped= NULL, *opt_columns= NULL;
61
69
static uint32_t opt_drizzle_port= 0;
70
static char * opt_drizzle_unix_port= 0;
62
71
static int64_t opt_ignore_lines= -1;
64
std::string opt_columns,
78
static int get_options(void)
81
if (! enclosed.empty() && ! opt_enclosed.empty())
73
static struct my_option my_long_options[] =
76
"Use only these columns to import the data to. Give the column names in a comma separated list. This is same as giving columns to LOAD DATA INFILE.",
77
(char**) &opt_columns, (char**) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
79
{"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
80
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
81
{"delete", 'd', "First delete all rows from table.", (char**) &opt_delete,
82
(char**) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
83
{"fields-terminated-by", OPT_FTB,
84
"Fields in the textfile are terminated by ...", (char**) &fields_terminated,
85
(char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
86
{"fields-enclosed-by", OPT_ENC,
87
"Fields in the importfile are enclosed by ...", (char**) &enclosed,
88
(char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
89
{"fields-optionally-enclosed-by", OPT_O_ENC,
90
"Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
91
(char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
92
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
93
(char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
95
{"force", 'f', "Continue even if we get an sql-error.",
96
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
98
{"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG,
100
{"host", 'h', "Connect to host.", (char**) ¤t_host,
101
(char**) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
102
{"ignore", 'i', "If duplicate unique key was found, keep old row.",
103
(char**) &ignore_unique, (char**) &ignore_unique, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
104
{"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.",
105
(char**) &opt_ignore_lines, (char**) &opt_ignore_lines, 0, GET_LL,
106
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
107
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
108
(char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
109
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
110
{"local", 'L', "Read all files through the client.", (char**) &opt_local_file,
111
(char**) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
112
{"lock-tables", 'l', "Lock all tables for write (this disables threads).",
113
(char**) &lock_tables, (char**) &lock_tables, 0, GET_BOOL, NO_ARG,
115
{"low-priority", OPT_LOW_PRIORITY,
116
"Use LOW_PRIORITY when updating the table.", (char**) &opt_low_priority,
117
(char**) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
119
"Password to use when connecting to server. If password is not given it's asked from the tty.",
120
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
121
{"port", 'p', "Port number to use for connection or 0 for default to, in "
122
"order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
123
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
124
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
125
{"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
126
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
127
{"replace", 'r', "If duplicate unique key was found, replace old row.",
128
(char**) &opt_replace, (char**) &opt_replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
129
{"silent", 's', "Be more silent.", (char**) &silent, (char**) &silent, 0,
130
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
131
{"socket", 'S', "Socket file to use for connection.",
132
(char**) &opt_drizzle_unix_port, (char**) &opt_drizzle_unix_port, 0, GET_STR,
133
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
134
{"use-threads", OPT_USE_THREADS,
135
"Load files in parallel. The argument is the number "
136
"of threads to use for loading data.",
137
(char**) &opt_use_threads, (char**) &opt_use_threads, 0,
138
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
139
{"user", 'u', "User for login if not current user.", (char**) ¤t_user,
140
(char**) ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
141
{"verbose", 'v', "Print info about the various stages.", (char**) &verbose,
142
(char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
143
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
144
NO_ARG, 0, 0, 0, 0, 0, 0},
145
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
149
static const char *load_default_groups[]= { "drizzleimport","client",0 };
151
static void print_version(void)
153
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n" ,my_progname,
154
IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
158
static void usage(void)
161
puts("Copyright (C) 2008 Drizzle Open Source Development Team");
162
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");
164
Loads tables from text files in various formats. The base name of the\n\
165
text file must be the name of the table that should be used.\n\
166
If one uses sockets to connect to the Drizzle server, the server will open and\n\
167
read the text file directly. In other cases the client will open the text\n\
168
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
170
printf("\nUsage: %s [OPTIONS] database textfile...",my_progname);
171
print_defaults("drizzle",load_default_groups);
172
my_print_help(my_long_options);
173
my_print_variables(my_long_options);
176
bool get_one_option(int optid, const struct my_option *, char *argument)
179
uint64_t temp_drizzle_port= 0;
183
temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
184
/* if there is an alpha character this is not a valid port */
185
if (strlen(endchar) != 0)
187
fprintf(stderr, _("Non-integer value supplied for port. If you are trying to enter a password please use --password instead.\n"));
190
/* If the port number is > 65535 it is not a valid port
191
This also helps with potential data loss casting unsigned long to a
193
if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
195
fprintf(stderr, _("Value supplied for port is not valid.\n"));
200
opt_drizzle_port= (uint32_t) temp_drizzle_port;
206
char *start=argument;
209
opt_password = strdup(argument);
210
if (opt_password == NULL)
212
fprintf(stderr, "Memory allocation error while copying password. "
218
/* Overwriting password with 'x' */
223
/* Cut length of argument */
231
case OPT_DRIZZLE_PROTOCOL:
233
case 'V': print_version(); exit(0);
243
static int get_options(int *argc, char ***argv)
247
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
250
if (enclosed && opt_enclosed)
83
252
fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n");
349
561
int main(int argc, char **argv)
355
po::options_description commandline_options("Options used only in command line");
356
commandline_options.add_options()
358
("debug,#", po::value<string>(),
359
"Output debug log. Often this is 'd:t:o,filename'.")
360
("delete,d", po::value<bool>(&opt_delete)->default_value(false)->zero_tokens(),
361
"First delete all rows from table.")
362
("help,?", "Displays this help and exits.")
363
("ignore,i", po::value<bool>(&ignore_unique)->default_value(false)->zero_tokens(),
364
"If duplicate unique key was found, keep old row.")
365
("low-priority", po::value<bool>(&opt_low_priority)->default_value(false)->zero_tokens(),
366
"Use LOW_PRIORITY when updating the table.")
367
("replace,r", po::value<bool>(&opt_replace)->default_value(false)->zero_tokens(),
368
"If duplicate unique key was found, replace old row.")
369
("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
370
"Print info about the various stages.")
371
("version,V", "Output version information and exit.")
374
po::options_description import_options("Options specific to the drizzleimport");
375
import_options.add_options()
376
("columns,C", po::value<string>(&opt_columns)->default_value(""),
377
"Use only these columns to import the data to. Give the column names in a comma separated list. This is same as giving columns to LOAD DATA INFILE.")
378
("fields-terminated-by", po::value<string>(&fields_terminated)->default_value(""),
379
"Fields in the textfile are terminated by ...")
380
("fields-enclosed-by", po::value<string>(&enclosed)->default_value(""),
381
"Fields in the importfile are enclosed by ...")
382
("fields-optionally-enclosed-by", po::value<string>(&opt_enclosed)->default_value(""),
383
"Fields in the i.file are opt. enclosed by ...")
384
("fields-escaped-by", po::value<string>(&escaped)->default_value(""),
385
"Fields in the i.file are escaped by ...")
386
("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
387
"Continue even if we get an sql-error.")
388
("ignore-lines", po::value<int64_t>(&opt_ignore_lines)->default_value(0),
389
"Ignore first n lines of data infile.")
390
("lines-terminated-by", po::value<string>(&lines_terminated)->default_value(""),
391
"Lines in the i.file are terminated by ...")
392
("local,L", po::value<bool>(&opt_local_file)->default_value(false)->zero_tokens(),
393
"Read all files through the client.")
394
("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
396
("use-threads", po::value<uint32_t>(&opt_use_threads)->default_value(4),
397
"Load files in parallel. The argument is the number of threads to use for loading data (default is 4.")
400
po::options_description client_options("Options specific to the client");
401
client_options.add_options()
402
("host,h", po::value<string>(¤t_host)->default_value("localhost"),
404
("password,P", po::value<string>(&password),
405
"Password to use when connecting to server. If password is not given it's asked from the tty." )
406
("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
407
"Port number to use for connection")
408
("protocol", po::value<string>(&opt_protocol)->default_value("mysql"),
409
"The protocol of connection (mysql or drizzle).")
410
("user,u", po::value<string>(¤t_user)->default_value(""),
411
"User for login if not current user.")
414
po::options_description long_options("Allowed Options");
415
long_options.add(commandline_options).add(import_options).add(client_options);
417
std::string system_config_dir_import(SYSCONFDIR);
418
system_config_dir_import.append("/drizzle/drizzleimport.cnf");
420
std::string system_config_dir_client(SYSCONFDIR);
421
system_config_dir_client.append("/drizzle/client.cnf");
423
std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
425
if (user_config_dir.compare(0, 2, "~/") == 0)
428
homedir= getenv("HOME");
430
user_config_dir.replace(0, 1, homedir);
433
po::variables_map vm;
435
// Disable allow_guessing
436
int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
438
po::store(po::command_line_parser(argc, argv).options(long_options).
439
style(style).extra_parser(parse_password_arg).run(), vm);
441
std::string user_config_dir_import(user_config_dir);
442
user_config_dir_import.append("/drizzle/drizzleimport.cnf");
444
std::string user_config_dir_client(user_config_dir);
445
user_config_dir_client.append("/drizzle/client.cnf");
447
ifstream user_import_ifs(user_config_dir_import.c_str());
448
po::store(parse_config_file(user_import_ifs, import_options), vm);
450
ifstream user_client_ifs(user_config_dir_client.c_str());
451
po::store(parse_config_file(user_client_ifs, client_options), vm);
453
ifstream system_import_ifs(system_config_dir_import.c_str());
454
store(parse_config_file(system_import_ifs, import_options), vm);
456
ifstream system_client_ifs(system_config_dir_client.c_str());
457
po::store(parse_config_file(system_client_ifs, client_options), vm);
460
if (vm.count("protocol"))
462
std::transform(opt_protocol.begin(), opt_protocol.end(),
463
opt_protocol.begin(), ::tolower);
465
if (not opt_protocol.compare("mysql"))
466
use_drizzle_protocol=false;
467
else if (not opt_protocol.compare("drizzle"))
468
use_drizzle_protocol=true;
471
cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
476
if (vm.count("port"))
479
/* If the port number is > 65535 it is not a valid port
480
This also helps with potential data loss casting unsigned long to a
482
if (opt_drizzle_port > 65535)
484
fprintf(stderr, _("Value supplied for port is not valid.\n"));
485
exit(EXIT_ARGUMENT_INVALID);
489
if( vm.count("password") )
491
if (!opt_password.empty())
492
opt_password.erase();
493
if (password == PASSWORD_SENTINEL)
499
opt_password= password;
509
if (vm.count("version"))
511
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n", program_name,
512
IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
515
if (vm.count("help") || argc < 2)
517
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n", program_name,
518
IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
519
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");
521
Loads tables from text files in various formats. The base name of the\n\
522
text file must be the name of the table that should be used.\n\
523
If one uses sockets to connect to the Drizzle server, the server will open and\n\
524
read the text file directly. In other cases the client will open the text\n\
525
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
527
printf("\nUsage: %s [OPTIONS] database textfile...", program_name);
567
load_defaults("drizzle",load_default_groups,&argc,&argv);
568
/* argv is changed in the program */
570
if (get_options(&argc, &argv))
572
free_defaults(argv_to_free);
538
current_db= (*argv)++;
576
#ifdef HAVE_LIBPTHREAD
577
if (opt_use_threads && !lock_tables)
543
579
pthread_t mainthread; /* Thread descriptor */
544
580
pthread_attr_t attr; /* Thread attributes */