~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
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
30
/* Added this for string translation. */
31
#include <drizzled/gettext.h>
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
32
#include <drizzled/configmake.h>
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
33
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
34
namespace po= boost::program_options;
279.2.5 by Monty Taylor
Removed DYNAMIC_STRING from drizzleimport.
35
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
36
using namespace drizzled;
1 by brian
clean slate
37
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
38
extern "C" void * worker_thread(void *arg);
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
39
40
int exitcode= 0;
41
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
42
const char *program_name= "drizzlesimport";
43
1 by brian
clean slate
44
/* Global Thread counter */
893 by Brian Aker
First pass of stripping uint
45
uint32_t counter;
1 by brian
clean slate
46
pthread_mutex_t counter_mutex;
47
pthread_cond_t count_threshhold;
48
928.1.6 by Eric Day
All utilities done except slap.
49
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
50
                     drizzle_return_t ret, char *table);
893 by Brian Aker
First pass of stripping uint
51
static char *field_escape(char *to,const char *from,uint32_t length);
1 by brian
clean slate
52
static char *add_load_option(char *ptr,const char *object,
206.3.1 by Patrick Galbraith
Most everything working with client rename
53
           const char *statement);
1 by brian
clean slate
54
1707.1.23 by Brian Aker
Cleanup of import.
55
static bool verbose= false, ignore_errors= false,
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
56
            opt_delete= false, opt_replace= false, silent= false,
1235.3.7 by Stewart Smith
remove outdated --compress option from drizzleimport
57
            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.
58
            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.
59
1707.1.23 by Brian Aker
Cleanup of import.
60
static uint32_t opt_use_threads;
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
61
static uint32_t opt_drizzle_port= 0;
152 by Brian Aker
longlong replacement
62
static int64_t opt_ignore_lines= -1;
1 by brian
clean slate
63
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
64
std::string opt_columns,
65
  opt_enclosed,
66
  escaped,
67
  password,
68
  current_db,
69
  lines_terminated,
70
  current_user,
71
  opt_password,
72
  enclosed,  
73
  current_host,
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
74
  fields_terminated,
75
  opt_protocol;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
76
77
78
static int get_options(void)
79
{
80
81
  if (! enclosed.empty() && ! opt_enclosed.empty())
1 by brian
clean slate
82
  {
83
    fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n");
84
    return(1);
85
  }
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
86
  if (opt_replace && ignore_unique)
1 by brian
clean slate
87
  {
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
88
    fprintf(stderr, "You can't use --ignore_unique (-i) and --replace (-r) at the same time.\n");
1 by brian
clean slate
89
    return(1);
90
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
91
1 by brian
clean slate
92
  if (tty_password)
928.1.6 by Eric Day
All utilities done except slap.
93
    opt_password=client_get_tty_password(NULL);
1 by brian
clean slate
94
  return(0);
95
}
96
97
98
928.1.6 by Eric Day
All utilities done except slap.
99
static int write_to_table(char *filename, drizzle_con_st *con)
1 by brian
clean slate
100
{
101
  char tablename[FN_REFLEN], hard_path[FN_REFLEN],
102
       sql_statement[FN_REFLEN*16+256], *end;
928.1.6 by Eric Day
All utilities done except slap.
103
  drizzle_result_st result;
104
  drizzle_return_t ret;
1 by brian
clean slate
105
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
106
  internal::fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
107
  if (not opt_local_file)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
108
    strcpy(hard_path,filename);
1 by brian
clean slate
109
  else
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
110
    internal::my_load_path(hard_path, filename, NULL); /* filename includes the path */
1 by brian
clean slate
111
112
  if (opt_delete)
113
  {
114
    if (verbose)
115
      fprintf(stdout, "Deleting the old data from table %s\n", tablename);
116
#ifdef HAVE_SNPRINTF
1366.1.13 by Siddharth Prakash Singh
more sprintf->snprintf
117
    snprintf(sql_statement, sizeof(sql_statement), "DELETE FROM %s", tablename);
1 by brian
clean slate
118
#else
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
#endif
928.1.6 by Eric Day
All utilities done except slap.
121
    if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
122
        ret != DRIZZLE_RETURN_OK)
1 by brian
clean slate
123
    {
928.1.6 by Eric Day
All utilities done except slap.
124
      db_error(con, &result, ret, tablename);
142.1.2 by Patrick
All DBUG_x removed from client/
125
      return(1);
1 by brian
clean slate
126
    }
928.1.6 by Eric Day
All utilities done except slap.
127
    drizzle_result_free(&result);
1 by brian
clean slate
128
  }
129
  if (verbose)
130
  {
131
    if (opt_local_file)
132
      fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
133
        hard_path, tablename);
1 by brian
clean slate
134
    else
135
      fprintf(stdout, "Loading data from SERVER file: %s into %s\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
136
        hard_path, tablename);
1 by brian
clean slate
137
  }
1366.1.14 by Siddharth Prakash Singh
bug fixing
138
  snprintf(sql_statement, sizeof(sql_statement), "LOAD DATA %s %s INFILE '%s'",
206.3.1 by Patrick Galbraith
Most everything working with client rename
139
    opt_low_priority ? "LOW_PRIORITY" : "",
140
    opt_local_file ? "LOCAL" : "", hard_path);
376 by Brian Aker
strend remove
141
  end= strchr(sql_statement, '\0');
279.2.5 by Monty Taylor
Removed DYNAMIC_STRING from drizzleimport.
142
  if (opt_replace)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
143
    end= strcpy(end, " REPLACE")+8;
923.2.2 by Monty Taylor
Changed some names that conflict with c++0x reserved names.
144
  if (ignore_unique)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
145
    end= strcpy(end, " IGNORE")+7;
146
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
147
  end+= sprintf(end, " INTO TABLE %s", tablename);
1 by brian
clean slate
148
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
149
  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
150
      end= strcpy(end, " FIELDS")+7;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
151
  end= add_load_option(end, (char *)fields_terminated.c_str(), " TERMINATED BY");
152
  end= add_load_option(end, (char *)enclosed.c_str(), " ENCLOSED BY");
153
  end= add_load_option(end, (char *)opt_enclosed.c_str(),
206.3.1 by Patrick Galbraith
Most everything working with client rename
154
           " OPTIONALLY ENCLOSED BY");
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 *)escaped.c_str(), " ESCAPED BY");
156
  end= add_load_option(end, (char *)lines_terminated.c_str(), " LINES TERMINATED BY");
1 by brian
clean slate
157
  if (opt_ignore_lines >= 0)
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
158
  {
159
    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.
160
    ostringstream buffer;
161
    buffer << opt_ignore_lines;
162
    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
163
    end= strcpy(end, " LINES")+6;
164
  }
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
165
  if (! opt_columns.empty())
641.4.2 by Toru Maesaka
Second pass of replacing MySQL's my_stpcpy() with appropriate libc calls
166
  {
167
    end= strcpy(end, " (")+2;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
168
    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
169
    end= strcpy(end, ")")+1;
170
  }
1 by brian
clean slate
171
  *end= '\0';
172
928.1.6 by Eric Day
All utilities done except slap.
173
  if (drizzle_query_str(con, &result, sql_statement, &ret) == NULL ||
174
      ret != DRIZZLE_RETURN_OK)
1 by brian
clean slate
175
  {
928.1.6 by Eric Day
All utilities done except slap.
176
    db_error(con, &result, ret, tablename);
142.1.2 by Patrick
All DBUG_x removed from client/
177
    return(1);
1 by brian
clean slate
178
  }
179
  if (!silent)
180
  {
928.1.6 by Eric Day
All utilities done except slap.
181
    if (strcmp(drizzle_result_info(&result), ""))
1 by brian
clean slate
182
    {
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
183
      fprintf(stdout, "%s.%s: %s\n", current_db.c_str(), tablename,
928.1.6 by Eric Day
All utilities done except slap.
184
        drizzle_result_info(&result));
1 by brian
clean slate
185
    }
186
  }
928.1.6 by Eric Day
All utilities done except slap.
187
  drizzle_result_free(&result);
142.1.2 by Patrick
All DBUG_x removed from client/
188
  return(0);
1 by brian
clean slate
189
}
190
191
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
192
static drizzle_con_st *db_connect(const string host, const string database,
193
                                  const string user, const string passwd)
1 by brian
clean slate
194
{
928.1.6 by Eric Day
All utilities done except slap.
195
  drizzle_st *drizzle;
196
  drizzle_con_st *con;
197
  drizzle_return_t ret;
198
1 by brian
clean slate
199
  if (verbose)
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
200
    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.
201
  if (!(drizzle= drizzle_create(NULL)))
202
    return 0;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
203
  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.
204
                                 (char *)database.c_str(), use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL)))
928.1.6 by Eric Day
All utilities done except slap.
205
  {
206
    return 0;
207
  }
208
209
  if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
1 by brian
clean slate
210
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
211
    ignore_errors=0;    /* NO RETURN FROM db_error */
928.1.6 by Eric Day
All utilities done except slap.
212
    db_error(con, NULL, ret, NULL);
1 by brian
clean slate
213
  }
928.1.6 by Eric Day
All utilities done except slap.
214
1 by brian
clean slate
215
  if (verbose)
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
216
    fprintf(stdout, "Selecting database %s\n", database.c_str());
928.1.6 by Eric Day
All utilities done except slap.
217
218
  return con;
1 by brian
clean slate
219
}
220
221
222
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
223
static void db_disconnect(const string host, drizzle_con_st *con)
1 by brian
clean slate
224
{
225
  if (verbose)
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
226
    fprintf(stdout, "Disconnecting from %s\n", ! host.empty() ? host.c_str() : "localhost");
928.1.6 by Eric Day
All utilities done except slap.
227
  drizzle_free(drizzle_con_drizzle(con));
1 by brian
clean slate
228
}
229
230
231
928.1.6 by Eric Day
All utilities done except slap.
232
static void safe_exit(int error, drizzle_con_st *con)
1 by brian
clean slate
233
{
234
  if (ignore_errors)
235
    return;
928.1.6 by Eric Day
All utilities done except slap.
236
  if (con)
237
    drizzle_free(drizzle_con_drizzle(con));
1 by brian
clean slate
238
  exit(error);
239
}
240
241
242
928.1.6 by Eric Day
All utilities done except slap.
243
static void db_error(drizzle_con_st *con, drizzle_result_st *result,
244
                     drizzle_return_t ret, char *table)
245
{
246
  if (ret == DRIZZLE_RETURN_ERROR_CODE)
247
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
248
    fprintf(stdout, "Error: %d, %s%s%s",
249
            drizzle_result_error_code(result),
250
            drizzle_result_error(result),
251
            table ? ", when using table: " : "", table ? table : "");
928.1.6 by Eric Day
All utilities done except slap.
252
    drizzle_result_free(result);
253
  }
254
  else
255
  {
1707.1.24 by Brian Aker
Merge in small fixes around drizzleimport.
256
    fprintf(stdout, "Error: %d, %s%s%s", ret, drizzle_con_error(con),
257
            table ? ", when using table: " : "", table ? table : "");
928.1.6 by Eric Day
All utilities done except slap.
258
  }
259
260
  safe_exit(1, con);
1 by brian
clean slate
261
}
262
263
264
static char *add_load_option(char *ptr, const char *object,
206.3.1 by Patrick Galbraith
Most everything working with client rename
265
           const char *statement)
1 by brian
clean slate
266
{
267
  if (object)
268
  {
269
    /* Don't escape hex constants */
270
    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
271
      ptr+= sprintf(ptr, " %s %s", statement, object);
1 by brian
clean slate
272
    else
273
    {
274
      /* char constant; escape */
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
275
      ptr+= sprintf(ptr, " %s '", statement); 
895 by Brian Aker
Completion (?) of uint conversion.
276
      ptr= field_escape(ptr,object,(uint32_t) strlen(object));
1 by brian
clean slate
277
      *ptr++= '\'';
278
    }
279
  }
280
  return ptr;
281
}
282
283
/*
284
** Allow the user to specify field terminator strings like:
285
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
286
** This is done by doubleing ' and add a end -\ if needed to avoid
287
** syntax errors from the SQL parser.
206.3.1 by Patrick Galbraith
Most everything working with client rename
288
*/
1 by brian
clean slate
289
893 by Brian Aker
First pass of stripping uint
290
static char *field_escape(char *to,const char *from,uint32_t length)
1 by brian
clean slate
291
{
292
  const char *end;
893 by Brian Aker
First pass of stripping uint
293
  uint32_t end_backslashes=0;
1 by brian
clean slate
294
295
  for (end= from+length; from != end; from++)
296
  {
297
    *to++= *from;
298
    if (*from == '\\')
299
      end_backslashes^=1;    /* find odd number of backslashes */
206.3.1 by Patrick Galbraith
Most everything working with client rename
300
    else
1 by brian
clean slate
301
    {
302
      if (*from == '\'' && !end_backslashes)
206.3.1 by Patrick Galbraith
Most everything working with client rename
303
  *to++= *from;      /* We want a dublicate of "'" for DRIZZLE */
1 by brian
clean slate
304
      end_backslashes=0;
305
    }
306
  }
307
  /* Add missing backslashes if user has specified odd number of backs.*/
308
  if (end_backslashes)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
309
    *to++= '\\';
1 by brian
clean slate
310
  return to;
311
}
312
632.1.12 by Monty Taylor
Fixed more sun studio warnings.
313
void * worker_thread(void *arg)
1 by brian
clean slate
314
{
315
  int error;
316
  char *raw_table_name= (char *)arg;
1707.1.23 by Brian Aker
Cleanup of import.
317
  drizzle_con_st *con;
1 by brian
clean slate
318
928.1.6 by Eric Day
All utilities done except slap.
319
  if (!(con= db_connect(current_host,current_db,current_user,opt_password)))
1 by brian
clean slate
320
  {
1707.1.23 by Brian Aker
Cleanup of import.
321
    return 0;
1 by brian
clean slate
322
  }
323
324
  /*
325
    We are not currently catching the error here.
326
  */
1707.1.23 by Brian Aker
Cleanup of import.
327
  if ((error= write_to_table(raw_table_name, con)))
328
  {
1 by brian
clean slate
329
    if (exitcode == 0)
1707.1.23 by Brian Aker
Cleanup of import.
330
    {
1 by brian
clean slate
331
      exitcode= error;
1707.1.23 by Brian Aker
Cleanup of import.
332
    }
333
  }
1 by brian
clean slate
334
928.1.6 by Eric Day
All utilities done except slap.
335
  if (con)
1707.1.23 by Brian Aker
Cleanup of import.
336
  {
928.1.6 by Eric Day
All utilities done except slap.
337
    db_disconnect(current_host, con);
1707.1.23 by Brian Aker
Cleanup of import.
338
  }
1 by brian
clean slate
339
340
  pthread_mutex_lock(&counter_mutex);
341
  counter--;
342
  pthread_cond_signal(&count_threshhold);
343
  pthread_mutex_unlock(&counter_mutex);
344
345
  return 0;
346
}
347
348
349
int main(int argc, char **argv)
350
{
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
351
try
352
{
1 by brian
clean slate
353
  int error=0;
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
354
355
  po::options_description commandline_options("Options used only in command line");
356
  commandline_options.add_options()
357
358
  ("debug,#", po::value<string>(),
359
  "Output debug log. Often this is 'd:t:o,filename'.")
360
  ("delete,d", po::value<bool>(&opt_delete)->default_value(false)->zero_tokens(),
361
  "First delete all rows from table.")
362
  ("help,?", "Displays this help and exits.")
363
  ("ignore,i", po::value<bool>(&ignore_unique)->default_value(false)->zero_tokens(),
364
  "If duplicate unique key was found, keep old row.")
365
  ("low-priority", po::value<bool>(&opt_low_priority)->default_value(false)->zero_tokens(),
366
  "Use LOW_PRIORITY when updating the table.")
367
  ("replace,r", po::value<bool>(&opt_replace)->default_value(false)->zero_tokens(),
368
  "If duplicate unique key was found, replace old row.")
369
  ("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
370
  "Print info about the various stages.")
371
  ("version,V", "Output version information and exit.")
372
  ;
373
374
  po::options_description import_options("Options specific to the drizzleimport");
375
  import_options.add_options()
376
  ("columns,C", po::value<string>(&opt_columns)->default_value(""),
377
  "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.")
378
  ("fields-terminated-by", po::value<string>(&fields_terminated)->default_value(""),
379
  "Fields in the textfile are terminated by ...")
380
  ("fields-enclosed-by", po::value<string>(&enclosed)->default_value(""),
381
  "Fields in the importfile are enclosed by ...")
382
  ("fields-optionally-enclosed-by", po::value<string>(&opt_enclosed)->default_value(""),
383
  "Fields in the i.file are opt. enclosed by ...")
384
  ("fields-escaped-by", po::value<string>(&escaped)->default_value(""),
385
  "Fields in the i.file are escaped by ...")
386
  ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
387
  "Continue even if we get an sql-error.")
388
  ("ignore-lines", po::value<int64_t>(&opt_ignore_lines)->default_value(0),
389
  "Ignore first n lines of data infile.")
390
  ("lines-terminated-by", po::value<string>(&lines_terminated)->default_value(""),
391
  "Lines in the i.file are terminated by ...")
392
  ("local,L", po::value<bool>(&opt_local_file)->default_value(false)->zero_tokens(),
393
  "Read all files through the client.")
394
  ("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
395
  "Be more silent.")
1707.1.23 by Brian Aker
Cleanup of import.
396
  ("use-threads", po::value<uint32_t>(&opt_use_threads)->default_value(4),
397
  "Load files in parallel. The argument is the number of threads to use for loading data (default is 4.")
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
398
  ;
399
400
  po::options_description client_options("Options specific to the client");
401
  client_options.add_options()
402
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
403
  "Connect to host.")
404
  ("password,P", po::value<string>(&password),
405
  "Password to use when connecting to server. If password is not given it's asked from the tty." )
406
  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
407
  "Port number to use for connection") 
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
408
  ("protocol", po::value<string>(&opt_protocol)->default_value("mysql"),
409
  "The protocol of connection (mysql or drizzle).")
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
410
  ("user,u", po::value<string>(&current_user)->default_value(""),
411
  "User for login if not current user.")
412
  ;
413
414
  po::options_description long_options("Allowed Options");
415
  long_options.add(commandline_options).add(import_options).add(client_options);
416
417
  std::string system_config_dir_import(SYSCONFDIR); 
418
  system_config_dir_import.append("/drizzle/drizzleimport.cnf");
419
420
  std::string system_config_dir_client(SYSCONFDIR); 
421
  system_config_dir_client.append("/drizzle/client.cnf");
422
  
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
423
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
424
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)
425
  if (user_config_dir.compare(0, 2, "~/") == 0)
426
  {
427
    char *homedir;
428
    homedir= getenv("HOME");
429
    if (homedir != NULL)
430
      user_config_dir.replace(0, 1, homedir);
431
  }
432
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
433
  po::variables_map vm;
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
434
1793.3.1 by Andrew Hutchings
Disable boost:po allow_guessing which was making some wrong assumptions
435
  // Disable allow_guessing
436
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
437
1633.5.2 by Vijay Samuel
Merge fix for password in client/
438
  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
439
            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.
440
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
441
  std::string user_config_dir_import(user_config_dir);
442
  user_config_dir_import.append("/drizzle/drizzleimport.cnf"); 
443
444
  std::string user_config_dir_client(user_config_dir);
445
  user_config_dir_client.append("/drizzle/client.cnf");
446
447
  ifstream user_import_ifs(user_config_dir_import.c_str());
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
448
  po::store(parse_config_file(user_import_ifs, import_options), vm);
1671.2.1 by Vijay Samuel
Merge new user config file processing system.
449
450
  ifstream user_client_ifs(user_config_dir_client.c_str());
451
  po::store(parse_config_file(user_client_ifs, client_options), vm);
452
1593.1.2 by Vijay Samuel
Merge re factored commandline option and configuration file processing using boost::program_options.
453
  ifstream system_import_ifs(system_config_dir_import.c_str());
454
  store(parse_config_file(system_import_ifs, import_options), vm);
455
 
456
  ifstream system_client_ifs(system_config_dir_client.c_str());
457
  po::store(parse_config_file(system_client_ifs, client_options), vm);
458
459
  po::notify(vm);
1745.2.1 by LinuxJedi
Remove the --mysql option and convert the --protocol option to do something similar.
460
  if (vm.count("protocol"))
461
  {
462
    std::transform(opt_protocol.begin(), opt_protocol.end(),
463
      opt_protocol.begin(), ::tolower);
464
465
    if (not opt_protocol.compare("mysql"))
466
      use_drizzle_protocol=false;
467
    else if (not opt_protocol.compare("drizzle"))
468
      use_drizzle_protocol=true;
469
    else
470
    {
471
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
472
      exit(-1);
473
    }
474
  }
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++)
928.1.6 by Eric Day
All utilities done except slap.
602
      if ((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
}