00001 /* Copyright (C) 2000 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /* 00018 ** mysqlimport.c - Imports all given files 00019 ** into a table(s). 00020 ** 00021 ** ************************* 00022 ** * * 00023 ** * AUTHOR: Monty & Jani * 00024 ** * DATE: June 24, 1997 * 00025 ** * * 00026 ** ************************* 00027 */ 00028 #define IMPORT_VERSION "3.5" 00029 00030 #include "client_priv.h" 00031 #include "mysql_version.h" 00032 #ifdef HAVE_LIBPTHREAD 00033 #include <my_pthread.h> 00034 #endif 00035 00036 00037 /* Global Thread counter */ 00038 int counter; 00039 #ifdef HAVE_LIBPTHREAD 00040 pthread_mutex_t counter_mutex; 00041 pthread_cond_t count_threshhold; 00042 #endif 00043 00044 static void db_error_with_table(MYSQL *mysql, char *table); 00045 static void db_error(MYSQL *mysql); 00046 static char *field_escape(char *to,const char *from,uint length); 00047 static char *add_load_option(char *ptr,const char *object, 00048 const char *statement); 00049 00050 static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0, 00051 replace=0,silent=0,ignore=0,opt_compress=0, 00052 opt_low_priority= 0, tty_password= 0; 00053 static my_bool opt_use_threads= 0; 00054 static uint opt_local_file=0; 00055 static char *opt_password=0, *current_user=0, 00056 *current_host=0, *current_db=0, *fields_terminated=0, 00057 *lines_terminated=0, *enclosed=0, *opt_enclosed=0, 00058 *escaped=0, *opt_columns=0, 00059 *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; 00060 static uint opt_mysql_port= 0, opt_protocol= 0; 00061 static my_string opt_mysql_unix_port=0; 00062 static longlong opt_ignore_lines= -1; 00063 static CHARSET_INFO *charset_info= &my_charset_latin1; 00064 #include <sslopt-vars.h> 00065 00066 #ifdef HAVE_SMEM 00067 static char *shared_memory_base_name=0; 00068 #endif 00069 00070 static struct my_option my_long_options[] = 00071 { 00072 #ifdef __NETWARE__ 00073 {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 00074 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 00075 #endif 00076 {"character-sets-dir", OPT_CHARSETS_DIR, 00077 "Directory where character sets are.", (gptr*) &charsets_dir, 00078 (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00079 {"default-character-set", OPT_DEFAULT_CHARSET, 00080 "Set the default character set.", (gptr*) &default_charset, 00081 (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00082 {"columns", 'c', 00083 "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.", 00084 (gptr*) &opt_columns, (gptr*) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 00085 0, 0, 0}, 00086 {"compress", 'C', "Use compression in server/client protocol.", 00087 (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 00088 0, 0, 0}, 00089 {"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, 00090 GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 00091 {"delete", 'd', "First delete all rows from table.", (gptr*) &opt_delete, 00092 (gptr*) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00093 {"fields-terminated-by", OPT_FTB, 00094 "Fields in the textfile are terminated by ...", (gptr*) &fields_terminated, 00095 (gptr*) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00096 {"fields-enclosed-by", OPT_ENC, 00097 "Fields in the importfile are enclosed by ...", (gptr*) &enclosed, 00098 (gptr*) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00099 {"fields-optionally-enclosed-by", OPT_O_ENC, 00100 "Fields in the i.file are opt. enclosed by ...", (gptr*) &opt_enclosed, 00101 (gptr*) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00102 {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...", 00103 (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 00104 0, 0}, 00105 {"force", 'f', "Continue even if we get an sql-error.", 00106 (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 00107 0, 0, 0, 0}, 00108 {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG, 00109 0, 0, 0, 0, 0, 0}, 00110 {"host", 'h', "Connect to host.", (gptr*) ¤t_host, 00111 (gptr*) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00112 {"ignore", 'i', "If duplicate unique key was found, keep old row.", 00113 (gptr*) &ignore, (gptr*) &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00114 {"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.", 00115 (gptr*) &opt_ignore_lines, (gptr*) &opt_ignore_lines, 0, GET_LL, 00116 REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00117 {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...", 00118 (gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR, 00119 REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00120 {"local", 'L', "Read all files through the client.", (gptr*) &opt_local_file, 00121 (gptr*) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00122 {"lock-tables", 'l', "Lock all tables for write (this disables threads).", 00123 (gptr*) &lock_tables, (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 00124 0, 0, 0, 0, 0, 0}, 00125 {"low-priority", OPT_LOW_PRIORITY, 00126 "Use LOW_PRIORITY when updating the table.", (gptr*) &opt_low_priority, 00127 (gptr*) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00128 {"password", 'p', 00129 "Password to use when connecting to server. If password is not given it's asked from the tty.", 00130 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 00131 #ifdef __WIN__ 00132 {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, 00133 NO_ARG, 0, 0, 0, 0, 0, 0}, 00134 #endif 00135 {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, 00136 (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 00137 0}, 00138 {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 00139 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00140 {"replace", 'r', "If duplicate unique key was found, replace old row.", 00141 (gptr*) &replace, (gptr*) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00142 #ifdef HAVE_SMEM 00143 {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, 00144 "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 00145 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00146 #endif 00147 {"silent", 's', "Be more silent.", (gptr*) &silent, (gptr*) &silent, 0, 00148 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00149 {"socket", 'S', "Socket file to use for connection.", 00150 (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, 00151 REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00152 #include <sslopt-longopts.h> 00153 {"use-threads", OPT_USE_THREADS, 00154 "Load files in parallel. The argument is the number " 00155 "of threads to use for loading data.", 00156 (gptr*) &opt_use_threads, (gptr*) &opt_use_threads, 0, 00157 GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00158 #ifndef DONT_ALLOW_USER_CHANGE 00159 {"user", 'u', "User for login if not current user.", (gptr*) ¤t_user, 00160 (gptr*) ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00161 #endif 00162 {"verbose", 'v', "Print info about the various stages.", (gptr*) &verbose, 00163 (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00164 {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, 00165 NO_ARG, 0, 0, 0, 0, 0, 0}, 00166 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} 00167 }; 00168 00169 00170 static const char *load_default_groups[]= { "mysqlimport","client",0 }; 00171 00172 #include <help_start.h> 00173 00174 static void print_version(void) 00175 { 00176 printf("%s Ver %s Distrib %s, for %s (%s)\n" ,my_progname, 00177 IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); 00178 NETWARE_SET_SCREEN_MODE(1); 00179 } 00180 00181 00182 static void usage(void) 00183 { 00184 print_version(); 00185 puts("Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB"); 00186 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"); 00187 printf("\ 00188 Loads tables from text files in various formats. The base name of the\n\ 00189 text file must be the name of the table that should be used.\n\ 00190 If one uses sockets to connect to the MySQL server, the server will open and\n\ 00191 read the text file directly. In other cases the client will open the text\n\ 00192 file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n"); 00193 00194 printf("\nUsage: %s [OPTIONS] database textfile...",my_progname); 00195 print_defaults("my",load_default_groups); 00196 my_print_help(my_long_options); 00197 my_print_variables(my_long_options); 00198 } 00199 00200 #include <help_end.h> 00201 00202 static my_bool 00203 get_one_option(int optid, const struct my_option *opt __attribute__((unused)), 00204 char *argument) 00205 { 00206 switch(optid) { 00207 #ifdef __NETWARE__ 00208 case OPT_AUTO_CLOSE: 00209 setscreenmode(SCR_AUTOCLOSE_ON_EXIT); 00210 break; 00211 #endif 00212 case 'p': 00213 if (argument) 00214 { 00215 char *start=argument; 00216 my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); 00217 opt_password=my_strdup(argument,MYF(MY_FAE)); 00218 while (*argument) *argument++= 'x'; /* Destroy argument */ 00219 if (*start) 00220 start[1]=0; /* Cut length of argument */ 00221 tty_password= 0; 00222 } 00223 else 00224 tty_password= 1; 00225 break; 00226 #ifdef __WIN__ 00227 case 'W': 00228 opt_protocol = MYSQL_PROTOCOL_PIPE; 00229 opt_local_file=1; 00230 break; 00231 #endif 00232 case OPT_MYSQL_PROTOCOL: 00233 { 00234 if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0) 00235 { 00236 fprintf(stderr, "Unknown option to protocol: %s\n", argument); 00237 exit(1); 00238 } 00239 break; 00240 } 00241 case '#': 00242 DBUG_PUSH(argument ? argument : "d:t:o"); 00243 break; 00244 #include <sslopt-case.h> 00245 case 'V': print_version(); exit(0); 00246 case 'I': 00247 case '?': 00248 usage(); 00249 exit(0); 00250 } 00251 return 0; 00252 } 00253 00254 00255 static int get_options(int *argc, char ***argv) 00256 { 00257 int ho_error; 00258 00259 if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) 00260 exit(ho_error); 00261 00262 if (enclosed && opt_enclosed) 00263 { 00264 fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n"); 00265 return(1); 00266 } 00267 if (replace && ignore) 00268 { 00269 fprintf(stderr, "You can't use --ignore (-i) and --replace (-r) at the same time.\n"); 00270 return(1); 00271 } 00272 if (strcmp(default_charset, charset_info->csname) && 00273 !(charset_info= get_charset_by_csname(default_charset, 00274 MY_CS_PRIMARY, MYF(MY_WME)))) 00275 exit(1); 00276 if (*argc < 2) 00277 { 00278 usage(); 00279 return 1; 00280 } 00281 current_db= *((*argv)++); 00282 (*argc)--; 00283 if (tty_password) 00284 opt_password=get_tty_password(NullS); 00285 return(0); 00286 } 00287 00288 00289 00290 static int write_to_table(char *filename, MYSQL *mysql) 00291 { 00292 char tablename[FN_REFLEN], hard_path[FN_REFLEN], 00293 sql_statement[FN_REFLEN*16+256], *end; 00294 DBUG_ENTER("write_to_table"); 00295 DBUG_PRINT("enter",("filename: %s",filename)); 00296 00297 fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */ 00298 if (!opt_local_file) 00299 strmov(hard_path,filename); 00300 else 00301 my_load_path(hard_path, filename, NULL); /* filename includes the path */ 00302 00303 if (opt_delete) 00304 { 00305 if (verbose) 00306 fprintf(stdout, "Deleting the old data from table %s\n", tablename); 00307 #ifdef HAVE_SNPRINTF 00308 snprintf(sql_statement, FN_REFLEN*16+256, "DELETE FROM %s", tablename); 00309 #else 00310 sprintf(sql_statement, "DELETE FROM %s", tablename); 00311 #endif 00312 if (mysql_query(mysql, sql_statement)) 00313 { 00314 db_error_with_table(mysql, tablename); 00315 DBUG_RETURN(1); 00316 } 00317 } 00318 to_unix_path(hard_path); 00319 if (verbose) 00320 { 00321 if (opt_local_file) 00322 fprintf(stdout, "Loading data from LOCAL file: %s into %s\n", 00323 hard_path, tablename); 00324 else 00325 fprintf(stdout, "Loading data from SERVER file: %s into %s\n", 00326 hard_path, tablename); 00327 } 00328 sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'", 00329 opt_low_priority ? "LOW_PRIORITY" : "", 00330 opt_local_file ? "LOCAL" : "", hard_path); 00331 end= strend(sql_statement); 00332 if (replace) 00333 end= strmov(end, " REPLACE"); 00334 if (ignore) 00335 end= strmov(end, " IGNORE"); 00336 end= strmov(strmov(end, " INTO TABLE "), tablename); 00337 00338 if (fields_terminated || enclosed || opt_enclosed || escaped) 00339 end= strmov(end, " FIELDS"); 00340 end= add_load_option(end, fields_terminated, " TERMINATED BY"); 00341 end= add_load_option(end, enclosed, " ENCLOSED BY"); 00342 end= add_load_option(end, opt_enclosed, 00343 " OPTIONALLY ENCLOSED BY"); 00344 end= add_load_option(end, escaped, " ESCAPED BY"); 00345 end= add_load_option(end, lines_terminated, " LINES TERMINATED BY"); 00346 if (opt_ignore_lines >= 0) 00347 end= strmov(longlong10_to_str(opt_ignore_lines, 00348 strmov(end, " IGNORE "),10), " LINES"); 00349 if (opt_columns) 00350 end= strmov(strmov(strmov(end, " ("), opt_columns), ")"); 00351 *end= '\0'; 00352 00353 if (mysql_query(mysql, sql_statement)) 00354 { 00355 db_error_with_table(mysql, tablename); 00356 DBUG_RETURN(1); 00357 } 00358 if (!silent) 00359 { 00360 if (mysql_info(mysql)) /* If NULL-pointer, print nothing */ 00361 { 00362 fprintf(stdout, "%s.%s: %s\n", current_db, tablename, 00363 mysql_info(mysql)); 00364 } 00365 } 00366 DBUG_RETURN(0); 00367 } 00368 00369 00370 00371 static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename) 00372 { 00373 DYNAMIC_STRING query; 00374 int i; 00375 char tablename[FN_REFLEN]; 00376 00377 if (verbose) 00378 fprintf(stdout, "Locking tables for write\n"); 00379 init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); 00380 for (i=0 ; i < tablecount ; i++) 00381 { 00382 fn_format(tablename, raw_tablename[i], "", "", 1 | 2); 00383 dynstr_append(&query, tablename); 00384 dynstr_append(&query, " WRITE,"); 00385 } 00386 if (mysql_real_query(mysql, query.str, query.length-1)) 00387 db_error(mysql); /* We shall countinue here, if --force was given */ 00388 } 00389 00390 00391 00392 00393 static MYSQL *db_connect(char *host, char *database, 00394 char *user, char *passwd) 00395 { 00396 MYSQL *mysql; 00397 if (verbose) 00398 fprintf(stdout, "Connecting to %s\n", host ? host : "localhost"); 00399 if (!(mysql= mysql_init(NULL))) 00400 return 0; 00401 if (opt_compress) 00402 mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS); 00403 if (opt_local_file) 00404 mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE, 00405 (char*) &opt_local_file); 00406 #ifdef HAVE_OPENSSL 00407 if (opt_use_ssl) 00408 mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, 00409 opt_ssl_capath, opt_ssl_cipher); 00410 mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, 00411 (char*)&opt_ssl_verify_server_cert); 00412 #endif 00413 if (opt_protocol) 00414 mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); 00415 #ifdef HAVE_SMEM 00416 if (shared_memory_base_name) 00417 mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); 00418 #endif 00419 if (!(mysql_real_connect(mysql,host,user,passwd, 00420 database,opt_mysql_port,opt_mysql_unix_port, 00421 0))) 00422 { 00423 ignore_errors=0; /* NO RETURN FROM db_error */ 00424 db_error(mysql); 00425 } 00426 mysql->reconnect= 0; 00427 if (verbose) 00428 fprintf(stdout, "Selecting database %s\n", database); 00429 if (mysql_select_db(mysql, database)) 00430 { 00431 ignore_errors=0; 00432 db_error(mysql); 00433 } 00434 return mysql; 00435 } 00436 00437 00438 00439 static void db_disconnect(char *host, MYSQL *mysql) 00440 { 00441 if (verbose) 00442 fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost"); 00443 mysql_close(mysql); 00444 } 00445 00446 00447 00448 static void safe_exit(int error, MYSQL *mysql) 00449 { 00450 if (ignore_errors) 00451 return; 00452 if (mysql) 00453 mysql_close(mysql); 00454 exit(error); 00455 } 00456 00457 00458 00459 static void db_error_with_table(MYSQL *mysql, char *table) 00460 { 00461 my_printf_error(0,"Error: %d, %s, when using table: %s", 00462 MYF(0), mysql_errno(mysql), mysql_error(mysql), table); 00463 safe_exit(1, mysql); 00464 } 00465 00466 00467 00468 static void db_error(MYSQL *mysql) 00469 { 00470 my_printf_error(0,"Error: %d %s", MYF(0), mysql_errno(mysql), mysql_error(mysql)); 00471 safe_exit(1, mysql); 00472 } 00473 00474 00475 static char *add_load_option(char *ptr, const char *object, 00476 const char *statement) 00477 { 00478 if (object) 00479 { 00480 /* Don't escape hex constants */ 00481 if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X')) 00482 ptr= strxmov(ptr," ",statement," ",object,NullS); 00483 else 00484 { 00485 /* char constant; escape */ 00486 ptr= strxmov(ptr," ",statement," '",NullS); 00487 ptr= field_escape(ptr,object,(uint) strlen(object)); 00488 *ptr++= '\''; 00489 } 00490 } 00491 return ptr; 00492 } 00493 00494 /* 00495 ** Allow the user to specify field terminator strings like: 00496 ** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline) 00497 ** This is done by doubleing ' and add a end -\ if needed to avoid 00498 ** syntax errors from the SQL parser. 00499 */ 00500 00501 static char *field_escape(char *to,const char *from,uint length) 00502 { 00503 const char *end; 00504 uint end_backslashes=0; 00505 00506 for (end= from+length; from != end; from++) 00507 { 00508 *to++= *from; 00509 if (*from == '\\') 00510 end_backslashes^=1; /* find odd number of backslashes */ 00511 else 00512 { 00513 if (*from == '\'' && !end_backslashes) 00514 *to++= *from; /* We want a dublicate of "'" for MySQL */ 00515 end_backslashes=0; 00516 } 00517 } 00518 /* Add missing backslashes if user has specified odd number of backs.*/ 00519 if (end_backslashes) 00520 *to++= '\\'; 00521 return to; 00522 } 00523 00524 int exitcode= 0; 00525 00526 #ifdef HAVE_LIBPTHREAD 00527 pthread_handler_t worker_thread(void *arg) 00528 { 00529 int error; 00530 char *raw_table_name= (char *)arg; 00531 MYSQL *mysql= 0; 00532 00533 if (mysql_thread_init()) 00534 goto error; 00535 00536 if (!(mysql= db_connect(current_host,current_db,current_user,opt_password))) 00537 { 00538 goto error; 00539 } 00540 00541 if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;")) 00542 { 00543 db_error(mysql); /* We shall countinue here, if --force was given */ 00544 goto error; 00545 } 00546 00547 /* 00548 We are not currently catching the error here. 00549 */ 00550 if((error= write_to_table(raw_table_name, mysql))) 00551 if (exitcode == 0) 00552 exitcode= error; 00553 00554 error: 00555 if (mysql) 00556 db_disconnect(current_host, mysql); 00557 00558 pthread_mutex_lock(&counter_mutex); 00559 counter--; 00560 pthread_cond_signal(&count_threshhold); 00561 pthread_mutex_unlock(&counter_mutex); 00562 my_thread_end(); 00563 00564 return 0; 00565 } 00566 #endif 00567 00568 00569 int main(int argc, char **argv) 00570 { 00571 int error=0; 00572 char **argv_to_free; 00573 MY_INIT(argv[0]); 00574 00575 load_defaults("my",load_default_groups,&argc,&argv); 00576 /* argv is changed in the program */ 00577 argv_to_free= argv; 00578 if (get_options(&argc, &argv)) 00579 { 00580 free_defaults(argv_to_free); 00581 return(1); 00582 } 00583 00584 #ifdef HAVE_LIBPTHREAD 00585 if (opt_use_threads && !lock_tables) 00586 { 00587 pthread_t mainthread; /* Thread descriptor */ 00588 pthread_attr_t attr; /* Thread attributes */ 00589 pthread_attr_init(&attr); 00590 pthread_attr_setdetachstate(&attr, 00591 PTHREAD_CREATE_DETACHED); 00592 00593 VOID(pthread_mutex_init(&counter_mutex, NULL)); 00594 VOID(pthread_cond_init(&count_threshhold, NULL)); 00595 00596 for (counter= 0; *argv != NULL; argv++) /* Loop through tables */ 00597 { 00598 pthread_mutex_lock(&counter_mutex); 00599 while (counter == opt_use_threads) 00600 { 00601 struct timespec abstime; 00602 00603 set_timespec(abstime, 3); 00604 pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime); 00605 } 00606 /* Before exiting the lock we set ourselves up for the next thread */ 00607 counter++; 00608 pthread_mutex_unlock(&counter_mutex); 00609 /* now create the thread */ 00610 if (pthread_create(&mainthread, &attr, worker_thread, 00611 (void *)*argv) != 0) 00612 { 00613 pthread_mutex_lock(&counter_mutex); 00614 counter--; 00615 pthread_mutex_unlock(&counter_mutex); 00616 fprintf(stderr,"%s: Could not create thread\n", 00617 my_progname); 00618 } 00619 } 00620 00621 /* 00622 We loop until we know that all children have cleaned up. 00623 */ 00624 pthread_mutex_lock(&counter_mutex); 00625 while (counter) 00626 { 00627 struct timespec abstime; 00628 00629 set_timespec(abstime, 3); 00630 pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime); 00631 } 00632 pthread_mutex_unlock(&counter_mutex); 00633 VOID(pthread_mutex_destroy(&counter_mutex)); 00634 VOID(pthread_cond_destroy(&count_threshhold)); 00635 pthread_attr_destroy(&attr); 00636 } 00637 else 00638 #endif 00639 { 00640 MYSQL *mysql= 0; 00641 if (!(mysql= db_connect(current_host,current_db,current_user,opt_password))) 00642 { 00643 free_defaults(argv_to_free); 00644 return(1); /* purecov: deadcode */ 00645 } 00646 00647 if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;")) 00648 { 00649 db_error(mysql); /* We shall countinue here, if --force was given */ 00650 return(1); 00651 } 00652 00653 if (lock_tables) 00654 lock_table(mysql, argc, argv); 00655 for (; *argv != NULL; argv++) 00656 if ((error= write_to_table(*argv, mysql))) 00657 if (exitcode == 0) 00658 exitcode= error; 00659 db_disconnect(current_host, mysql); 00660 } 00661 my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); 00662 #ifdef HAVE_SMEM 00663 my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); 00664 #endif 00665 free_defaults(argv_to_free); 00666 my_end(0); 00667 return(exitcode); 00668 }
1.4.7

