~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqlimport.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2000-2006 MySQL AB
2
 
   Copyright (C) 2008-2009 Sun Microsystems, Inc
3
2
 
4
3
   This program is free software; you can redistribute it and/or modify
5
4
   it under the terms of the GNU General Public License as published by
15
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
16
15
 
17
16
/*
18
 
**     drizzleimport.c  - Imports all given files
19
 
**          into a table(s).
 
17
**         mysqlimport.c  - Imports all given files
 
18
**                          into a table(s).
20
19
**
21
 
**         *************************
22
 
**         *         *
23
 
**         * AUTHOR: Monty & Jani  *
24
 
**         * DATE:   June 24, 1997 *
25
 
**         *         *
26
 
**         *************************
 
20
**                         *************************
 
21
**                         *                       *
 
22
**                         * AUTHOR: Monty & Jani  *
 
23
**                         * DATE:   June 24, 1997 *
 
24
**                         *                       *
 
25
**                         *************************
27
26
*/
28
27
#define IMPORT_VERSION "3.7"
29
28
 
30
29
#include "client_priv.h"
31
 
#include <string>
32
 
#include <sstream>
33
 
 
34
 
#include <pthread.h>
35
 
 
36
 
/* Added this for string translation. */
37
 
#include <drizzled/gettext.h>
38
 
 
39
 
using namespace std;
40
 
using namespace drizzled;
41
 
 
42
 
extern "C" void * worker_thread(void *arg);
43
 
 
44
 
int exitcode= 0;
 
30
#include "mysql_version.h"
 
31
#ifdef HAVE_LIBPTHREAD
 
32
#include <my_pthread.h>
 
33
#endif
 
34
 
45
35
 
46
36
/* Global Thread counter */
47
 
uint32_t counter;
 
37
uint counter;
 
38
#ifdef HAVE_LIBPTHREAD
48
39
pthread_mutex_t counter_mutex;
49
40
pthread_cond_t count_threshhold;
 
41
#endif
50
42
 
51
 
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
52
 
                     drizzle_return_t ret, char *table);
53
 
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);
54
46
static char *add_load_option(char *ptr,const char *object,
55
 
           const char *statement);
56
 
 
57
 
static bool verbose= false, lock_tables= false, ignore_errors= false,
58
 
            opt_delete= false, opt_replace= false, silent= false,
59
 
            ignore_unique= false, opt_low_priority= false,
60
 
            tty_password= false, opt_mysql= false;
61
 
 
62
 
static uint32_t opt_use_threads= 0, opt_local_file= 0;
63
 
static char  *opt_password= NULL, *current_user= NULL,
64
 
    *current_host= NULL, *current_db= NULL, *fields_terminated= NULL,
65
 
    *lines_terminated= NULL, *enclosed= NULL, *opt_enclosed= NULL,
66
 
    *escaped= NULL, *opt_columns= NULL;
67
 
static uint32_t opt_drizzle_port= 0;
68
 
static int64_t opt_ignore_lines= -1;
 
47
                             const char *statement);
 
48
 
 
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;
 
63
 
 
64
#ifdef HAVE_SMEM
 
65
static char *shared_memory_base_name=0;
 
66
#endif
69
67
 
70
68
static struct my_option my_long_options[] =
71
69
{
 
70
#ifdef __NETWARE__
 
71
  {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
 
72
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
73
#endif
 
74
  {"character-sets-dir", OPT_CHARSETS_DIR,
 
75
   "Directory where character sets are.", (uchar**) &charsets_dir,
 
76
   (uchar**) &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.", (uchar**) &default_charset,
 
79
   (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
72
80
  {"columns", 'c',
73
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.",
74
 
   (char**) &opt_columns, (char**) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
 
82
   (uchar**) &opt_columns, (uchar**) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
 
83
   0, 0, 0},
 
84
  {"compress", 'C', "Use compression in server/client protocol.",
 
85
   (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
75
86
   0, 0, 0},
76
87
  {"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
77
88
   GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
78
 
  {"delete", 'd', "First delete all rows from table.", (char**) &opt_delete,
79
 
   (char**) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
89
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
 
90
   (uchar**) &debug_check_flag, (uchar**) &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
   (uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
 
94
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
95
  {"delete", 'd', "First delete all rows from table.", (uchar**) &opt_delete,
 
96
   (uchar**) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
80
97
  {"fields-terminated-by", OPT_FTB,
81
 
   "Fields in the textfile are terminated by ...", (char**) &fields_terminated,
82
 
   (char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
98
   "Fields in the textfile are terminated by ...", (uchar**) &fields_terminated,
 
99
   (uchar**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
83
100
  {"fields-enclosed-by", OPT_ENC,
84
 
   "Fields in the importfile are enclosed by ...", (char**) &enclosed,
85
 
   (char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
101
   "Fields in the importfile are enclosed by ...", (uchar**) &enclosed,
 
102
   (uchar**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
86
103
  {"fields-optionally-enclosed-by", OPT_O_ENC,
87
 
   "Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
88
 
   (char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
104
   "Fields in the i.file are opt. enclosed by ...", (uchar**) &opt_enclosed,
 
105
   (uchar**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
89
106
  {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
90
 
   (char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
 
107
   (uchar**) &escaped, (uchar**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
91
108
   0, 0},
92
109
  {"force", 'f', "Continue even if we get an sql-error.",
93
 
   (char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
 
110
   (uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
94
111
   0, 0, 0, 0},
95
112
  {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG,
96
113
   0, 0, 0, 0, 0, 0},
97
 
  {"host", 'h', "Connect to host.", (char**) &current_host,
98
 
   (char**) &current_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
114
  {"host", 'h', "Connect to host.", (uchar**) &current_host,
 
115
   (uchar**) &current_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
99
116
  {"ignore", 'i', "If duplicate unique key was found, keep old row.",
100
 
   (char**) &ignore_unique, (char**) &ignore_unique, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
117
   (uchar**) &ignore, (uchar**) &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
101
118
  {"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.",
102
 
   (char**) &opt_ignore_lines, (char**) &opt_ignore_lines, 0, GET_LL,
 
119
   (uchar**) &opt_ignore_lines, (uchar**) &opt_ignore_lines, 0, GET_LL,
103
120
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
104
121
  {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
105
 
   (char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
 
122
   (uchar**) &lines_terminated, (uchar**) &lines_terminated, 0, GET_STR,
106
123
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
107
 
  {"local", 'L', "Read all files through the client.", (char**) &opt_local_file,
108
 
   (char**) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
124
  {"local", 'L', "Read all files through the client.", (uchar**) &opt_local_file,
 
125
   (uchar**) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
109
126
  {"lock-tables", 'l', "Lock all tables for write (this disables threads).",
110
 
    (char**) &lock_tables, (char**) &lock_tables, 0, GET_BOOL, NO_ARG,
 
127
    (uchar**) &lock_tables, (uchar**) &lock_tables, 0, GET_BOOL, NO_ARG, 
111
128
    0, 0, 0, 0, 0, 0},
112
129
  {"low-priority", OPT_LOW_PRIORITY,
113
 
   "Use LOW_PRIORITY when updating the table.", (char**) &opt_low_priority,
114
 
   (char**) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
115
 
  {"mysql", 'm', N_("Use MySQL Protocol."),
116
 
   (char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 0, 0, 0,
117
 
   0, 0, 0},
118
 
  {"password", 'P',
 
130
   "Use LOW_PRIORITY when updating the table.", (uchar**) &opt_low_priority,
 
131
   (uchar**) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
132
  {"password", 'p',
119
133
   "Password to use when connecting to server. If password is not given it's asked from the tty.",
120
134
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
121
 
  {"port", 'p', "Port number to use for connection or 0 for default to, in "
122
 
   "order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
123
 
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
124
 
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
125
 
  {"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
 
135
#ifdef __WIN__
 
136
  {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
 
137
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
138
#endif
 
139
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
 
140
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
 
141
#if MYSQL_PORT_DEFAULT == 0
 
142
   "/etc/services, "
 
143
#endif
 
144
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
 
145
   (uchar**) &opt_mysql_port,
 
146
   (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
 
147
   0},
 
148
  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
126
149
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
127
150
  {"replace", 'r', "If duplicate unique key was found, replace old row.",
128
 
   (char**) &opt_replace, (char**) &opt_replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
129
 
  {"silent", 's', "Be more silent.", (char**) &silent, (char**) &silent, 0,
 
151
   (uchar**) &replace, (uchar**) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
152
#ifdef HAVE_SMEM
 
153
  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
 
154
   "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
 
155
   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
156
#endif
 
157
  {"silent", 's', "Be more silent.", (uchar**) &silent, (uchar**) &silent, 0,
130
158
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
159
  {"socket", 'S', "Socket file to use for connection.",
 
160
   (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
 
161
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
131
162
  {"use-threads", OPT_USE_THREADS,
132
163
   "Load files in parallel. The argument is the number "
133
164
   "of threads to use for loading data.",
134
 
   (char**) &opt_use_threads, (char**) &opt_use_threads, 0,
 
165
   (uchar**) &opt_use_threads, (uchar**) &opt_use_threads, 0, 
135
166
   GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
136
 
  {"user", 'u', "User for login if not current user.", (char**) &current_user,
137
 
   (char**) &current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
138
 
  {"verbose", 'v', "Print info about the various stages.", (char**) &verbose,
139
 
   (char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
167
#ifndef DONT_ALLOW_USER_CHANGE
 
168
  {"user", 'u', "User for login if not current user.", (uchar**) &current_user,
 
169
   (uchar**) &current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
170
#endif
 
171
  {"verbose", 'v', "Print info about the various stages.", (uchar**) &verbose,
 
172
   (uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
140
173
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
141
174
   NO_ARG, 0, 0, 0, 0, 0, 0},
142
175
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
143
176
};
144
177
 
145
178
 
146
 
static const char *load_default_groups[]= { "drizzleimport","client",0 };
 
179
static const char *load_default_groups[]= { "mysqlimport","client",0 };
 
180
 
 
181
#include <help_start.h>
147
182
 
148
183
static void print_version(void)
149
184
{
150
 
  printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n" ,internal::my_progname,
151
 
    IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
 
185
  printf("%s  Ver %s Distrib %s, for %s (%s)\n" ,my_progname,
 
186
          IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
 
187
  NETWARE_SET_SCREEN_MODE(1);
152
188
}
153
189
 
154
190
 
155
191
static void usage(void)
156
192
{
157
193
  print_version();
158
 
  puts("Copyright (C) 2008 Drizzle Open Source Development Team");
 
194
  puts("Copyright (C) 2000-2006 MySQL AB");
159
195
  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");
160
196
  printf("\
161
197
Loads tables from text files in various formats.  The base name of the\n\
162
198
text file must be the name of the table that should be used.\n\
163
 
If one uses sockets to connect to the Drizzle server, the server will open and\n\
 
199
If one uses sockets to connect to the MySQL server, the server will open and\n\
164
200
read the text file directly. In other cases the client will open the text\n\
165
201
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
166
202
 
167
 
  printf("\nUsage: %s [OPTIONS] database textfile...",internal::my_progname);
168
 
  internal::print_defaults("drizzle",load_default_groups);
 
203
  printf("\nUsage: %s [OPTIONS] database textfile...",my_progname);
 
204
  print_defaults("my",load_default_groups);
169
205
  my_print_help(my_long_options);
170
206
  my_print_variables(my_long_options);
171
207
}
172
208
 
173
 
static bool get_one_option(int optid, const struct my_option *, char *argument)
 
209
#include <help_end.h>
 
210
 
 
211
static my_bool
 
212
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
 
213
               char *argument)
174
214
{
175
 
  char *endchar= NULL;
176
 
  uint64_t temp_drizzle_port= 0;
177
 
 
178
215
  switch(optid) {
 
216
#ifdef __NETWARE__
 
217
  case OPT_AUTO_CLOSE:
 
218
    setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
 
219
    break;
 
220
#endif
179
221
  case 'p':
180
 
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
181
 
    /* if there is an alpha character this is not a valid port */
182
 
    if (strlen(endchar) != 0)
183
 
    {
184
 
      fprintf(stderr, _("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead.\n"));
185
 
      exit(1);
186
 
    }
187
 
    /* If the port number is > 65535 it is not a valid port
188
 
       This also helps with potential data loss casting unsigned long to a
189
 
       uint32_t. */
190
 
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
191
 
    {
192
 
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
193
 
      exit(1);
194
 
    }
195
 
    else
196
 
    {
197
 
      opt_drizzle_port= (uint32_t) temp_drizzle_port;
198
 
    }
199
 
    break;
200
 
  case 'P':
201
222
    if (argument)
202
223
    {
203
224
      char *start=argument;
204
 
      if (opt_password)
205
 
        free(opt_password);
206
 
      opt_password = strdup(argument);
207
 
      if (opt_password == NULL)
208
 
      {
209
 
        fprintf(stderr, "Memory allocation error while copying password. "
210
 
                        "Aborting.\n");
211
 
        exit(ENOMEM);
212
 
      }
213
 
      while (*argument)
214
 
      {
215
 
        /* Overwriting password with 'x' */
216
 
        *argument++= 'x';
217
 
      }
 
225
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
 
226
      opt_password=my_strdup(argument,MYF(MY_FAE));
 
227
      while (*argument) *argument++= 'x';               /* Destroy argument */
218
228
      if (*start)
219
 
      {
220
 
        /* Cut length of argument */
221
 
        start[1]= 0;
222
 
      }
 
229
        start[1]=0;                             /* Cut length of argument */
223
230
      tty_password= 0;
224
231
    }
225
232
    else
226
233
      tty_password= 1;
227
234
    break;
228
 
  case OPT_DRIZZLE_PROTOCOL:
 
235
#ifdef __WIN__
 
236
  case 'W':
 
237
    opt_protocol = MYSQL_PROTOCOL_PIPE;
 
238
    opt_local_file=1;
 
239
    break;
 
240
#endif
 
241
  case OPT_MYSQL_PROTOCOL:
 
242
    opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
 
243
                                    opt->name);
 
244
    break;
 
245
  case '#':
 
246
    DBUG_PUSH(argument ? argument : "d:t:o");
 
247
    debug_check_flag= 1;
229
248
    break;
230
249
  case 'V': print_version(); exit(0);
231
250
  case 'I':
243
262
 
244
263
  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
245
264
    exit(ho_error);
 
265
  if (debug_info_flag)
 
266
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
 
267
  if (debug_check_flag)
 
268
    my_end_arg= MY_CHECK_ERROR;
246
269
 
247
270
  if (enclosed && opt_enclosed)
248
271
  {
249
272
    fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n");
250
273
    return(1);
251
274
  }
252
 
  if (opt_replace && ignore_unique)
 
275
  if (replace && ignore)
253
276
  {
254
 
    fprintf(stderr, "You can't use --ignore_unique (-i) and --replace (-r) at the same time.\n");
 
277
    fprintf(stderr, "You can't use --ignore (-i) and --replace (-r) at the same time.\n");
255
278
    return(1);
256
279
  }
 
280
  if (strcmp(default_charset, charset_info->csname) &&
 
281
      !(charset_info= get_charset_by_csname(default_charset,
 
282
                                            MY_CS_PRIMARY, MYF(MY_WME))))
 
283
    exit(1);
257
284
  if (*argc < 2)
258
285
  {
259
286
    usage();
262
289
  current_db= *((*argv)++);
263
290
  (*argc)--;
264
291
  if (tty_password)
265
 
    opt_password=client_get_tty_password(NULL);
 
292
    opt_password=get_tty_password(NullS);
266
293
  return(0);
267
294
}
268
295
 
269
296
 
270
297
 
271
 
static int write_to_table(char *filename, drizzle_con_st *con)
 
298
static int write_to_table(char *filename, MYSQL *mysql)
272
299
{
273
300
  char tablename[FN_REFLEN], hard_path[FN_REFLEN],
274
301
       sql_statement[FN_REFLEN*16+256], *end;
275
 
  drizzle_result_st result;
276
 
  drizzle_return_t ret;
 
302
  DBUG_ENTER("write_to_table");
 
303
  DBUG_PRINT("enter",("filename: %s",filename));
277
304
 
278
 
  internal::fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
 
305
  fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
279
306
  if (!opt_local_file)
280
 
    strcpy(hard_path,filename);
 
307
    strmov(hard_path,filename);
281
308
  else
282
 
    internal::my_load_path(hard_path, filename, NULL); /* filename includes the path */
 
309
    my_load_path(hard_path, filename, NULL); /* filename includes the path */
283
310
 
284
311
  if (opt_delete)
285
312
  {
290
317
#else
291
318
    sprintf(sql_statement, "DELETE FROM %s", tablename);
292
319
#endif
293
 
    if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
294
 
        ret != DRIZZLE_RETURN_OK)
 
320
    if (mysql_query(mysql, sql_statement))
295
321
    {
296
 
      db_error(con, &result, ret, tablename);
297
 
      return(1);
 
322
      db_error_with_table(mysql, tablename);
 
323
      DBUG_RETURN(1);
298
324
    }
299
 
    drizzle_result_free(&result);
300
325
  }
 
326
  to_unix_path(hard_path);
301
327
  if (verbose)
302
328
  {
303
329
    if (opt_local_file)
304
330
      fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
305
 
        hard_path, tablename);
 
331
              hard_path, tablename);
306
332
    else
307
333
      fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
308
 
        hard_path, tablename);
 
334
              hard_path, tablename);
309
335
  }
310
336
  sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
311
 
    opt_low_priority ? "LOW_PRIORITY" : "",
312
 
    opt_local_file ? "LOCAL" : "", hard_path);
313
 
  end= strchr(sql_statement, '\0');
314
 
  if (opt_replace)
315
 
    end= strcpy(end, " REPLACE")+8;
316
 
  if (ignore_unique)
317
 
    end= strcpy(end, " IGNORE")+7;
318
 
 
319
 
  end+= sprintf(end, " INTO TABLE %s", tablename);
 
337
          opt_low_priority ? "LOW_PRIORITY" : "",
 
338
          opt_local_file ? "LOCAL" : "", hard_path);
 
339
  end= strend(sql_statement);
 
340
  if (replace)
 
341
    end= strmov(end, " REPLACE");
 
342
  if (ignore)
 
343
    end= strmov(end, " IGNORE");
 
344
  end= strmov(strmov(end, " INTO TABLE "), tablename);
320
345
 
321
346
  if (fields_terminated || enclosed || opt_enclosed || escaped)
322
 
      end= strcpy(end, " FIELDS")+7;
 
347
      end= strmov(end, " FIELDS");
323
348
  end= add_load_option(end, fields_terminated, " TERMINATED BY");
324
349
  end= add_load_option(end, enclosed, " ENCLOSED BY");
325
350
  end= add_load_option(end, opt_enclosed,
326
 
           " OPTIONALLY ENCLOSED BY");
 
351
                       " OPTIONALLY ENCLOSED BY");
327
352
  end= add_load_option(end, escaped, " ESCAPED BY");
328
353
  end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
329
354
  if (opt_ignore_lines >= 0)
330
 
  {
331
 
    end= strcpy(end, " IGNORE ")+8;
332
 
    ostringstream buffer;
333
 
    buffer << opt_ignore_lines;
334
 
    end= strcpy(end, buffer.str().c_str())+ buffer.str().size();
335
 
    end= strcpy(end, " LINES")+6;
336
 
  }
 
355
    end= strmov(longlong10_to_str(opt_ignore_lines, 
 
356
                                  strmov(end, " IGNORE "),10), " LINES");
337
357
  if (opt_columns)
338
 
  {
339
 
    end= strcpy(end, " (")+2;
340
 
    end= strcpy(end, opt_columns)+strlen(opt_columns);
341
 
    end= strcpy(end, ")")+1;
342
 
  }
 
358
    end= strmov(strmov(strmov(end, " ("), opt_columns), ")");
343
359
  *end= '\0';
344
360
 
345
 
  if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
346
 
      ret != DRIZZLE_RETURN_OK)
 
361
  if (mysql_query(mysql, sql_statement))
347
362
  {
348
 
    db_error(con, &result, ret, tablename);
349
 
    return(1);
 
363
    db_error_with_table(mysql, tablename);
 
364
    DBUG_RETURN(1);
350
365
  }
351
366
  if (!silent)
352
367
  {
353
 
    if (strcmp(drizzle_result_info(&result), ""))
 
368
    if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
354
369
    {
355
370
      fprintf(stdout, "%s.%s: %s\n", current_db, tablename,
356
 
        drizzle_result_info(&result));
 
371
              mysql_info(mysql));
357
372
    }
358
373
  }
359
 
  drizzle_result_free(&result);
360
 
  return(0);
 
374
  DBUG_RETURN(0);
361
375
}
362
376
 
363
377
 
364
 
static void lock_table(drizzle_con_st *con, int tablecount, char **raw_tablename)
 
378
 
 
379
static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
365
380
{
366
 
  string query;
 
381
  DYNAMIC_STRING query;
367
382
  int i;
368
383
  char tablename[FN_REFLEN];
369
 
  drizzle_result_st result;
370
 
  drizzle_return_t ret;
371
384
 
372
385
  if (verbose)
373
386
    fprintf(stdout, "Locking tables for write\n");
374
 
  query.append("LOCK TABLES ");
 
387
  init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
375
388
  for (i=0 ; i < tablecount ; i++)
376
389
  {
377
 
    internal::fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
378
 
    query.append(tablename);
379
 
    query.append(" WRITE,");
380
 
  }
381
 
  if (drizzle_query(con, &result, query.c_str(), query.length()-1,
382
 
                    &ret) == NULL ||
383
 
      ret != DRIZZLE_RETURN_OK)
384
 
  {
385
 
    db_error(con, &result, ret, NULL);
386
 
    /* We shall countinue here, if --force was given */
387
 
    return;
388
 
  }
389
 
  drizzle_result_free(&result);
 
390
    fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
 
391
    dynstr_append(&query, tablename);
 
392
    dynstr_append(&query, " WRITE,");
 
393
  }
 
394
  if (mysql_real_query(mysql, query.str, query.length-1))
 
395
    db_error(mysql); /* We shall countinue here, if --force was given */
390
396
}
391
397
 
392
398
 
393
 
static drizzle_con_st *db_connect(char *host, char *database,
394
 
                                  char *user, char *passwd)
 
399
 
 
400
 
 
401
static MYSQL *db_connect(char *host, char *database,
 
402
                         char *user, char *passwd)
395
403
{
396
 
  drizzle_st *drizzle;
397
 
  drizzle_con_st *con;
398
 
  drizzle_return_t ret;
399
 
 
 
404
  MYSQL *mysql;
400
405
  if (verbose)
401
406
    fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
402
 
  if (!(drizzle= drizzle_create(NULL)))
403
 
    return 0;
404
 
  if (!(con= drizzle_con_add_tcp(drizzle,NULL,host,opt_drizzle_port,user,passwd,
405
 
                                 database, opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE)))
406
 
  {
407
 
    return 0;
408
 
  }
409
 
 
410
 
  if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
411
 
  {
412
 
    ignore_errors=0;    /* NO RETURN FROM db_error */
413
 
    db_error(con, NULL, ret, NULL);
414
 
  }
415
 
 
 
407
  if (!(mysql= mysql_init(NULL)))
 
408
    return 0;
 
409
  if (opt_compress)
 
410
    mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
 
411
  if (opt_local_file)
 
412
    mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
 
413
                  (char*) &opt_local_file);
 
414
#ifdef HAVE_OPENSSL
 
415
  if (opt_use_ssl)
 
416
    mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
 
417
                  opt_ssl_capath, opt_ssl_cipher);
 
418
  mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
 
419
                (char*)&opt_ssl_verify_server_cert);
 
420
#endif
 
421
  if (opt_protocol)
 
422
    mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
423
#ifdef HAVE_SMEM
 
424
  if (shared_memory_base_name)
 
425
    mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
 
426
#endif
 
427
  if (!(mysql_real_connect(mysql,host,user,passwd,
 
428
                           database,opt_mysql_port,opt_mysql_unix_port,
 
429
                           0)))
 
430
  {
 
431
    ignore_errors=0;      /* NO RETURN FROM db_error */
 
432
    db_error(mysql);
 
433
  }
 
434
  mysql->reconnect= 0;
416
435
  if (verbose)
417
436
    fprintf(stdout, "Selecting database %s\n", database);
418
 
 
419
 
  return con;
 
437
  if (mysql_select_db(mysql, database))
 
438
  {
 
439
    ignore_errors=0;
 
440
    db_error(mysql);
 
441
  }
 
442
  return mysql;
420
443
}
421
444
 
422
445
 
423
446
 
424
 
static void db_disconnect(char *host, drizzle_con_st *con)
 
447
static void db_disconnect(char *host, MYSQL *mysql)
425
448
{
426
449
  if (verbose)
427
450
    fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
428
 
  drizzle_free(drizzle_con_drizzle(con));
 
451
  mysql_close(mysql);
429
452
}
430
453
 
431
454
 
432
455
 
433
 
static void safe_exit(int error, drizzle_con_st *con)
 
456
static void safe_exit(int error, MYSQL *mysql)
434
457
{
435
458
  if (ignore_errors)
436
459
    return;
437
 
  if (con)
438
 
    drizzle_free(drizzle_con_drizzle(con));
 
460
  if (mysql)
 
461
    mysql_close(mysql);
439
462
  exit(error);
440
463
}
441
464
 
442
465
 
443
466
 
444
 
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
445
 
                     drizzle_return_t ret, char *table)
446
 
{
447
 
  if (ret == DRIZZLE_RETURN_ERROR_CODE)
448
 
  {
449
 
    my_printf_error(0,"Error: %d, %s%s%s", MYF(0),
450
 
                    drizzle_result_error_code(result),
451
 
                    drizzle_result_error(result),
452
 
                    table ? ", when using table: " : "", table ? table : "");
453
 
    drizzle_result_free(result);
454
 
  }
455
 
  else
456
 
  {
457
 
    my_printf_error(0,"Error: %d, %s%s%s", MYF(0), ret, drizzle_con_error(con),
458
 
                    table ? ", when using table: " : "", table ? table : "");
459
 
  }
460
 
 
461
 
  safe_exit(1, con);
 
467
static void db_error_with_table(MYSQL *mysql, char *table)
 
468
{
 
469
  my_printf_error(0,"Error: %d, %s, when using table: %s",
 
470
                  MYF(0), mysql_errno(mysql), mysql_error(mysql), table);
 
471
  safe_exit(1, mysql);
 
472
}
 
473
 
 
474
 
 
475
 
 
476
static void db_error(MYSQL *mysql)
 
477
{
 
478
  my_printf_error(0,"Error: %d %s", MYF(0), mysql_errno(mysql), mysql_error(mysql));
 
479
  safe_exit(1, mysql);
462
480
}
463
481
 
464
482
 
465
483
static char *add_load_option(char *ptr, const char *object,
466
 
           const char *statement)
 
484
                             const char *statement)
467
485
{
468
486
  if (object)
469
487
  {
470
488
    /* Don't escape hex constants */
471
489
    if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
472
 
      ptr+= sprintf(ptr, " %s %s", statement, object);
 
490
      ptr= strxmov(ptr," ",statement," ",object,NullS);
473
491
    else
474
492
    {
475
493
      /* char constant; escape */
476
 
      ptr+= sprintf(ptr, " %s '", statement); 
477
 
      ptr= field_escape(ptr,object,(uint32_t) strlen(object));
 
494
      ptr= strxmov(ptr," ",statement," '",NullS);
 
495
      ptr= field_escape(ptr,object,(uint) strlen(object));
478
496
      *ptr++= '\'';
479
497
    }
480
498
  }
486
504
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
487
505
** This is done by doubleing ' and add a end -\ if needed to avoid
488
506
** syntax errors from the SQL parser.
489
 
*/
 
507
*/ 
490
508
 
491
 
static char *field_escape(char *to,const char *from,uint32_t length)
 
509
static char *field_escape(char *to,const char *from,uint length)
492
510
{
493
511
  const char *end;
494
 
  uint32_t end_backslashes=0;
 
512
  uint end_backslashes=0; 
495
513
 
496
514
  for (end= from+length; from != end; from++)
497
515
  {
498
516
    *to++= *from;
499
517
    if (*from == '\\')
500
518
      end_backslashes^=1;    /* find odd number of backslashes */
501
 
    else
 
519
    else 
502
520
    {
503
521
      if (*from == '\'' && !end_backslashes)
504
 
  *to++= *from;      /* We want a dublicate of "'" for DRIZZLE */
 
522
        *to++= *from;      /* We want a dublicate of "'" for MySQL */
505
523
      end_backslashes=0;
506
524
    }
507
525
  }
508
526
  /* Add missing backslashes if user has specified odd number of backs.*/
509
527
  if (end_backslashes)
510
 
    *to++= '\\';
 
528
    *to++= '\\';          
511
529
  return to;
512
530
}
513
531
 
514
 
void * worker_thread(void *arg)
 
532
int exitcode= 0;
 
533
 
 
534
#ifdef HAVE_LIBPTHREAD
 
535
pthread_handler_t worker_thread(void *arg)
515
536
{
516
537
  int error;
517
538
  char *raw_table_name= (char *)arg;
518
 
  drizzle_con_st *con= NULL;
519
 
  drizzle_result_st result;
520
 
  drizzle_return_t ret;
 
539
  MYSQL *mysql= 0;
521
540
 
522
 
  if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
 
541
  if (mysql_thread_init())
 
542
    goto error;
 
543
  
 
544
  if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
523
545
  {
524
546
    goto error;
525
547
  }
526
548
 
527
 
  if (drizzle_query_str(con, &result,
528
 
                        "/*!40101 set @@character_set_database=binary */;",
529
 
                        &ret) == NULL ||
530
 
      ret != DRIZZLE_RETURN_OK)
 
549
  if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
531
550
  {
532
 
    db_error(con, &result, ret, NULL);
533
 
    /* We shall countinue here, if --force was given */
 
551
    db_error(mysql); /* We shall countinue here, if --force was given */
534
552
    goto error;
535
553
  }
536
554
 
537
555
  /*
538
556
    We are not currently catching the error here.
539
557
  */
540
 
  if((error= write_to_table(raw_table_name, con)))
 
558
  if((error= write_to_table(raw_table_name, mysql)))
541
559
    if (exitcode == 0)
542
560
      exitcode= error;
543
561
 
544
562
error:
545
 
  if (con)
546
 
    db_disconnect(current_host, con);
 
563
  if (mysql)
 
564
    db_disconnect(current_host, mysql);
547
565
 
548
566
  pthread_mutex_lock(&counter_mutex);
549
567
  counter--;
550
568
  pthread_cond_signal(&count_threshhold);
551
569
  pthread_mutex_unlock(&counter_mutex);
552
 
  internal::my_thread_end();
 
570
  my_thread_end();
553
571
 
554
572
  return 0;
555
573
}
 
574
#endif
556
575
 
557
576
 
558
577
int main(int argc, char **argv)
561
580
  char **argv_to_free;
562
581
  MY_INIT(argv[0]);
563
582
 
564
 
  internal::load_defaults("drizzle",load_default_groups,&argc,&argv);
 
583
  load_defaults("my",load_default_groups,&argc,&argv);
565
584
  /* argv is changed in the program */
566
585
  argv_to_free= argv;
567
586
  if (get_options(&argc, &argv))
568
587
  {
569
 
    internal::free_defaults(argv_to_free);
 
588
    free_defaults(argv_to_free);
570
589
    return(1);
571
590
  }
572
591
 
579
598
    pthread_attr_setdetachstate(&attr,
580
599
                                PTHREAD_CREATE_DETACHED);
581
600
 
582
 
    pthread_mutex_init(&counter_mutex, NULL);
583
 
    pthread_cond_init(&count_threshhold, NULL);
 
601
    VOID(pthread_mutex_init(&counter_mutex, NULL));
 
602
    VOID(pthread_cond_init(&count_threshhold, NULL));
584
603
 
585
604
    for (counter= 0; *argv != NULL; argv++) /* Loop through tables */
586
605
    {
596
615
      counter++;
597
616
      pthread_mutex_unlock(&counter_mutex);
598
617
      /* now create the thread */
599
 
      if (pthread_create(&mainthread, &attr, worker_thread,
 
618
      if (pthread_create(&mainthread, &attr, worker_thread, 
600
619
                         (void *)*argv) != 0)
601
620
      {
602
621
        pthread_mutex_lock(&counter_mutex);
603
622
        counter--;
604
623
        pthread_mutex_unlock(&counter_mutex);
605
624
        fprintf(stderr,"%s: Could not create thread\n",
606
 
                internal::my_progname);
 
625
                my_progname);
607
626
      }
608
627
    }
609
628
 
619
638
      pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
620
639
    }
621
640
    pthread_mutex_unlock(&counter_mutex);
622
 
    pthread_mutex_destroy(&counter_mutex);
623
 
    pthread_cond_destroy(&count_threshhold);
 
641
    VOID(pthread_mutex_destroy(&counter_mutex));
 
642
    VOID(pthread_cond_destroy(&count_threshhold));
624
643
    pthread_attr_destroy(&attr);
625
644
  }
626
645
  else
627
646
#endif
628
647
  {
629
 
    drizzle_con_st *con= 0;
630
 
    drizzle_result_st result;
631
 
    drizzle_return_t ret;
632
 
    if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
633
 
    {
634
 
      internal::free_defaults(argv_to_free);
635
 
      return(1);
636
 
    }
637
 
 
638
 
    if (drizzle_query_str(con, &result,
639
 
                          "/*!40101 set @@character_set_database=binary */;",
640
 
                          &ret) == NULL ||
641
 
        ret != DRIZZLE_RETURN_OK)
642
 
    {
643
 
      db_error(con, &result, ret, NULL);
644
 
      /* We shall countinue here, if --force was given */
645
 
      return(1);
646
 
    }
647
 
 
648
 
    drizzle_result_free(&result);
 
648
    MYSQL *mysql= 0;
 
649
    if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
 
650
    {
 
651
      free_defaults(argv_to_free);
 
652
      return(1); /* purecov: deadcode */
 
653
    }
 
654
 
 
655
    if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
 
656
    {
 
657
      db_error(mysql); /* We shall countinue here, if --force was given */
 
658
      return(1);
 
659
    }
649
660
 
650
661
    if (lock_tables)
651
 
      lock_table(con, argc, argv);
 
662
      lock_table(mysql, argc, argv);
652
663
    for (; *argv != NULL; argv++)
653
 
      if ((error= write_to_table(*argv, con)))
 
664
      if ((error= write_to_table(*argv, mysql)))
654
665
        if (exitcode == 0)
655
666
          exitcode= error;
656
 
    db_disconnect(current_host, con);
 
667
    db_disconnect(current_host, mysql);
657
668
  }
658
 
  free(opt_password);
659
 
  internal::free_defaults(argv_to_free);
660
 
  internal::my_end();
 
669
  my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
 
670
#ifdef HAVE_SMEM
 
671
  my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
 
672
#endif
 
673
  free_defaults(argv_to_free);
 
674
  my_end(my_end_arg);
661
675
  return(exitcode);
662
676
}