~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleimport.c

Merged build changes from Antony.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB
 
1
/* Copyright (C) 2008 Drizzle Open Source Development Team
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/*
17
 
**         mysqlimport.c  - Imports all given files
18
 
**                          into a table(s).
 
17
**     drizzleimport.c  - Imports all given files
 
18
**          into a table(s).
19
19
**
20
 
**                         *************************
21
 
**                         *                       *
22
 
**                         * AUTHOR: Monty & Jani  *
23
 
**                         * DATE:   June 24, 1997 *
24
 
**                         *                       *
25
 
**                         *************************
 
20
**         *************************
 
21
**         *         *
 
22
**         * AUTHOR: Monty & Jani  *
 
23
**         * DATE:   June 24, 1997 *
 
24
**         *         *
 
25
**         *************************
26
26
*/
27
27
#define IMPORT_VERSION "3.7"
28
28
 
29
29
#include "client_priv.h"
30
 
#include "drizzle_version.h"
31
 
#include <my_pthread.h>
 
30
#include <mysys/my_pthread.h>
32
31
 
33
32
 
34
33
/* Global Thread counter */
36
35
pthread_mutex_t counter_mutex;
37
36
pthread_cond_t count_threshhold;
38
37
 
39
 
static void db_error_with_table(MYSQL *mysql, char *table);
40
 
static void db_error(MYSQL *mysql);
 
38
static void db_error_with_table(DRIZZLE *drizzle, char *table);
 
39
static void db_error(DRIZZLE *drizzle);
41
40
static char *field_escape(char *to,const char *from,uint length);
42
41
static char *add_load_option(char *ptr,const char *object,
43
 
                             const char *statement);
 
42
           const char *statement);
44
43
 
45
 
static bool     verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
46
 
                replace=0,silent=0,ignore=0,opt_compress=0,
 
44
static bool  verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
 
45
    replace=0,silent=0,ignore=0,opt_compress=0,
47
46
                opt_low_priority= 0, tty_password= 0;
48
47
static bool debug_info_flag= 0, debug_check_flag= 0;
49
48
static uint opt_use_threads=0, opt_local_file=0, my_end_arg= 0;
50
 
static char     *opt_password=0, *current_user=0,
51
 
                *current_host=0, *current_db=0, *fields_terminated=0,
52
 
                *lines_terminated=0, *enclosed=0, *opt_enclosed=0,
53
 
                *escaped=0, *opt_columns=0, 
54
 
                *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
55
 
static uint     opt_mysql_port= 0, opt_protocol= 0;
56
 
static char * opt_mysql_unix_port=0;
 
49
static char  *opt_password=0, *current_user=0,
 
50
    *current_host=0, *current_db=0, *fields_terminated=0,
 
51
    *lines_terminated=0, *enclosed=0, *opt_enclosed=0,
 
52
    *escaped=0, *opt_columns=0,
 
53
    *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
 
54
static uint     opt_drizzle_port= 0, opt_protocol= 0;
 
55
static char * opt_drizzle_unix_port=0;
57
56
static int64_t opt_ignore_lines= -1;
58
57
static CHARSET_INFO *charset_info= &my_charset_latin1;
59
58
 
112
111
  {"local", 'L', "Read all files through the client.", (char**) &opt_local_file,
113
112
   (char**) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
114
113
  {"lock-tables", 'l', "Lock all tables for write (this disables threads).",
115
 
    (char**) &lock_tables, (char**) &lock_tables, 0, GET_BOOL, NO_ARG, 
 
114
    (char**) &lock_tables, (char**) &lock_tables, 0, GET_BOOL, NO_ARG,
116
115
    0, 0, 0, 0, 0, 0},
117
116
  {"low-priority", OPT_LOW_PRIORITY,
118
117
   "Use LOW_PRIORITY when updating the table.", (char**) &opt_low_priority,
126
125
   "/etc/services, "
127
126
#endif
128
127
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
129
 
   (char**) &opt_mysql_port,
130
 
   (char**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
 
128
   (char**) &opt_drizzle_port,
 
129
   (char**) &opt_drizzle_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
131
130
   0},
132
 
  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
 
131
  {"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
133
132
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
134
133
  {"replace", 'r', "If duplicate unique key was found, replace old row.",
135
134
   (char**) &replace, (char**) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
136
135
  {"silent", 's', "Be more silent.", (char**) &silent, (char**) &silent, 0,
137
136
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
138
137
  {"socket", 'S', "Socket file to use for connection.",
139
 
   (char**) &opt_mysql_unix_port, (char**) &opt_mysql_unix_port, 0, GET_STR,
 
138
   (char**) &opt_drizzle_unix_port, (char**) &opt_drizzle_unix_port, 0, GET_STR,
140
139
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
141
140
  {"use-threads", OPT_USE_THREADS,
142
141
   "Load files in parallel. The argument is the number "
143
142
   "of threads to use for loading data.",
144
 
   (char**) &opt_use_threads, (char**) &opt_use_threads, 0, 
 
143
   (char**) &opt_use_threads, (char**) &opt_use_threads, 0,
145
144
   GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
146
145
#ifndef DONT_ALLOW_USER_CHANGE
147
146
  {"user", 'u', "User for login if not current user.", (char**) &current_user,
155
154
};
156
155
 
157
156
 
158
 
static const char *load_default_groups[]= { "mysqlimport","client",0 };
159
 
 
160
 
#include <help_start.h>
 
157
static const char *load_default_groups[]= { "drizzleimport","client",0 };
161
158
 
162
159
static void print_version(void)
163
160
{
164
161
  printf("%s  Ver %s Distrib %s, for %s (%s)\n" ,my_progname,
165
 
          IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
 
162
    IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
166
163
}
167
164
 
168
165
 
169
166
static void usage(void)
170
167
{
171
168
  print_version();
172
 
  puts("Copyright (C) 2000-2006 MySQL AB");
 
169
  puts("Copyright (C) 2008 Drizzle Open Source Development Team");
173
170
  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");
174
171
  printf("\
175
172
Loads tables from text files in various formats.  The base name of the\n\
176
173
text file must be the name of the table that should be used.\n\
177
 
If one uses sockets to connect to the MySQL server, the server will open and\n\
 
174
If one uses sockets to connect to the Drizzle server, the server will open and\n\
178
175
read the text file directly. In other cases the client will open the text\n\
179
176
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
180
177
 
184
181
  my_print_variables(my_long_options);
185
182
}
186
183
 
187
 
#include <help_end.h>
188
 
 
189
184
static bool
190
185
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
191
 
               char *argument)
 
186
         char *argument)
192
187
{
193
188
  switch(optid) {
194
189
  case 'p':
197
192
      char *start=argument;
198
193
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
199
194
      opt_password=my_strdup(argument,MYF(MY_FAE));
200
 
      while (*argument) *argument++= 'x';               /* Destroy argument */
 
195
      while (*argument) *argument++= 'x';    /* Destroy argument */
201
196
      if (*start)
202
 
        start[1]=0;                             /* Cut length of argument */
 
197
  start[1]=0;        /* Cut length of argument */
203
198
      tty_password= 0;
204
199
    }
205
200
    else
206
201
      tty_password= 1;
207
202
    break;
208
 
  case OPT_MYSQL_PROTOCOL:
 
203
  case OPT_DRIZZLE_PROTOCOL:
209
204
    opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
210
205
                                    opt->name);
211
206
    break;
242
237
  }
243
238
  if (strcmp(default_charset, charset_info->csname) &&
244
239
      !(charset_info= get_charset_by_csname(default_charset,
245
 
                                            MY_CS_PRIMARY, MYF(MY_WME))))
 
240
                MY_CS_PRIMARY, MYF(MY_WME))))
246
241
    exit(1);
247
242
  if (*argc < 2)
248
243
  {
258
253
 
259
254
 
260
255
 
261
 
static int write_to_table(char *filename, MYSQL *mysql)
 
256
static int write_to_table(char *filename, DRIZZLE *drizzle)
262
257
{
263
258
  char tablename[FN_REFLEN], hard_path[FN_REFLEN],
264
259
       sql_statement[FN_REFLEN*16+256], *end;
278
273
#else
279
274
    sprintf(sql_statement, "DELETE FROM %s", tablename);
280
275
#endif
281
 
    if (mysql_query(mysql, sql_statement))
 
276
    if (drizzle_query(drizzle, sql_statement))
282
277
    {
283
 
      db_error_with_table(mysql, tablename);
 
278
      db_error_with_table(drizzle, tablename);
284
279
      return(1);
285
280
    }
286
281
  }
289
284
  {
290
285
    if (opt_local_file)
291
286
      fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
292
 
              hard_path, tablename);
 
287
        hard_path, tablename);
293
288
    else
294
289
      fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
295
 
              hard_path, tablename);
 
290
        hard_path, tablename);
296
291
  }
297
292
  sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
298
 
          opt_low_priority ? "LOW_PRIORITY" : "",
299
 
          opt_local_file ? "LOCAL" : "", hard_path);
 
293
    opt_low_priority ? "LOW_PRIORITY" : "",
 
294
    opt_local_file ? "LOCAL" : "", hard_path);
300
295
  end= strend(sql_statement);
301
296
  if (replace)
302
297
    end= strmov(end, " REPLACE");
309
304
  end= add_load_option(end, fields_terminated, " TERMINATED BY");
310
305
  end= add_load_option(end, enclosed, " ENCLOSED BY");
311
306
  end= add_load_option(end, opt_enclosed,
312
 
                       " OPTIONALLY ENCLOSED BY");
 
307
           " OPTIONALLY ENCLOSED BY");
313
308
  end= add_load_option(end, escaped, " ESCAPED BY");
314
309
  end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
315
310
  if (opt_ignore_lines >= 0)
316
 
    end= strmov(int64_t10_to_str(opt_ignore_lines, 
317
 
                                  strmov(end, " IGNORE "),10), " LINES");
 
311
    end= strmov(int64_t10_to_str(opt_ignore_lines,
 
312
          strmov(end, " IGNORE "),10), " LINES");
318
313
  if (opt_columns)
319
314
    end= strmov(strmov(strmov(end, " ("), opt_columns), ")");
320
315
  *end= '\0';
321
316
 
322
 
  if (mysql_query(mysql, sql_statement))
 
317
  if (drizzle_query(drizzle, sql_statement))
323
318
  {
324
 
    db_error_with_table(mysql, tablename);
 
319
    db_error_with_table(drizzle, tablename);
325
320
    return(1);
326
321
  }
327
322
  if (!silent)
328
323
  {
329
 
    if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
 
324
    if (drizzle_info(drizzle)) /* If NULL-pointer, print nothing */
330
325
    {
331
326
      fprintf(stdout, "%s.%s: %s\n", current_db, tablename,
332
 
              mysql_info(mysql));
 
327
        drizzle_info(drizzle));
333
328
    }
334
329
  }
335
330
  return(0);
337
332
 
338
333
 
339
334
 
340
 
static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
 
335
static void lock_table(DRIZZLE *drizzle, int tablecount, char **raw_tablename)
341
336
{
342
337
  DYNAMIC_STRING query;
343
338
  int i;
352
347
    dynstr_append(&query, tablename);
353
348
    dynstr_append(&query, " WRITE,");
354
349
  }
355
 
  if (mysql_real_query(mysql, query.str, query.length-1))
356
 
    db_error(mysql); /* We shall countinue here, if --force was given */
 
350
  if (drizzle_real_query(drizzle, query.str, query.length-1))
 
351
    db_error(drizzle); /* We shall countinue here, if --force was given */
357
352
}
358
353
 
359
354
 
360
355
 
361
356
 
362
 
static MYSQL *db_connect(char *host, char *database,
 
357
static DRIZZLE *db_connect(char *host, char *database,
363
358
                         char *user, char *passwd)
364
359
{
365
 
  MYSQL *mysql;
 
360
  DRIZZLE *drizzle;
366
361
  if (verbose)
367
362
    fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
368
 
  if (!(mysql= mysql_init(NULL)))
 
363
  if (!(drizzle= drizzle_create(NULL)))
369
364
    return 0;
370
365
  if (opt_compress)
371
 
    mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
 
366
    drizzle_options(drizzle,DRIZZLE_OPT_COMPRESS,NullS);
372
367
  if (opt_local_file)
373
 
    mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
374
 
                  (char*) &opt_local_file);
 
368
    drizzle_options(drizzle,DRIZZLE_OPT_LOCAL_INFILE,
 
369
      (char*) &opt_local_file);
375
370
  if (opt_protocol)
376
 
    mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
377
 
  if (!(mysql_real_connect(mysql,host,user,passwd,
378
 
                           database,opt_mysql_port,opt_mysql_unix_port,
 
371
    drizzle_options(drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
 
372
  if (!(drizzle_connect(drizzle,host,user,passwd,
 
373
                           database,opt_drizzle_port,opt_drizzle_unix_port,
379
374
                           0)))
380
375
  {
381
 
    ignore_errors=0;      /* NO RETURN FROM db_error */
382
 
    db_error(mysql);
 
376
    ignore_errors=0;    /* NO RETURN FROM db_error */
 
377
    db_error(drizzle);
383
378
  }
384
 
  mysql->reconnect= 0;
 
379
  drizzle->reconnect= 0;
385
380
  if (verbose)
386
381
    fprintf(stdout, "Selecting database %s\n", database);
387
 
  if (mysql_select_db(mysql, database))
 
382
  if (drizzle_select_db(drizzle, database))
388
383
  {
389
384
    ignore_errors=0;
390
 
    db_error(mysql);
 
385
    db_error(drizzle);
391
386
  }
392
 
  return mysql;
 
387
  return drizzle;
393
388
}
394
389
 
395
390
 
396
391
 
397
 
static void db_disconnect(char *host, MYSQL *mysql)
 
392
static void db_disconnect(char *host, DRIZZLE *drizzle)
398
393
{
399
394
  if (verbose)
400
395
    fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
401
 
  mysql_close(mysql);
 
396
  drizzle_close(drizzle);
402
397
}
403
398
 
404
399
 
405
400
 
406
 
static void safe_exit(int error, MYSQL *mysql)
 
401
static void safe_exit(int error, DRIZZLE *drizzle)
407
402
{
408
403
  if (ignore_errors)
409
404
    return;
410
 
  if (mysql)
411
 
    mysql_close(mysql);
 
405
  if (drizzle)
 
406
    drizzle_close(drizzle);
412
407
  exit(error);
413
408
}
414
409
 
415
410
 
416
411
 
417
 
static void db_error_with_table(MYSQL *mysql, char *table)
 
412
static void db_error_with_table(DRIZZLE *drizzle, char *table)
418
413
{
419
414
  my_printf_error(0,"Error: %d, %s, when using table: %s",
420
 
                  MYF(0), mysql_errno(mysql), mysql_error(mysql), table);
421
 
  safe_exit(1, mysql);
 
415
      MYF(0), drizzle_errno(drizzle), drizzle_error(drizzle), table);
 
416
  safe_exit(1, drizzle);
422
417
}
423
418
 
424
419
 
425
420
 
426
 
static void db_error(MYSQL *mysql)
 
421
static void db_error(DRIZZLE *drizzle)
427
422
{
428
 
  my_printf_error(0,"Error: %d %s", MYF(0), mysql_errno(mysql), mysql_error(mysql));
429
 
  safe_exit(1, mysql);
 
423
  my_printf_error(0,"Error: %d %s", MYF(0), drizzle_errno(drizzle), drizzle_error(drizzle));
 
424
  safe_exit(1, drizzle);
430
425
}
431
426
 
432
427
 
433
428
static char *add_load_option(char *ptr, const char *object,
434
 
                             const char *statement)
 
429
           const char *statement)
435
430
{
436
431
  if (object)
437
432
  {
454
449
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
455
450
** This is done by doubleing ' and add a end -\ if needed to avoid
456
451
** syntax errors from the SQL parser.
457
 
*/ 
 
452
*/
458
453
 
459
454
static char *field_escape(char *to,const char *from,uint length)
460
455
{
461
456
  const char *end;
462
 
  uint end_backslashes=0; 
 
457
  uint end_backslashes=0;
463
458
 
464
459
  for (end= from+length; from != end; from++)
465
460
  {
466
461
    *to++= *from;
467
462
    if (*from == '\\')
468
463
      end_backslashes^=1;    /* find odd number of backslashes */
469
 
    else 
 
464
    else
470
465
    {
471
466
      if (*from == '\'' && !end_backslashes)
472
 
        *to++= *from;      /* We want a dublicate of "'" for MySQL */
 
467
  *to++= *from;      /* We want a dublicate of "'" for DRIZZLE */
473
468
      end_backslashes=0;
474
469
    }
475
470
  }
476
471
  /* Add missing backslashes if user has specified odd number of backs.*/
477
472
  if (end_backslashes)
478
 
    *to++= '\\';          
 
473
    *to++= '\\';         
479
474
  return to;
480
475
}
481
476
 
485
480
{
486
481
  int error;
487
482
  char *raw_table_name= (char *)arg;
488
 
  MYSQL *mysql= 0;
 
483
  DRIZZLE *drizzle= 0;
489
484
 
490
 
  if (mysql_thread_init())
 
485
  if (drizzle_thread_init())
491
486
    goto error;
492
 
  
493
 
  if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
 
487
 
 
488
  if (!(drizzle= db_connect(current_host,current_db,current_user,opt_password)))
494
489
  {
495
490
    goto error;
496
491
  }
497
492
 
498
 
  if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
 
493
  if (drizzle_query(drizzle, "/*!40101 set @@character_set_database=binary */;"))
499
494
  {
500
 
    db_error(mysql); /* We shall countinue here, if --force was given */
 
495
    db_error(drizzle); /* We shall countinue here, if --force was given */
501
496
    goto error;
502
497
  }
503
498
 
504
499
  /*
505
500
    We are not currently catching the error here.
506
501
  */
507
 
  if((error= write_to_table(raw_table_name, mysql)))
 
502
  if((error= write_to_table(raw_table_name, drizzle)))
508
503
    if (exitcode == 0)
509
504
      exitcode= error;
510
505
 
511
506
error:
512
 
  if (mysql)
513
 
    db_disconnect(current_host, mysql);
 
507
  if (drizzle)
 
508
    db_disconnect(current_host, drizzle);
514
509
 
515
510
  pthread_mutex_lock(&counter_mutex);
516
511
  counter--;
563
558
      counter++;
564
559
      pthread_mutex_unlock(&counter_mutex);
565
560
      /* now create the thread */
566
 
      if (pthread_create(&mainthread, &attr, worker_thread, 
 
561
      if (pthread_create(&mainthread, &attr, worker_thread,
567
562
                         (void *)*argv) != 0)
568
563
      {
569
564
        pthread_mutex_lock(&counter_mutex);
593
588
  else
594
589
#endif
595
590
  {
596
 
    MYSQL *mysql= 0;
597
 
    if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
 
591
    DRIZZLE *drizzle= 0;
 
592
    if (!(drizzle= db_connect(current_host,current_db,current_user,opt_password)))
598
593
    {
599
594
      free_defaults(argv_to_free);
600
595
      return(1); /* purecov: deadcode */
601
596
    }
602
597
 
603
 
    if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
 
598
    if (drizzle_query(drizzle, "/*!40101 set @@character_set_database=binary */;"))
604
599
    {
605
 
      db_error(mysql); /* We shall countinue here, if --force was given */
 
600
      db_error(drizzle); /* We shall countinue here, if --force was given */
606
601
      return(1);
607
602
    }
608
603
 
609
604
    if (lock_tables)
610
 
      lock_table(mysql, argc, argv);
 
605
      lock_table(drizzle, argc, argv);
611
606
    for (; *argv != NULL; argv++)
612
 
      if ((error= write_to_table(*argv, mysql)))
 
607
      if ((error= write_to_table(*argv, drizzle)))
613
608
        if (exitcode == 0)
614
609
          exitcode= error;
615
 
    db_disconnect(current_host, mysql);
 
610
    db_disconnect(current_host, drizzle);
616
611
  }
617
612
  my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
618
613
  free_defaults(argv_to_free);