2
Copyright (C) 2010 Vijay Samuel
3
Copyright (C) 2010 Brian Aker
4
Copyright (C) 2000-2006 MySQL AB
5
Copyright (C) 2008-2009 Sun Microsystems, Inc
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; version 2 of the License.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
20
#define IMPORT_VERSION "4.0"
1
/* Copyright (C) 2000-2006 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
** mysqlimport.c - Imports all given files
20
** *************************
22
** * AUTHOR: Monty & Jani *
23
** * DATE: June 24, 1997 *
25
** *************************
27
#define IMPORT_VERSION "3.7"
22
29
#include "client_priv.h"
27
#include <boost/program_options.hpp>
30
/* Added this for string translation. */
31
#include <drizzled/gettext.h>
32
#include <drizzled/configmake.h>
34
namespace po= boost::program_options;
36
using namespace drizzled;
38
extern "C" void * worker_thread(void *arg);
42
const char *program_name= "drizzlesimport";
30
#include "mysql_version.h"
31
#ifdef HAVE_LIBPTHREAD
32
#include <my_pthread.h>
44
36
/* Global Thread counter */
38
#ifdef HAVE_LIBPTHREAD
46
39
pthread_mutex_t counter_mutex;
47
40
pthread_cond_t count_threshhold;
49
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
50
drizzle_return_t ret, char *table);
51
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);
52
46
static char *add_load_option(char *ptr,const char *object,
53
const char *statement);
55
static bool verbose= false, ignore_errors= false,
56
opt_delete= false, opt_replace= false, silent= false,
57
ignore_unique= false, opt_low_priority= false,
58
use_drizzle_protocol= false, opt_local_file;
60
static uint32_t opt_use_threads;
61
static uint32_t opt_drizzle_port= 0;
62
static int64_t opt_ignore_lines= -1;
64
std::string opt_columns,
78
static int get_options(void)
81
if (! enclosed.empty() && ! opt_enclosed.empty())
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;
68
static struct my_option my_long_options[] =
70
{"character-sets-dir", OPT_CHARSETS_DIR,
71
"Directory where character sets are.", (uchar**) &charsets_dir,
72
(uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
73
{"default-character-set", OPT_DEFAULT_CHARSET,
74
"Set the default character set.", (uchar**) &default_charset,
75
(uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
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.",
78
(uchar**) &opt_columns, (uchar**) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
80
{"compress", 'C', "Use compression in server/client protocol.",
81
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
83
{"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
84
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
85
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
86
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
87
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
88
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
89
(uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
90
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},
93
{"fields-terminated-by", OPT_FTB,
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},
96
{"fields-enclosed-by", OPT_ENC,
97
"Fields in the importfile are enclosed by ...", (uchar**) &enclosed,
98
(uchar**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
99
{"fields-optionally-enclosed-by", OPT_O_ENC,
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},
102
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
103
(uchar**) &escaped, (uchar**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
105
{"force", 'f', "Continue even if we get an sql-error.",
106
(uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
108
{"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG,
110
{"host", 'h', "Connect to host.", (uchar**) ¤t_host,
111
(uchar**) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
112
{"ignore", 'i', "If duplicate unique key was found, keep old row.",
113
(uchar**) &ignore, (uchar**) &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
114
{"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.",
115
(uchar**) &opt_ignore_lines, (uchar**) &opt_ignore_lines, 0, GET_LL,
116
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
117
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
118
(uchar**) &lines_terminated, (uchar**) &lines_terminated, 0, GET_STR,
119
REQUIRED_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},
122
{"lock-tables", 'l', "Lock all tables for write (this disables threads).",
123
(uchar**) &lock_tables, (uchar**) &lock_tables, 0, GET_BOOL, NO_ARG,
125
{"low-priority", OPT_LOW_PRIORITY,
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},
129
"Password to use when connecting to server. If password is not given it's asked from the tty.",
130
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
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
(uchar**) &opt_mysql_port,
138
(uchar**) &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).",
141
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
142
{"replace", 'r', "If duplicate unique key was found, replace old row.",
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,
150
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
151
{"socket", 'S', "Socket file to use for connection.",
152
(uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
153
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
154
{"use-threads", OPT_USE_THREADS,
155
"Load files in parallel. The argument is the number "
156
"of threads to use for loading data.",
157
(uchar**) &opt_use_threads, (uchar**) &opt_use_threads, 0,
158
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
159
#ifndef DONT_ALLOW_USER_CHANGE
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},
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},
165
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
166
NO_ARG, 0, 0, 0, 0, 0, 0},
167
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
171
static const char *load_default_groups[]= { "mysqlimport","client",0 };
173
#include <help_start.h>
175
static void print_version(void)
177
printf("%s Ver %s Distrib %s, for %s (%s)\n" ,my_progname,
178
IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
182
static void usage(void)
185
puts("Copyright (C) 2000-2006 MySQL AB");
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");
188
Loads tables from text files in various formats. The base name of the\n\
189
text file must be the name of the table that should be used.\n\
190
If one uses sockets to connect to the MySQL server, the server will open and\n\
191
read the text file directly. In other cases the client will open the text\n\
192
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
194
printf("\nUsage: %s [OPTIONS] database textfile...",my_progname);
195
print_defaults("my",load_default_groups);
196
my_print_help(my_long_options);
197
my_print_variables(my_long_options);
200
#include <help_end.h>
203
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
210
char *start=argument;
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 */
215
start[1]=0; /* Cut length of argument */
221
case OPT_MYSQL_PROTOCOL:
222
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
226
DBUG_PUSH(argument ? argument : "d:t:o");
229
case 'V': print_version(); exit(0);
239
static int get_options(int *argc, char ***argv)
243
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
246
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
247
if (debug_check_flag)
248
my_end_arg= MY_CHECK_ERROR;
250
if (enclosed && opt_enclosed)
83
252
fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n");
86
if (opt_replace && ignore_unique)
255
if (replace && ignore)
88
fprintf(stderr, "You can't use --ignore_unique (-i) and --replace (-r) at the same time.\n");
257
fprintf(stderr, "You can't use --ignore (-i) and --replace (-r) at the same time.\n");
260
if (strcmp(default_charset, charset_info->csname) &&
261
!(charset_info= get_charset_by_csname(default_charset,
262
MY_CS_PRIMARY, MYF(MY_WME))))
269
current_db= *((*argv)++);
93
opt_password=client_get_tty_password(NULL);
272
opt_password=get_tty_password(NullS);
99
static int write_to_table(char *filename, drizzle_con_st *con)
278
static int write_to_table(char *filename, MYSQL *mysql)
101
280
char tablename[FN_REFLEN], hard_path[FN_REFLEN],
102
281
sql_statement[FN_REFLEN*16+256], *end;
103
drizzle_result_st result;
104
drizzle_return_t ret;
282
DBUG_ENTER("write_to_table");
283
DBUG_PRINT("enter",("filename: %s",filename));
106
internal::fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
107
if (not opt_local_file)
108
strcpy(hard_path,filename);
285
fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
287
strmov(hard_path,filename);
110
internal::my_load_path(hard_path, filename, NULL); /* filename includes the path */
289
my_load_path(hard_path, filename, NULL); /* filename includes the path */
115
294
fprintf(stdout, "Deleting the old data from table %s\n", tablename);
116
295
#ifdef HAVE_SNPRINTF
117
snprintf(sql_statement, sizeof(sql_statement), "DELETE FROM %s", tablename);
296
snprintf(sql_statement, FN_REFLEN*16+256, "DELETE FROM %s", tablename);
119
snprintf(sql_statement, sizeof(sql_statement), "DELETE FROM %s", tablename);
298
sprintf(sql_statement, "DELETE FROM %s", tablename);
121
if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
122
ret != DRIZZLE_RETURN_OK)
300
if (mysql_query(mysql, sql_statement))
124
db_error(con, &result, ret, tablename);
302
db_error_with_table(mysql, tablename);
127
drizzle_result_free(&result);
306
to_unix_path(hard_path);
131
309
if (opt_local_file)
132
310
fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
133
hard_path, tablename);
311
hard_path, tablename);
135
313
fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
136
hard_path, tablename);
314
hard_path, tablename);
138
snprintf(sql_statement, sizeof(sql_statement), "LOAD DATA %s %s INFILE '%s'",
139
opt_low_priority ? "LOW_PRIORITY" : "",
140
opt_local_file ? "LOCAL" : "", hard_path);
141
end= strchr(sql_statement, '\0');
143
end= strcpy(end, " REPLACE")+8;
145
end= strcpy(end, " IGNORE")+7;
147
end+= sprintf(end, " INTO TABLE %s", tablename);
149
if (! fields_terminated.empty() || ! enclosed.empty() || ! opt_enclosed.empty() || ! escaped.empty())
150
end= strcpy(end, " FIELDS")+7;
151
end= add_load_option(end, (char *)fields_terminated.c_str(), " TERMINATED BY");
152
end= add_load_option(end, (char *)enclosed.c_str(), " ENCLOSED BY");
153
end= add_load_option(end, (char *)opt_enclosed.c_str(),
154
" OPTIONALLY ENCLOSED BY");
155
end= add_load_option(end, (char *)escaped.c_str(), " ESCAPED BY");
156
end= add_load_option(end, (char *)lines_terminated.c_str(), " LINES TERMINATED BY");
316
sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
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);
326
if (fields_terminated || enclosed || opt_enclosed || escaped)
327
end= strmov(end, " FIELDS");
328
end= add_load_option(end, fields_terminated, " TERMINATED BY");
329
end= add_load_option(end, enclosed, " ENCLOSED BY");
330
end= add_load_option(end, opt_enclosed,
331
" OPTIONALLY ENCLOSED BY");
332
end= add_load_option(end, escaped, " ESCAPED BY");
333
end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
157
334
if (opt_ignore_lines >= 0)
159
end= strcpy(end, " IGNORE ")+8;
160
ostringstream buffer;
161
buffer << opt_ignore_lines;
162
end= strcpy(end, buffer.str().c_str())+ buffer.str().size();
163
end= strcpy(end, " LINES")+6;
165
if (! opt_columns.empty())
167
end= strcpy(end, " (")+2;
168
end= strcpy(end, (char *)opt_columns.c_str()+opt_columns.length());
169
end= strcpy(end, ")")+1;
335
end= strmov(longlong10_to_str(opt_ignore_lines,
336
strmov(end, " IGNORE "),10), " LINES");
338
end= strmov(strmov(strmov(end, " ("), opt_columns), ")");
173
if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
174
ret != DRIZZLE_RETURN_OK)
341
if (mysql_query(mysql, sql_statement))
176
db_error(con, &result, ret, tablename);
343
db_error_with_table(mysql, tablename);
181
if (strcmp(drizzle_result_info(&result), ""))
348
if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
183
fprintf(stdout, "%s.%s: %s\n", current_db.c_str(), tablename,
184
drizzle_result_info(&result));
350
fprintf(stdout, "%s.%s: %s\n", current_db, tablename,
187
drizzle_result_free(&result);
192
static drizzle_con_st *db_connect(const string host, const string database,
193
const string user, const string passwd)
197
drizzle_return_t ret;
200
fprintf(stdout, "Connecting to %s, using protocol %s...\n", ! host.empty() ? host.c_str() : "localhost", opt_protocol.c_str());
201
if (!(drizzle= drizzle_create(NULL)))
203
if (!(con= drizzle_con_add_tcp(drizzle,NULL,(char *)host.c_str(),opt_drizzle_port,(char *)user.c_str(),(char *)passwd.c_str(),
204
(char *)database.c_str(), use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL)))
209
if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
211
ignore_errors=0; /* NO RETURN FROM db_error */
212
db_error(con, NULL, ret, NULL);
216
fprintf(stdout, "Selecting database %s\n", database.c_str());
223
static void db_disconnect(const string host, drizzle_con_st *con)
226
fprintf(stdout, "Disconnecting from %s\n", ! host.empty() ? host.c_str() : "localhost");
227
drizzle_free(drizzle_con_drizzle(con));
232
static void safe_exit(int error, drizzle_con_st *con)
359
static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
361
DYNAMIC_STRING query;
363
char tablename[FN_REFLEN];
366
fprintf(stdout, "Locking tables for write\n");
367
init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
368
for (i=0 ; i < tablecount ; i++)
370
fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
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 */
381
static MYSQL *db_connect(char *host, char *database,
382
char *user, char *passwd)
386
fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
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 */
409
fprintf(stdout, "Selecting database %s\n", database);
410
if (mysql_select_db(mysql, database))
420
static void db_disconnect(char *host, MYSQL *mysql)
423
fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
429
static void safe_exit(int error, MYSQL *mysql)
234
431
if (ignore_errors)
237
drizzle_free(drizzle_con_drizzle(con));
243
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
244
drizzle_return_t ret, char *table)
246
if (ret == DRIZZLE_RETURN_ERROR_CODE)
248
fprintf(stdout, "Error: %d, %s%s%s",
249
drizzle_result_error_code(result),
250
drizzle_result_error(result),
251
table ? ", when using table: " : "", table ? table : "");
252
drizzle_result_free(result);
256
fprintf(stdout, "Error: %d, %s%s%s", ret, drizzle_con_error(con),
257
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));
264
456
static char *add_load_option(char *ptr, const char *object,
265
const char *statement)
457
const char *statement)
269
461
/* Don't escape hex constants */
270
462
if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
271
ptr+= sprintf(ptr, " %s %s", statement, object);
463
ptr= strxmov(ptr," ",statement," ",object,NullS);
274
466
/* char constant; escape */
275
ptr+= sprintf(ptr, " %s '", statement);
276
ptr= field_escape(ptr,object,(uint32_t) strlen(object));
467
ptr= strxmov(ptr," ",statement," '",NullS);
468
ptr= field_escape(ptr,object,(uint) strlen(object));
285
477
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
286
478
** This is done by doubleing ' and add a end -\ if needed to avoid
287
479
** syntax errors from the SQL parser.
290
static char *field_escape(char *to,const char *from,uint32_t length)
482
static char *field_escape(char *to,const char *from,uint length)
293
uint32_t end_backslashes=0;
485
uint end_backslashes=0;
295
487
for (end= from+length; from != end; from++)
298
490
if (*from == '\\')
299
491
end_backslashes^=1; /* find odd number of backslashes */
302
494
if (*from == '\'' && !end_backslashes)
303
*to++= *from; /* We want a dublicate of "'" for DRIZZLE */
495
*to++= *from; /* We want a dublicate of "'" for MySQL */
304
496
end_backslashes=0;
307
499
/* Add missing backslashes if user has specified odd number of backs.*/
308
500
if (end_backslashes)
313
void * worker_thread(void *arg)
507
#ifdef HAVE_LIBPTHREAD
508
static pthread_handler_t worker_thread(void *arg)
316
511
char *raw_table_name= (char *)arg;
319
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)))
522
if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
524
db_error(mysql); /* We shall countinue here, if --force was given */
325
529
We are not currently catching the error here.
327
if ((error= write_to_table(raw_table_name, con)))
531
if((error= write_to_table(raw_table_name, mysql)))
329
532
if (exitcode == 0)
337
db_disconnect(current_host, con);
537
db_disconnect(current_host, mysql);
340
539
pthread_mutex_lock(&counter_mutex);
342
541
pthread_cond_signal(&count_threshhold);
343
542
pthread_mutex_unlock(&counter_mutex);
349
550
int main(int argc, char **argv)
355
po::options_description commandline_options("Options used only in command line");
356
commandline_options.add_options()
358
("debug,#", po::value<string>(),
359
"Output debug log. Often this is 'd:t:o,filename'.")
360
("delete,d", po::value<bool>(&opt_delete)->default_value(false)->zero_tokens(),
361
"First delete all rows from table.")
362
("help,?", "Displays this help and exits.")
363
("ignore,i", po::value<bool>(&ignore_unique)->default_value(false)->zero_tokens(),
364
"If duplicate unique key was found, keep old row.")
365
("low-priority", po::value<bool>(&opt_low_priority)->default_value(false)->zero_tokens(),
366
"Use LOW_PRIORITY when updating the table.")
367
("replace,r", po::value<bool>(&opt_replace)->default_value(false)->zero_tokens(),
368
"If duplicate unique key was found, replace old row.")
369
("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
370
"Print info about the various stages.")
371
("version,V", "Output version information and exit.")
374
po::options_description import_options("Options specific to the drizzleimport");
375
import_options.add_options()
376
("columns,C", po::value<string>(&opt_columns)->default_value(""),
377
"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.")
378
("fields-terminated-by", po::value<string>(&fields_terminated)->default_value(""),
379
"Fields in the textfile are terminated by ...")
380
("fields-enclosed-by", po::value<string>(&enclosed)->default_value(""),
381
"Fields in the importfile are enclosed by ...")
382
("fields-optionally-enclosed-by", po::value<string>(&opt_enclosed)->default_value(""),
383
"Fields in the i.file are opt. enclosed by ...")
384
("fields-escaped-by", po::value<string>(&escaped)->default_value(""),
385
"Fields in the i.file are escaped by ...")
386
("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
387
"Continue even if we get an sql-error.")
388
("ignore-lines", po::value<int64_t>(&opt_ignore_lines)->default_value(0),
389
"Ignore first n lines of data infile.")
390
("lines-terminated-by", po::value<string>(&lines_terminated)->default_value(""),
391
"Lines in the i.file are terminated by ...")
392
("local,L", po::value<bool>(&opt_local_file)->default_value(false)->zero_tokens(),
393
"Read all files through the client.")
394
("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
396
("use-threads", po::value<uint32_t>(&opt_use_threads)->default_value(4),
397
"Load files in parallel. The argument is the number of threads to use for loading data (default is 4.")
400
po::options_description client_options("Options specific to the client");
401
client_options.add_options()
402
("host,h", po::value<string>(¤t_host)->default_value("localhost"),
404
("password,P", po::value<string>(&password),
405
"Password to use when connecting to server. If password is not given it's asked from the tty." )
406
("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
407
"Port number to use for connection")
408
("protocol", po::value<string>(&opt_protocol)->default_value("mysql"),
409
"The protocol of connection (mysql or drizzle).")
410
("user,u", po::value<string>(¤t_user)->default_value(""),
411
"User for login if not current user.")
414
po::options_description long_options("Allowed Options");
415
long_options.add(commandline_options).add(import_options).add(client_options);
417
std::string system_config_dir_import(SYSCONFDIR);
418
system_config_dir_import.append("/drizzle/drizzleimport.cnf");
420
std::string system_config_dir_client(SYSCONFDIR);
421
system_config_dir_client.append("/drizzle/client.cnf");
423
std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
425
po::variables_map vm;
427
// Disable allow_guessing
428
int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
430
po::store(po::command_line_parser(argc, argv).options(long_options).
431
style(style).extra_parser(parse_password_arg).run(), vm);
433
std::string user_config_dir_import(user_config_dir);
434
user_config_dir_import.append("/drizzle/drizzleimport.cnf");
436
std::string user_config_dir_client(user_config_dir);
437
user_config_dir_client.append("/drizzle/client.cnf");
439
ifstream user_import_ifs(user_config_dir_import.c_str());
440
po::store(parse_config_file(user_import_ifs, import_options), vm);
442
ifstream user_client_ifs(user_config_dir_client.c_str());
443
po::store(parse_config_file(user_client_ifs, client_options), vm);
445
ifstream system_import_ifs(system_config_dir_import.c_str());
446
store(parse_config_file(system_import_ifs, import_options), vm);
448
ifstream system_client_ifs(system_config_dir_client.c_str());
449
po::store(parse_config_file(system_client_ifs, client_options), vm);
452
if (vm.count("protocol"))
454
std::transform(opt_protocol.begin(), opt_protocol.end(),
455
opt_protocol.begin(), ::tolower);
457
if (not opt_protocol.compare("mysql"))
458
use_drizzle_protocol=false;
459
else if (not opt_protocol.compare("drizzle"))
460
use_drizzle_protocol=true;
463
cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
468
if (vm.count("port"))
471
/* If the port number is > 65535 it is not a valid port
472
This also helps with potential data loss casting unsigned long to a
474
if (opt_drizzle_port > 65535)
476
fprintf(stderr, _("Value supplied for port is not valid.\n"));
477
exit(EXIT_ARGUMENT_INVALID);
481
if( vm.count("password") )
483
if (!opt_password.empty())
484
opt_password.erase();
485
if (password == PASSWORD_SENTINEL)
491
opt_password= password;
501
if (vm.count("version"))
503
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n", program_name,
504
IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
507
if (vm.count("help") || argc < 2)
509
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n", program_name,
510
IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
511
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");
513
Loads tables from text files in various formats. The base name of the\n\
514
text file must be the name of the table that should be used.\n\
515
If one uses sockets to connect to the Drizzle server, the server will open and\n\
516
read the text file directly. In other cases the client will open the text\n\
517
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
519
printf("\nUsage: %s [OPTIONS] database textfile...", program_name);
556
load_defaults("my",load_default_groups,&argc,&argv);
557
/* argv is changed in the program */
559
if (get_options(&argc, &argv))
561
free_defaults(argv_to_free);
530
current_db= (*argv)++;
565
#ifdef HAVE_LIBPTHREAD
566
if (opt_use_threads && !lock_tables)
535
568
pthread_t mainthread; /* Thread descriptor */
536
569
pthread_attr_t attr; /* Thread attributes */