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;
51
static bool debug_info_flag= 0, debug_check_flag= 0;
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;
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[] =
65
70
{"character-sets-dir", OPT_CHARSETS_DIR,
66
"Directory where character sets are.", (char**) &charsets_dir,
67
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
71
"Directory where character sets are.", (uchar**) &charsets_dir,
72
(uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
68
73
{"default-character-set", OPT_DEFAULT_CHARSET,
69
"Set the default character set.", (char**) &default_charset,
70
(char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
74
"Set the default character set.", (uchar**) &default_charset,
75
(uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
72
77
"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.",
73
(char**) &opt_columns, (char**) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
78
(uchar**) &opt_columns, (uchar**) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
75
80
{"compress", 'C', "Use compression in server/client protocol.",
76
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
81
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
78
83
{"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
79
84
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
80
85
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
81
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
86
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
82
87
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
83
88
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
84
(char**) &debug_info_flag, (char**) &debug_info_flag,
89
(uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
85
90
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
86
{"delete", 'd', "First delete all rows from table.", (char**) &opt_delete,
87
(char**) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
91
{"delete", 'd', "First delete all rows from table.", (uchar**) &opt_delete,
92
(uchar**) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
88
93
{"fields-terminated-by", OPT_FTB,
89
"Fields in the textfile are terminated by ...", (char**) &fields_terminated,
90
(char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
94
"Fields in the textfile are terminated by ...", (uchar**) &fields_terminated,
95
(uchar**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
91
96
{"fields-enclosed-by", OPT_ENC,
92
"Fields in the importfile are enclosed by ...", (char**) &enclosed,
93
(char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
97
"Fields in the importfile are enclosed by ...", (uchar**) &enclosed,
98
(uchar**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
94
99
{"fields-optionally-enclosed-by", OPT_O_ENC,
95
"Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
96
(char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
100
"Fields in the i.file are opt. enclosed by ...", (uchar**) &opt_enclosed,
101
(uchar**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
97
102
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
98
(char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
103
(uchar**) &escaped, (uchar**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
100
105
{"force", 'f', "Continue even if we get an sql-error.",
101
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
106
(uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
103
108
{"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG,
104
109
0, 0, 0, 0, 0, 0},
105
{"host", 'h', "Connect to host.", (char**) ¤t_host,
106
(char**) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
110
{"host", 'h', "Connect to host.", (uchar**) ¤t_host,
111
(uchar**) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
107
112
{"ignore", 'i', "If duplicate unique key was found, keep old row.",
108
(char**) &ignore, (char**) &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
113
(uchar**) &ignore, (uchar**) &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
109
114
{"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.",
110
(char**) &opt_ignore_lines, (char**) &opt_ignore_lines, 0, GET_LL,
115
(uchar**) &opt_ignore_lines, (uchar**) &opt_ignore_lines, 0, GET_LL,
111
116
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
112
117
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
113
(char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
118
(uchar**) &lines_terminated, (uchar**) &lines_terminated, 0, GET_STR,
114
119
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
115
{"local", 'L', "Read all files through the client.", (char**) &opt_local_file,
116
(char**) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
120
{"local", 'L', "Read all files through the client.", (uchar**) &opt_local_file,
121
(uchar**) &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
(uchar**) &lock_tables, (uchar**) &lock_tables, 0, GET_BOOL, NO_ARG,
119
124
0, 0, 0, 0, 0, 0},
120
125
{"low-priority", OPT_LOW_PRIORITY,
121
"Use LOW_PRIORITY when updating the table.", (char**) &opt_low_priority,
122
(char**) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
126
"Use LOW_PRIORITY when updating the table.", (uchar**) &opt_low_priority,
127
(uchar**) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
123
128
{"password", 'p',
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
(uchar**) &opt_mysql_port,
138
(uchar**) &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},
136
{"silent", 's', "Be more silent.", (char**) &silent, (char**) &silent, 0,
143
(uchar**) &replace, (uchar**) &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.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
147
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
149
{"silent", 's', "Be more silent.", (uchar**) &silent, (uchar**) &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
(uchar**) &opt_mysql_unix_port, (uchar**) &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
(uchar**) &opt_use_threads, (uchar**) &opt_use_threads, 0,
145
158
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
146
159
#ifndef DONT_ALLOW_USER_CHANGE
147
{"user", 'u', "User for login if not current user.", (char**) ¤t_user,
148
(char**) ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
160
{"user", 'u', "User for login if not current user.", (uchar**) ¤t_user,
161
(uchar**) ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
150
{"verbose", 'v', "Print info about the various stages.", (char**) &verbose,
151
(char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
163
{"verbose", 'v', "Print info about the various stages.", (uchar**) &verbose,
164
(uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
152
165
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
153
166
NO_ARG, 0, 0, 0, 0, 0, 0},
154
167
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
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
309
if (opt_local_file)
285
310
fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
286
hard_path, tablename);
311
hard_path, tablename);
288
313
fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
289
hard_path, tablename);
314
hard_path, tablename);
291
316
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");
317
opt_low_priority ? "LOW_PRIORITY" : "",
318
opt_local_file ? "LOCAL" : "", hard_path);
319
end= strend(sql_statement);
321
end= strmov(end, " REPLACE");
298
end= my_stpcpy(end, " IGNORE");
299
end= my_stpcpy(my_stpcpy(end, " INTO TABLE "), tablename);
323
end= strmov(end, " IGNORE");
324
end= strmov(strmov(end, " INTO TABLE "), tablename);
301
326
if (fields_terminated || enclosed || opt_enclosed || escaped)
302
end= my_stpcpy(end, " FIELDS");
327
end= strmov(end, " FIELDS");
303
328
end= add_load_option(end, fields_terminated, " TERMINATED BY");
304
329
end= add_load_option(end, enclosed, " ENCLOSED BY");
305
330
end= add_load_option(end, opt_enclosed,
306
" OPTIONALLY ENCLOSED BY");
331
" OPTIONALLY ENCLOSED BY");
307
332
end= add_load_option(end, escaped, " ESCAPED BY");
308
333
end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
309
334
if (opt_ignore_lines >= 0)
310
end= my_stpcpy(int64_t10_to_str(opt_ignore_lines,
311
my_stpcpy(end, " IGNORE "),10), " LINES");
335
end= strmov(longlong10_to_str(opt_ignore_lines,
336
strmov(end, " IGNORE "),10), " LINES");
313
end= my_stpcpy(my_stpcpy(my_stpcpy(end, " ("), opt_columns), ")");
338
end= strmov(strmov(strmov(end, " ("), opt_columns), ")");
316
if (drizzle_query(drizzle, sql_statement))
341
if (mysql_query(mysql, sql_statement))
318
db_error_with_table(drizzle, tablename);
343
db_error_with_table(mysql, tablename);
323
if (drizzle_info(drizzle)) /* If NULL-pointer, print nothing */
348
if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
325
350
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)
359
static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
361
DYNAMIC_STRING query;
338
363
char tablename[FN_REFLEN];
341
366
fprintf(stdout, "Locking tables for write\n");
342
query.append("LOCK TABLES ");
367
init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
343
368
for (i=0 ; i < tablecount ; i++)
345
370
fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
346
query.append(tablename);
347
query.append(" WRITE,");
371
dynstr_append(&query, tablename);
372
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 */
374
if (mysql_real_query(mysql, query.str, query.length-1))
375
db_error(mysql); /* We shall countinue here, if --force was given */
356
static DRIZZLE *db_connect(char *host, char *database,
381
static MYSQL *db_connect(char *host, char *database,
357
382
char *user, char *passwd)
361
386
fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
362
if (!(drizzle= drizzle_create(NULL)))
387
if (!(mysql= mysql_init(NULL)))
364
389
if (opt_compress)
365
drizzle_options(drizzle,DRIZZLE_OPT_COMPRESS,NULL);
390
mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
366
391
if (opt_local_file)
367
drizzle_options(drizzle,DRIZZLE_OPT_LOCAL_INFILE,
368
(char*) &opt_local_file);
392
mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
393
(char*) &opt_local_file);
369
394
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,
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,
375
ignore_errors=0; /* NO RETURN FROM db_error */
404
ignore_errors=0; /* NO RETURN FROM db_error */
378
drizzle->reconnect= 0;
380
409
fprintf(stdout, "Selecting database %s\n", database);
381
if (drizzle_select_db(drizzle, database))
410
if (mysql_select_db(mysql, database))
391
static void db_disconnect(char *host, DRIZZLE *drizzle)
420
static void db_disconnect(char *host, MYSQL *mysql)
394
423
fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
395
drizzle_close(drizzle);
400
static void safe_exit(int error, DRIZZLE *drizzle)
429
static void safe_exit(int error, MYSQL *mysql)
402
431
if (ignore_errors)
405
drizzle_close(drizzle);
411
static void db_error_with_table(DRIZZLE *drizzle, char *table)
440
static void db_error_with_table(MYSQL *mysql, char *table)
413
442
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);
443
MYF(0), mysql_errno(mysql), mysql_error(mysql), table);
420
static void db_error(DRIZZLE *drizzle)
449
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);
451
my_printf_error(0,"Error: %d %s", MYF(0), mysql_errno(mysql), mysql_error(mysql));
427
456
static char *add_load_option(char *ptr, const char *object,
428
const char *statement)
457
const char *statement)
432
461
/* Don't escape hex constants */
433
462
if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
434
ptr= strxmov(ptr," ",statement," ",object,NULL);
463
ptr= strxmov(ptr," ",statement," ",object,NullS);
437
466
/* char constant; escape */
438
ptr= strxmov(ptr," ",statement," '",NULL);
467
ptr= strxmov(ptr," ",statement," '",NullS);
439
468
ptr= field_escape(ptr,object,(uint) strlen(object));