~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
2281.7.1 by Andrew Hutchings
Add better shell user detect functionality and add it to console
36
#include "user_detect.h"
37
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
38
namespace po= boost::program_options;
279.2.5 by Monty Taylor
Removed DYNAMIC_STRING from drizzleimport.
39
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
40
using namespace drizzled;
1 by brian
clean slate
41
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
42
extern "C" void * worker_thread(void *arg);
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
43
44
int exitcode= 0;
45
2155.3.1 by Stewart Smith
drizzleimport had incorrect program_name (typo)
46
const char *program_name= "drizzleimport";
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
47
1 by brian
clean slate
48
/* Global Thread counter */
893 by Brian Aker
First pass of stripping uint
49
uint32_t counter;
1 by brian
clean slate
50
pthread_mutex_t counter_mutex;
51
pthread_cond_t count_threshhold;
52
928.1.6 by Eric Day
All utilities done except slap.
53
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
54
                     drizzle_return_t ret, char *table);
893 by Brian Aker
First pass of stripping uint
55
static char *field_escape(char *to,const char *from,uint32_t length);
1 by brian
clean slate
56
static char *add_load_option(char *ptr,const char *object,
206.3.1 by Patrick Galbraith
Most everything working with client rename
57
           const char *statement);
1 by brian
clean slate
58
1707.1.23 by Brian Aker
Cleanup of import.
59
static bool verbose= false, ignore_errors= false,
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
60
            opt_delete= false, opt_replace= false, silent= false,
1235.3.7 by Stewart Smith
remove outdated --compress option from drizzleimport
61
            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.
62
            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.
63
1707.1.23 by Brian Aker
Cleanup of import.
64
static uint32_t opt_use_threads;
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
65
static uint32_t opt_drizzle_port= 0;
152 by Brian Aker
longlong replacement
66
static int64_t opt_ignore_lines= -1;
1 by brian
clean slate
67
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
68
std::string opt_columns,
69
  opt_enclosed,
70
  escaped,
71
  password,
72
  current_db,
73
  lines_terminated,
74
  current_user,
75
  opt_password,
76
  enclosed,  
77
  current_host,
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
78
  fields_terminated,
79
  opt_protocol;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
80
81
82
static int get_options(void)
83
{
84
85
  if (! enclosed.empty() && ! opt_enclosed.empty())
1 by brian
clean slate
86
  {
87
    fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n");
88
    return(1);
89
  }
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
90
  if (opt_replace && ignore_unique)
1 by brian
clean slate
91
  {
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
92
    fprintf(stderr, "You can't use --ignore_unique (-i) and --replace (-r) at the same time.\n");
1 by brian
clean slate
93
    return(1);
94
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
95
1 by brian
clean slate
96
  if (tty_password)
928.1.6 by Eric Day
All utilities done except slap.
97
    opt_password=client_get_tty_password(NULL);
1 by brian
clean slate
98
  return(0);
99
}
100
101
102
928.1.6 by Eric Day
All utilities done except slap.
103
static int write_to_table(char *filename, drizzle_con_st *con)
1 by brian
clean slate
104
{
105
  char tablename[FN_REFLEN], hard_path[FN_REFLEN],
106
       sql_statement[FN_REFLEN*16+256], *end;
928.1.6 by Eric Day
All utilities done except slap.
107
  drizzle_result_st result;
108
  drizzle_return_t ret;
1 by brian
clean slate
109
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
110
  internal::fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
111
  if (not opt_local_file)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
112
    strcpy(hard_path,filename);
1 by brian
clean slate
113
  else
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
114
    internal::my_load_path(hard_path, filename, NULL); /* filename includes the path */
1 by brian
clean slate
115
116
  if (opt_delete)
117
  {
118
    if (verbose)
119
      fprintf(stdout, "Deleting the old data from table %s\n", tablename);
120
#ifdef HAVE_SNPRINTF
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
#else
1366.1.13 by Siddharth Prakash Singh
more sprintf->snprintf
123
    snprintf(sql_statement, sizeof(sql_statement), "DELETE FROM %s", tablename);
1 by brian
clean slate
124
#endif
928.1.6 by Eric Day
All utilities done except slap.
125
    if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
126
        ret != DRIZZLE_RETURN_OK)
1 by brian
clean slate
127
    {
928.1.6 by Eric Day
All utilities done except slap.
128
      db_error(con, &result, ret, tablename);
142.1.2 by Patrick
All DBUG_x removed from client/
129
      return(1);
1 by brian
clean slate
130
    }
928.1.6 by Eric Day
All utilities done except slap.
131
    drizzle_result_free(&result);
1 by brian
clean slate
132
  }
133
  if (verbose)
134
  {
135
    if (opt_local_file)
136
      fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
137
        hard_path, tablename);
1 by brian
clean slate
138
    else
139
      fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
140
        hard_path, tablename);
1 by brian
clean slate
141
  }
1366.1.14 by Siddharth Prakash Singh
bug fixing
142
  snprintf(sql_statement, sizeof(sql_statement), "LOAD DATA %s %s INFILE '%s'",
206.3.1 by Patrick Galbraith
Most everything working with client rename
143
    opt_low_priority ? "LOW_PRIORITY" : "",
144
    opt_local_file ? "LOCAL" : "", hard_path);
376 by Brian Aker
strend remove
145
  end= strchr(sql_statement, '\0');
279.2.5 by Monty Taylor
Removed DYNAMIC_STRING from drizzleimport.
146
  if (opt_replace)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
147
    end= strcpy(end, " REPLACE")+8;
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
148
  if (ignore_unique)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
149
    end= strcpy(end, " IGNORE")+7;
150
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
151
  end+= sprintf(end, " INTO TABLE %s", tablename);
1 by brian
clean slate
152
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
153
  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
154
      end= strcpy(end, " FIELDS")+7;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
155
  end= add_load_option(end, (char *)fields_terminated.c_str(), " TERMINATED BY");
156
  end= add_load_option(end, (char *)enclosed.c_str(), " ENCLOSED BY");
157
  end= add_load_option(end, (char *)opt_enclosed.c_str(),
206.3.1 by Patrick Galbraith
Most everything working with client rename
158
           " OPTIONALLY ENCLOSED BY");
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
159
  end= add_load_option(end, (char *)escaped.c_str(), " ESCAPED BY");
160
  end= add_load_option(end, (char *)lines_terminated.c_str(), " LINES TERMINATED BY");
1 by brian
clean slate
161
  if (opt_ignore_lines >= 0)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
162
  {
163
    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.
164
    ostringstream buffer;
165
    buffer << opt_ignore_lines;
166
    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
167
    end= strcpy(end, " LINES")+6;
168
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
169
  if (! opt_columns.empty())
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
170
  {
171
    end= strcpy(end, " (")+2;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
172
    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
173
    end= strcpy(end, ")")+1;
174
  }
1 by brian
clean slate
175
  *end= '\0';
176
928.1.6 by Eric Day
All utilities done except slap.
177
  if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
178
      ret != DRIZZLE_RETURN_OK)
1 by brian
clean slate
179
  {
928.1.6 by Eric Day
All utilities done except slap.
180
    db_error(con, &result, ret, tablename);
142.1.2 by Patrick
All DBUG_x removed from client/
181
    return(1);
1 by brian
clean slate
182
  }
183
  if (!silent)
184
  {
928.1.6 by Eric Day
All utilities done except slap.
185
    if (strcmp(drizzle_result_info(&result), ""))
1 by brian
clean slate
186
    {
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
187
      fprintf(stdout, "%s.%s: %s\n", current_db.c_str(), tablename,
928.1.6 by Eric Day
All utilities done except slap.
188
        drizzle_result_info(&result));
1 by brian
clean slate
189
    }
190
  }
928.1.6 by Eric Day
All utilities done except slap.
191
  drizzle_result_free(&result);
142.1.2 by Patrick
All DBUG_x removed from client/
192
  return(0);
1 by brian
clean slate
193
}
194
195
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
196
static drizzle_con_st *db_connect(const string host, const string database,
197
                                  const string user, const string passwd)
1 by brian
clean slate
198
{
928.1.6 by Eric Day
All utilities done except slap.
199
  drizzle_st *drizzle;
200
  drizzle_con_st *con;
201
  drizzle_return_t ret;
202
1 by brian
clean slate
203
  if (verbose)
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
204
    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.
205
  if (!(drizzle= drizzle_create(NULL)))
206
    return 0;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
207
  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.
208
                                 (char *)database.c_str(), use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL)))
928.1.6 by Eric Day
All utilities done except slap.
209
  {
210
    return 0;
211
  }
212
213
  if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
1 by brian
clean slate
214
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
215
    ignore_errors=0;    /* NO RETURN FROM db_error */
928.1.6 by Eric Day
All utilities done except slap.
216
    db_error(con, NULL, ret, NULL);
1 by brian
clean slate
217
  }
928.1.6 by Eric Day
All utilities done except slap.
218
1 by brian
clean slate
219
  if (verbose)
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
220
    fprintf(stdout, "Selecting database %s\n", database.c_str());
928.1.6 by Eric Day
All utilities done except slap.
221
222
  return con;
1 by brian
clean slate
223
}
224
225
226
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
227
static void db_disconnect(const string host, drizzle_con_st *con)
1 by brian
clean slate
228
{
229
  if (verbose)
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
230
    fprintf(stdout, "Disconnecting from %s\n", ! host.empty() ? host.c_str() : "localhost");
928.1.6 by Eric Day
All utilities done except slap.
231
  drizzle_free(drizzle_con_drizzle(con));
1 by brian
clean slate
232
}
233
234
235
928.1.6 by Eric Day
All utilities done except slap.
236
static void safe_exit(int error, drizzle_con_st *con)
1 by brian
clean slate
237
{
238
  if (ignore_errors)
239
    return;
928.1.6 by Eric Day
All utilities done except slap.
240
  if (con)
241
    drizzle_free(drizzle_con_drizzle(con));
1 by brian
clean slate
242
  exit(error);
243
}
244
245
246
928.1.6 by Eric Day
All utilities done except slap.
247
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
248
                     drizzle_return_t ret, char *table)
249
{
250
  if (ret == DRIZZLE_RETURN_ERROR_CODE)
251
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
252
    fprintf(stdout, "Error: %d, %s%s%s",
253
            drizzle_result_error_code(result),
254
            drizzle_result_error(result),
255
            table ? ", when using table: " : "", table ? table : "");
928.1.6 by Eric Day
All utilities done except slap.
256
    drizzle_result_free(result);
257
  }
258
  else
259
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
260
    fprintf(stdout, "Error: %d, %s%s%s", ret, drizzle_con_error(con),
261
            table ? ", when using table: " : "", table ? table : "");
928.1.6 by Eric Day
All utilities done except slap.
262
  }
263
264
  safe_exit(1, con);
1 by brian
clean slate
265
}
266
267
268
static char *add_load_option(char *ptr, const char *object,
206.3.1 by Patrick Galbraith
Most everything working with client rename
269
           const char *statement)
1 by brian
clean slate
270
{
271
  if (object)
272
  {
273
    /* Don't escape hex constants */
274
    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
275
      ptr+= sprintf(ptr, " %s %s", statement, object);
1 by brian
clean slate
276
    else
277
    {
278
      /* char constant; escape */
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
279
      ptr+= sprintf(ptr, " %s '", statement); 
895 by Brian Aker
Completion (?) of uint conversion.
280
      ptr= field_escape(ptr,object,(uint32_t) strlen(object));
1 by brian
clean slate
281
      *ptr++= '\'';
282
    }
283
  }
284
  return ptr;
285
}
286
287
/*
288
** Allow the user to specify field terminator strings like:
289
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
290
** This is done by doubleing ' and add a end -\ if needed to avoid
291
** syntax errors from the SQL parser.
206.3.1 by Patrick Galbraith
Most everything working with client rename
292
*/
1 by brian
clean slate
293
893 by Brian Aker
First pass of stripping uint
294
static char *field_escape(char *to,const char *from,uint32_t length)
1 by brian
clean slate
295
{
296
  const char *end;
893 by Brian Aker
First pass of stripping uint
297
  uint32_t end_backslashes=0;
1 by brian
clean slate
298
299
  for (end= from+length; from != end; from++)
300
  {
301
    *to++= *from;
302
    if (*from == '\\')
303
      end_backslashes^=1;    /* find odd number of backslashes */
206.3.1 by Patrick Galbraith
Most everything working with client rename
304
    else
1 by brian
clean slate
305
    {
306
      if (*from == '\'' && !end_backslashes)
206.3.1 by Patrick Galbraith
Most everything working with client rename
307
  *to++= *from;      /* We want a dublicate of "'" for DRIZZLE */
1 by brian
clean slate
308
      end_backslashes=0;
309
    }
310
  }
311
  /* Add missing backslashes if user has specified odd number of backs.*/
312
  if (end_backslashes)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
313
    *to++= '\\';
1 by brian
clean slate
314
  return to;
315
}
316
632.1.12 by Monty Taylor
Fixed more sun studio warnings.
317
void * worker_thread(void *arg)
1 by brian
clean slate
318
{
319
  int error;
320
  char *raw_table_name= (char *)arg;
1707.1.23 by Brian Aker
Cleanup of import.
321
  drizzle_con_st *con;
1 by brian
clean slate
322
928.1.6 by Eric Day
All utilities done except slap.
323
  if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
1 by brian
clean slate
324
  {
1707.1.23 by Brian Aker
Cleanup of import.
325
    return 0;
1 by brian
clean slate
326
  }
327
328
  /*
329
    We are not currently catching the error here.
330
  */
1707.1.23 by Brian Aker
Cleanup of import.
331
  if ((error= write_to_table(raw_table_name, con)))
332
  {
1 by brian
clean slate
333
    if (exitcode == 0)
1707.1.23 by Brian Aker
Cleanup of import.
334
    {
1 by brian
clean slate
335
      exitcode= error;
1707.1.23 by Brian Aker
Cleanup of import.
336
    }
337
  }
1 by brian
clean slate
338
928.1.6 by Eric Day
All utilities done except slap.
339
  if (con)
1707.1.23 by Brian Aker
Cleanup of import.
340
  {
928.1.6 by Eric Day
All utilities done except slap.
341
    db_disconnect(current_host, con);
1707.1.23 by Brian Aker
Cleanup of import.
342
  }
1 by brian
clean slate
343
344
  pthread_mutex_lock(&counter_mutex);
345
  counter--;
346
  pthread_cond_signal(&count_threshhold);
347
  pthread_mutex_unlock(&counter_mutex);
348
349
  return 0;
350
}
351
352
353
int main(int argc, char **argv)
354
{
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
355
try
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
402
  po::options_description client_options("Options specific to the client");
403
  client_options.add_options()
404
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
405
  "Connect to host.")
406
  ("password,P", po::value<string>(&password),
407
  "Password to use when connecting to server. If password is not given it's asked from the tty." )
408
  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
409
  "Port number to use for connection") 
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
410
  ("protocol", po::value<string>(&opt_protocol)->default_value("mysql"),
411
  "The protocol of connection (mysql or drizzle).")
2318.4.7 by Olaf van der Spek
Refactor
412
  ("user,u", po::value<string>(&current_user)->default_value(UserDetect().getUser()),
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
413
  "User for login if not current user.")
414
  ;
415
416
  po::options_description long_options("Allowed Options");
417
  long_options.add(commandline_options).add(import_options).add(client_options);
418
419
  std::string system_config_dir_import(SYSCONFDIR); 
420
  system_config_dir_import.append("/drizzle/drizzleimport.cnf");
421
422
  std::string system_config_dir_client(SYSCONFDIR); 
423
  system_config_dir_client.append("/drizzle/client.cnf");
424
  
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
425
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
426
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)
427
  if (user_config_dir.compare(0, 2, "~/") == 0)
428
  {
429
    char *homedir;
430
    homedir= getenv("HOME");
431
    if (homedir != NULL)
432
      user_config_dir.replace(0, 1, homedir);
433
  }
434
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
435
  po::variables_map vm;
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
436
1793.3.1 by Andrew Hutchings
Disable boost:po allow_guessing which was making some wrong assumptions
437
  // Disable allow_guessing
438
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
439
1633.5.2 by Vijay Samuel
Merge fix for password in client/
440
  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
441
            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.
442
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
443
  std::string user_config_dir_import(user_config_dir);
444
  user_config_dir_import.append("/drizzle/drizzleimport.cnf"); 
445
446
  std::string user_config_dir_client(user_config_dir);
447
  user_config_dir_client.append("/drizzle/client.cnf");
448
449
  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.
450
  po::store(parse_config_file(user_import_ifs, import_options), vm);
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
451
452
  ifstream user_client_ifs(user_config_dir_client.c_str());
453
  po::store(parse_config_file(user_client_ifs, client_options), vm);
454
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
455
  ifstream system_import_ifs(system_config_dir_import.c_str());
456
  store(parse_config_file(system_import_ifs, import_options), vm);
457
 
458
  ifstream system_client_ifs(system_config_dir_client.c_str());
459
  po::store(parse_config_file(system_client_ifs, client_options), vm);
460
461
  po::notify(vm);
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
462
  if (vm.count("protocol"))
463
  {
2318.7.21 by Olaf van der Spek
Use boost::to_lower
464
    boost::to_lower(opt_protocol);
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
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
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
475
476
  if (vm.count("port"))
477
  {
478
    
479
    /* If the port number is > 65535 it is not a valid port
480
       This also helps with potential data loss casting unsigned long to a
481
       uint32_t. */
482
    if (opt_drizzle_port > 65535)
483
    {
484
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
485
      exit(EXIT_ARGUMENT_INVALID);
486
    }
487
  }
488
1633.5.2 by Vijay Samuel
Merge fix for password in client/
489
  if( vm.count("password") )
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
490
  {
491
    if (!opt_password.empty())
492
      opt_password.erase();
1633.5.2 by Vijay Samuel
Merge fix for password in client/
493
    if (password == PASSWORD_SENTINEL)
494
    {
495
      opt_password= "";
496
    }
497
    else
498
    {
499
      opt_password= password;
500
      tty_password= false;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
501
    }
502
  }
503
  else
504
  {
505
      tty_password= true;
506
  }
507
1633.5.2 by Vijay Samuel
Merge fix for password in client/
508
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
509
  if (vm.count("version"))
510
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
511
    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.
512
    IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
513
  }
514
  
515
  if (vm.count("help") || argc < 2)
516
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
517
    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.
518
    IMPORT_VERSION, drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
519
    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
    printf("\
521
    Loads tables from text files in various formats.  The base name of the\n\
522
    text file must be the name of the table that should be used.\n\
523
    If one uses sockets to connect to the Drizzle server, the server will open and\n\
524
    read the text file directly. In other cases the client will open the text\n\
525
    file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
526
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
527
    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.
528
    cout<<long_options;
529
    exit(0);
530
  }
531
532
533
  if (get_options())
534
  {
1 by brian
clean slate
535
    return(1);
536
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
537
  
538
  current_db= (*argv)++;
539
  argc--;
1 by brian
clean slate
540
1707.1.23 by Brian Aker
Cleanup of import.
541
  if (opt_use_threads)
1 by brian
clean slate
542
  {
543
    pthread_t mainthread;            /* Thread descriptor */
544
    pthread_attr_t attr;          /* Thread attributes */
545
    pthread_attr_init(&attr);
546
    pthread_attr_setdetachstate(&attr,
547
                                PTHREAD_CREATE_DETACHED);
548
398.1.10 by Monty Taylor
Actually removed VOID() this time.
549
    pthread_mutex_init(&counter_mutex, NULL);
550
    pthread_cond_init(&count_threshhold, NULL);
1 by brian
clean slate
551
552
    for (counter= 0; *argv != NULL; argv++) /* Loop through tables */
553
    {
554
      pthread_mutex_lock(&counter_mutex);
555
      while (counter == opt_use_threads)
556
      {
557
        struct timespec abstime;
558
559
        set_timespec(abstime, 3);
560
        pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
561
      }
562
      /* Before exiting the lock we set ourselves up for the next thread */
563
      counter++;
564
      pthread_mutex_unlock(&counter_mutex);
565
      /* now create the thread */
206.3.1 by Patrick Galbraith
Most everything working with client rename
566
      if (pthread_create(&mainthread, &attr, worker_thread,
1 by brian
clean slate
567
                         (void *)*argv) != 0)
568
      {
569
        pthread_mutex_lock(&counter_mutex);
570
        counter--;
571
        pthread_mutex_unlock(&counter_mutex);
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
572
        fprintf(stderr,"%s: Could not create thread\n", program_name);
1 by brian
clean slate
573
      }
574
    }
575
576
    /*
577
      We loop until we know that all children have cleaned up.
578
    */
579
    pthread_mutex_lock(&counter_mutex);
580
    while (counter)
581
    {
582
      struct timespec abstime;
583
584
      set_timespec(abstime, 3);
585
      pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
586
    }
587
    pthread_mutex_unlock(&counter_mutex);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
588
    pthread_mutex_destroy(&counter_mutex);
589
    pthread_cond_destroy(&count_threshhold);
1 by brian
clean slate
590
    pthread_attr_destroy(&attr);
591
  }
592
  else
593
  {
1707.1.23 by Brian Aker
Cleanup of import.
594
    drizzle_con_st *con;
595
928.1.6 by Eric Day
All utilities done except slap.
596
    if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
1 by brian
clean slate
597
    {
971.6.11 by Eric Day
Removed purecov messages.
598
      return(1);
1 by brian
clean slate
599
    }
600
601
    for (; *argv != NULL; argv++)
2385.2.3 by Olaf van der Spek
cppcheck
602
      if (int error= write_to_table(*argv, con))
1 by brian
clean slate
603
        if (exitcode == 0)
604
          exitcode= error;
928.1.6 by Eric Day
All utilities done except slap.
605
    db_disconnect(current_host, con);
1 by brian
clean slate
606
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
607
  opt_password.empty();
608
}
609
  catch(exception &err)
610
  {
611
    cerr<<err.what()<<endl;
612
  }
1 by brian
clean slate
613
  return(exitcode);
614
}