~drizzle-trunk/drizzle/development

1615 by Brian Aker
MErge VJ
1
/* 
2
  Copyright (C) 2010 Vijay Samuel
1707.1.23 by Brian Aker
Cleanup of import.
3
  Copyright (C) 2010 Brian Aker
1615 by Brian Aker
MErge VJ
4
  Copyright (C) 2000-2006 MySQL AB
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
5
  Copyright (C) 2008-2009 Sun Microsystems, Inc.
1615 by Brian Aker
MErge VJ
6
7
  This program is free software; you can redistribute it and/or modify
8
  it under the terms of the GNU General Public License as published by
9
  the Free Software Foundation; version 2 of the License.
10
11
  This program is distributed in the hope that it will be useful,
12
  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
  GNU General Public License for more details.
15
16
  You should have received a copy of the GNU General Public License
17
  along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
18
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
19
1707.1.23 by Brian Aker
Cleanup of import.
20
#define IMPORT_VERSION "4.0"
1 by brian
clean slate
21
612.2.4 by Monty Taylor
Moved some defines to config.h. Stopped including config.h directly anywhere.
22
#include "client_priv.h"
279.2.5 by Monty Taylor
Removed DYNAMIC_STRING from drizzleimport.
23
#include <string>
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
24
#include <sstream>
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
25
#include <iostream>
26
#include <fstream>
27
#include <boost/program_options.hpp>
279.2.4 by Monty Taylor
Moved import, check and dump to C++... fixed errors.
28
#include <pthread.h>
1 by brian
clean slate
29
2241.4.14 by Stewart Smith
remove some includes from my_sys.h and instead only include where needed. This helps reduce the number of files that have to be rebuilt when you change some of the more widely included header files (such as the drizzled::identifier ones)
30
#include <drizzled/definitions.h>
31
#include <drizzled/internal/my_sys.h>
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
32
/* Added this for string translation. */
33
#include <drizzled/gettext.h>
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
34
#include <drizzled/configmake.h>
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
35
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
36
namespace po= boost::program_options;
279.2.5 by Monty Taylor
Removed DYNAMIC_STRING from drizzleimport.
37
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
38
using namespace drizzled;
1 by brian
clean slate
39
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
40
extern "C" void * worker_thread(void *arg);
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
41
42
int exitcode= 0;
43
2155.3.1 by Stewart Smith
drizzleimport had incorrect program_name (typo)
44
const char *program_name= "drizzleimport";
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
45
1 by brian
clean slate
46
/* Global Thread counter */
893 by Brian Aker
First pass of stripping uint
47
uint32_t counter;
1 by brian
clean slate
48
pthread_mutex_t counter_mutex;
49
pthread_cond_t count_threshhold;
50
928.1.6 by Eric Day
All utilities done except slap.
51
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
52
                     drizzle_return_t ret, char *table);
893 by Brian Aker
First pass of stripping uint
53
static char *field_escape(char *to,const char *from,uint32_t length);
1 by brian
clean slate
54
static char *add_load_option(char *ptr,const char *object,
206.3.1 by Patrick Galbraith
Most everything working with client rename
55
           const char *statement);
1 by brian
clean slate
56
1707.1.23 by Brian Aker
Cleanup of import.
57
static bool verbose= false, ignore_errors= false,
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
58
            opt_delete= false, opt_replace= false, silent= false,
1235.3.7 by Stewart Smith
remove outdated --compress option from drizzleimport
59
            ignore_unique= false, opt_low_priority= false,
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
60
            use_drizzle_protocol= false, opt_local_file;
1235.3.13 by Stewart Smith
remove MY_GIVE_INFO parameter to my_end() that really just gave us the output of time(1). Use UNIX, don't re-implement the kitchen sink. This also removes --debug-info from most command line utilities.
61
1707.1.23 by Brian Aker
Cleanup of import.
62
static uint32_t opt_use_threads;
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
63
static uint32_t opt_drizzle_port= 0;
152 by Brian Aker
longlong replacement
64
static int64_t opt_ignore_lines= -1;
1 by brian
clean slate
65
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
66
std::string opt_columns,
67
  opt_enclosed,
68
  escaped,
69
  password,
70
  current_db,
71
  lines_terminated,
72
  current_user,
73
  opt_password,
74
  enclosed,  
75
  current_host,
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
76
  fields_terminated,
77
  opt_protocol;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
78
79
80
static int get_options(void)
81
{
82
83
  if (! enclosed.empty() && ! opt_enclosed.empty())
1 by brian
clean slate
84
  {
85
    fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n");
86
    return(1);
87
  }
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
88
  if (opt_replace && ignore_unique)
1 by brian
clean slate
89
  {
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
90
    fprintf(stderr, "You can't use --ignore_unique (-i) and --replace (-r) at the same time.\n");
1 by brian
clean slate
91
    return(1);
92
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
93
1 by brian
clean slate
94
  if (tty_password)
928.1.6 by Eric Day
All utilities done except slap.
95
    opt_password=client_get_tty_password(NULL);
1 by brian
clean slate
96
  return(0);
97
}
98
99
100
928.1.6 by Eric Day
All utilities done except slap.
101
static int write_to_table(char *filename, drizzle_con_st *con)
1 by brian
clean slate
102
{
103
  char tablename[FN_REFLEN], hard_path[FN_REFLEN],
104
       sql_statement[FN_REFLEN*16+256], *end;
928.1.6 by Eric Day
All utilities done except slap.
105
  drizzle_result_st result;
106
  drizzle_return_t ret;
1 by brian
clean slate
107
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
108
  internal::fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
109
  if (not opt_local_file)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
110
    strcpy(hard_path,filename);
1 by brian
clean slate
111
  else
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
112
    internal::my_load_path(hard_path, filename, NULL); /* filename includes the path */
1 by brian
clean slate
113
114
  if (opt_delete)
115
  {
116
    if (verbose)
117
      fprintf(stdout, "Deleting the old data from table %s\n", tablename);
118
#ifdef HAVE_SNPRINTF
1366.1.13 by Siddharth Prakash Singh
more sprintf->snprintf
119
    snprintf(sql_statement, sizeof(sql_statement), "DELETE FROM %s", tablename);
1 by brian
clean slate
120
#else
1366.1.13 by Siddharth Prakash Singh
more sprintf->snprintf
121
    snprintf(sql_statement, sizeof(sql_statement), "DELETE FROM %s", tablename);
1 by brian
clean slate
122
#endif
928.1.6 by Eric Day
All utilities done except slap.
123
    if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
124
        ret != DRIZZLE_RETURN_OK)
1 by brian
clean slate
125
    {
928.1.6 by Eric Day
All utilities done except slap.
126
      db_error(con, &result, ret, tablename);
142.1.2 by Patrick
All DBUG_x removed from client/
127
      return(1);
1 by brian
clean slate
128
    }
928.1.6 by Eric Day
All utilities done except slap.
129
    drizzle_result_free(&result);
1 by brian
clean slate
130
  }
131
  if (verbose)
132
  {
133
    if (opt_local_file)
134
      fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
135
        hard_path, tablename);
1 by brian
clean slate
136
    else
137
      fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
138
        hard_path, tablename);
1 by brian
clean slate
139
  }
1366.1.14 by Siddharth Prakash Singh
bug fixing
140
  snprintf(sql_statement, sizeof(sql_statement), "LOAD DATA %s %s INFILE '%s'",
206.3.1 by Patrick Galbraith
Most everything working with client rename
141
    opt_low_priority ? "LOW_PRIORITY" : "",
142
    opt_local_file ? "LOCAL" : "", hard_path);
376 by Brian Aker
strend remove
143
  end= strchr(sql_statement, '\0');
279.2.5 by Monty Taylor
Removed DYNAMIC_STRING from drizzleimport.
144
  if (opt_replace)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
145
    end= strcpy(end, " REPLACE")+8;
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
146
  if (ignore_unique)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
147
    end= strcpy(end, " IGNORE")+7;
148
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
149
  end+= sprintf(end, " INTO TABLE %s", tablename);
1 by brian
clean slate
150
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
151
  if (! fields_terminated.empty() || ! enclosed.empty() || ! opt_enclosed.empty() || ! escaped.empty())
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
152
      end= strcpy(end, " FIELDS")+7;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
153
  end= add_load_option(end, (char *)fields_terminated.c_str(), " TERMINATED BY");
154
  end= add_load_option(end, (char *)enclosed.c_str(), " ENCLOSED BY");
155
  end= add_load_option(end, (char *)opt_enclosed.c_str(),
206.3.1 by Patrick Galbraith
Most everything working with client rename
156
           " OPTIONALLY ENCLOSED BY");
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
157
  end= add_load_option(end, (char *)escaped.c_str(), " ESCAPED BY");
158
  end= add_load_option(end, (char *)lines_terminated.c_str(), " LINES TERMINATED BY");
1 by brian
clean slate
159
  if (opt_ignore_lines >= 0)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
160
  {
161
    end= strcpy(end, " IGNORE ")+8;
971.1.77 by Monty Taylor
Removed mysys/mystrings things from client/ progs. Still need to get rid of my_getopt, but I think that's all now.
162
    ostringstream buffer;
163
    buffer << opt_ignore_lines;
164
    end= strcpy(end, buffer.str().c_str())+ buffer.str().size();
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
165
    end= strcpy(end, " LINES")+6;
166
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
167
  if (! opt_columns.empty())
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
168
  {
169
    end= strcpy(end, " (")+2;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
170
    end= strcpy(end, (char *)opt_columns.c_str()+opt_columns.length());
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
171
    end= strcpy(end, ")")+1;
172
  }
1 by brian
clean slate
173
  *end= '\0';
174
928.1.6 by Eric Day
All utilities done except slap.
175
  if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
176
      ret != DRIZZLE_RETURN_OK)
1 by brian
clean slate
177
  {
928.1.6 by Eric Day
All utilities done except slap.
178
    db_error(con, &result, ret, tablename);
142.1.2 by Patrick
All DBUG_x removed from client/
179
    return(1);
1 by brian
clean slate
180
  }
181
  if (!silent)
182
  {
928.1.6 by Eric Day
All utilities done except slap.
183
    if (strcmp(drizzle_result_info(&result), ""))
1 by brian
clean slate
184
    {
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
185
      fprintf(stdout, "%s.%s: %s\n", current_db.c_str(), tablename,
928.1.6 by Eric Day
All utilities done except slap.
186
        drizzle_result_info(&result));
1 by brian
clean slate
187
    }
188
  }
928.1.6 by Eric Day
All utilities done except slap.
189
  drizzle_result_free(&result);
142.1.2 by Patrick
All DBUG_x removed from client/
190
  return(0);
1 by brian
clean slate
191
}
192
193
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
194
static drizzle_con_st *db_connect(const string host, const string database,
195
                                  const string user, const string passwd)
1 by brian
clean slate
196
{
928.1.6 by Eric Day
All utilities done except slap.
197
  drizzle_st *drizzle;
198
  drizzle_con_st *con;
199
  drizzle_return_t ret;
200
1 by brian
clean slate
201
  if (verbose)
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
202
    fprintf(stdout, "Connecting to %s, using protocol %s...\n", ! host.empty() ? host.c_str() : "localhost", opt_protocol.c_str());
928.1.6 by Eric Day
All utilities done except slap.
203
  if (!(drizzle= drizzle_create(NULL)))
204
    return 0;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
205
  if (!(con= drizzle_con_add_tcp(drizzle,NULL,(char *)host.c_str(),opt_drizzle_port,(char *)user.c_str(),(char *)passwd.c_str(),
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
206
                                 (char *)database.c_str(), use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL)))
928.1.6 by Eric Day
All utilities done except slap.
207
  {
208
    return 0;
209
  }
210
211
  if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
1 by brian
clean slate
212
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
213
    ignore_errors=0;    /* NO RETURN FROM db_error */
928.1.6 by Eric Day
All utilities done except slap.
214
    db_error(con, NULL, ret, NULL);
1 by brian
clean slate
215
  }
928.1.6 by Eric Day
All utilities done except slap.
216
1 by brian
clean slate
217
  if (verbose)
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
218
    fprintf(stdout, "Selecting database %s\n", database.c_str());
928.1.6 by Eric Day
All utilities done except slap.
219
220
  return con;
1 by brian
clean slate
221
}
222
223
224
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
225
static void db_disconnect(const string host, drizzle_con_st *con)
1 by brian
clean slate
226
{
227
  if (verbose)
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
228
    fprintf(stdout, "Disconnecting from %s\n", ! host.empty() ? host.c_str() : "localhost");
928.1.6 by Eric Day
All utilities done except slap.
229
  drizzle_free(drizzle_con_drizzle(con));
1 by brian
clean slate
230
}
231
232
233
928.1.6 by Eric Day
All utilities done except slap.
234
static void safe_exit(int error, drizzle_con_st *con)
1 by brian
clean slate
235
{
236
  if (ignore_errors)
237
    return;
928.1.6 by Eric Day
All utilities done except slap.
238
  if (con)
239
    drizzle_free(drizzle_con_drizzle(con));
1 by brian
clean slate
240
  exit(error);
241
}
242
243
244
928.1.6 by Eric Day
All utilities done except slap.
245
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
246
                     drizzle_return_t ret, char *table)
247
{
248
  if (ret == DRIZZLE_RETURN_ERROR_CODE)
249
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
250
    fprintf(stdout, "Error: %d, %s%s%s",
251
            drizzle_result_error_code(result),
252
            drizzle_result_error(result),
253
            table ? ", when using table: " : "", table ? table : "");
928.1.6 by Eric Day
All utilities done except slap.
254
    drizzle_result_free(result);
255
  }
256
  else
257
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
258
    fprintf(stdout, "Error: %d, %s%s%s", ret, drizzle_con_error(con),
259
            table ? ", when using table: " : "", table ? table : "");
928.1.6 by Eric Day
All utilities done except slap.
260
  }
261
262
  safe_exit(1, con);
1 by brian
clean slate
263
}
264
265
266
static char *add_load_option(char *ptr, const char *object,
206.3.1 by Patrick Galbraith
Most everything working with client rename
267
           const char *statement)
1 by brian
clean slate
268
{
269
  if (object)
270
  {
271
    /* Don't escape hex constants */
272
    if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
273
      ptr+= sprintf(ptr, " %s %s", statement, object);
1 by brian
clean slate
274
    else
275
    {
276
      /* char constant; escape */
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
277
      ptr+= sprintf(ptr, " %s '", statement); 
895 by Brian Aker
Completion (?) of uint conversion.
278
      ptr= field_escape(ptr,object,(uint32_t) strlen(object));
1 by brian
clean slate
279
      *ptr++= '\'';
280
    }
281
  }
282
  return ptr;
283
}
284
285
/*
286
** Allow the user to specify field terminator strings like:
287
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
288
** This is done by doubleing ' and add a end -\ if needed to avoid
289
** syntax errors from the SQL parser.
206.3.1 by Patrick Galbraith
Most everything working with client rename
290
*/
1 by brian
clean slate
291
893 by Brian Aker
First pass of stripping uint
292
static char *field_escape(char *to,const char *from,uint32_t length)
1 by brian
clean slate
293
{
294
  const char *end;
893 by Brian Aker
First pass of stripping uint
295
  uint32_t end_backslashes=0;
1 by brian
clean slate
296
297
  for (end= from+length; from != end; from++)
298
  {
299
    *to++= *from;
300
    if (*from == '\\')
301
      end_backslashes^=1;    /* find odd number of backslashes */
206.3.1 by Patrick Galbraith
Most everything working with client rename
302
    else
1 by brian
clean slate
303
    {
304
      if (*from == '\'' && !end_backslashes)
206.3.1 by Patrick Galbraith
Most everything working with client rename
305
  *to++= *from;      /* We want a dublicate of "'" for DRIZZLE */
1 by brian
clean slate
306
      end_backslashes=0;
307
    }
308
  }
309
  /* Add missing backslashes if user has specified odd number of backs.*/
310
  if (end_backslashes)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
311
    *to++= '\\';
1 by brian
clean slate
312
  return to;
313
}
314
632.1.12 by Monty Taylor
Fixed more sun studio warnings.
315
void * worker_thread(void *arg)
1 by brian
clean slate
316
{
317
  int error;
318
  char *raw_table_name= (char *)arg;
1707.1.23 by Brian Aker
Cleanup of import.
319
  drizzle_con_st *con;
1 by brian
clean slate
320
928.1.6 by Eric Day
All utilities done except slap.
321
  if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
1 by brian
clean slate
322
  {
1707.1.23 by Brian Aker
Cleanup of import.
323
    return 0;
1 by brian
clean slate
324
  }
325
326
  /*
327
    We are not currently catching the error here.
328
  */
1707.1.23 by Brian Aker
Cleanup of import.
329
  if ((error= write_to_table(raw_table_name, con)))
330
  {
1 by brian
clean slate
331
    if (exitcode == 0)
1707.1.23 by Brian Aker
Cleanup of import.
332
    {
1 by brian
clean slate
333
      exitcode= error;
1707.1.23 by Brian Aker
Cleanup of import.
334
    }
335
  }
1 by brian
clean slate
336
928.1.6 by Eric Day
All utilities done except slap.
337
  if (con)
1707.1.23 by Brian Aker
Cleanup of import.
338
  {
928.1.6 by Eric Day
All utilities done except slap.
339
    db_disconnect(current_host, con);
1707.1.23 by Brian Aker
Cleanup of import.
340
  }
1 by brian
clean slate
341
342
  pthread_mutex_lock(&counter_mutex);
343
  counter--;
344
  pthread_cond_signal(&count_threshhold);
345
  pthread_mutex_unlock(&counter_mutex);
346
347
  return 0;
348
}
349
350
351
int main(int argc, char **argv)
352
{
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
353
try
354
{
1 by brian
clean slate
355
  int error=0;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
356
357
  po::options_description commandline_options("Options used only in command line");
358
  commandline_options.add_options()
359
360
  ("debug,#", po::value<string>(),
361
  "Output debug log. Often this is 'd:t:o,filename'.")
362
  ("delete,d", po::value<bool>(&opt_delete)->default_value(false)->zero_tokens(),
363
  "First delete all rows from table.")
364
  ("help,?", "Displays this help and exits.")
365
  ("ignore,i", po::value<bool>(&ignore_unique)->default_value(false)->zero_tokens(),
366
  "If duplicate unique key was found, keep old row.")
367
  ("low-priority", po::value<bool>(&opt_low_priority)->default_value(false)->zero_tokens(),
368
  "Use LOW_PRIORITY when updating the table.")
369
  ("replace,r", po::value<bool>(&opt_replace)->default_value(false)->zero_tokens(),
370
  "If duplicate unique key was found, replace old row.")
371
  ("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
372
  "Print info about the various stages.")
373
  ("version,V", "Output version information and exit.")
374
  ;
375
376
  po::options_description import_options("Options specific to the drizzleimport");
377
  import_options.add_options()
378
  ("columns,C", po::value<string>(&opt_columns)->default_value(""),
379
  "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.")
380
  ("fields-terminated-by", po::value<string>(&fields_terminated)->default_value(""),
381
  "Fields in the textfile are terminated by ...")
382
  ("fields-enclosed-by", po::value<string>(&enclosed)->default_value(""),
383
  "Fields in the importfile are enclosed by ...")
384
  ("fields-optionally-enclosed-by", po::value<string>(&opt_enclosed)->default_value(""),
385
  "Fields in the i.file are opt. enclosed by ...")
386
  ("fields-escaped-by", po::value<string>(&escaped)->default_value(""),
387
  "Fields in the i.file are escaped by ...")
388
  ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
389
  "Continue even if we get an sql-error.")
390
  ("ignore-lines", po::value<int64_t>(&opt_ignore_lines)->default_value(0),
391
  "Ignore first n lines of data infile.")
392
  ("lines-terminated-by", po::value<string>(&lines_terminated)->default_value(""),
393
  "Lines in the i.file are terminated by ...")
394
  ("local,L", po::value<bool>(&opt_local_file)->default_value(false)->zero_tokens(),
395
  "Read all files through the client.")
396
  ("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
397
  "Be more silent.")
1707.1.23 by Brian Aker
Cleanup of import.
398
  ("use-threads", po::value<uint32_t>(&opt_use_threads)->default_value(4),
399
  "Load files in parallel. The argument is the number of threads to use for loading data (default is 4.")
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
400
  ;
401
2216.2.1 by Andrew Hutchings
Use current unix username as login by default for our client apps
402
  const char* unix_user= getlogin();
403
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
404
  po::options_description client_options("Options specific to the client");
405
  client_options.add_options()
406
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
407
  "Connect to host.")
408
  ("password,P", po::value<string>(&password),
409
  "Password to use when connecting to server. If password is not given it's asked from the tty." )
410
  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
411
  "Port number to use for connection") 
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
412
  ("protocol", po::value<string>(&opt_protocol)->default_value("mysql"),
413
  "The protocol of connection (mysql or drizzle).")
2216.2.1 by Andrew Hutchings
Use current unix username as login by default for our client apps
414
  ("user,u", po::value<string>(&current_user)->default_value((unix_user ? unix_user : "")),
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
415
  "User for login if not current user.")
416
  ;
417
418
  po::options_description long_options("Allowed Options");
419
  long_options.add(commandline_options).add(import_options).add(client_options);
420
421
  std::string system_config_dir_import(SYSCONFDIR); 
422
  system_config_dir_import.append("/drizzle/drizzleimport.cnf");
423
424
  std::string system_config_dir_client(SYSCONFDIR); 
425
  system_config_dir_client.append("/drizzle/client.cnf");
426
  
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
427
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
428
1921.3.1 by Andrew Hutchings
Using '~' to represent home is a shell standard, POSIX functions do not understand it. So for home config file loading substitute it for env variable $HOME if possible (also a POSIX standard)
429
  if (user_config_dir.compare(0, 2, "~/") == 0)
430
  {
431
    char *homedir;
432
    homedir= getenv("HOME");
433
    if (homedir != NULL)
434
      user_config_dir.replace(0, 1, homedir);
435
  }
436
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
437
  po::variables_map vm;
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
438
1793.3.1 by Andrew Hutchings
Disable boost:po allow_guessing which was making some wrong assumptions
439
  // Disable allow_guessing
440
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
441
1633.5.2 by Vijay Samuel
Merge fix for password in client/
442
  po::store(po::command_line_parser(argc, argv).options(long_options).
1793.3.1 by Andrew Hutchings
Disable boost:po allow_guessing which was making some wrong assumptions
443
            style(style).extra_parser(parse_password_arg).run(), vm);
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
444
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
445
  std::string user_config_dir_import(user_config_dir);
446
  user_config_dir_import.append("/drizzle/drizzleimport.cnf"); 
447
448
  std::string user_config_dir_client(user_config_dir);
449
  user_config_dir_client.append("/drizzle/client.cnf");
450
451
  ifstream user_import_ifs(user_config_dir_import.c_str());
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
452
  po::store(parse_config_file(user_import_ifs, import_options), vm);
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
453
454
  ifstream user_client_ifs(user_config_dir_client.c_str());
455
  po::store(parse_config_file(user_client_ifs, client_options), vm);
456
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
457
  ifstream system_import_ifs(system_config_dir_import.c_str());
458
  store(parse_config_file(system_import_ifs, import_options), vm);
459
 
460
  ifstream system_client_ifs(system_config_dir_client.c_str());
461
  po::store(parse_config_file(system_client_ifs, client_options), vm);
462
463
  po::notify(vm);
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
464
  if (vm.count("protocol"))
465
  {
466
    std::transform(opt_protocol.begin(), opt_protocol.end(),
467
      opt_protocol.begin(), ::tolower);
468
469
    if (not opt_protocol.compare("mysql"))
470
      use_drizzle_protocol=false;
471
    else if (not opt_protocol.compare("drizzle"))
472
      use_drizzle_protocol=true;
473
    else
474
    {
475
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
476
      exit(-1);
477
    }
478
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
479
480
  if (vm.count("port"))
481
  {
482
    
483
    /* If the port number is > 65535 it is not a valid port
484
       This also helps with potential data loss casting unsigned long to a
485
       uint32_t. */
486
    if (opt_drizzle_port > 65535)
487
    {
488
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
489
      exit(EXIT_ARGUMENT_INVALID);
490
    }
491
  }
492
1633.5.2 by Vijay Samuel
Merge fix for password in client/
493
  if( vm.count("password") )
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
494
  {
495
    if (!opt_password.empty())
496
      opt_password.erase();
1633.5.2 by Vijay Samuel
Merge fix for password in client/
497
    if (password == PASSWORD_SENTINEL)
498
    {
499
      opt_password= "";
500
    }
501
    else
502
    {
503
      opt_password= password;
504
      tty_password= false;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
505
    }
506
  }
507
  else
508
  {
509
      tty_password= true;
510
  }
511
1633.5.2 by Vijay Samuel
Merge fix for password in client/
512
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
513
  if (vm.count("version"))
514
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
515
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n", program_name,
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
516
    IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
517
  }
518
  
519
  if (vm.count("help") || argc < 2)
520
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
521
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n", program_name,
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
522
    IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
523
    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");
524
    printf("\
525
    Loads tables from text files in various formats.  The base name of the\n\
526
    text file must be the name of the table that should be used.\n\
527
    If one uses sockets to connect to the Drizzle server, the server will open and\n\
528
    read the text file directly. In other cases the client will open the text\n\
529
    file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
530
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
531
    printf("\nUsage: %s [OPTIONS] database textfile...", program_name);
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
532
    cout<<long_options;
533
    exit(0);
534
  }
535
536
537
  if (get_options())
538
  {
1 by brian
clean slate
539
    return(1);
540
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
541
  
542
  current_db= (*argv)++;
543
  argc--;
1 by brian
clean slate
544
1707.1.23 by Brian Aker
Cleanup of import.
545
  if (opt_use_threads)
1 by brian
clean slate
546
  {
547
    pthread_t mainthread;            /* Thread descriptor */
548
    pthread_attr_t attr;          /* Thread attributes */
549
    pthread_attr_init(&attr);
550
    pthread_attr_setdetachstate(&attr,
551
                                PTHREAD_CREATE_DETACHED);
552
398.1.10 by Monty Taylor
Actually removed VOID() this time.
553
    pthread_mutex_init(&counter_mutex, NULL);
554
    pthread_cond_init(&count_threshhold, NULL);
1 by brian
clean slate
555
556
    for (counter= 0; *argv != NULL; argv++) /* Loop through tables */
557
    {
558
      pthread_mutex_lock(&counter_mutex);
559
      while (counter == opt_use_threads)
560
      {
561
        struct timespec abstime;
562
563
        set_timespec(abstime, 3);
564
        pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
565
      }
566
      /* Before exiting the lock we set ourselves up for the next thread */
567
      counter++;
568
      pthread_mutex_unlock(&counter_mutex);
569
      /* now create the thread */
206.3.1 by Patrick Galbraith
Most everything working with client rename
570
      if (pthread_create(&mainthread, &attr, worker_thread,
1 by brian
clean slate
571
                         (void *)*argv) != 0)
572
      {
573
        pthread_mutex_lock(&counter_mutex);
574
        counter--;
575
        pthread_mutex_unlock(&counter_mutex);
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
576
        fprintf(stderr,"%s: Could not create thread\n", program_name);
1 by brian
clean slate
577
      }
578
    }
579
580
    /*
581
      We loop until we know that all children have cleaned up.
582
    */
583
    pthread_mutex_lock(&counter_mutex);
584
    while (counter)
585
    {
586
      struct timespec abstime;
587
588
      set_timespec(abstime, 3);
589
      pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
590
    }
591
    pthread_mutex_unlock(&counter_mutex);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
592
    pthread_mutex_destroy(&counter_mutex);
593
    pthread_cond_destroy(&count_threshhold);
1 by brian
clean slate
594
    pthread_attr_destroy(&attr);
595
  }
596
  else
597
  {
1707.1.23 by Brian Aker
Cleanup of import.
598
    drizzle_con_st *con;
599
928.1.6 by Eric Day
All utilities done except slap.
600
    if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
1 by brian
clean slate
601
    {
971.6.11 by Eric Day
Removed purecov messages.
602
      return(1);
1 by brian
clean slate
603
    }
604
605
    for (; *argv != NULL; argv++)
928.1.6 by Eric Day
All utilities done except slap.
606
      if ((error= write_to_table(*argv, con)))
1 by brian
clean slate
607
        if (exitcode == 0)
608
          exitcode= error;
928.1.6 by Eric Day
All utilities done except slap.
609
    db_disconnect(current_host, con);
1 by brian
clean slate
610
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
611
  opt_password.empty();
612
}
613
  catch(exception &err)
614
  {
615
    cerr<<err.what()<<endl;
616
  }
1 by brian
clean slate
617
  return(exitcode);
618
}