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"
32
29
#include "client_priv.h"
30
#include "drizzle_version.h"
31
#ifdef HAVE_LIBPTHREAD
32
#include <my_pthread.h>
37
36
/* Global Thread counter */
38
#ifdef HAVE_LIBPTHREAD
39
39
pthread_mutex_t counter_mutex;
40
40
pthread_cond_t count_threshhold;
42
static void db_error_with_table(DRIZZLE *drizzle, char *table);
43
static void db_error(DRIZZLE *drizzle);
43
static void db_error_with_table(MYSQL *mysql, char *table);
44
static void db_error(MYSQL *mysql);
44
45
static char *field_escape(char *to,const char *from,uint length);
45
46
static char *add_load_option(char *ptr,const char *object,
46
const char *statement);
47
const char *statement);
48
static bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
49
opt_replace=0,silent=0,ignore=0,opt_compress=0,
50
opt_low_priority= 0, tty_password= 0;
49
static 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;
51
52
static bool debug_info_flag= 0, debug_check_flag= 0;
52
53
static uint opt_use_threads=0, opt_local_file=0, my_end_arg= 0;
53
static char *opt_password=0, *current_user=0,
54
*current_host=0, *current_db=0, *fields_terminated=0,
55
*lines_terminated=0, *enclosed=0, *opt_enclosed=0,
56
*escaped=0, *opt_columns=0,
57
*default_charset= (char*) DRIZZLE_DEFAULT_CHARSET_NAME;
58
static uint opt_drizzle_port= 0, opt_protocol= 0;
59
static char * opt_drizzle_unix_port=0;
60
static int64_t opt_ignore_lines= -1;
61
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
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;
63
68
static struct my_option my_long_options[] =
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,
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
131
{"port", 'P', "Port number to use for connection or 0 for default to, in "
127
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
128
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
129
(char**) &opt_drizzle_port,
130
(char**) &opt_drizzle_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
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,
132
{"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
140
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
133
141
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
134
142
{"replace", 'r', "If duplicate unique key was found, replace old row.",
135
(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},
136
149
{"silent", 's', "Be more silent.", (char**) &silent, (char**) &silent, 0,
137
150
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
138
151
{"socket", 'S', "Socket file to use for connection.",
139
(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,
140
153
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
141
154
{"use-threads", OPT_USE_THREADS,
142
155
"Load files in parallel. The argument is the number "
143
156
"of threads to use for loading data.",
144
(char**) &opt_use_threads, (char**) &opt_use_threads, 0,
157
(char**) &opt_use_threads, (char**) &opt_use_threads, 0,
145
158
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
146
159
#ifndef DONT_ALLOW_USER_CHANGE
147
160
{"user", 'u', "User for login if not current user.", (char**) ¤t_user,
158
static const char *load_default_groups[]= { "drizzleimport","client",0 };
171
static const char *load_default_groups[]= { "mysqlimport","client",0 };
173
#include <help_start.h>
160
175
static void print_version(void)
162
177
printf("%s Ver %s Distrib %s, for %s (%s)\n" ,my_progname,
163
IMPORT_VERSION, drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
178
IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
167
182
static void usage(void)
170
puts("Copyright (C) 2008 Drizzle Open Source Development Team");
185
puts("Copyright (C) 2000-2006 MySQL AB");
171
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");
173
188
Loads tables from text files in various formats. The base name of the\n\
174
189
text file must be the name of the table that should be used.\n\
175
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\
176
191
read the text file directly. In other cases the client will open the text\n\
177
192
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
284
303
if (opt_local_file)
285
304
fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
286
hard_path, tablename);
305
hard_path, tablename);
288
307
fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
289
hard_path, tablename);
308
hard_path, tablename);
291
310
sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
292
opt_low_priority ? "LOW_PRIORITY" : "",
293
opt_local_file ? "LOCAL" : "", hard_path);
294
end= strchr(sql_statement, '\0');
296
end= my_stpcpy(end, " REPLACE");
311
opt_low_priority ? "LOW_PRIORITY" : "",
312
opt_local_file ? "LOCAL" : "", hard_path);
313
end= strend(sql_statement);
315
end= strmov(end, " REPLACE");
298
end= my_stpcpy(end, " IGNORE");
299
end= my_stpcpy(my_stpcpy(end, " INTO TABLE "), tablename);
317
end= strmov(end, " IGNORE");
318
end= strmov(strmov(end, " INTO TABLE "), tablename);
301
320
if (fields_terminated || enclosed || opt_enclosed || escaped)
302
end= my_stpcpy(end, " FIELDS");
321
end= strmov(end, " FIELDS");
303
322
end= add_load_option(end, fields_terminated, " TERMINATED BY");
304
323
end= add_load_option(end, enclosed, " ENCLOSED BY");
305
324
end= add_load_option(end, opt_enclosed,
306
" OPTIONALLY ENCLOSED BY");
325
" OPTIONALLY ENCLOSED BY");
307
326
end= add_load_option(end, escaped, " ESCAPED BY");
308
327
end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
309
328
if (opt_ignore_lines >= 0)
310
end= my_stpcpy(int64_t10_to_str(opt_ignore_lines,
311
my_stpcpy(end, " IGNORE "),10), " LINES");
329
end= strmov(longlong10_to_str(opt_ignore_lines,
330
strmov(end, " IGNORE "),10), " LINES");
313
end= my_stpcpy(my_stpcpy(my_stpcpy(end, " ("), opt_columns), ")");
332
end= strmov(strmov(strmov(end, " ("), opt_columns), ")");
316
if (drizzle_query(drizzle, sql_statement))
335
if (mysql_query(mysql, sql_statement))
318
db_error_with_table(drizzle, tablename);
337
db_error_with_table(mysql, tablename);
323
if (drizzle_info(drizzle)) /* If NULL-pointer, print nothing */
342
if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
325
344
fprintf(stdout, "%s.%s: %s\n", current_db, tablename,
326
drizzle_info(drizzle));
334
static void lock_table(DRIZZLE *drizzle, int tablecount, char **raw_tablename)
353
static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
355
DYNAMIC_STRING query;
338
357
char tablename[FN_REFLEN];
341
360
fprintf(stdout, "Locking tables for write\n");
342
query.append("LOCK TABLES ");
361
init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
343
362
for (i=0 ; i < tablecount ; i++)
345
364
fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
346
query.append(tablename);
347
query.append(" WRITE,");
365
dynstr_append(&query, tablename);
366
dynstr_append(&query, " WRITE,");
349
if (drizzle_real_query(drizzle, query.c_str(), query.length()-1))
350
db_error(drizzle); /* We shall countinue here, if --force was given */
368
if (mysql_real_query(mysql, query.str, query.length-1))
369
db_error(mysql); /* We shall countinue here, if --force was given */
356
static DRIZZLE *db_connect(char *host, char *database,
375
static MYSQL *db_connect(char *host, char *database,
357
376
char *user, char *passwd)
361
380
fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
362
if (!(drizzle= drizzle_create(NULL)))
381
if (!(mysql= mysql_init(NULL)))
364
383
if (opt_compress)
365
drizzle_options(drizzle,DRIZZLE_OPT_COMPRESS,NULL);
384
mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
366
385
if (opt_local_file)
367
drizzle_options(drizzle,DRIZZLE_OPT_LOCAL_INFILE,
368
(char*) &opt_local_file);
386
mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
387
(char*) &opt_local_file);
369
388
if (opt_protocol)
370
drizzle_options(drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
371
if (!(drizzle_connect(drizzle,host,user,passwd,
372
database,opt_drizzle_port,opt_drizzle_unix_port,
389
mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
391
if (shared_memory_base_name)
392
mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
394
if (!(mysql_real_connect(mysql,host,user,passwd,
395
database,opt_mysql_port,opt_mysql_unix_port,
375
ignore_errors=0; /* NO RETURN FROM db_error */
398
ignore_errors=0; /* NO RETURN FROM db_error */
378
drizzle->reconnect= 0;
380
403
fprintf(stdout, "Selecting database %s\n", database);
381
if (drizzle_select_db(drizzle, database))
404
if (mysql_select_db(mysql, database))
391
static void db_disconnect(char *host, DRIZZLE *drizzle)
414
static void db_disconnect(char *host, MYSQL *mysql)
394
417
fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
395
drizzle_close(drizzle);
400
static void safe_exit(int error, DRIZZLE *drizzle)
423
static void safe_exit(int error, MYSQL *mysql)
402
425
if (ignore_errors)
405
drizzle_close(drizzle);
411
static void db_error_with_table(DRIZZLE *drizzle, char *table)
434
static void db_error_with_table(MYSQL *mysql, char *table)
413
436
my_printf_error(0,"Error: %d, %s, when using table: %s",
414
MYF(0), drizzle_errno(drizzle), drizzle_error(drizzle), table);
415
safe_exit(1, drizzle);
437
MYF(0), mysql_errno(mysql), mysql_error(mysql), table);
420
static void db_error(DRIZZLE *drizzle)
443
static void db_error(MYSQL *mysql)
422
my_printf_error(0,"Error: %d %s", MYF(0), drizzle_errno(drizzle), drizzle_error(drizzle));
423
safe_exit(1, drizzle);
445
my_printf_error(0,"Error: %d %s", MYF(0), mysql_errno(mysql), mysql_error(mysql));
427
450
static char *add_load_option(char *ptr, const char *object,
428
const char *statement)
451
const char *statement)
432
455
/* Don't escape hex constants */
433
456
if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
434
ptr= strxmov(ptr," ",statement," ",object,NULL);
457
ptr= strxmov(ptr," ",statement," ",object,NullS);
437
460
/* char constant; escape */
438
ptr= strxmov(ptr," ",statement," '",NULL);
461
ptr= strxmov(ptr," ",statement," '",NullS);
439
462
ptr= field_escape(ptr,object,(uint) strlen(object));
448
471
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
449
472
** This is done by doubleing ' and add a end -\ if needed to avoid
450
473
** syntax errors from the SQL parser.
453
476
static char *field_escape(char *to,const char *from,uint length)
456
uint end_backslashes=0;
479
uint end_backslashes=0;
458
481
for (end= from+length; from != end; from++)
461
484
if (*from == '\\')
462
485
end_backslashes^=1; /* find odd number of backslashes */
465
488
if (*from == '\'' && !end_backslashes)
466
*to++= *from; /* We want a dublicate of "'" for DRIZZLE */
489
*to++= *from; /* We want a dublicate of "'" for MySQL */
467
490
end_backslashes=0;
470
493
/* Add missing backslashes if user has specified odd number of backs.*/
471
494
if (end_backslashes)
478
static void * worker_thread(void *arg)
501
#ifdef HAVE_LIBPTHREAD
502
static pthread_handler_t worker_thread(void *arg)
481
505
char *raw_table_name= (char *)arg;
484
if (!(drizzle= db_connect(current_host,current_db,current_user,opt_password)))
508
if (mysql_thread_init())
511
if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
489
if (drizzle_query(drizzle, "/*!40101 set @@character_set_database=binary */;"))
516
if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
491
db_error(drizzle); /* We shall countinue here, if --force was given */
518
db_error(mysql); /* We shall countinue here, if --force was given */
496
523
We are not currently catching the error here.
498
if((error= write_to_table(raw_table_name, drizzle)))
525
if((error= write_to_table(raw_table_name, mysql)))
499
526
if (exitcode == 0)
504
db_disconnect(current_host, drizzle);
531
db_disconnect(current_host, mysql);
506
533
pthread_mutex_lock(&counter_mutex);
577
605
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
579
607
pthread_mutex_unlock(&counter_mutex);
580
pthread_mutex_destroy(&counter_mutex);
581
pthread_cond_destroy(&count_threshhold);
608
VOID(pthread_mutex_destroy(&counter_mutex));
609
VOID(pthread_cond_destroy(&count_threshhold));
582
610
pthread_attr_destroy(&attr);
588
if (!(drizzle= db_connect(current_host,current_db,current_user,opt_password)))
616
if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
590
618
free_defaults(argv_to_free);
591
619
return(1); /* purecov: deadcode */
594
if (drizzle_query(drizzle, "/*!40101 set @@character_set_database=binary */;"))
622
if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
596
db_error(drizzle); /* We shall countinue here, if --force was given */
624
db_error(mysql); /* We shall countinue here, if --force was given */
601
lock_table(drizzle, argc, argv);
629
lock_table(mysql, argc, argv);
602
630
for (; *argv != NULL; argv++)
603
if ((error= write_to_table(*argv, drizzle)))
631
if ((error= write_to_table(*argv, mysql)))
604
632
if (exitcode == 0)
606
db_disconnect(current_host, drizzle);
634
db_disconnect(current_host, mysql);
636
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
638
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
609
640
free_defaults(argv_to_free);
610
641
my_end(my_end_arg);
611
642
return(exitcode);