~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleimport.cc

  • Committer: Monty Taylor
  • Date: 2010-06-18 00:34:51 UTC
  • mto: (1627.2.5 build)
  • mto: This revision was merged to the branch mainline in revision 1628.
  • Revision ID: mordred@inaugust.com-20100618003451-2b3fs2m2hvpch91r
Add function pointer hook for plugins to register program_options.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* 
2
2
  Copyright (C) 2010 Vijay Samuel
3
 
  Copyright (C) 2010 Brian Aker
4
3
  Copyright (C) 2000-2006 MySQL AB
5
 
  Copyright (C) 2008-2009 Sun Microsystems, Inc.
 
4
  Copyright (C) 2008-2009 Sun Microsystems, Inc
6
5
 
7
6
  This program is free software; you can redistribute it and/or modify
8
7
  it under the terms of the GNU General Public License as published by
15
14
 
16
15
  You should have received a copy of the GNU General Public License
17
16
  along with this program; if not, write to the Free Software
18
 
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
17
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
19
18
 
20
 
#define IMPORT_VERSION "4.0"
 
19
/*
 
20
**     drizzleimport.c  - Imports all given files
 
21
**          into a table(s).
 
22
**
 
23
**         *************************
 
24
**         *         *
 
25
**         * AUTHOR: Monty & Jani  *
 
26
**         * DATE:   June 24, 1997 *
 
27
**         *         *
 
28
**         *************************
 
29
*/
 
30
#define IMPORT_VERSION "3.7"
21
31
 
22
32
#include "client_priv.h"
23
33
#include <string>
39
49
 
40
50
int exitcode= 0;
41
51
 
42
 
const char *program_name= "drizzleimport";
43
 
 
44
52
/* Global Thread counter */
45
53
uint32_t counter;
46
54
pthread_mutex_t counter_mutex;
52
60
static char *add_load_option(char *ptr,const char *object,
53
61
           const char *statement);
54
62
 
55
 
static bool verbose= false, ignore_errors= false,
 
63
static bool verbose= false, lock_tables= false, ignore_errors= false,
56
64
            opt_delete= false, opt_replace= false, silent= false,
57
65
            ignore_unique= false, opt_low_priority= false,
58
 
            use_drizzle_protocol= false, opt_local_file;
 
66
            tty_password= false, opt_mysql= false, opt_local_file;
59
67
 
60
 
static uint32_t opt_use_threads;
 
68
static uint32_t opt_use_threads= 0;
61
69
static uint32_t opt_drizzle_port= 0;
62
70
static int64_t opt_ignore_lines= -1;
63
71
 
71
79
  opt_password,
72
80
  enclosed,  
73
81
  current_host,
74
 
  fields_terminated,
75
 
  opt_protocol;
 
82
  fields_terminated;
76
83
 
77
84
 
78
85
static int get_options(void)
104
111
  drizzle_return_t ret;
105
112
 
106
113
  internal::fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
107
 
  if (not opt_local_file)
 
114
  if (!opt_local_file)
108
115
    strcpy(hard_path,filename);
109
116
  else
110
117
    internal::my_load_path(hard_path, filename, NULL); /* filename includes the path */
189
196
}
190
197
 
191
198
 
 
199
static void lock_table(drizzle_con_st *con, int tablecount, char **raw_tablename)
 
200
{
 
201
  string query;
 
202
  int i;
 
203
  char tablename[FN_REFLEN];
 
204
  drizzle_result_st result;
 
205
  drizzle_return_t ret;
 
206
 
 
207
  if (verbose)
 
208
    fprintf(stdout, "Locking tables for write\n");
 
209
  query.append("LOCK TABLES ");
 
210
  for (i=0 ; i < tablecount ; i++)
 
211
  {
 
212
    internal::fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
 
213
    query.append(tablename);
 
214
    query.append(" WRITE,");
 
215
  }
 
216
  if (drizzle_query(con, &result, query.c_str(), query.length()-1,
 
217
                    &ret) == NULL ||
 
218
      ret != DRIZZLE_RETURN_OK)
 
219
  {
 
220
    db_error(con, &result, ret, NULL);
 
221
    /* We shall countinue here, if --force was given */
 
222
    return;
 
223
  }
 
224
  drizzle_result_free(&result);
 
225
}
 
226
 
 
227
 
192
228
static drizzle_con_st *db_connect(const string host, const string database,
193
229
                                  const string user, const string passwd)
194
230
{
197
233
  drizzle_return_t ret;
198
234
 
199
235
  if (verbose)
200
 
    fprintf(stdout, "Connecting to %s, using protocol %s...\n", ! host.empty() ? host.c_str() : "localhost", opt_protocol.c_str());
 
236
    fprintf(stdout, "Connecting to %s\n", ! host.empty() ? host.c_str() : "localhost");
201
237
  if (!(drizzle= drizzle_create(NULL)))
202
238
    return 0;
203
239
  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)))
 
240
                                 (char *)database.c_str(), opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE)))
205
241
  {
206
242
    return 0;
207
243
  }
245
281
{
246
282
  if (ret == DRIZZLE_RETURN_ERROR_CODE)
247
283
  {
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 : "");
 
284
    my_printf_error(0,"Error: %d, %s%s%s", MYF(0),
 
285
                    drizzle_result_error_code(result),
 
286
                    drizzle_result_error(result),
 
287
                    table ? ", when using table: " : "", table ? table : "");
252
288
    drizzle_result_free(result);
253
289
  }
254
290
  else
255
291
  {
256
 
    fprintf(stdout, "Error: %d, %s%s%s", ret, drizzle_con_error(con),
257
 
            table ? ", when using table: " : "", table ? table : "");
 
292
    my_printf_error(0,"Error: %d, %s%s%s", MYF(0), ret, drizzle_con_error(con),
 
293
                    table ? ", when using table: " : "", table ? table : "");
258
294
  }
259
295
 
260
296
  safe_exit(1, con);
314
350
{
315
351
  int error;
316
352
  char *raw_table_name= (char *)arg;
317
 
  drizzle_con_st *con;
 
353
  drizzle_con_st *con= NULL;
 
354
  drizzle_result_st result;
 
355
  drizzle_return_t ret;
318
356
 
319
357
  if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
320
358
  {
321
 
    return 0;
 
359
    goto error;
 
360
  }
 
361
 
 
362
  if (drizzle_query_str(con, &result,
 
363
                        "/*!40101 set @@character_set_database=binary */;",
 
364
                        &ret) == NULL ||
 
365
      ret != DRIZZLE_RETURN_OK)
 
366
  {
 
367
    db_error(con, &result, ret, NULL);
 
368
    /* We shall countinue here, if --force was given */
 
369
    goto error;
322
370
  }
323
371
 
324
372
  /*
325
373
    We are not currently catching the error here.
326
374
  */
327
 
  if ((error= write_to_table(raw_table_name, con)))
328
 
  {
 
375
  if((error= write_to_table(raw_table_name, con)))
329
376
    if (exitcode == 0)
330
 
    {
331
377
      exitcode= error;
332
 
    }
333
 
  }
334
378
 
 
379
error:
335
380
  if (con)
336
 
  {
337
381
    db_disconnect(current_host, con);
338
 
  }
339
382
 
340
383
  pthread_mutex_lock(&counter_mutex);
341
384
  counter--;
342
385
  pthread_cond_signal(&count_threshhold);
343
386
  pthread_mutex_unlock(&counter_mutex);
 
387
  internal::my_thread_end();
344
388
 
345
389
  return 0;
346
390
}
362
406
  ("help,?", "Displays this help and exits.")
363
407
  ("ignore,i", po::value<bool>(&ignore_unique)->default_value(false)->zero_tokens(),
364
408
  "If duplicate unique key was found, keep old row.")
 
409
  ("lock-tables,l", po::value<bool>(&lock_tables)->default_value(false)->zero_tokens(),
 
410
  "Lock all tables for write (this disables threads).")
365
411
  ("low-priority", po::value<bool>(&opt_low_priority)->default_value(false)->zero_tokens(),
366
412
  "Use LOW_PRIORITY when updating the table.")
367
413
  ("replace,r", po::value<bool>(&opt_replace)->default_value(false)->zero_tokens(),
393
439
  "Read all files through the client.")
394
440
  ("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
395
441
  "Be more silent.")
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.")
 
442
  ("use-threads", po::value<uint32_t>(&opt_use_threads)->default_value(0),
 
443
  "Load files in parallel. The argument is the number of threads to use for loading data.")
398
444
  ;
399
445
 
400
446
  po::options_description client_options("Options specific to the client");
401
447
  client_options.add_options()
402
448
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
403
449
  "Connect to host.")
 
450
  ("mysql,m", po::value<bool>(&opt_mysql)->default_value(true)->zero_tokens(),
 
451
  N_("Use MySQL Protocol."))
404
452
  ("password,P", po::value<string>(&password),
405
453
  "Password to use when connecting to server. If password is not given it's asked from the tty." )
406
454
  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
407
455
  "Port number to use for connection") 
408
 
  ("protocol", po::value<string>(&opt_protocol)->default_value("mysql"),
409
 
  "The protocol of connection (mysql or drizzle).")
 
456
  ("protocol", po::value<string>(),
 
457
  "The protocol of connection (tcp,socket,pipe,memory).")
410
458
  ("user,u", po::value<string>(&current_user)->default_value(""),
411
459
  "User for login if not current user.")
412
460
  ;
420
468
  std::string system_config_dir_client(SYSCONFDIR); 
421
469
  system_config_dir_client.append("/drizzle/client.cnf");
422
470
  
423
 
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
424
 
 
425
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
426
 
  {
427
 
    char *homedir;
428
 
    homedir= getenv("HOME");
429
 
    if (homedir != NULL)
430
 
      user_config_dir.replace(0, 1, homedir);
431
 
  }
432
 
 
433
471
  po::variables_map vm;
434
 
 
435
 
  // Disable allow_guessing
436
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
437
 
 
438
 
  po::store(po::command_line_parser(argc, argv).options(long_options).
439
 
            style(style).extra_parser(parse_password_arg).run(), vm);
440
 
 
441
 
  std::string user_config_dir_import(user_config_dir);
442
 
  user_config_dir_import.append("/drizzle/drizzleimport.cnf"); 
443
 
 
444
 
  std::string user_config_dir_client(user_config_dir);
445
 
  user_config_dir_client.append("/drizzle/client.cnf");
446
 
 
447
 
  ifstream user_import_ifs(user_config_dir_import.c_str());
 
472
  po::store(po::command_line_parser(argc, argv).options(long_options).run(), vm);
 
473
 
 
474
  ifstream user_import_ifs("~/.drizzle/drizzleimport.cnf");
448
475
  po::store(parse_config_file(user_import_ifs, import_options), vm);
449
 
 
450
 
  ifstream user_client_ifs(user_config_dir_client.c_str());
451
 
  po::store(parse_config_file(user_client_ifs, client_options), vm);
452
 
 
 
476
 
453
477
  ifstream system_import_ifs(system_config_dir_import.c_str());
454
478
  store(parse_config_file(system_import_ifs, import_options), vm);
 
479
 
 
480
  ifstream user_client_ifs("~/.drizzle/client.cnf");
 
481
  po::store(parse_config_file(user_client_ifs, client_options), vm);
455
482
 
456
483
  ifstream system_client_ifs(system_config_dir_client.c_str());
457
484
  po::store(parse_config_file(system_client_ifs, client_options), vm);
458
485
 
459
486
  po::notify(vm);
460
 
  if (vm.count("protocol"))
461
 
  {
462
 
    std::transform(opt_protocol.begin(), opt_protocol.end(),
463
 
      opt_protocol.begin(), ::tolower);
464
 
 
465
 
    if (not opt_protocol.compare("mysql"))
466
 
      use_drizzle_protocol=false;
467
 
    else if (not opt_protocol.compare("drizzle"))
468
 
      use_drizzle_protocol=true;
469
 
    else
470
 
    {
471
 
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
472
 
      exit(-1);
473
 
    }
474
 
  }
475
487
 
476
488
  if (vm.count("port"))
477
489
  {
486
498
    }
487
499
  }
488
500
 
489
 
  if( vm.count("password") )
 
501
  if (vm.count("password"))
490
502
  {
491
503
    if (!opt_password.empty())
492
504
      opt_password.erase();
493
 
    if (password == PASSWORD_SENTINEL)
494
 
    {
495
 
      opt_password= "";
496
 
    }
497
 
    else
498
 
    {
499
 
      opt_password= password;
500
 
      tty_password= false;
 
505
    opt_password= password;
 
506
    if (opt_password.c_str() == NULL)
 
507
    {
 
508
      fprintf(stderr, _("Memory allocation error while copying password. "
 
509
                        "Aborting.\n"));
 
510
      exit(EXIT_OUT_OF_MEMORY);
 
511
    }
 
512
    char *start= (char *)password.c_str();
 
513
    char *temp_pass= (char *)password.c_str();
 
514
    while (*temp_pass)
 
515
    {
 
516
        /* Overwriting password with 'x' */
 
517
        *temp_pass++= 'x';
 
518
    }
 
519
    if (*start)
 
520
    {
 
521
      start[1]= 0;
501
522
    }
502
523
  }
503
524
  else
505
526
      tty_password= true;
506
527
  }
507
528
 
508
 
 
509
529
  if (vm.count("version"))
510
530
  {
511
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n", program_name,
 
531
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n" ,internal::my_progname,
512
532
    IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
513
533
  }
514
534
  
515
535
  if (vm.count("help") || argc < 2)
516
536
  {
517
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n", program_name,
 
537
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n" ,internal::my_progname,
518
538
    IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
519
539
    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");
520
540
    printf("\
524
544
    read the text file directly. In other cases the client will open the text\n\
525
545
    file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
526
546
 
527
 
    printf("\nUsage: %s [OPTIONS] database textfile...", program_name);
 
547
    printf("\nUsage: %s [OPTIONS] database textfile...",internal::my_progname);
528
548
    cout<<long_options;
529
549
    exit(0);
530
550
  }
538
558
  current_db= (*argv)++;
539
559
  argc--;
540
560
 
541
 
  if (opt_use_threads)
 
561
#ifdef HAVE_LIBPTHREAD
 
562
  if (opt_use_threads && !lock_tables)
542
563
  {
543
564
    pthread_t mainthread;            /* Thread descriptor */
544
565
    pthread_attr_t attr;          /* Thread attributes */
569
590
        pthread_mutex_lock(&counter_mutex);
570
591
        counter--;
571
592
        pthread_mutex_unlock(&counter_mutex);
572
 
        fprintf(stderr,"%s: Could not create thread\n", program_name);
 
593
        fprintf(stderr,"%s: Could not create thread\n",
 
594
                internal::my_progname);
573
595
      }
574
596
    }
575
597
 
590
612
    pthread_attr_destroy(&attr);
591
613
  }
592
614
  else
 
615
#endif
593
616
  {
594
 
    drizzle_con_st *con;
595
 
 
 
617
    drizzle_con_st *con= 0;
 
618
    drizzle_result_st result;
 
619
    drizzle_return_t ret;
596
620
    if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
597
621
    {
598
622
      return(1);
599
623
    }
600
624
 
 
625
    if (drizzle_query_str(con, &result,
 
626
                          "/*!40101 set @@character_set_database=binary */;",
 
627
                          &ret) == NULL ||
 
628
        ret != DRIZZLE_RETURN_OK)
 
629
    {
 
630
      db_error(con, &result, ret, NULL);
 
631
      /* We shall countinue here, if --force was given */
 
632
      return(1);
 
633
    }
 
634
 
 
635
    drizzle_result_free(&result);
 
636
 
 
637
    if (lock_tables)
 
638
      lock_table(con, argc, argv);
601
639
    for (; *argv != NULL; argv++)
602
640
      if ((error= write_to_table(*argv, con)))
603
641
        if (exitcode == 0)