MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mysqlimport.c
1 /*
2  Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /*
19 ** mysqlimport.c - Imports all given files
20 ** into a table(s).
21 */
22 
23 #define IMPORT_VERSION "3.7"
24 
25 #include "client_priv.h"
26 #include "my_default.h"
27 #include "mysql_version.h"
28 #ifdef HAVE_LIBPTHREAD
29 #include <my_pthread.h>
30 #endif
31 
32 #include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
33 
34 
35 /* Global Thread counter */
36 uint counter;
37 #ifdef HAVE_LIBPTHREAD
38 pthread_mutex_t counter_mutex;
39 pthread_cond_t count_threshhold;
40 #endif
41 
42 static void db_error_with_table(MYSQL *mysql, char *table);
43 static void db_error(MYSQL *mysql);
44 static char *field_escape(char *to,const char *from,uint length);
45 static char *add_load_option(char *ptr,const char *object,
46  const char *statement);
47 
48 static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
49  replace=0,silent=0,ignore=0,opt_compress=0,
50  opt_low_priority= 0, tty_password= 0;
51 static my_bool debug_info_flag= 0, debug_check_flag= 0;
52 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*) MYSQL_AUTODETECT_CHARSET_NAME;
58 static uint opt_mysql_port= 0, opt_protocol= 0;
59 static char *opt_bind_addr = NULL;
60 static char * opt_mysql_unix_port=0;
61 static char *opt_plugin_dir= 0, *opt_default_auth= 0;
62 static longlong opt_ignore_lines= -1;
63 #include <sslopt-vars.h>
64 
65 #ifdef HAVE_SMEM
66 static char *shared_memory_base_name=0;
67 #endif
68 
69 static struct my_option my_long_options[] =
70 {
71  {"bind-address", 0, "IP address to bind to.",
72  (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
73  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
74  {"character-sets-dir", OPT_CHARSETS_DIR,
75  "Directory for character set files.", &charsets_dir,
76  &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
77  {"default-character-set", OPT_DEFAULT_CHARSET,
78  "Set the default character set.", &default_charset,
79  &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
80  {"columns", 'c',
81  "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.",
82  &opt_columns, &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
83  0, 0, 0},
84  {"compress", 'C', "Use compression in server/client protocol.",
85  &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
86  0, 0, 0},
87  {"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
88  GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
89  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
90  &debug_check_flag, &debug_check_flag, 0,
91  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
92  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
93  &debug_info_flag, &debug_info_flag,
94  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
95  {"default_auth", OPT_DEFAULT_AUTH,
96  "Default authentication client-side plugin to use.",
97  &opt_default_auth, &opt_default_auth, 0,
98  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
99  {"delete", 'd', "First delete all rows from table.", &opt_delete,
100  &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
101  {"fields-terminated-by", OPT_FTB,
102  "Fields in the input file are terminated by the given string.",
103  &fields_terminated, &fields_terminated, 0,
104  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
105  {"fields-enclosed-by", OPT_ENC,
106  "Fields in the import file are enclosed by the given character.",
107  &enclosed, &enclosed, 0,
108  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
109  {"fields-optionally-enclosed-by", OPT_O_ENC,
110  "Fields in the input file are optionally enclosed by the given character.",
111  &opt_enclosed, &opt_enclosed, 0,
112  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
113  {"fields-escaped-by", OPT_ESC,
114  "Fields in the input file are escaped by the given character.",
115  &escaped, &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
116  0, 0},
117  {"force", 'f', "Continue even if we get an SQL error.",
118  &ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
119  0, 0, 0, 0},
120  {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG,
121  0, 0, 0, 0, 0, 0},
122  {"host", 'h', "Connect to host.", &current_host,
123  &current_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
124  {"ignore", 'i', "If duplicate unique key was found, keep old row.",
125  &ignore, &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
126  {"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.",
127  &opt_ignore_lines, &opt_ignore_lines, 0, GET_LL,
128  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
129  {"lines-terminated-by", OPT_LTB,
130  "Lines in the input file are terminated by the given string.",
131  &lines_terminated, &lines_terminated, 0, GET_STR,
132  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
133  {"local", 'L', "Read all files through the client.", &opt_local_file,
134  &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
135  {"lock-tables", 'l', "Lock all tables for write (this disables threads).",
136  &lock_tables, &lock_tables, 0, GET_BOOL, NO_ARG,
137  0, 0, 0, 0, 0, 0},
138  {"low-priority", OPT_LOW_PRIORITY,
139  "Use LOW_PRIORITY when updating the table.", &opt_low_priority,
140  &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
141  {"password", 'p',
142  "Password to use when connecting to server. If password is not given it's asked from the tty.",
143  0, 0, 0, GET_PASSWORD, OPT_ARG, 0, 0, 0, 0, 0, 0},
144 #ifdef __WIN__
145  {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
146  NO_ARG, 0, 0, 0, 0, 0, 0},
147 #endif
148  {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
149  &opt_plugin_dir, &opt_plugin_dir, 0,
150  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
151  {"port", 'P', "Port number to use for connection or 0 for default to, in "
152  "order of preference, my.cnf, $MYSQL_TCP_PORT, "
153 #if MYSQL_PORT_DEFAULT == 0
154  "/etc/services, "
155 #endif
156  "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
157  &opt_mysql_port,
158  &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
159  0},
160  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).",
161  0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
162  {"replace", 'r', "If duplicate unique key was found, replace old row.",
163  &replace, &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
164 #ifdef HAVE_SMEM
165  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
166  "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name,
167  0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
168 #endif
169  {"silent", 's', "Be more silent.", &silent, &silent, 0,
170  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
171  {"socket", 'S', "The socket file to use for connection.",
172  &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR,
173  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
174 #include <sslopt-longopts.h>
175  {"use-threads", OPT_USE_THREADS,
176  "Load files in parallel. The argument is the number "
177  "of threads to use for loading data.",
178  &opt_use_threads, &opt_use_threads, 0,
179  GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
180 #ifndef DONT_ALLOW_USER_CHANGE
181  {"user", 'u', "User for login if not current user.", &current_user,
182  &current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
183 #endif
184  {"verbose", 'v', "Print info about the various stages.", &verbose,
185  &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
186  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
187  NO_ARG, 0, 0, 0, 0, 0, 0},
188  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
189 };
190 
191 
192 static const char *load_default_groups[]= { "mysqlimport","client",0 };
193 
194 
195 static void print_version(void)
196 {
197  printf("%s Ver %s Distrib %s, for %s (%s)\n" ,my_progname,
198  IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
199 }
200 
201 
202 static void usage(void)
203 {
204  print_version();
205  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
206  printf("\
207 Loads tables from text files in various formats. The base name of the\n\
208 text file must be the name of the table that should be used.\n\
209 If one uses sockets to connect to the MySQL server, the server will open and\n\
210 read the text file directly. In other cases the client will open the text\n\
211 file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
212 
213  printf("\nUsage: %s [OPTIONS] database textfile...",my_progname);
214  print_defaults("my",load_default_groups);
215  my_print_help(my_long_options);
216  my_print_variables(my_long_options);
217 }
218 
219 
220 static my_bool
221 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
222  char *argument)
223 {
224  switch(optid) {
225  case 'p':
226  if (argument == disabled_my_option)
227  argument= (char*) ""; /* Don't require password */
228  if (argument)
229  {
230  char *start=argument;
231  my_free(opt_password);
232  opt_password=my_strdup(argument,MYF(MY_FAE));
233  while (*argument) *argument++= 'x'; /* Destroy argument */
234  if (*start)
235  start[1]=0; /* Cut length of argument */
236  tty_password= 0;
237  }
238  else
239  tty_password= 1;
240  break;
241 #ifdef __WIN__
242  case 'W':
243  opt_protocol = MYSQL_PROTOCOL_PIPE;
244  opt_local_file=1;
245  break;
246 #endif
247  case OPT_MYSQL_PROTOCOL:
248  opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
249  opt->name);
250  break;
251  case '#':
252  DBUG_PUSH(argument ? argument : "d:t:o");
253  debug_check_flag= 1;
254  break;
255 #include <sslopt-case.h>
256  case 'V': print_version(); exit(0);
257  case 'I':
258  case '?':
259  usage();
260  exit(0);
261  }
262  return 0;
263 }
264 
265 
266 static int get_options(int *argc, char ***argv)
267 {
268  int ho_error;
269 
270  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
271  exit(ho_error);
272  if (debug_info_flag)
273  my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
274  if (debug_check_flag)
275  my_end_arg= MY_CHECK_ERROR;
276 
277  if (enclosed && opt_enclosed)
278  {
279  fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n");
280  return(1);
281  }
282  if (replace && ignore)
283  {
284  fprintf(stderr, "You can't use --ignore (-i) and --replace (-r) at the same time.\n");
285  return(1);
286  }
287  if (*argc < 2)
288  {
289  usage();
290  return 1;
291  }
292  current_db= *((*argv)++);
293  (*argc)--;
294  if (tty_password)
295  opt_password=get_tty_password(NullS);
296  return(0);
297 }
298 
299 
300 
301 static int write_to_table(char *filename, MYSQL *mysql)
302 {
303  char tablename[FN_REFLEN], hard_path[FN_REFLEN],
304  escaped_name[FN_REFLEN * 2 + 1],
305  sql_statement[FN_REFLEN*16+256], *end, *pos;
306  DBUG_ENTER("write_to_table");
307  DBUG_PRINT("enter",("filename: %s",filename));
308 
309  fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
310  if (!opt_local_file)
311  strmov(hard_path,filename);
312  else
313  my_load_path(hard_path, filename, NULL); /* filename includes the path */
314 
315  if (opt_delete)
316  {
317  if (verbose)
318  fprintf(stdout, "Deleting the old data from table %s\n", tablename);
319 #ifdef HAVE_SNPRINTF
320  snprintf(sql_statement, FN_REFLEN*16+256, "DELETE FROM %s", tablename);
321 #else
322  sprintf(sql_statement, "DELETE FROM %s", tablename);
323 #endif
324  if (mysql_query(mysql, sql_statement))
325  {
326  db_error_with_table(mysql, tablename);
327  DBUG_RETURN(1);
328  }
329  }
330  to_unix_path(hard_path);
331  if (verbose)
332  {
333  if (opt_local_file)
334  fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
335  hard_path, tablename);
336  else
337  fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
338  hard_path, tablename);
339  }
340  mysql_real_escape_string(mysql, escaped_name, hard_path,
341  (unsigned long) strlen(hard_path));
342  sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
343  opt_low_priority ? "LOW_PRIORITY" : "",
344  opt_local_file ? "LOCAL" : "", escaped_name);
345  end= strend(sql_statement);
346  if (replace)
347  end= strmov(end, " REPLACE");
348  if (ignore)
349  end= strmov(end, " IGNORE");
350  end= strmov(end, " INTO TABLE `");
351  /* Turn any ` into `` in table name. */
352  for (pos= tablename; *pos; pos++)
353  {
354  if (*pos == '`')
355  *end++= '`';
356  *end++= *pos;
357  }
358  end= strmov(end, "`");
359 
360  if (fields_terminated || enclosed || opt_enclosed || escaped)
361  end= strmov(end, " FIELDS");
362  end= add_load_option(end, fields_terminated, " TERMINATED BY");
363  end= add_load_option(end, enclosed, " ENCLOSED BY");
364  end= add_load_option(end, opt_enclosed,
365  " OPTIONALLY ENCLOSED BY");
366  end= add_load_option(end, escaped, " ESCAPED BY");
367  end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
368  if (opt_ignore_lines >= 0)
369  end= strmov(longlong10_to_str(opt_ignore_lines,
370  strmov(end, " IGNORE "),10), " LINES");
371  if (opt_columns)
372  end= strmov(strmov(strmov(end, " ("), opt_columns), ")");
373  *end= '\0';
374 
375  if (mysql_query(mysql, sql_statement))
376  {
377  db_error_with_table(mysql, tablename);
378  DBUG_RETURN(1);
379  }
380  if (!silent)
381  {
382  if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
383  {
384  fprintf(stdout, "%s.%s: %s\n", current_db, tablename,
385  mysql_info(mysql));
386  }
387  }
388  DBUG_RETURN(0);
389 }
390 
391 
392 
393 static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
394 {
396  int i;
397  char tablename[FN_REFLEN];
398 
399  if (verbose)
400  fprintf(stdout, "Locking tables for write\n");
401  init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
402  for (i=0 ; i < tablecount ; i++)
403  {
404  fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
405  dynstr_append(&query, tablename);
406  dynstr_append(&query, " WRITE,");
407  }
408  if (mysql_real_query(mysql, query.str, query.length-1))
409  db_error(mysql); /* We shall countinue here, if --force was given */
410 }
411 
412 
413 
414 
415 static MYSQL *db_connect(char *host, char *database,
416  char *user, char *passwd)
417 {
418  MYSQL *mysql;
419  if (verbose)
420  fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
421  if (!(mysql= mysql_init(NULL)))
422  return 0;
423  if (opt_compress)
424  mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
425  if (opt_local_file)
426  mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
427  (char*) &opt_local_file);
428 #ifdef HAVE_OPENSSL
429  if (opt_use_ssl)
430  {
431  mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
432  opt_ssl_capath, opt_ssl_cipher);
433  mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
434  mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
435  }
436  mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
437  (char*)&opt_ssl_verify_server_cert);
438 #endif
439  if (opt_protocol)
440  mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
441  if (opt_bind_addr)
442  mysql_options(mysql,MYSQL_OPT_BIND,opt_bind_addr);
443 #ifdef HAVE_SMEM
444  if (shared_memory_base_name)
445  mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
446 #endif
447 
448  if (opt_plugin_dir && *opt_plugin_dir)
449  mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
450 
451  if (opt_default_auth && *opt_default_auth)
452  mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
453 
454  mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
455  mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
456  mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
457  "program_name", "mysqlimport");
458  if (!(mysql_real_connect(mysql,host,user,passwd,
459  database,opt_mysql_port,opt_mysql_unix_port,
460  0)))
461  {
462  ignore_errors=0; /* NO RETURN FROM db_error */
463  db_error(mysql);
464  }
465  mysql->reconnect= 0;
466  if (verbose)
467  fprintf(stdout, "Selecting database %s\n", database);
468  if (mysql_select_db(mysql, database))
469  {
470  ignore_errors=0;
471  db_error(mysql);
472  }
473  return mysql;
474 }
475 
476 
477 
478 static void db_disconnect(char *host, MYSQL *mysql)
479 {
480  if (verbose)
481  fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
482  mysql_close(mysql);
483 }
484 
485 
486 
487 static void safe_exit(int error, MYSQL *mysql)
488 {
489  if (ignore_errors)
490  return;
491  if (mysql)
492  mysql_close(mysql);
493  exit(error);
494 }
495 
496 
497 
498 static void db_error_with_table(MYSQL *mysql, char *table)
499 {
500  my_printf_error(0,"Error: %d, %s, when using table: %s",
501  MYF(0), mysql_errno(mysql), mysql_error(mysql), table);
502  safe_exit(1, mysql);
503 }
504 
505 
506 
507 static void db_error(MYSQL *mysql)
508 {
509  my_printf_error(0,"Error: %d %s", MYF(0), mysql_errno(mysql), mysql_error(mysql));
510  safe_exit(1, mysql);
511 }
512 
513 
514 static char *add_load_option(char *ptr, const char *object,
515  const char *statement)
516 {
517  if (object)
518  {
519  /* Don't escape hex constants */
520  if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
521  ptr= strxmov(ptr," ",statement," ",object,NullS);
522  else
523  {
524  /* char constant; escape */
525  ptr= strxmov(ptr," ",statement," '",NullS);
526  ptr= field_escape(ptr,object,(uint) strlen(object));
527  *ptr++= '\'';
528  }
529  }
530  return ptr;
531 }
532 
533 /*
534 ** Allow the user to specify field terminator strings like:
535 ** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
536 ** This is done by doubleing ' and add a end -\ if needed to avoid
537 ** syntax errors from the SQL parser.
538 */
539 
540 static char *field_escape(char *to,const char *from,uint length)
541 {
542  const char *end;
543  uint end_backslashes=0;
544 
545  for (end= from+length; from != end; from++)
546  {
547  *to++= *from;
548  if (*from == '\\')
549  end_backslashes^=1; /* find odd number of backslashes */
550  else
551  {
552  if (*from == '\'' && !end_backslashes)
553  *to++= *from; /* We want a dublicate of "'" for MySQL */
554  end_backslashes=0;
555  }
556  }
557  /* Add missing backslashes if user has specified odd number of backs.*/
558  if (end_backslashes)
559  *to++= '\\';
560  return to;
561 }
562 
563 int exitcode= 0;
564 
565 #ifdef HAVE_LIBPTHREAD
566 pthread_handler_t worker_thread(void *arg)
567 {
568  int error;
569  char *raw_table_name= (char *)arg;
570  MYSQL *mysql= 0;
571 
572  if (mysql_thread_init())
573  goto error;
574 
575  if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
576  {
577  goto error;
578  }
579 
580  if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
581  {
582  db_error(mysql); /* We shall countinue here, if --force was given */
583  goto error;
584  }
585 
586  /*
587  We are not currently catching the error here.
588  */
589  if((error= write_to_table(raw_table_name, mysql)))
590  if (exitcode == 0)
591  exitcode= error;
592 
593 error:
594  if (mysql)
595  db_disconnect(current_host, mysql);
596 
597  pthread_mutex_lock(&counter_mutex);
598  counter--;
599  pthread_cond_signal(&count_threshhold);
600  pthread_mutex_unlock(&counter_mutex);
601  mysql_thread_end();
602 
603  return 0;
604 }
605 #endif
606 
607 
608 int main(int argc, char **argv)
609 {
610  int error=0;
611  char **argv_to_free;
612  MY_INIT(argv[0]);
613 
614  my_getopt_use_args_separator= TRUE;
615  if (load_defaults("my",load_default_groups,&argc,&argv))
616  return 1;
617  my_getopt_use_args_separator= FALSE;
618 
619  /* argv is changed in the program */
620  argv_to_free= argv;
621  if (get_options(&argc, &argv))
622  {
623  free_defaults(argv_to_free);
624  return(1);
625  }
626 
627 #ifdef HAVE_LIBPTHREAD
628  if (opt_use_threads && !lock_tables)
629  {
630  pthread_t mainthread; /* Thread descriptor */
631  pthread_attr_t attr; /* Thread attributes */
632  pthread_attr_init(&attr);
633  pthread_attr_setdetachstate(&attr,
634  PTHREAD_CREATE_DETACHED);
635 
636  pthread_mutex_init(&counter_mutex, NULL);
637  pthread_cond_init(&count_threshhold, NULL);
638 
639  for (counter= 0; *argv != NULL; argv++) /* Loop through tables */
640  {
641  pthread_mutex_lock(&counter_mutex);
642  while (counter == opt_use_threads)
643  {
644  struct timespec abstime;
645 
646  set_timespec(abstime, 3);
647  pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
648  }
649  /* Before exiting the lock we set ourselves up for the next thread */
650  counter++;
651  pthread_mutex_unlock(&counter_mutex);
652  /* now create the thread */
653  if (pthread_create(&mainthread, &attr, worker_thread,
654  (void *)*argv) != 0)
655  {
656  pthread_mutex_lock(&counter_mutex);
657  counter--;
658  pthread_mutex_unlock(&counter_mutex);
659  fprintf(stderr,"%s: Could not create thread\n",
660  my_progname);
661  }
662  }
663 
664  /*
665  We loop until we know that all children have cleaned up.
666  */
667  pthread_mutex_lock(&counter_mutex);
668  while (counter)
669  {
670  struct timespec abstime;
671 
672  set_timespec(abstime, 3);
673  pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
674  }
675  pthread_mutex_unlock(&counter_mutex);
676  pthread_mutex_destroy(&counter_mutex);
677  pthread_cond_destroy(&count_threshhold);
678  pthread_attr_destroy(&attr);
679  }
680  else
681 #endif
682  {
683  MYSQL *mysql= 0;
684  if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
685  {
686  free_defaults(argv_to_free);
687  return(1); /* purecov: deadcode */
688  }
689 
690  if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
691  {
692  db_error(mysql); /* We shall countinue here, if --force was given */
693  return(1);
694  }
695 
696  if (lock_tables)
697  lock_table(mysql, argc, argv);
698  for (; *argv != NULL; argv++)
699  if ((error= write_to_table(*argv, mysql)))
700  if (exitcode == 0)
701  exitcode= error;
702  db_disconnect(current_host, mysql);
703  }
704  my_free(opt_password);
705 #ifdef HAVE_SMEM
706  my_free(shared_memory_base_name);
707 #endif
708  free_defaults(argv_to_free);
709  my_end(my_end_arg);
710  return(exitcode);
711 }