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
#include <my_pthread.h>
37
34
/* Global Thread counter */
39
36
pthread_mutex_t counter_mutex;
40
37
pthread_cond_t count_threshhold;
42
static void db_error_with_table(DRIZZLE *drizzle, char *table);
43
static void db_error(DRIZZLE *drizzle);
39
static void db_error_with_table(MYSQL *mysql, char *table);
40
static void db_error(MYSQL *mysql);
44
41
static char *field_escape(char *to,const char *from,uint length);
45
42
static char *add_load_option(char *ptr,const char *object,
46
const char *statement);
43
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;
45
static bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
46
replace=0,silent=0,ignore=0,opt_compress=0,
47
opt_low_priority= 0, tty_password= 0;
51
48
static bool debug_info_flag= 0, debug_check_flag= 0;
52
49
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;
50
static char *opt_password=0, *current_user=0,
51
*current_host=0, *current_db=0, *fields_terminated=0,
52
*lines_terminated=0, *enclosed=0, *opt_enclosed=0,
53
*escaped=0, *opt_columns=0,
54
*default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
55
static uint opt_mysql_port= 0, opt_protocol= 0;
56
static char * opt_mysql_unix_port=0;
60
57
static int64_t opt_ignore_lines= -1;
61
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
58
static CHARSET_INFO *charset_info= &my_charset_latin1;
63
60
static struct my_option my_long_options[] =
115
112
{"local", 'L', "Read all files through the client.", (char**) &opt_local_file,
116
113
(char**) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
117
114
{"lock-tables", 'l', "Lock all tables for write (this disables threads).",
118
(char**) &lock_tables, (char**) &lock_tables, 0, GET_BOOL, NO_ARG,
115
(char**) &lock_tables, (char**) &lock_tables, 0, GET_BOOL, NO_ARG,
119
116
0, 0, 0, 0, 0, 0},
120
117
{"low-priority", OPT_LOW_PRIORITY,
121
118
"Use LOW_PRIORITY when updating the table.", (char**) &opt_low_priority,
124
121
"Password to use when connecting to server. If password is not given it's asked from the tty.",
125
122
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
126
123
{"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,
124
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
125
#if MYSQL_PORT_DEFAULT == 0
128
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
129
(char**) &opt_mysql_port,
130
(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).",
132
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
133
133
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
134
134
{"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},
135
(char**) &replace, (char**) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
136
136
{"silent", 's', "Be more silent.", (char**) &silent, (char**) &silent, 0,
137
137
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
138
138
{"socket", 'S', "Socket file to use for connection.",
139
(char**) &opt_drizzle_unix_port, (char**) &opt_drizzle_unix_port, 0, GET_STR,
139
(char**) &opt_mysql_unix_port, (char**) &opt_mysql_unix_port, 0, GET_STR,
140
140
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
141
141
{"use-threads", OPT_USE_THREADS,
142
142
"Load files in parallel. The argument is the number "
143
143
"of threads to use for loading data.",
144
(char**) &opt_use_threads, (char**) &opt_use_threads, 0,
144
(char**) &opt_use_threads, (char**) &opt_use_threads, 0,
145
145
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
146
146
#ifndef DONT_ALLOW_USER_CHANGE
147
147
{"user", 'u', "User for login if not current user.", (char**) ¤t_user,
158
static const char *load_default_groups[]= { "drizzleimport","client",0 };
158
static const char *load_default_groups[]= { "mysqlimport","client",0 };
160
#include <help_start.h>
160
162
static void print_version(void)
162
164
printf("%s Ver %s Distrib %s, for %s (%s)\n" ,my_progname,
163
IMPORT_VERSION, drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
165
IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
167
169
static void usage(void)
170
puts("Copyright (C) 2008 Drizzle Open Source Development Team");
172
puts("Copyright (C) 2000-2006 MySQL AB");
171
173
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
175
Loads tables from text files in various formats. The base name of the\n\
174
176
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\
177
If one uses sockets to connect to the MySQL server, the server will open and\n\
176
178
read the text file directly. In other cases the client will open the text\n\
177
179
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
284
290
if (opt_local_file)
285
291
fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
286
hard_path, tablename);
292
hard_path, tablename);
288
294
fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
289
hard_path, tablename);
295
hard_path, tablename);
291
297
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");
298
opt_low_priority ? "LOW_PRIORITY" : "",
299
opt_local_file ? "LOCAL" : "", hard_path);
300
end= strend(sql_statement);
302
end= strmov(end, " REPLACE");
298
end= my_stpcpy(end, " IGNORE");
299
end= my_stpcpy(my_stpcpy(end, " INTO TABLE "), tablename);
304
end= strmov(end, " IGNORE");
305
end= strmov(strmov(end, " INTO TABLE "), tablename);
301
307
if (fields_terminated || enclosed || opt_enclosed || escaped)
302
end= my_stpcpy(end, " FIELDS");
308
end= strmov(end, " FIELDS");
303
309
end= add_load_option(end, fields_terminated, " TERMINATED BY");
304
310
end= add_load_option(end, enclosed, " ENCLOSED BY");
305
311
end= add_load_option(end, opt_enclosed,
306
" OPTIONALLY ENCLOSED BY");
312
" OPTIONALLY ENCLOSED BY");
307
313
end= add_load_option(end, escaped, " ESCAPED BY");
308
314
end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
309
315
if (opt_ignore_lines >= 0)
310
end= my_stpcpy(int64_t10_to_str(opt_ignore_lines,
311
my_stpcpy(end, " IGNORE "),10), " LINES");
316
end= strmov(int64_t10_to_str(opt_ignore_lines,
317
strmov(end, " IGNORE "),10), " LINES");
313
end= my_stpcpy(my_stpcpy(my_stpcpy(end, " ("), opt_columns), ")");
319
end= strmov(strmov(strmov(end, " ("), opt_columns), ")");
316
if (drizzle_query(drizzle, sql_statement))
322
if (mysql_query(mysql, sql_statement))
318
db_error_with_table(drizzle, tablename);
324
db_error_with_table(mysql, tablename);
323
if (drizzle_info(drizzle)) /* If NULL-pointer, print nothing */
329
if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
325
331
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)
340
static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
342
DYNAMIC_STRING query;
338
344
char tablename[FN_REFLEN];
341
347
fprintf(stdout, "Locking tables for write\n");
342
query.append("LOCK TABLES ");
348
init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
343
349
for (i=0 ; i < tablecount ; i++)
345
351
fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
346
query.append(tablename);
347
query.append(" WRITE,");
352
dynstr_append(&query, tablename);
353
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 */
355
if (mysql_real_query(mysql, query.str, query.length-1))
356
db_error(mysql); /* We shall countinue here, if --force was given */
356
static DRIZZLE *db_connect(char *host, char *database,
362
static MYSQL *db_connect(char *host, char *database,
357
363
char *user, char *passwd)
361
367
fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
362
if (!(drizzle= drizzle_create(NULL)))
368
if (!(mysql= mysql_init(NULL)))
364
370
if (opt_compress)
365
drizzle_options(drizzle,DRIZZLE_OPT_COMPRESS,NULL);
371
mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
366
372
if (opt_local_file)
367
drizzle_options(drizzle,DRIZZLE_OPT_LOCAL_INFILE,
368
(char*) &opt_local_file);
373
mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
374
(char*) &opt_local_file);
369
375
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,
376
mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
377
if (!(mysql_real_connect(mysql,host,user,passwd,
378
database,opt_mysql_port,opt_mysql_unix_port,
375
ignore_errors=0; /* NO RETURN FROM db_error */
381
ignore_errors=0; /* NO RETURN FROM db_error */
378
drizzle->reconnect= 0;
380
386
fprintf(stdout, "Selecting database %s\n", database);
381
if (drizzle_select_db(drizzle, database))
387
if (mysql_select_db(mysql, database))
391
static void db_disconnect(char *host, DRIZZLE *drizzle)
397
static void db_disconnect(char *host, MYSQL *mysql)
394
400
fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
395
drizzle_close(drizzle);
400
static void safe_exit(int error, DRIZZLE *drizzle)
406
static void safe_exit(int error, MYSQL *mysql)
402
408
if (ignore_errors)
405
drizzle_close(drizzle);
411
static void db_error_with_table(DRIZZLE *drizzle, char *table)
417
static void db_error_with_table(MYSQL *mysql, char *table)
413
419
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);
420
MYF(0), mysql_errno(mysql), mysql_error(mysql), table);
420
static void db_error(DRIZZLE *drizzle)
426
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);
428
my_printf_error(0,"Error: %d %s", MYF(0), mysql_errno(mysql), mysql_error(mysql));
427
433
static char *add_load_option(char *ptr, const char *object,
428
const char *statement)
434
const char *statement)
432
438
/* Don't escape hex constants */
433
439
if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
434
ptr= strxmov(ptr," ",statement," ",object,NULL);
440
ptr= strxmov(ptr," ",statement," ",object,NullS);
437
443
/* char constant; escape */
438
ptr= strxmov(ptr," ",statement," '",NULL);
444
ptr= strxmov(ptr," ",statement," '",NullS);
439
445
ptr= field_escape(ptr,object,(uint) strlen(object));
448
454
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
449
455
** This is done by doubleing ' and add a end -\ if needed to avoid
450
456
** syntax errors from the SQL parser.
453
459
static char *field_escape(char *to,const char *from,uint length)
456
uint end_backslashes=0;
462
uint end_backslashes=0;
458
464
for (end= from+length; from != end; from++)
461
467
if (*from == '\\')
462
468
end_backslashes^=1; /* find odd number of backslashes */
465
471
if (*from == '\'' && !end_backslashes)
466
*to++= *from; /* We want a dublicate of "'" for DRIZZLE */
472
*to++= *from; /* We want a dublicate of "'" for MySQL */
467
473
end_backslashes=0;
470
476
/* Add missing backslashes if user has specified odd number of backs.*/
471
477
if (end_backslashes)
478
static void * worker_thread(void *arg)
484
static pthread_handler_t worker_thread(void *arg)
481
487
char *raw_table_name= (char *)arg;
484
if (!(drizzle= db_connect(current_host,current_db,current_user,opt_password)))
490
if (mysql_thread_init())
493
if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
489
if (drizzle_query(drizzle, "/*!40101 set @@character_set_database=binary */;"))
498
if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
491
db_error(drizzle); /* We shall countinue here, if --force was given */
500
db_error(mysql); /* We shall countinue here, if --force was given */
496
505
We are not currently catching the error here.
498
if((error= write_to_table(raw_table_name, drizzle)))
507
if((error= write_to_table(raw_table_name, mysql)))
499
508
if (exitcode == 0)
504
db_disconnect(current_host, drizzle);
513
db_disconnect(current_host, mysql);
506
515
pthread_mutex_lock(&counter_mutex);
577
586
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
579
588
pthread_mutex_unlock(&counter_mutex);
580
pthread_mutex_destroy(&counter_mutex);
581
pthread_cond_destroy(&count_threshhold);
589
VOID(pthread_mutex_destroy(&counter_mutex));
590
VOID(pthread_cond_destroy(&count_threshhold));
582
591
pthread_attr_destroy(&attr);
588
if (!(drizzle= db_connect(current_host,current_db,current_user,opt_password)))
597
if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
590
599
free_defaults(argv_to_free);
591
600
return(1); /* purecov: deadcode */
594
if (drizzle_query(drizzle, "/*!40101 set @@character_set_database=binary */;"))
603
if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
596
db_error(drizzle); /* We shall countinue here, if --force was given */
605
db_error(mysql); /* We shall countinue here, if --force was given */
601
lock_table(drizzle, argc, argv);
610
lock_table(mysql, argc, argv);
602
611
for (; *argv != NULL; argv++)
603
if ((error= write_to_table(*argv, drizzle)))
612
if ((error= write_to_table(*argv, mysql)))
604
613
if (exitcode == 0)
606
db_disconnect(current_host, drizzle);
615
db_disconnect(current_host, mysql);
617
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
609
618
free_defaults(argv_to_free);
610
619
my_end(my_end_arg);
611
620
return(exitcode);