27
28
#define IMPORT_VERSION "3.7"
30
#include "client_priv.h"
31
#include "client_priv.h"
32
34
#include <pthread.h>
36
/* Added this for string translation. */
37
#include <drizzled/gettext.h>
34
39
using namespace std;
40
using namespace drizzled;
42
extern "C" void * worker_thread(void *arg);
36
46
/* Global Thread counter */
38
48
pthread_mutex_t counter_mutex;
39
49
pthread_cond_t count_threshhold;
41
static void db_error_with_table(DRIZZLE *drizzle, char *table);
42
static void db_error(DRIZZLE *drizzle);
43
static char *field_escape(char *to,const char *from,uint length);
51
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
52
drizzle_return_t ret, char *table);
53
static char *field_escape(char *to,const char *from,uint32_t length);
44
54
static char *add_load_option(char *ptr,const char *object,
45
55
const char *statement);
47
static bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
48
opt_replace=0,silent=0,ignore=0,opt_compress=0,
49
opt_low_priority= 0, tty_password= 0;
50
static bool debug_info_flag= 0, debug_check_flag= 0;
51
static uint opt_use_threads=0, opt_local_file=0, my_end_arg= 0;
52
static char *opt_password=0, *current_user=0,
53
*current_host=0, *current_db=0, *fields_terminated=0,
54
*lines_terminated=0, *enclosed=0, *opt_enclosed=0,
55
*escaped=0, *opt_columns=0,
56
*default_charset= (char*) DRIZZLE_DEFAULT_CHARSET_NAME;
57
static uint opt_drizzle_port= 0, opt_protocol= 0;
58
static char * opt_drizzle_unix_port=0;
57
static bool verbose= false, lock_tables= false, ignore_errors= false,
58
opt_delete= false, opt_replace= false, silent= false,
59
ignore_unique= false, opt_low_priority= false,
60
tty_password= false, opt_mysql= false;
62
static uint32_t opt_use_threads= 0, opt_local_file= 0;
63
static char *opt_password= NULL, *current_user= NULL,
64
*current_host= NULL, *current_db= NULL, *fields_terminated= NULL,
65
*lines_terminated= NULL, *enclosed= NULL, *opt_enclosed= NULL,
66
*escaped= NULL, *opt_columns= NULL;
67
static uint32_t opt_drizzle_port= 0;
59
68
static int64_t opt_ignore_lines= -1;
60
static const CHARSET_INFO *charset_info= &my_charset_latin1;
62
static struct my_option my_long_options[] =
70
static struct option my_long_options[] =
64
{"character-sets-dir", OPT_CHARSETS_DIR,
65
"Directory where character sets are.", (char**) &charsets_dir,
66
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
67
{"default-character-set", OPT_DEFAULT_CHARSET,
68
"Set the default character set.", (char**) &default_charset,
69
(char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
71
73
"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.",
72
74
(char**) &opt_columns, (char**) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
74
{"compress", 'C', "Use compression in server/client protocol.",
75
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
77
76
{"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
78
77
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
79
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
80
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
81
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
82
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
83
(char**) &debug_info_flag, (char**) &debug_info_flag,
84
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
85
78
{"delete", 'd', "First delete all rows from table.", (char**) &opt_delete,
86
79
(char**) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
87
80
{"fields-terminated-by", OPT_FTB,
104
97
{"host", 'h', "Connect to host.", (char**) ¤t_host,
105
98
(char**) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
106
99
{"ignore", 'i', "If duplicate unique key was found, keep old row.",
107
(char**) &ignore, (char**) &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
100
(char**) &ignore_unique, (char**) &ignore_unique, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
108
101
{"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.",
109
102
(char**) &opt_ignore_lines, (char**) &opt_ignore_lines, 0, GET_LL,
110
103
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
119
112
{"low-priority", OPT_LOW_PRIORITY,
120
113
"Use LOW_PRIORITY when updating the table.", (char**) &opt_low_priority,
121
114
(char**) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
115
{"mysql", 'm', N_("Use MySQL Protocol."),
116
(char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
123
119
"Password to use when connecting to server. If password is not given it's asked from the tty.",
124
120
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
125
{"port", 'P', "Port number to use for connection or 0 for default to, in "
126
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
121
{"port", 'p', "Port number to use for connection or 0 for default to, in "
122
"order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
127
123
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
128
(char**) &opt_drizzle_port,
129
(char**) &opt_drizzle_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
124
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
131
125
{"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
132
126
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
133
127
{"replace", 'r', "If duplicate unique key was found, replace old row.",
134
128
(char**) &opt_replace, (char**) &opt_replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
135
129
{"silent", 's', "Be more silent.", (char**) &silent, (char**) &silent, 0,
136
130
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
137
{"socket", 'S', "Socket file to use for connection.",
138
(char**) &opt_drizzle_unix_port, (char**) &opt_drizzle_unix_port, 0, GET_STR,
139
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
140
131
{"use-threads", OPT_USE_THREADS,
141
132
"Load files in parallel. The argument is the number "
142
133
"of threads to use for loading data.",
143
134
(char**) &opt_use_threads, (char**) &opt_use_threads, 0,
144
135
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
145
#ifndef DONT_ALLOW_USER_CHANGE
146
136
{"user", 'u', "User for login if not current user.", (char**) ¤t_user,
147
137
(char**) ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
149
138
{"verbose", 'v', "Print info about the various stages.", (char**) &verbose,
150
139
(char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
151
140
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
175
164
read the text file directly. In other cases the client will open the text\n\
176
165
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
178
printf("\nUsage: %s [OPTIONS] database textfile...",my_progname);
179
print_defaults("my",load_default_groups);
167
printf("\nUsage: %s [OPTIONS] database textfile...",internal::my_progname);
168
internal::print_defaults("drizzle",load_default_groups);
180
169
my_print_help(my_long_options);
181
170
my_print_variables(my_long_options);
185
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
173
static int get_one_option(int optid, const struct option *, char *argument)
176
uint64_t temp_drizzle_port= 0;
180
temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
181
/* if there is an alpha character this is not a valid port */
182
if (strlen(endchar) != 0)
184
fprintf(stderr, _("Non-integer value supplied for port. If you are trying to enter a password please use --password instead.\n"));
185
return EXIT_ARGUMENT_INVALID;
187
/* If the port number is > 65535 it is not a valid port
188
This also helps with potential data loss casting unsigned long to a
190
if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
192
fprintf(stderr, _("Value supplied for port is not valid.\n"));
193
return EXIT_ARGUMENT_INVALID;
197
opt_drizzle_port= (uint32_t) temp_drizzle_port;
192
203
char *start=argument;
193
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
194
opt_password=my_strdup(argument,MYF(MY_FAE));
195
while (*argument) *argument++= 'x'; /* Destroy argument */
206
opt_password = strdup(argument);
207
if (opt_password == NULL)
209
fprintf(stderr, "Memory allocation error while copying password. "
211
return EXIT_OUT_OF_MEMORY;
215
/* Overwriting password with 'x' */
197
start[1]=0; /* Cut length of argument */
220
/* Cut length of argument */
203
228
case OPT_DRIZZLE_PROTOCOL:
204
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
207
230
case 'V': print_version(); exit(0);
247
262
current_db= *((*argv)++);
249
264
if (tty_password)
250
opt_password=get_tty_password(NullS);
265
opt_password=client_get_tty_password(NULL);
256
static int write_to_table(char *filename, DRIZZLE *drizzle)
271
static int write_to_table(char *filename, drizzle_con_st *con)
258
273
char tablename[FN_REFLEN], hard_path[FN_REFLEN],
259
274
sql_statement[FN_REFLEN*16+256], *end;
275
drizzle_result_st result;
276
drizzle_return_t ret;
261
fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
278
internal::fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
262
279
if (!opt_local_file)
263
stpcpy(hard_path,filename);
280
strcpy(hard_path,filename);
265
my_load_path(hard_path, filename, NULL); /* filename includes the path */
282
internal::my_load_path(hard_path, filename, NULL); /* filename includes the path */
270
287
fprintf(stdout, "Deleting the old data from table %s\n", tablename);
271
288
#ifdef HAVE_SNPRINTF
272
snprintf(sql_statement, FN_REFLEN*16+256, "DELETE FROM %s", tablename);
289
snprintf(sql_statement, sizeof(sql_statement), "DELETE FROM %s", tablename);
274
sprintf(sql_statement, "DELETE FROM %s", tablename);
291
snprintf(sql_statement, sizeof(sql_statement), "DELETE FROM %s", tablename);
276
if (drizzle_query(drizzle, sql_statement))
293
if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
294
ret != DRIZZLE_RETURN_OK)
278
db_error_with_table(drizzle, tablename);
296
db_error(con, &result, ret, tablename);
299
drizzle_result_free(&result);
282
to_unix_path(hard_path);
285
303
if (opt_local_file)
289
307
fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
290
308
hard_path, tablename);
292
sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
310
snprintf(sql_statement, sizeof(sql_statement), "LOAD DATA %s %s INFILE '%s'",
293
311
opt_low_priority ? "LOW_PRIORITY" : "",
294
312
opt_local_file ? "LOCAL" : "", hard_path);
295
end= strend(sql_statement);
313
end= strchr(sql_statement, '\0');
297
end= stpcpy(end, " REPLACE");
299
end= stpcpy(end, " IGNORE");
300
end= stpcpy(stpcpy(end, " INTO TABLE "), tablename);
315
end= strcpy(end, " REPLACE")+8;
317
end= strcpy(end, " IGNORE")+7;
319
end+= sprintf(end, " INTO TABLE %s", tablename);
302
321
if (fields_terminated || enclosed || opt_enclosed || escaped)
303
end= stpcpy(end, " FIELDS");
322
end= strcpy(end, " FIELDS")+7;
304
323
end= add_load_option(end, fields_terminated, " TERMINATED BY");
305
324
end= add_load_option(end, enclosed, " ENCLOSED BY");
306
325
end= add_load_option(end, opt_enclosed,
308
327
end= add_load_option(end, escaped, " ESCAPED BY");
309
328
end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
310
329
if (opt_ignore_lines >= 0)
311
end= stpcpy(int64_t10_to_str(opt_ignore_lines,
312
stpcpy(end, " IGNORE "),10), " LINES");
331
end= strcpy(end, " IGNORE ")+8;
332
ostringstream buffer;
333
buffer << opt_ignore_lines;
334
end= strcpy(end, buffer.str().c_str())+ buffer.str().size();
335
end= strcpy(end, " LINES")+6;
314
end= stpcpy(stpcpy(stpcpy(end, " ("), opt_columns), ")");
339
end= strcpy(end, " (")+2;
340
end= strcpy(end, opt_columns)+strlen(opt_columns);
341
end= strcpy(end, ")")+1;
317
if (drizzle_query(drizzle, sql_statement))
345
if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
346
ret != DRIZZLE_RETURN_OK)
319
db_error_with_table(drizzle, tablename);
348
db_error(con, &result, ret, tablename);
324
if (drizzle_info(drizzle)) /* If NULL-pointer, print nothing */
353
if (strcmp(drizzle_result_info(&result), ""))
326
355
fprintf(stdout, "%s.%s: %s\n", current_db, tablename,
327
drizzle_info(drizzle));
356
drizzle_result_info(&result));
359
drizzle_result_free(&result);
335
static void lock_table(DRIZZLE *drizzle, int tablecount, char **raw_tablename)
364
static void lock_table(drizzle_con_st *con, int tablecount, char **raw_tablename)
339
368
char tablename[FN_REFLEN];
369
drizzle_result_st result;
370
drizzle_return_t ret;
342
373
fprintf(stdout, "Locking tables for write\n");
343
374
query.append("LOCK TABLES ");
344
375
for (i=0 ; i < tablecount ; i++)
346
fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
377
internal::fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
347
378
query.append(tablename);
348
379
query.append(" WRITE,");
350
if (drizzle_real_query(drizzle, query.c_str(), query.length()-1))
351
db_error(drizzle); /* We shall countinue here, if --force was given */
381
if (drizzle_query(con, &result, query.c_str(), query.length()-1,
383
ret != DRIZZLE_RETURN_OK)
385
db_error(con, &result, ret, NULL);
386
/* We shall countinue here, if --force was given */
389
drizzle_result_free(&result);
357
static DRIZZLE *db_connect(char *host, char *database,
358
char *user, char *passwd)
393
static drizzle_con_st *db_connect(char *host, char *database,
394
char *user, char *passwd)
398
drizzle_return_t ret;
362
401
fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
363
402
if (!(drizzle= drizzle_create(NULL)))
366
drizzle_options(drizzle,DRIZZLE_OPT_COMPRESS,NullS);
368
drizzle_options(drizzle,DRIZZLE_OPT_LOCAL_INFILE,
369
(char*) &opt_local_file);
371
drizzle_options(drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
372
if (!(drizzle_connect(drizzle,host,user,passwd,
373
database,opt_drizzle_port,opt_drizzle_unix_port,
404
if (!(con= drizzle_con_add_tcp(drizzle,NULL,host,opt_drizzle_port,user,passwd,
405
database, opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE)))
410
if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
376
412
ignore_errors=0; /* NO RETURN FROM db_error */
413
db_error(con, NULL, ret, NULL);
379
drizzle->reconnect= 0;
381
417
fprintf(stdout, "Selecting database %s\n", database);
382
if (drizzle_select_db(drizzle, database))
392
static void db_disconnect(char *host, DRIZZLE *drizzle)
424
static void db_disconnect(char *host, drizzle_con_st *con)
395
427
fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
396
drizzle_close(drizzle);
428
drizzle_free(drizzle_con_drizzle(con));
401
static void safe_exit(int error, DRIZZLE *drizzle)
433
static void safe_exit(int error, drizzle_con_st *con)
403
435
if (ignore_errors)
406
drizzle_close(drizzle);
438
drizzle_free(drizzle_con_drizzle(con));
412
static void db_error_with_table(DRIZZLE *drizzle, char *table)
414
my_printf_error(0,"Error: %d, %s, when using table: %s",
415
MYF(0), drizzle_errno(drizzle), drizzle_error(drizzle), table);
416
safe_exit(1, drizzle);
421
static void db_error(DRIZZLE *drizzle)
423
my_printf_error(0,"Error: %d %s", MYF(0), drizzle_errno(drizzle), drizzle_error(drizzle));
424
safe_exit(1, drizzle);
444
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
445
drizzle_return_t ret, char *table)
447
if (ret == DRIZZLE_RETURN_ERROR_CODE)
449
my_printf_error(0,"Error: %d, %s%s%s", MYF(0),
450
drizzle_result_error_code(result),
451
drizzle_result_error(result),
452
table ? ", when using table: " : "", table ? table : "");
453
drizzle_result_free(result);
457
my_printf_error(0,"Error: %d, %s%s%s", MYF(0), ret, drizzle_con_error(con),
458
table ? ", when using table: " : "", table ? table : "");
471
508
/* Add missing backslashes if user has specified odd number of backs.*/
472
509
if (end_backslashes)
479
static void * worker_thread(void *arg)
514
void * worker_thread(void *arg)
482
517
char *raw_table_name= (char *)arg;
518
drizzle_con_st *con= NULL;
519
drizzle_result_st result;
520
drizzle_return_t ret;
485
if (drizzle_thread_init())
488
if (!(drizzle= db_connect(current_host,current_db,current_user,opt_password)))
522
if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
493
if (drizzle_query(drizzle, "/*!40101 set @@character_set_database=binary */;"))
527
if (drizzle_query_str(con, &result,
528
"/*!40101 set @@character_set_database=binary */;",
530
ret != DRIZZLE_RETURN_OK)
495
db_error(drizzle); /* We shall countinue here, if --force was given */
532
db_error(con, &result, ret, NULL);
533
/* We shall countinue here, if --force was given */
500
538
We are not currently catching the error here.
502
if((error= write_to_table(raw_table_name, drizzle)))
540
if((error= write_to_table(raw_table_name, con)))
503
541
if (exitcode == 0)
508
db_disconnect(current_host, drizzle);
546
db_disconnect(current_host, con);
510
548
pthread_mutex_lock(&counter_mutex);
512
550
pthread_cond_signal(&count_threshhold);
513
551
pthread_mutex_unlock(&counter_mutex);
552
internal::my_thread_end();
581
619
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
583
621
pthread_mutex_unlock(&counter_mutex);
584
VOID(pthread_mutex_destroy(&counter_mutex));
585
VOID(pthread_cond_destroy(&count_threshhold));
622
pthread_mutex_destroy(&counter_mutex);
623
pthread_cond_destroy(&count_threshhold);
586
624
pthread_attr_destroy(&attr);
592
if (!(drizzle= db_connect(current_host,current_db,current_user,opt_password)))
594
free_defaults(argv_to_free);
595
return(1); /* purecov: deadcode */
598
if (drizzle_query(drizzle, "/*!40101 set @@character_set_database=binary */;"))
600
db_error(drizzle); /* We shall countinue here, if --force was given */
629
drizzle_con_st *con= 0;
630
drizzle_result_st result;
631
drizzle_return_t ret;
632
if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
634
internal::free_defaults(argv_to_free);
638
if (drizzle_query_str(con, &result,
639
"/*!40101 set @@character_set_database=binary */;",
641
ret != DRIZZLE_RETURN_OK)
643
db_error(con, &result, ret, NULL);
644
/* We shall countinue here, if --force was given */
648
drizzle_result_free(&result);
605
lock_table(drizzle, argc, argv);
651
lock_table(con, argc, argv);
606
652
for (; *argv != NULL; argv++)
607
if ((error= write_to_table(*argv, drizzle)))
653
if ((error= write_to_table(*argv, con)))
608
654
if (exitcode == 0)
610
db_disconnect(current_host, drizzle);
656
db_disconnect(current_host, con);
612
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
613
free_defaults(argv_to_free);
659
internal::free_defaults(argv_to_free);
615
661
return(exitcode);