14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
** drizzleimport.c - Imports all given files
17
** mysqlimport.c - Imports all given files
20
** *************************
22
** * AUTHOR: Monty & Jani *
23
** * DATE: June 24, 1997 *
25
** *************************
20
** *************************
22
** * AUTHOR: Monty & Jani *
23
** * DATE: June 24, 1997 *
25
** *************************
27
27
#define IMPORT_VERSION "3.7"
29
29
#include "client_priv.h"
34
/* Added this for string translation. */
35
#include <drizzled/gettext.h>
30
#include "drizzle_version.h"
31
#ifdef HAVE_LIBPTHREAD
32
#include <my_pthread.h>
39
36
/* Global Thread counter */
38
#ifdef HAVE_LIBPTHREAD
41
39
pthread_mutex_t counter_mutex;
42
40
pthread_cond_t count_threshhold;
44
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
45
drizzle_return_t ret, char *table);
46
static char *field_escape(char *to,const char *from,uint32_t length);
43
static void db_error_with_table(MYSQL *mysql, char *table);
44
static void db_error(MYSQL *mysql);
45
static char *field_escape(char *to,const char *from,uint length);
47
46
static char *add_load_option(char *ptr,const char *object,
48
const char *statement);
50
static bool verbose= false, lock_tables= false, ignore_errors= false,
51
opt_delete= false, opt_replace= false, silent= false,
52
ignore_unique= false, opt_compress= false, opt_low_priority= false,
54
static bool debug_info_flag= false, debug_check_flag= false;
55
static uint32_t opt_use_threads= 0, opt_local_file= 0, my_end_arg= 0;
56
static char *opt_password= NULL, *current_user= NULL,
57
*current_host= NULL, *current_db= NULL, *fields_terminated= NULL,
58
*lines_terminated= NULL, *enclosed= NULL, *opt_enclosed= NULL,
59
*escaped= NULL, *opt_columns= NULL,
60
*default_charset= (char*) DRIZZLE_DEFAULT_CHARSET_NAME;
61
static uint32_t opt_drizzle_port= 0;
62
static char * opt_drizzle_unix_port= 0;
63
static int64_t opt_ignore_lines= -1;
64
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
47
const char *statement);
49
static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
50
replace=0,silent=0,ignore=0,opt_compress=0,
51
opt_low_priority= 0, tty_password= 0;
52
static my_bool debug_info_flag= 0, debug_check_flag= 0;
53
static uint opt_use_threads=0, opt_local_file=0, my_end_arg= 0;
54
static char *opt_password=0, *current_user=0,
55
*current_host=0, *current_db=0, *fields_terminated=0,
56
*lines_terminated=0, *enclosed=0, *opt_enclosed=0,
57
*escaped=0, *opt_columns=0,
58
*default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
59
static uint opt_mysql_port= 0, opt_protocol= 0;
60
static char * opt_mysql_unix_port=0;
61
static longlong opt_ignore_lines= -1;
62
static CHARSET_INFO *charset_info= &my_charset_latin1;
65
static char *shared_memory_base_name=0;
66
68
static struct my_option my_long_options[] =
70
{"character-sets-dir", OPT_CHARSETS_DIR,
71
"Directory where character sets are.", (char**) &charsets_dir,
72
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
68
73
{"default-character-set", OPT_DEFAULT_CHARSET,
69
74
"Set the default character set.", (char**) &default_charset,
70
75
(char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
115
120
{"local", 'L', "Read all files through the client.", (char**) &opt_local_file,
116
121
(char**) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
117
122
{"lock-tables", 'l', "Lock all tables for write (this disables threads).",
118
(char**) &lock_tables, (char**) &lock_tables, 0, GET_BOOL, NO_ARG,
123
(char**) &lock_tables, (char**) &lock_tables, 0, GET_BOOL, NO_ARG,
119
124
0, 0, 0, 0, 0, 0},
120
125
{"low-priority", OPT_LOW_PRIORITY,
121
126
"Use LOW_PRIORITY when updating the table.", (char**) &opt_low_priority,
122
127
(char**) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
124
129
"Password to use when connecting to server. If password is not given it's asked from the tty.",
125
130
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
126
{"port", 'p', "Port number to use for connection or 0 for default to, in "
127
"order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
128
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
129
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
130
{"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
131
{"port", 'P', "Port number to use for connection or 0 for default to, in "
132
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
133
#if MYSQL_PORT_DEFAULT == 0
136
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
137
(char**) &opt_mysql_port,
138
(char**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
140
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
131
141
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
132
142
{"replace", 'r', "If duplicate unique key was found, replace old row.",
133
(char**) &opt_replace, (char**) &opt_replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
143
(char**) &replace, (char**) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
145
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
146
"Base name of shared memory.", (char**) &shared_memory_base_name, (char**) &shared_memory_base_name,
147
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
134
149
{"silent", 's', "Be more silent.", (char**) &silent, (char**) &silent, 0,
135
150
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
136
151
{"socket", 'S', "Socket file to use for connection.",
137
(char**) &opt_drizzle_unix_port, (char**) &opt_drizzle_unix_port, 0, GET_STR,
152
(char**) &opt_mysql_unix_port, (char**) &opt_mysql_unix_port, 0, GET_STR,
138
153
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
139
154
{"use-threads", OPT_USE_THREADS,
140
155
"Load files in parallel. The argument is the number "
141
156
"of threads to use for loading data.",
142
(char**) &opt_use_threads, (char**) &opt_use_threads, 0,
157
(char**) &opt_use_threads, (char**) &opt_use_threads, 0,
143
158
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
144
159
#ifndef DONT_ALLOW_USER_CHANGE
145
160
{"user", 'u', "User for login if not current user.", (char**) ¤t_user,
156
static const char *load_default_groups[]= { "drizzleimport","client",0 };
171
static const char *load_default_groups[]= { "mysqlimport","client",0 };
173
#include <help_start.h>
158
175
static void print_version(void)
160
177
printf("%s Ver %s Distrib %s, for %s (%s)\n" ,my_progname,
161
IMPORT_VERSION, drizzle_version(),SYSTEM_TYPE,MACHINE_TYPE);
178
IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
165
182
static void usage(void)
168
puts("Copyright (C) 2008 Drizzle Open Source Development Team");
185
puts("Copyright (C) 2000-2006 MySQL AB");
169
186
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");
171
188
Loads tables from text files in various formats. The base name of the\n\
172
189
text file must be the name of the table that should be used.\n\
173
If one uses sockets to connect to the Drizzle server, the server will open and\n\
190
If one uses sockets to connect to the MySQL server, the server will open and\n\
174
191
read the text file directly. In other cases the client will open the text\n\
175
192
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
177
194
printf("\nUsage: %s [OPTIONS] database textfile...",my_progname);
178
print_defaults("drizzle",load_default_groups);
195
print_defaults("my",load_default_groups);
179
196
my_print_help(my_long_options);
180
197
my_print_variables(my_long_options);
184
bool get_one_option(int optid, const struct my_option *, char *argument)
200
#include <help_end.h>
203
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
187
uint64_t temp_drizzle_port= 0;
191
temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
192
/* if there is an alpha character this is not a valid port */
193
if (strlen(endchar) != 0)
195
fprintf(stderr, _("Non-integer value supplied for port. If you are trying to enter a password please use --password instead.\n"));
198
/* If the port number is > 65535 it is not a valid port
199
This also helps with potential data loss casting unsigned long to a
201
if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
203
fprintf(stderr, _("Value supplied for port is not valid.\n"));
208
opt_drizzle_port= (uint32_t) temp_drizzle_port;
214
210
char *start=argument;
217
opt_password = strdup(argument);
218
if (opt_password == NULL)
220
fprintf(stderr, "Memory allocation error while copying password. "
226
/* Overwriting password with 'x' */
211
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
212
opt_password=my_strdup(argument,MYF(MY_FAE));
213
while (*argument) *argument++= 'x'; /* Destroy argument */
231
/* Cut length of argument */
215
start[1]=0; /* Cut length of argument */
239
case OPT_DRIZZLE_PROTOCOL:
221
case OPT_MYSQL_PROTOCOL:
222
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
226
DBUG_PUSH(argument ? argument : "d:t:o");
241
229
case 'V': print_version(); exit(0);
309
298
sprintf(sql_statement, "DELETE FROM %s", tablename);
311
if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
312
ret != DRIZZLE_RETURN_OK)
300
if (mysql_query(mysql, sql_statement))
314
db_error(con, &result, ret, tablename);
302
db_error_with_table(mysql, tablename);
317
drizzle_result_free(&result);
306
to_unix_path(hard_path);
321
309
if (opt_local_file)
322
310
fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
323
hard_path, tablename);
311
hard_path, tablename);
325
313
fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
326
hard_path, tablename);
314
hard_path, tablename);
328
316
sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
329
opt_low_priority ? "LOW_PRIORITY" : "",
330
opt_local_file ? "LOCAL" : "", hard_path);
331
end= strchr(sql_statement, '\0');
333
end= strcpy(end, " REPLACE")+8;
335
end= strcpy(end, " IGNORE")+7;
337
end+= sprintf(end, " INTO TABLE %s", tablename);
317
opt_low_priority ? "LOW_PRIORITY" : "",
318
opt_local_file ? "LOCAL" : "", hard_path);
319
end= strend(sql_statement);
321
end= strmov(end, " REPLACE");
323
end= strmov(end, " IGNORE");
324
end= strmov(strmov(end, " INTO TABLE "), tablename);
339
326
if (fields_terminated || enclosed || opt_enclosed || escaped)
340
end= strcpy(end, " FIELDS")+7;
327
end= strmov(end, " FIELDS");
341
328
end= add_load_option(end, fields_terminated, " TERMINATED BY");
342
329
end= add_load_option(end, enclosed, " ENCLOSED BY");
343
330
end= add_load_option(end, opt_enclosed,
344
" OPTIONALLY ENCLOSED BY");
331
" OPTIONALLY ENCLOSED BY");
345
332
end= add_load_option(end, escaped, " ESCAPED BY");
346
333
end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
347
334
if (opt_ignore_lines >= 0)
349
end= strcpy(end, " IGNORE ")+8;
350
ostringstream buffer;
351
buffer << opt_ignore_lines;
352
end= strcpy(end, buffer.str().c_str())+ buffer.str().size();
353
end= strcpy(end, " LINES")+6;
335
end= strmov(longlong10_to_str(opt_ignore_lines,
336
strmov(end, " IGNORE "),10), " LINES");
357
end= strcpy(end, " (")+2;
358
end= strcpy(end, opt_columns)+strlen(opt_columns);
359
end= strcpy(end, ")")+1;
338
end= strmov(strmov(strmov(end, " ("), opt_columns), ")");
363
if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
364
ret != DRIZZLE_RETURN_OK)
341
if (mysql_query(mysql, sql_statement))
366
db_error(con, &result, ret, tablename);
343
db_error_with_table(mysql, tablename);
371
if (strcmp(drizzle_result_info(&result), ""))
348
if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
373
350
fprintf(stdout, "%s.%s: %s\n", current_db, tablename,
374
drizzle_result_info(&result));
377
drizzle_result_free(&result);
382
static void lock_table(drizzle_con_st *con, int tablecount, char **raw_tablename)
359
static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
361
DYNAMIC_STRING query;
386
363
char tablename[FN_REFLEN];
387
drizzle_result_st result;
388
drizzle_return_t ret;
391
366
fprintf(stdout, "Locking tables for write\n");
392
query.append("LOCK TABLES ");
367
init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
393
368
for (i=0 ; i < tablecount ; i++)
395
370
fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
396
query.append(tablename);
397
query.append(" WRITE,");
399
if (drizzle_query(con, &result, query.c_str(), query.length()-1,
401
ret != DRIZZLE_RETURN_OK)
403
db_error(con, &result, ret, NULL);
404
/* We shall countinue here, if --force was given */
407
drizzle_result_free(&result);
371
dynstr_append(&query, tablename);
372
dynstr_append(&query, " WRITE,");
374
if (mysql_real_query(mysql, query.str, query.length-1))
375
db_error(mysql); /* We shall countinue here, if --force was given */
411
static drizzle_con_st *db_connect(char *host, char *database,
412
char *user, char *passwd)
381
static MYSQL *db_connect(char *host, char *database,
382
char *user, char *passwd)
416
drizzle_return_t ret;
419
386
fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
420
if (!(drizzle= drizzle_create(NULL)))
422
if (!(con= drizzle_con_add_tcp(drizzle,NULL,host,opt_drizzle_port,user,passwd,
423
database, DRIZZLE_CON_NONE)))
428
if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
430
ignore_errors=0; /* NO RETURN FROM db_error */
431
db_error(con, NULL, ret, NULL);
387
if (!(mysql= mysql_init(NULL)))
390
mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
392
mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
393
(char*) &opt_local_file);
395
mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
397
if (shared_memory_base_name)
398
mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
400
if (!(mysql_real_connect(mysql,host,user,passwd,
401
database,opt_mysql_port,opt_mysql_unix_port,
404
ignore_errors=0; /* NO RETURN FROM db_error */
435
409
fprintf(stdout, "Selecting database %s\n", database);
410
if (mysql_select_db(mysql, database))
442
static void db_disconnect(char *host, drizzle_con_st *con)
420
static void db_disconnect(char *host, MYSQL *mysql)
445
423
fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
446
drizzle_free(drizzle_con_drizzle(con));
451
static void safe_exit(int error, drizzle_con_st *con)
429
static void safe_exit(int error, MYSQL *mysql)
453
431
if (ignore_errors)
456
drizzle_free(drizzle_con_drizzle(con));
462
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
463
drizzle_return_t ret, char *table)
465
if (ret == DRIZZLE_RETURN_ERROR_CODE)
467
my_printf_error(0,"Error: %d, %s%s%s", MYF(0),
468
drizzle_result_error_code(result),
469
drizzle_result_error(result),
470
table ? ", when using table: " : "", table ? table : "");
471
drizzle_result_free(result);
475
my_printf_error(0,"Error: %d, %s%s%s", MYF(0), ret, drizzle_con_error(con),
476
table ? ", when using table: " : "", table ? table : "");
440
static void db_error_with_table(MYSQL *mysql, char *table)
442
my_printf_error(0,"Error: %d, %s, when using table: %s",
443
MYF(0), mysql_errno(mysql), mysql_error(mysql), table);
449
static void db_error(MYSQL *mysql)
451
my_printf_error(0,"Error: %d %s", MYF(0), mysql_errno(mysql), mysql_error(mysql));
483
456
static char *add_load_option(char *ptr, const char *object,
484
const char *statement)
457
const char *statement)
488
461
/* Don't escape hex constants */
489
462
if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
490
ptr+= sprintf(ptr, " %s %s", statement, object);
463
ptr= strxmov(ptr," ",statement," ",object,NullS);
493
466
/* char constant; escape */
494
ptr+= sprintf(ptr, " %s '", statement);
495
ptr= field_escape(ptr,object,(uint32_t) strlen(object));
467
ptr= strxmov(ptr," ",statement," '",NullS);
468
ptr= field_escape(ptr,object,(uint) strlen(object));
504
477
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
505
478
** This is done by doubleing ' and add a end -\ if needed to avoid
506
479
** syntax errors from the SQL parser.
509
static char *field_escape(char *to,const char *from,uint32_t length)
482
static char *field_escape(char *to,const char *from,uint length)
512
uint32_t end_backslashes=0;
485
uint end_backslashes=0;
514
487
for (end= from+length; from != end; from++)
517
490
if (*from == '\\')
518
491
end_backslashes^=1; /* find odd number of backslashes */
521
494
if (*from == '\'' && !end_backslashes)
522
*to++= *from; /* We want a dublicate of "'" for DRIZZLE */
495
*to++= *from; /* We want a dublicate of "'" for MySQL */
523
496
end_backslashes=0;
526
499
/* Add missing backslashes if user has specified odd number of backs.*/
527
500
if (end_backslashes)
535
void * worker_thread(void *arg)
507
#ifdef HAVE_LIBPTHREAD
508
static pthread_handler_t worker_thread(void *arg)
538
511
char *raw_table_name= (char *)arg;
539
drizzle_con_st *con= NULL;
540
drizzle_result_st result;
541
drizzle_return_t ret;
543
if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
514
if (mysql_thread_init())
517
if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
548
if (drizzle_query_str(con, &result,
549
"/*!40101 set @@character_set_database=binary */;",
551
ret != DRIZZLE_RETURN_OK)
522
if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
553
db_error(con, &result, ret, NULL);
554
/* We shall countinue here, if --force was given */
524
db_error(mysql); /* We shall countinue here, if --force was given */
559
529
We are not currently catching the error here.
561
if((error= write_to_table(raw_table_name, con)))
531
if((error= write_to_table(raw_table_name, mysql)))
562
532
if (exitcode == 0)
567
db_disconnect(current_host, con);
537
db_disconnect(current_host, mysql);
569
539
pthread_mutex_lock(&counter_mutex);
640
611
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
642
613
pthread_mutex_unlock(&counter_mutex);
643
pthread_mutex_destroy(&counter_mutex);
644
pthread_cond_destroy(&count_threshhold);
614
VOID(pthread_mutex_destroy(&counter_mutex));
615
VOID(pthread_cond_destroy(&count_threshhold));
645
616
pthread_attr_destroy(&attr);
650
drizzle_con_st *con= 0;
651
drizzle_result_st result;
652
drizzle_return_t ret;
653
if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
622
if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
655
624
free_defaults(argv_to_free);
656
625
return(1); /* purecov: deadcode */
659
if (drizzle_query_str(con, &result,
660
"/*!40101 set @@character_set_database=binary */;",
662
ret != DRIZZLE_RETURN_OK)
628
if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
664
db_error(con, &result, ret, NULL);
665
/* We shall countinue here, if --force was given */
630
db_error(mysql); /* We shall countinue here, if --force was given */
669
drizzle_result_free(&result);
672
lock_table(con, argc, argv);
635
lock_table(mysql, argc, argv);
673
636
for (; *argv != NULL; argv++)
674
if ((error= write_to_table(*argv, con)))
637
if ((error= write_to_table(*argv, mysql)))
675
638
if (exitcode == 0)
677
db_disconnect(current_host, con);
640
db_disconnect(current_host, mysql);
642
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
644
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
680
646
free_defaults(argv_to_free);
681
647
my_end(my_end_arg);
682
648
return(exitcode);