~drizzle-trunk/drizzle/development

381 by Monty Taylor
Reformatted slap and test.
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
3
 * 
4
 *  Copyright (C) 2010 Vijay Samuel
381 by Monty Taylor
Reformatted slap and test.
5
 *  Copyright (C) 2008 MySQL
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; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
 */
1 by brian
clean slate
21
22
/*
206.3.1 by Patrick Galbraith
Most everything working with client rename
23
  drizzletest
1 by brian
clean slate
24
25
  Tool used for executing a .test file
26
2367.2.7 by Olaf van der Spek
Refactor
27
  See the "MySQL Test framework manual" for more information
28
  http://dev.mysql.com/doc/mysqltest/en/index.html
1 by brian
clean slate
29
30
  Please keep the test framework tools identical in all versions!
31
32
  Written by:
33
  Sasha Pachev <sasha@mysql.com>
34
  Matt Wagner  <matt@mysql.com>
35
  Monty
36
  Jani
37
  Holyfoot
38
*/
39
40
#define MTEST_VERSION "3.3"
373.1.6 by Monty Taylor
Moved q_lines to vector.
41
2318.4.2 by Olaf van der Spek
Add libdrizzle/libdrizzle.hpp
42
#include <config.h>
43
#include <client/get_password.h>
2449.1.2 by Brian Aker
Additional fixes for libdrizzle.
44
#include <libdrizzle-2.0/libdrizzle.hpp>
139.1.16 by Trond Norbye
Include config.h first to aviod redefining macro warning
45
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
46
#include <queue>
373.1.6 by Monty Taylor
Moved q_lines to vector.
47
#include <map>
48
#include <string>
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.
49
#include <sstream>
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
50
#include <fstream>
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.
51
#include <iostream>
496.1.6 by Paul McCullagh
Fixed the --sorted_result command and changed to sorting accending
52
#include <vector>
1067.4.5 by Nathan Williams
Converted single usage of cmin in drizzletest to std::min.
53
#include <algorithm>
1099.2.1 by rm
get things compiling on FreeBSD (7.1)
54
#ifdef HAVE_SYS_WAIT_H
55
#include <sys/wait.h>
56
#endif
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
57
#include <cassert>
58
#include <sys/stat.h>
59
#include <sys/types.h>
60
#include <fcntl.h>
2151.2.19 by Olaf van der Spek
refactor
61
#include <boost/array.hpp>
2151.2.22 by Olaf van der Spek
refactor
62
#include <boost/foreach.hpp>
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
63
#include <boost/program_options.hpp>
2151.2.21 by Olaf van der Spek
refactor
64
#include <boost/smart_ptr.hpp>
373.1.6 by Monty Taylor
Moved q_lines to vector.
65
859.1.6 by Monty Taylor
Fix for multi-versions of PCRE thing.
66
#include PCRE_HEADER
1 by brian
clean slate
67
68
#include <stdarg.h>
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
69
#include <boost/unordered_map.hpp>
15 by brian
Fix for stat, NETWARE removal
70
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
71
/* Added this for string translation. */
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
72
#include <drizzled/gettext.h>
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)
73
74
#include <drizzled/definitions.h>
75
#include <drizzled/internal/my_sys.h>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
76
#include <drizzled/type/time.h>
77
#include <drizzled/charset.h>
78
#include <drizzled/typelib.h>
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
79
#include <drizzled/configmake.h>
2192.5.1 by Olaf van der Spek
Use find_ptr
80
#include <drizzled/util/find_ptr.h>
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
81
2168.2.32 by Stewart Smith
move PTR_BYTE_DIFF to drizzletest.cc as it's the only place that still uses it
82
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
83
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
84
namespace po= boost::program_options;
373.1.6 by Monty Taylor
Moved q_lines to vector.
85
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
86
using namespace drizzled;
373.1.6 by Monty Taylor
Moved q_lines to vector.
87
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
88
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
89
1410.3.4 by Djellel E. Difallah
update references to old my_'s
90
int get_one_option(int optid, const struct option *, char *argument);
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
91
1 by brian
clean slate
92
#define MAX_VAR_NAME_LENGTH    256
93
#define MAX_COLUMNS            256
94
#define MAX_DELIMITER_LENGTH 16
95
/* Flags controlling send and reap */
96
#define QUERY_SEND_FLAG  1
97
#define QUERY_REAP_FLAG  2
98
1996.3.7 by Monty Taylor
Replaced static error code mapping with a query of data_dictionary.errors.
99
typedef boost::unordered_map<std::string, uint32_t> ErrorCodes;
1103.4.1 by Robert Klahn
make client/drizzletest.cc, new client/errname.cc compile in a reasonable amount of time and memory
100
ErrorCodes global_error_names;
101
1 by brian
clean slate
102
enum {
103
  OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
685.1.22 by Monty Taylor
Added testdir setting support to drizzletest.
104
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
105
  OPT_TESTDIR
1 by brian
clean slate
106
};
107
108
static int record= 0, opt_sleep= -1;
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
109
static char *opt_pass= NULL;
110
const char *unix_sock= NULL;
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
111
static uint32_t opt_port= 0;
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
112
static uint32_t opt_max_connect_retries;
1235.3.2 by Stewart Smith
remove unused --compress option from drizzletest
113
static bool silent= false, verbose= false;
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
114
static bool opt_mark_progress= false;
115
static bool parsing_disabled= false;
163 by Brian Aker
Merge Monty's code.
116
static bool display_result_vertically= false,
117
  display_metadata= false, display_result_sorted= false;
673.5.13 by Andrew Hutchings
Apply -p means port changes to all client apps
118
static bool disable_query_log= false, disable_result_log= false;
119
static bool disable_warnings= false;
120
static bool disable_info= true;
121
static bool abort_on_error= true;
122
static bool server_initialized= false;
123
static bool is_windows= false;
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
124
static bool use_drizzle_protocol= false;
1 by brian
clean slate
125
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
2151.2.21 by Olaf van der Spek
refactor
126
static void free_all_replace();
1 by brian
clean slate
127
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
128
std::string opt_basedir,
129
  opt_charsets_dir,
130
  opt_db,
131
  opt_host,
132
  opt_include,
133
  opt_testdir,
134
  opt_logdir,
135
  password,
136
  opt_password,
137
  result_file_name,
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
138
  opt_user,
139
  opt_protocol;
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
140
893 by Brian Aker
First pass of stripping uint
141
static uint32_t start_lineno= 0; /* Start line of current command */
1 by brian
clean slate
142
143
/* Number of lines of the result to include in failure report */
893 by Brian Aker
First pass of stripping uint
144
static uint32_t opt_tail_lines= 0;
1 by brian
clean slate
145
146
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
893 by Brian Aker
First pass of stripping uint
147
static uint32_t delimiter_length= 1;
1 by brian
clean slate
148
149
static char TMPDIR[FN_REFLEN];
150
151
/* Block stack */
152
enum block_cmd {
153
  cmd_none,
154
  cmd_if,
155
  cmd_while
156
};
157
158
struct st_block
159
{
160
  int             line; /* Start line of block */
143 by Brian Aker
Bool cleanup.
161
  bool         ok;   /* Should block be executed */
1 by brian
clean slate
162
  enum block_cmd  cmd;  /* Command owning the block */
163
};
164
165
static struct st_block block_stack[32];
166
static struct st_block *cur_block, *block_stack_end;
167
168
/* Open file stack */
169
struct st_test_file
170
{
171
  FILE* file;
172
  const char *file_name;
893 by Brian Aker
First pass of stripping uint
173
  uint32_t lineno; /* Current line in file */
1 by brian
clean slate
174
};
175
2151.2.27 by Olaf van der Spek
refactor
176
static boost::array<st_test_file, 16> file_stack;
177
static st_test_file* cur_file;
1 by brian
clean slate
178
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
179
static const charset_info_st *charset_info= &my_charset_utf8_general_ci; /* Default charset */
1 by brian
clean slate
180
181
/*
182
  Timer related variables
183
  See the timer_output() definition for details
184
*/
185
static char *timer_file = NULL;
151 by Brian Aker
Ulonglong to uint64_t
186
static uint64_t timer_start;
2151.2.17 by Olaf van der Spek
drizzletest refactoring
187
static void timer_output();
188
static uint64_t timer_now();
1 by brian
clean slate
189
151 by Brian Aker
Ulonglong to uint64_t
190
static uint64_t progress_start= 0;
1 by brian
clean slate
191
373.1.6 by Monty Taylor
Moved q_lines to vector.
192
vector<struct st_command*> q_lines;
1 by brian
clean slate
193
2318.4.4 by Olaf van der Spek
Refactor
194
struct parser_st
195
{
196
  int read_lines;
197
  int current_line;
198
} parser;
1 by brian
clean slate
199
2318.4.4 by Olaf van der Spek
Refactor
200
struct master_pos_st
1 by brian
clean slate
201
{
202
  char file[FN_REFLEN];
297 by Brian Aker
Final ulong cleanup in clients
203
  uint32_t pos;
2318.4.4 by Olaf van der Spek
Refactor
204
};
77.1.31 by Monty Taylor
Replaced regex lib with pcre. Reworked mysqltest to use it.
205
206
master_pos_st master_pos;
1 by brian
clean slate
207
208
/* if set, all results are concated and compared against this file */
209
2151.2.24 by Olaf van der Spek
refactor
210
class VAR
1 by brian
clean slate
211
{
2151.2.24 by Olaf van der Spek
refactor
212
public:
1 by brian
clean slate
213
  char *name;
214
  int name_len;
215
  char *str_val;
216
  int str_val_len;
217
  int int_val;
218
  int alloced_len;
219
  int int_dirty; /* do not update string if int is updated until first read */
220
  int alloced;
221
  char *env_s;
2151.2.24 by Olaf van der Spek
refactor
222
};
1 by brian
clean slate
223
224
/*Perl/shell-like variable registers */
2151.2.22 by Olaf van der Spek
refactor
225
boost::array<VAR, 10> var_reg;
1 by brian
clean slate
226
2151.2.24 by Olaf van der Spek
refactor
227
typedef boost::unordered_map<string, VAR *> var_hash_t;
228
var_hash_t var_hash;
1 by brian
clean slate
229
2318.5.25 by Olaf van der Spek
Refactor
230
class st_connection
1 by brian
clean slate
231
{
2318.5.25 by Olaf van der Spek
Refactor
232
public:
2318.5.26 by Olaf van der Spek
Refactor
233
  st_connection() : con(drizzle)
234
  {
235
    drizzle_con_add_options(*this, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
236
  }
237
2318.5.32 by Olaf van der Spek
Refactor
238
  operator drizzle::connection_c&()
239
  {
240
    return con;
241
  }
242
2318.5.26 by Olaf van der Spek
Refactor
243
  operator drizzle_con_st*()
244
  {
2407.1.2 by Olaf van der Spek
Make base members private
245
    return con;
2318.5.26 by Olaf van der Spek
Refactor
246
  }
247
248
  drizzle::drizzle_c drizzle;
249
  drizzle::connection_c con;
1 by brian
clean slate
250
};
2318.5.24 by Olaf van der Spek
Refactor
251
252
typedef map<string, st_connection*> connections_t;
253
connections_t g_connections;
254
st_connection* cur_con= NULL;
1 by brian
clean slate
255
256
/*
206.3.1 by Patrick Galbraith
Most everything working with client rename
257
  List of commands in drizzletest
1 by brian
clean slate
258
  Must match the "command_names" array
259
  Add new commands before Q_UNKNOWN!
260
*/
2318.4.4 by Olaf van der Spek
Refactor
261
enum enum_commands 
262
{
1 by brian
clean slate
263
  Q_CONNECTION=1,     Q_QUERY,
206.3.1 by Patrick Galbraith
Most everything working with client rename
264
  Q_CONNECT,      Q_SLEEP, Q_REAL_SLEEP,
265
  Q_INC,        Q_DEC,
266
  Q_SOURCE,      Q_DISCONNECT,
267
  Q_LET,        Q_ECHO,
268
  Q_WHILE,      Q_END_BLOCK,
269
  Q_SYSTEM,      Q_RESULT,
270
  Q_REQUIRE,      Q_SAVE_MASTER_POS,
1 by brian
clean slate
271
  Q_SYNC_WITH_MASTER,
272
  Q_SYNC_SLAVE_WITH_MASTER,
273
  Q_ERROR,
206.3.1 by Patrick Galbraith
Most everything working with client rename
274
  Q_SEND,        Q_REAP,
275
  Q_DIRTY_CLOSE,      Q_REPLACE, Q_REPLACE_COLUMN,
276
  Q_PING,        Q_EVAL,
1 by brian
clean slate
277
  Q_EVAL_RESULT,
278
  Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
279
  Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
280
  Q_WAIT_FOR_SLAVE_TO_STOP,
281
  Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
282
  Q_ENABLE_INFO, Q_DISABLE_INFO,
283
  Q_ENABLE_METADATA, Q_DISABLE_METADATA,
284
  Q_EXEC, Q_DELIMITER,
285
  Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
286
  Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
287
  Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
288
  Q_START_TIMER, Q_END_TIMER,
496.1.7 by Paul McCullagh
Fixed the --replace_regex command
289
  Q_CHARACTER_SET,
1 by brian
clean slate
290
  Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
291
  Q_IF,
292
  Q_DISABLE_PARSING, Q_ENABLE_PARSING,
293
  Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST,
294
  Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP,
295
  Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
296
  Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
297
206.3.1 by Patrick Galbraith
Most everything working with client rename
298
  Q_UNKNOWN,             /* Unknown command.   */
299
  Q_COMMENT,             /* Comments, ignored. */
1 by brian
clean slate
300
  Q_COMMENT_WITH_COMMAND
301
};
302
303
304
const char *command_names[]=
305
{
306
  "connection",
307
  "query",
308
  "connect",
309
  "sleep",
310
  "real_sleep",
311
  "inc",
312
  "dec",
313
  "source",
314
  "disconnect",
315
  "let",
316
  "echo",
317
  "while",
318
  "end",
319
  "system",
320
  "result",
321
  "require",
322
  "save_master_pos",
323
  "sync_with_master",
324
  "sync_slave_with_master",
325
  "error",
326
  "send",
327
  "reap",
328
  "dirty_close",
329
  "replace_result",
330
  "replace_column",
331
  "ping",
332
  "eval",
333
  "eval_result",
334
  /* Enable/disable that the _query_ is logged to result file */
335
  "enable_query_log",
336
  "disable_query_log",
337
  /* Enable/disable that the _result_ from a query is logged to result file */
338
  "enable_result_log",
339
  "disable_result_log",
340
  "wait_for_slave_to_stop",
341
  "enable_warnings",
342
  "disable_warnings",
343
  "enable_info",
344
  "disable_info",
345
  "enable_metadata",
346
  "disable_metadata",
347
  "exec",
348
  "delimiter",
349
  "disable_abort_on_error",
350
  "enable_abort_on_error",
351
  "vertical_results",
352
  "horizontal_results",
353
  "query_vertical",
354
  "query_horizontal",
355
  "sorted_result",
356
  "start_timer",
357
  "end_timer",
358
  "character_set",
359
  "disable_reconnect",
360
  "enable_reconnect",
361
  "if",
362
  "disable_parsing",
363
  "enable_parsing",
364
  "replace_regex",
365
  "remove_file",
366
  "file_exists",
367
  "write_file",
368
  "copy_file",
369
  "perl",
370
  "die",
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
371
1 by brian
clean slate
372
  /* Don't execute any more commands, compare result */
373
  "exit",
374
  "skip",
375
  "chmod",
376
  "append_file",
377
  "cat_file",
378
  "diff_files",
379
  "send_quit",
380
  "change_user",
381
  "mkdir",
382
  "rmdir",
383
384
  0
385
};
386
387
388
/*
389
  The list of error codes to --error are stored in an internal array of
390
  structs. This struct can hold numeric SQL error codes, error names or
391
  SQLSTATE codes as strings. The element next to the last active element
392
  in the list is set to type ERR_EMPTY. When an SQL statement returns an
393
  error, we use this list to check if this is an expected error.
394
*/
395
enum match_err_type
396
{
397
  ERR_EMPTY= 0,
398
  ERR_ERRNO,
399
  ERR_SQLSTATE
400
};
401
402
struct st_match_err
403
{
404
  enum match_err_type type;
405
  union
406
  {
893 by Brian Aker
First pass of stripping uint
407
    uint32_t errnum;
928.1.6 by Eric Day
All utilities done except slap.
408
    char sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE+1];  /* \0 terminated string */
1 by brian
clean slate
409
  } code;
410
};
411
412
struct st_expected_errors
413
{
414
  struct st_match_err err[10];
893 by Brian Aker
First pass of stripping uint
415
  uint32_t count;
1 by brian
clean slate
416
};
2151.2.24 by Olaf van der Spek
refactor
417
418
static st_expected_errors saved_expected_errors;
1 by brian
clean slate
419
2151.2.22 by Olaf van der Spek
refactor
420
class st_command
1 by brian
clean slate
421
{
2151.2.22 by Olaf van der Spek
refactor
422
public:
1 by brian
clean slate
423
  char *query, *query_buf,*first_argument,*last_argument,*end;
424
  int first_word_len, query_len;
143 by Brian Aker
Bool cleanup.
425
  bool abort_on_error;
1134.1.3 by Monty Taylor
Fixed up drizzletest.cc
426
  st_expected_errors expected_errors;
427
  string require_file;
2151.2.22 by Olaf van der Spek
refactor
428
  enum_commands type;
1159 by Brian Aker
Merge Monty
429
1134.1.3 by Monty Taylor
Fixed up drizzletest.cc
430
  st_command()
431
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
432
      end(NULL), first_word_len(0), query_len(0), abort_on_error(false),
433
      require_file(""), type(Q_CONNECTION)
434
  {
435
    memset(&expected_errors, 0, sizeof(st_expected_errors));
436
  }
1159 by Brian Aker
Merge Monty
437
438
  ~st_command()
439
  {
2151.2.18 by Olaf van der Spek
refactor
440
    free(query_buf);
1159 by Brian Aker
Merge Monty
441
  }
1 by brian
clean slate
442
};
443
444
TYPELIB command_typelib= {array_elements(command_names),"",
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
445
                          command_names, 0};
1 by brian
clean slate
446
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
447
string ds_res, ds_progress, ds_warning_messages;
1 by brian
clean slate
448
449
char builtin_echo[FN_REFLEN];
450
451
void die(const char *fmt, ...)
212.5.26 by Monty Taylor
Removed my_attribute. Renaming __attribute__((format(x,y,z))) to ATTRIBUTE_FORMAT(x,y,z) is retarded. So we don't do it anymore.
452
  __attribute__((format(printf, 1, 2)));
1 by brian
clean slate
453
void abort_not_supported_test(const char *fmt, ...)
212.5.26 by Monty Taylor
Removed my_attribute. Renaming __attribute__((format(x,y,z))) to ATTRIBUTE_FORMAT(x,y,z) is retarded. So we don't do it anymore.
454
  __attribute__((format(printf, 1, 2)));
1 by brian
clean slate
455
void verbose_msg(const char *fmt, ...)
212.5.26 by Monty Taylor
Removed my_attribute. Renaming __attribute__((format(x,y,z))) to ATTRIBUTE_FORMAT(x,y,z) is retarded. So we don't do it anymore.
456
  __attribute__((format(printf, 1, 2)));
1 by brian
clean slate
457
void warning_msg(const char *fmt, ...)
212.5.26 by Monty Taylor
Removed my_attribute. Renaming __attribute__((format(x,y,z))) to ATTRIBUTE_FORMAT(x,y,z) is retarded. So we don't do it anymore.
458
  __attribute__((format(printf, 1, 2)));
1 by brian
clean slate
459
void log_msg(const char *fmt, ...)
212.5.26 by Monty Taylor
Removed my_attribute. Renaming __attribute__((format(x,y,z))) to ATTRIBUTE_FORMAT(x,y,z) is retarded. So we don't do it anymore.
460
  __attribute__((format(printf, 1, 2)));
1 by brian
clean slate
461
462
VAR* var_from_env(const char *, const char *);
463
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
464
              int val_len);
465
VAR* var_get(const char *var_name, const char** var_name_end,
143 by Brian Aker
Bool cleanup.
466
             bool raw, bool ignore_not_existing);
1 by brian
clean slate
467
void eval_expr(VAR* v, const char *p, const char** p_end);
893 by Brian Aker
First pass of stripping uint
468
bool match_delimiter(int c, const char *delim, uint32_t length);
1 by brian
clean slate
469
void dump_result_to_reject_file(char *buf, int size);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
470
void dump_result_to_log_file(const char *buf, int size);
2151.2.17 by Olaf van der Spek
drizzletest refactoring
471
void dump_warning_messages();
472
void dump_progress();
1 by brian
clean slate
473
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
474
void do_eval(string *query_eval, const char *query,
143 by Brian Aker
Bool cleanup.
475
             const char *query_end, bool pass_through_escape_chars);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
476
void str_to_file(const char *fname, const char *str, int size);
477
void str_to_file2(const char *fname, const char *str, int size, bool append);
1 by brian
clean slate
478
479
/* For replace_column */
480
static char *replace_column[MAX_COLUMNS];
893 by Brian Aker
First pass of stripping uint
481
static uint32_t max_replace_column= 0;
2318.5.23 by Olaf van der Spek
Refactor
482
void do_get_replace_column(st_command*);
2151.2.17 by Olaf van der Spek
drizzletest refactoring
483
void free_replace_column();
1 by brian
clean slate
484
485
/* For replace */
2318.4.6 by Olaf van der Spek
Refactor
486
void do_get_replace(st_command* command);
2151.2.17 by Olaf van der Spek
drizzletest refactoring
487
void free_replace();
1 by brian
clean slate
488
489
/* For replace_regex */
2318.4.6 by Olaf van der Spek
Refactor
490
void do_get_replace_regex(st_command* command);
1 by brian
clean slate
491
2318.5.22 by Olaf van der Spek
Refactor
492
void replace_append_mem(string& ds, const char *val, int len);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
493
void replace_append(string *ds, const char *val);
2318.6.1 by Olaf van der Spek
Refactor
494
void replace_append_uint(string& ds, uint32_t val);
2318.5.22 by Olaf van der Spek
Refactor
495
void append_sorted(string& ds, const string& ds_input);
1 by brian
clean slate
496
2318.5.23 by Olaf van der Spek
Refactor
497
void handle_error(st_command*,
1 by brian
clean slate
498
                  unsigned int err_errno, const char *err_error,
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
499
                  const char *err_sqlstate, string *ds);
2318.5.23 by Olaf van der Spek
Refactor
500
void handle_no_error(st_command*);
1 by brian
clean slate
501
502
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
503
void do_eval(string *query_eval, const char *query,
143 by Brian Aker
Bool cleanup.
504
             const char *query_end, bool pass_through_escape_chars)
1 by brian
clean slate
505
{
2151.2.17 by Olaf van der Spek
drizzletest refactoring
506
  char c, next_c;
507
  int escaped = 0;
142.1.1 by Patrick
Removing DBUG from client
508
2151.2.18 by Olaf van der Spek
refactor
509
  for (const char *p= query; (c= *p) && p < query_end; ++p)
1 by brian
clean slate
510
  {
2318.5.4 by Olaf van der Spek
Refactor
511
    switch(c) 
512
    {
1 by brian
clean slate
513
    case '$':
514
      if (escaped)
515
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
516
        escaped= 0;
517
        query_eval->append(p, 1);
1 by brian
clean slate
518
      }
519
      else
520
      {
2318.5.4 by Olaf van der Spek
Refactor
521
        VAR* v= var_get(p, &p, 0, 0);
522
        if (not v)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
523
          die("Bad variable in eval");
524
        query_eval->append(v->str_val, v->str_val_len);
1 by brian
clean slate
525
      }
526
      break;
527
    case '\\':
528
      next_c= *(p+1);
529
      if (escaped)
530
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
531
        escaped= 0;
532
        query_eval->append(p, 1);
1 by brian
clean slate
533
      }
534
      else if (next_c == '\\' || next_c == '$' || next_c == '"')
535
      {
536
        /* Set escaped only if next char is \, " or $ */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
537
        escaped= 1;
1 by brian
clean slate
538
539
        if (pass_through_escape_chars)
540
        {
541
          /* The escape char should be added to the output string. */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
542
          query_eval->append(p, 1);
1 by brian
clean slate
543
        }
544
      }
545
      else
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
546
        query_eval->append(p, 1);
1 by brian
clean slate
547
      break;
548
    default:
549
      escaped= 0;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
550
      query_eval->append(p, 1);
1 by brian
clean slate
551
    }
552
  }
553
}
554
555
556
/*
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
557
  Concatenates any number of strings, escapes any OS quote in the result then
558
  surround the whole affair in another set of quotes which is finally appended
559
  to specified string.  This function is especially useful when
560
  building strings to be executed with the system() function.
561
562
  @param str string which will have addtional strings appended.
563
  @param append string to be appended.
564
  @param ... Optional. Additional string(s) to be appended.
565
461 by Monty Taylor
Removed NullS. bu-bye.
566
  @note The final argument in the list must be NULL even if no additional
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
567
  options are passed.
568
*/
569
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
570
static void append_os_quoted(string *str, const char *append, ...)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
571
{
572
  const char *quote_str= "\'";
893 by Brian Aker
First pass of stripping uint
573
  const uint32_t  quote_len= 1;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
574
575
  va_list dirty_text;
576
577
  str->append(quote_str, quote_len); /* Leading quote */
578
  va_start(dirty_text, append);
461 by Monty Taylor
Removed NullS. bu-bye.
579
  while (append != NULL)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
580
  {
581
    const char  *cur_pos= append;
582
    const char *next_pos= cur_pos;
583
584
    /* Search for quote in each string and replace with escaped quote */
2318.5.3 by Olaf van der Spek
Refactor
585
    while ((next_pos= strrchr(cur_pos, quote_str[0])) != NULL)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
586
    {
587
      str->append(cur_pos, next_pos - cur_pos);
588
      str->append("\\", 1);
589
      str->append(quote_str, quote_len);
590
      cur_pos= next_pos + 1;
591
    }
482.1.1 by Monty Taylor
Fix for drizzletest crash from Paul McCullagh. (Fixes #279304)
592
    str->append(cur_pos);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
593
    append= va_arg(dirty_text, char *);
594
  }
595
  va_end(dirty_text);
596
  str->append(quote_str, quote_len); /* Trailing quote */
597
}
598
599
600
/*
1 by brian
clean slate
601
  Run query and dump the result to stdout in vertical format
602
603
  NOTE! This function should be safe to call when an error
604
  has occured and thus any further errors will be ignored(although logged)
605
606
  SYNOPSIS
607
  show_query
206.3.1 by Patrick Galbraith
Most everything working with client rename
608
  drizzle - connection to use
1 by brian
clean slate
609
  query - query to run
610
611
*/
612
2318.5.37 by Olaf van der Spek
Refactor
613
static int dt_query_log(drizzle::connection_c& con, drizzle::result_c& res, const std::string& query)
614
{
615
  if (drizzle_return_t ret= con.query(res, query))
616
  {
617
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
618
    {
619
      log_msg("Error running query '%s': %d %s", query.c_str(), res.error_code(), res.error());
620
    }
621
    else
622
    {
623
      log_msg("Error running query '%s': %d %s", query.c_str(), ret, con.error());
624
    }
625
    return 1;
626
  }
627
  return res.column_count() == 0;
628
}
629
2318.5.32 by Olaf van der Spek
Refactor
630
static void show_query(drizzle::connection_c& con, const char* query)
1 by brian
clean slate
631
{
2318.5.6 by Olaf van der Spek
Refactor
632
  drizzle::result_c res;
2318.5.37 by Olaf van der Spek
Refactor
633
  if (dt_query_log(con, res, query))
142.1.1 by Patrick
Removing DBUG from client
634
    return;
1 by brian
clean slate
635
2318.5.35 by Olaf van der Spek
Refactor
636
  unsigned int row_num= 0;
637
  unsigned int num_fields= res.column_count();
638
639
  fprintf(stderr, "=== %s ===\n", query);
640
  while (drizzle_row_t row= res.row_next())
1 by brian
clean slate
641
  {
2318.5.35 by Olaf van der Spek
Refactor
642
    size_t *lengths= res.row_field_sizes();
643
    row_num++;
1 by brian
clean slate
644
2318.5.35 by Olaf van der Spek
Refactor
645
    fprintf(stderr, "---- %d. ----\n", row_num);
646
    res.column_seek(0);
647
    for (unsigned int i= 0; i < num_fields; i++)
1 by brian
clean slate
648
    {
2318.5.35 by Olaf van der Spek
Refactor
649
      drizzle_column_st* column= res.column_next();
650
      fprintf(stderr, "%s\t%.*s\n", drizzle_column_name(column), (int)lengths[i], row[i] ? row[i] : "NULL");
1 by brian
clean slate
651
    }
652
  }
2318.5.35 by Olaf van der Spek
Refactor
653
  for (size_t i= 0; i < strlen(query)+8; i++)
654
    fprintf(stderr, "=");
655
  fprintf(stderr, "\n\n");
1 by brian
clean slate
656
}
657
658
659
/*
660
  Show any warnings just before the error. Since the last error
661
  is added to the warning stack, only print @@warning_count-1 warnings.
662
663
  NOTE! This function should be safe to call when an error
664
  has occured and this any further errors will be ignored(although logged)
665
666
  SYNOPSIS
667
  show_warnings_before_error
206.3.1 by Patrick Galbraith
Most everything working with client rename
668
  drizzle - connection to use
1 by brian
clean slate
669
670
*/
671
2318.5.34 by Olaf van der Spek
Refactor
672
static void show_warnings_before_error(drizzle::connection_c& con)
1 by brian
clean slate
673
{
2318.5.7 by Olaf van der Spek
Refactor
674
  drizzle::result_c res;
2318.5.37 by Olaf van der Spek
Refactor
675
  if (dt_query_log(con, res, "show warnings"))
142.1.1 by Patrick
Removing DBUG from client
676
    return;
1 by brian
clean slate
677
2318.5.7 by Olaf van der Spek
Refactor
678
  if (res.row_count() >= 2) /* Don't display the last row, it's "last error" */
1 by brian
clean slate
679
  {
680
    unsigned int row_num= 0;
2318.5.7 by Olaf van der Spek
Refactor
681
    unsigned int num_fields= res.column_count();
1 by brian
clean slate
682
683
    fprintf(stderr, "\nWarnings from just before the error:\n");
2318.5.7 by Olaf van der Spek
Refactor
684
    while (drizzle_row_t row= res.row_next())
1 by brian
clean slate
685
    {
2318.5.12 by Olaf van der Spek
Refactor
686
      size_t *lengths= res.row_field_sizes();
1 by brian
clean slate
687
2318.5.7 by Olaf van der Spek
Refactor
688
      if (++row_num >= res.row_count())
1 by brian
clean slate
689
      {
690
        /* Don't display the last row, it's "last error" */
691
        break;
692
      }
693
2318.5.2 by Olaf van der Spek
Refactor
694
      for (uint32_t i= 0; i < num_fields; i++)
1 by brian
clean slate
695
      {
2318.5.7 by Olaf van der Spek
Refactor
696
        fprintf(stderr, "%.*s ", (int)lengths[i], row[i] ? row[i] : "NULL");
1 by brian
clean slate
697
      }
698
      fprintf(stderr, "\n");
699
    }
700
  }
701
}
702
703
enum arg_type
704
{
705
  ARG_STRING,
706
  ARG_REST
707
};
708
2318.5.7 by Olaf van der Spek
Refactor
709
struct command_arg 
710
{
1 by brian
clean slate
711
  const char *argname;       /* Name of argument   */
712
  enum arg_type type;        /* Type of argument   */
143 by Brian Aker
Bool cleanup.
713
  bool required;          /* Argument required  */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
714
  string *ds;        /* Storage for argument */
1 by brian
clean slate
715
  const char *description;   /* Description of the argument */
716
};
717
718
2318.4.6 by Olaf van der Spek
Refactor
719
static void check_command_args(st_command* command,
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
720
                               const char *arguments,
721
                               const struct command_arg *args,
722
                               int num_args, const char delimiter_arg)
1 by brian
clean slate
723
{
724
  const char *ptr= arguments;
725
  const char *start;
726
2318.5.2 by Olaf van der Spek
Refactor
727
  for (int i= 0; i < num_args; i++)
1 by brian
clean slate
728
  {
729
    const struct command_arg *arg= &args[i];
1008.3.9 by Stewart Smith
Always clear destination string when parsing arguments in drizzletest.
730
    arg->ds->clear();
1 by brian
clean slate
731
1816.2.3 by Monty Taylor
Fixed some more ICC warnings. How did I get started on this this morning?
732
    bool known_arg_type= true;
1 by brian
clean slate
733
    switch (arg->type) {
734
      /* A string */
735
    case ARG_STRING:
736
      /* Skip leading spaces */
737
      while (*ptr && *ptr == ' ')
738
        ptr++;
739
      start= ptr;
740
      /* Find end of arg, terminated by "delimiter_arg" */
741
      while (*ptr && *ptr != delimiter_arg)
742
        ptr++;
743
      if (ptr > start)
744
      {
163 by Brian Aker
Merge Monty's code.
745
        do_eval(arg->ds, start, ptr, false);
1 by brian
clean slate
746
      }
747
      else
748
      {
749
        /* Empty string */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
750
        arg->ds->erase();
1 by brian
clean slate
751
      }
752
      command->last_argument= (char*)ptr;
753
754
      /* Step past the delimiter */
755
      if (*ptr && *ptr == delimiter_arg)
756
        ptr++;
757
      break;
758
759
      /* Rest of line */
760
    case ARG_REST:
761
      start= ptr;
163 by Brian Aker
Merge Monty's code.
762
      do_eval(arg->ds, start, command->end, false);
1 by brian
clean slate
763
      command->last_argument= command->end;
764
      break;
765
766
    default:
1816.2.3 by Monty Taylor
Fixed some more ICC warnings. How did I get started on this this morning?
767
      known_arg_type= false;
1 by brian
clean slate
768
      break;
769
    }
1816.2.3 by Monty Taylor
Fixed some more ICC warnings. How did I get started on this this morning?
770
    assert(known_arg_type);
1 by brian
clean slate
771
772
    /* Check required arg */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
773
    if (arg->ds->length() == 0 && arg->required)
1 by brian
clean slate
774
      die("Missing required argument '%s' to command '%.*s'", arg->argname,
775
          command->first_word_len, command->query);
776
777
  }
778
  /* Check for too many arguments passed */
779
  ptr= command->last_argument;
2318.5.3 by Olaf van der Spek
Refactor
780
  while (ptr <= command->end)
1 by brian
clean slate
781
  {
782
    if (*ptr && *ptr != ' ')
783
      die("Extra argument '%s' passed to '%.*s'",
784
          ptr, command->first_word_len, command->query);
785
    ptr++;
786
  }
142.1.1 by Patrick
Removing DBUG from client
787
  return;
1 by brian
clean slate
788
}
789
790
2318.4.6 by Olaf van der Spek
Refactor
791
static void handle_command_error(st_command* command, uint32_t error)
1 by brian
clean slate
792
{
793
  if (error != 0)
794
  {
795
    if (command->abort_on_error)
2318.5.2 by Olaf van der Spek
Refactor
796
      die("command \"%.*s\" failed with error %d", command->first_word_len, command->query, error);
797
    for (uint32_t i= 0; i < command->expected_errors.count; i++)
1 by brian
clean slate
798
    {
2318.5.2 by Olaf van der Spek
Refactor
799
      if (command->expected_errors.err[i].type == ERR_ERRNO &&
800
          command->expected_errors.err[i].code.errnum == error)
1 by brian
clean slate
801
      {
142.1.1 by Patrick
Removing DBUG from client
802
        return;
1 by brian
clean slate
803
      }
804
    }
805
    die("command \"%.*s\" failed with wrong error: %d",
806
        command->first_word_len, command->query, error);
807
  }
808
  else if (command->expected_errors.err[0].type == ERR_ERRNO &&
809
           command->expected_errors.err[0].code.errnum != 0)
810
  {
811
    /* Error code we wanted was != 0, i.e. not an expected success */
812
    die("command \"%.*s\" succeeded - should have failed with errno %d...",
813
        command->first_word_len, command->query,
814
        command->expected_errors.err[0].code.errnum);
815
  }
816
}
817
818
static void cleanup_and_exit(int exit_code)
819
{
2318.4.12 by Olaf van der Spek
Refactor
820
  if (!silent) 
821
  {
822
    switch (exit_code) 
823
    {
1 by brian
clean slate
824
    case 1:
825
      printf("not ok\n");
826
      break;
827
    case 0:
828
      printf("ok\n");
829
      break;
830
    case 62:
831
      printf("skipped\n");
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
832
      break;
1 by brian
clean slate
833
    default:
834
      printf("unknown exit code: %d\n", exit_code);
2318.4.12 by Olaf van der Spek
Refactor
835
      assert(false);
1 by brian
clean slate
836
    }
837
  }
838
  exit(exit_code);
839
}
840
841
void die(const char *fmt, ...)
842
{
843
  /*
844
    Protect against dying twice
845
    first time 'die' is called, try to write log files
846
    second time, just exit
847
  */
2318.5.37 by Olaf van der Spek
Refactor
848
  static bool dying= false;
1 by brian
clean slate
849
  if (dying)
850
    cleanup_and_exit(1);
2318.5.37 by Olaf van der Spek
Refactor
851
  dying= true;
1 by brian
clean slate
852
853
  /* Print the error message */
206.3.1 by Patrick Galbraith
Most everything working with client rename
854
  fprintf(stderr, "drizzletest: ");
2151.2.27 by Olaf van der Spek
refactor
855
  if (cur_file && cur_file != file_stack.data())
2318.5.37 by Olaf van der Spek
Refactor
856
    fprintf(stderr, "In included file \"%s\": ", cur_file->file_name);
1 by brian
clean slate
857
  if (start_lineno > 0)
858
    fprintf(stderr, "At line %u: ", start_lineno);
859
  if (fmt)
860
  {
2318.5.37 by Olaf van der Spek
Refactor
861
    va_list args;
1 by brian
clean slate
862
    va_start(args, fmt);
863
    vfprintf(stderr, fmt, args);
864
    va_end(args);
865
  }
866
  else
867
    fprintf(stderr, "unknown error");
868
  fprintf(stderr, "\n");
869
  fflush(stderr);
870
871
  /* Show results from queries just before failure */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
872
  if (ds_res.length() && opt_tail_lines)
1 by brian
clean slate
873
  {
874
    int tail_lines= opt_tail_lines;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
875
    const char* show_from= ds_res.c_str() + ds_res.length() - 1;
2318.5.3 by Olaf van der Spek
Refactor
876
    while (show_from > ds_res.c_str() && tail_lines > 0 )
1 by brian
clean slate
877
    {
878
      show_from--;
879
      if (*show_from == '\n')
880
        tail_lines--;
881
    }
882
    fprintf(stderr, "\nThe result from queries just before the failure was:\n");
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
883
    if (show_from > ds_res.c_str())
1 by brian
clean slate
884
      fprintf(stderr, "< snip >");
885
    fprintf(stderr, "%s", show_from);
886
    fflush(stderr);
887
  }
888
889
  /* Dump the result that has been accumulated so far to .log file */
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
890
  if (! result_file_name.empty() && ds_res.length())
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
891
    dump_result_to_log_file(ds_res.c_str(), ds_res.length());
1 by brian
clean slate
892
893
  /* Dump warning messages */
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
894
  if (! result_file_name.empty() && ds_warning_messages.length())
1 by brian
clean slate
895
    dump_warning_messages();
896
897
  /*
898
    Help debugging by displaying any warnings that might have
899
    been produced prior to the error
900
  */
901
  if (cur_con)
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
902
  {
2318.5.26 by Olaf van der Spek
Refactor
903
    show_warnings_before_error(*cur_con);
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
904
  }
1 by brian
clean slate
905
906
  cleanup_and_exit(1);
907
}
908
909
910
void abort_not_supported_test(const char *fmt, ...)
911
{
912
  va_list args;
2318.5.2 by Olaf van der Spek
Refactor
913
  st_test_file* err_file= cur_file;
142.1.1 by Patrick
Removing DBUG from client
914
1 by brian
clean slate
915
916
  /* Print include filestack */
917
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
2151.2.27 by Olaf van der Spek
refactor
918
          file_stack[0].file_name);
1 by brian
clean slate
919
  fprintf(stderr, "Detected in file %s at line %d\n",
920
          err_file->file_name, err_file->lineno);
2151.2.27 by Olaf van der Spek
refactor
921
  while (err_file != file_stack.data())
1 by brian
clean slate
922
  {
923
    err_file--;
924
    fprintf(stderr, "included from %s at line %d\n",
925
            err_file->file_name, err_file->lineno);
926
  }
927
928
  /* Print error message */
929
  va_start(args, fmt);
930
  if (fmt)
931
  {
932
    fprintf(stderr, "reason: ");
933
    vfprintf(stderr, fmt, args);
934
    fprintf(stderr, "\n");
935
    fflush(stderr);
936
  }
937
  va_end(args);
938
939
  cleanup_and_exit(62);
940
}
941
942
943
void verbose_msg(const char *fmt, ...)
944
{
945
  if (!verbose)
142.1.1 by Patrick
Removing DBUG from client
946
    return;
2318.5.2 by Olaf van der Spek
Refactor
947
  va_list args;
1 by brian
clean slate
948
  va_start(args, fmt);
206.3.1 by Patrick Galbraith
Most everything working with client rename
949
  fprintf(stderr, "drizzletest: ");
2151.2.27 by Olaf van der Spek
refactor
950
  if (cur_file && cur_file != file_stack.data())
2318.5.2 by Olaf van der Spek
Refactor
951
    fprintf(stderr, "In included file \"%s\": ", cur_file->file_name);
1 by brian
clean slate
952
  if (start_lineno != 0)
953
    fprintf(stderr, "At line %u: ", start_lineno);
954
  vfprintf(stderr, fmt, args);
955
  fprintf(stderr, "\n");
956
  va_end(args);
957
}
958
959
960
void warning_msg(const char *fmt, ...)
961
{
962
  va_list args;
963
  char buff[512];
964
  size_t len;
142.1.1 by Patrick
Removing DBUG from client
965
1 by brian
clean slate
966
  va_start(args, fmt);
2318.6.9 by Olaf van der Spek
Refactor
967
  ds_warning_messages += "drizzletest: ";
1 by brian
clean slate
968
  if (start_lineno != 0)
969
  {
2318.6.9 by Olaf van der Spek
Refactor
970
    ds_warning_messages += "Warning detected ";
2151.2.27 by Olaf van der Spek
refactor
971
    if (cur_file && cur_file != file_stack.data())
1 by brian
clean slate
972
    {
2318.6.8 by Olaf van der Spek
Refactor
973
      len= snprintf(buff, sizeof(buff), "in included file %s ", cur_file->file_name);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
974
      ds_warning_messages.append(buff, len);
1 by brian
clean slate
975
    }
2318.6.8 by Olaf van der Spek
Refactor
976
    len= snprintf(buff, sizeof(buff), "at line %d: ", start_lineno);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
977
    ds_warning_messages.append(buff, len);
1 by brian
clean slate
978
  }
979
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
980
  len= vsnprintf(buff, sizeof(buff), fmt, args);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
981
  ds_warning_messages.append(buff, len);
1 by brian
clean slate
982
2318.6.9 by Olaf van der Spek
Refactor
983
  ds_warning_messages += "\n";
1 by brian
clean slate
984
  va_end(args);
985
142.1.1 by Patrick
Removing DBUG from client
986
  return;
1 by brian
clean slate
987
}
988
989
990
void log_msg(const char *fmt, ...)
991
{
992
  va_list args;
993
  char buff[1024];
994
995
  va_start(args, fmt);
2318.4.13 by Olaf van der Spek
Refactor
996
  size_t len= vsnprintf(buff, sizeof(buff)-1, fmt, args);
1 by brian
clean slate
997
  va_end(args);
998
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
999
  ds_res.append(buff, len);
2318.6.9 by Olaf van der Spek
Refactor
1000
  ds_res += "\n";
1 by brian
clean slate
1001
}
1002
1003
1004
/*
1005
  Read a file and append it to ds
1006
1007
  SYNOPSIS
1008
  cat_file
1009
  ds - pointer to dynamic string where to add the files content
1010
  filename - name of the file to read
1011
1012
*/
1013
2318.5.22 by Olaf van der Spek
Refactor
1014
static void cat_file(string& ds, const char* filename)
1 by brian
clean slate
1015
{
2318.4.13 by Olaf van der Spek
Refactor
1016
  int fd= internal::my_open(filename, O_RDONLY, MYF(0));
1017
  if (fd < 0)
1 by brian
clean slate
1018
    die("Failed to open file '%s'", filename);
2318.4.13 by Olaf van der Spek
Refactor
1019
  char buff[512];
2318.5.3 by Olaf van der Spek
Refactor
1020
  while (uint32_t len= internal::my_read(fd, (unsigned char*)&buff, sizeof(buff), MYF(0)))
1 by brian
clean slate
1021
  {
1022
    char *p= buff, *start= buff;
1023
    while (p < buff+len)
1024
    {
1025
      /* Convert cr/lf to lf */
1026
      if (*p == '\r' && *(p+1) && *(p+1)== '\n')
1027
      {
1028
        /* Add fake newline instead of cr and output the line */
1029
        *p= '\n';
1030
        p++; /* Step past the "fake" newline */
2318.5.22 by Olaf van der Spek
Refactor
1031
        ds.append(start, p - start);
1 by brian
clean slate
1032
        p++; /* Step past the "fake" newline */
1033
        start= p;
1034
      }
1035
      else
1036
        p++;
1037
    }
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1038
    /* Output any chars that might be left */
2318.5.22 by Olaf van der Spek
Refactor
1039
    ds.append(start, p - start);
1 by brian
clean slate
1040
  }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1041
  internal::my_close(fd, MYF(0));
1 by brian
clean slate
1042
}
1043
1044
1045
/*
1046
  Run the specified command with popen
1047
1048
  SYNOPSIS
1049
  run_command
1050
  cmd - command to execute(should be properly quoted
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1051
  result - pointer to string where to store the result
1 by brian
clean slate
1052
1053
*/
1054
2318.4.13 by Olaf van der Spek
Refactor
1055
static int run_command(const char* cmd, string& result)
1 by brian
clean slate
1056
{
2318.4.13 by Olaf van der Spek
Refactor
1057
  FILE* res_file= popen(cmd, "r");
1058
  if (not res_file)
1059
    die("popen(\"%s\", \"r\") failed", cmd);
1060
1 by brian
clean slate
1061
  char buf[512]= {0};
1062
  while (fgets(buf, sizeof(buf), res_file))
1063
  {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1064
    /* Save the output of this command in the supplied string */
2318.4.13 by Olaf van der Spek
Refactor
1065
    result.append(buf);
1 by brian
clean slate
1066
  }
2318.4.13 by Olaf van der Spek
Refactor
1067
  int error= pclose(res_file);
1 by brian
clean slate
1068
  return WEXITSTATUS(error);
1069
}
1070
1071
1072
/*
1073
  Run the specified tool with variable number of arguments
1074
1075
  SYNOPSIS
1076
  run_tool
1077
  tool_path - the name of the tool to run
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1078
  result - pointer to dynamic string where to store the result
1 by brian
clean slate
1079
  ... - variable number of arguments that will be properly
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1080
  quoted and appended after the tool's name
1 by brian
clean slate
1081
1082
*/
1083
2318.4.13 by Olaf van der Spek
Refactor
1084
static int run_tool(const char *tool_path, string& result, ...)
1 by brian
clean slate
1085
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1086
  string ds_cmdline;
482.1.1 by Monty Taylor
Fix for drizzletest crash from Paul McCullagh. (Fixes #279304)
1087
  append_os_quoted(&ds_cmdline, tool_path, NULL);
2318.6.9 by Olaf van der Spek
Refactor
1088
  ds_cmdline += " ";
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1089
2318.4.13 by Olaf van der Spek
Refactor
1090
  va_list args;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1091
  va_start(args, result);
2318.4.13 by Olaf van der Spek
Refactor
1092
  while (const char* arg= va_arg(args, char *))
1 by brian
clean slate
1093
  {
1094
    /* Options should be os quoted */
1095
    if (strncmp(arg, "--", 2) == 0)
461 by Monty Taylor
Removed NullS. bu-bye.
1096
      append_os_quoted(&ds_cmdline, arg, NULL);
1 by brian
clean slate
1097
    else
2318.6.9 by Olaf van der Spek
Refactor
1098
      ds_cmdline += arg;
1099
    ds_cmdline += " ";
1 by brian
clean slate
1100
  }
1101
1102
  va_end(args);
1103
2318.4.13 by Olaf van der Spek
Refactor
1104
  return run_command(ds_cmdline.c_str(), result);
1 by brian
clean slate
1105
}
1106
1107
1108
/*
1109
  Show the diff of two files using the systems builtin diff
1110
  command. If no such diff command exist, just dump the content
1111
  of the two files and inform about how to get "diff"
1112
1113
  SYNOPSIS
1114
  show_diff
1115
  ds - pointer to dynamic string where to add the diff(may be NULL)
1116
  filename1 - name of first file
1117
  filename2 - name of second file
1118
1119
*/
1120
2318.5.23 by Olaf van der Spek
Refactor
1121
static void show_diff(string* ds, const char* filename1, const char* filename2)
1 by brian
clean slate
1122
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1123
  string ds_tmp;
1 by brian
clean slate
1124
1125
  /* First try with unified diff */
1126
  if (run_tool("diff",
2318.4.13 by Olaf van der Spek
Refactor
1127
               ds_tmp, /* Get output from diff in ds_tmp */
1 by brian
clean slate
1128
               "-u",
1129
               filename1,
1130
               filename2,
1131
               "2>&1",
1132
               NULL) > 1) /* Most "diff" tools return >1 if error */
1133
  {
1134
1135
    /* Fallback to context diff with "diff -c" */
1136
    if (run_tool("diff",
2318.4.13 by Olaf van der Spek
Refactor
1137
                 ds_tmp, /* Get output from diff in ds_tmp */
1 by brian
clean slate
1138
                 "-c",
1139
                 filename1,
1140
                 filename2,
1141
                 "2>&1",
1142
                 NULL) > 1) /* Most "diff" tools return >1 if error */
1143
    {
1144
      /*
1145
        Fallback to dump both files to result file and inform
1146
        about installing "diff"
1147
      */
2318.4.14 by Olaf van der Spek
Refactor
1148
      ds_tmp=
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1149
                    "\n"
1150
                    "The two files differ but it was not possible to execute 'diff' in\n"
1151
                    "order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
2318.4.14 by Olaf van der Spek
Refactor
1152
                    "Instead the whole content of the two files was shown for you to diff manually. ;)\n"
1153
                    "\n"
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1154
                    "To get a better report you should install 'diff' on your system, which you\n"
1155
                    "for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
2318.4.14 by Olaf van der Spek
Refactor
1156
                    "\n";
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1157
2318.6.9 by Olaf van der Spek
Refactor
1158
      ds_tmp += " --- ";
1159
      ds_tmp += filename1;
1160
      ds_tmp += " >>>\n";
2318.5.22 by Olaf van der Spek
Refactor
1161
      cat_file(ds_tmp, filename1);
2318.6.9 by Olaf van der Spek
Refactor
1162
      ds_tmp += "<<<\n --- ";
1163
      ds_tmp += filename1;
1164
      ds_tmp += " >>>\n";
2318.5.22 by Olaf van der Spek
Refactor
1165
      cat_file(ds_tmp, filename2);
2318.6.9 by Olaf van der Spek
Refactor
1166
      ds_tmp += "<<<<\n";
1 by brian
clean slate
1167
    }
1168
  }
1169
1170
  if (ds)
1171
  {
1172
    /* Add the diff to output */
2318.4.14 by Olaf van der Spek
Refactor
1173
    *ds += ds_tmp;
1 by brian
clean slate
1174
  }
1175
  else
1176
  {
1177
    /* Print diff directly to stdout */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1178
    fprintf(stderr, "%s\n", ds_tmp.c_str());
1 by brian
clean slate
1179
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
1180
1 by brian
clean slate
1181
}
1182
2318.4.14 by Olaf van der Spek
Refactor
1183
enum compare_files_result_enum 
1184
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1185
  RESULT_OK= 0,
1186
  RESULT_CONTENT_MISMATCH= 1,
1187
  RESULT_LENGTH_MISMATCH= 2
1 by brian
clean slate
1188
};
1189
1190
/*
1191
  Compare two files, given a fd to the first file and
1192
  name of the second file
1193
1194
  SYNOPSIS
1195
  compare_files2
1196
  fd - Open file descriptor of the first file
1197
  filename2 - Name of second file
1198
1199
  RETURN VALUES
1200
  According to the values in "compare_files_result_enum"
1201
1202
*/
1203
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
1204
static int compare_files2(int fd, const char* filename2)
1 by brian
clean slate
1205
{
1206
  int error= RESULT_OK;
893 by Brian Aker
First pass of stripping uint
1207
  uint32_t len, len2;
1 by brian
clean slate
1208
  char buff[512], buff2[512];
685.1.23 by Monty Taylor
Hacked in one more distcheck fix.
1209
  const char *fname= filename2;
685.1.26 by Monty Taylor
Fixed a small problem when running NOT in a VPATH build.
1210
  string tmpfile;
1 by brian
clean slate
1211
2318.4.14 by Olaf van der Spek
Refactor
1212
  int fd2= internal::my_open(fname, O_RDONLY, MYF(0));
1213
  if (fd2 < 0)
1 by brian
clean slate
1214
  {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1215
    internal::my_close(fd, MYF(0));
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
1216
    if (! opt_testdir.empty())
685.1.23 by Monty Taylor
Hacked in one more distcheck fix.
1217
    {
685.1.26 by Monty Taylor
Fixed a small problem when running NOT in a VPATH build.
1218
      tmpfile= opt_testdir;
685.1.23 by Monty Taylor
Hacked in one more distcheck fix.
1219
      if (tmpfile[tmpfile.length()] != '/')
2318.6.9 by Olaf van der Spek
Refactor
1220
        tmpfile += "/";
1221
      tmpfile += filename2;
685.1.23 by Monty Taylor
Hacked in one more distcheck fix.
1222
      fname= tmpfile.c_str();
1223
    }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1224
    if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
685.1.23 by Monty Taylor
Hacked in one more distcheck fix.
1225
    {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1226
      internal::my_close(fd, MYF(0));
685.1.23 by Monty Taylor
Hacked in one more distcheck fix.
1227
    
1228
      die("Failed to open second file: '%s'", fname);
1229
    }
1 by brian
clean slate
1230
  }
2318.5.3 by Olaf van der Spek
Refactor
1231
  while ((len= internal::my_read(fd, (unsigned char*)&buff,
1 by brian
clean slate
1232
                      sizeof(buff), MYF(0))) > 0)
1233
  {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1234
    if ((len2= internal::my_read(fd2, (unsigned char*)&buff2,
1 by brian
clean slate
1235
                       sizeof(buff2), MYF(0))) < len)
1236
    {
1237
      /* File 2 was smaller */
1238
      error= RESULT_LENGTH_MISMATCH;
1239
      break;
1240
    }
1241
    if (len2 > len)
1242
    {
1243
      /* File 1 was smaller */
1244
      error= RESULT_LENGTH_MISMATCH;
1245
      break;
1246
    }
1247
    if ((memcmp(buff, buff2, len)))
1248
    {
1249
      /* Content of this part differed */
1250
      error= RESULT_CONTENT_MISMATCH;
1251
      break;
1252
    }
1253
  }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1254
  if (!error && internal::my_read(fd2, (unsigned char*)&buff2,
1 by brian
clean slate
1255
                        sizeof(buff2), MYF(0)) > 0)
1256
  {
1257
    /* File 1 was smaller */
1258
    error= RESULT_LENGTH_MISMATCH;
1259
  }
1260
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1261
  internal::my_close(fd2, MYF(0));
1 by brian
clean slate
1262
1263
  return error;
1264
}
1265
1266
1267
/*
1268
  Compare two files, given their filenames
1269
1270
  SYNOPSIS
1271
  compare_files
1272
  filename1 - Name of first file
1273
  filename2 - Name of second file
1274
1275
  RETURN VALUES
1276
  See 'compare_files2'
1277
1278
*/
1279
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
1280
static int compare_files(const char* filename1, const char* filename2)
1 by brian
clean slate
1281
{
2241.2.10 by Olaf van der Spek
Refactor
1282
  int fd= internal::my_open(filename1, O_RDONLY, MYF(0));
1283
  if (fd < 0)
1 by brian
clean slate
1284
    die("Failed to open first file: '%s'", filename1);
2241.2.10 by Olaf van der Spek
Refactor
1285
  int error= compare_files2(fd, filename2);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1286
  internal::my_close(fd, MYF(0));
1 by brian
clean slate
1287
  return error;
1288
}
1289
1290
1291
/*
1292
  Compare content of the string in ds to content of file fname
1293
1294
  SYNOPSIS
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1295
  string_cmp
1 by brian
clean slate
1296
  ds - Dynamic string containing the string o be compared
1297
  fname - Name of file to compare with
1298
1299
  RETURN VALUES
1300
  See 'compare_files2'
1301
*/
1302
2318.5.23 by Olaf van der Spek
Refactor
1303
static int string_cmp(const string& ds, const char *fname)
1 by brian
clean slate
1304
{
1305
  char temp_file_path[FN_REFLEN];
1306
2318.4.14 by Olaf van der Spek
Refactor
1307
  int fd= internal::create_temp_file(temp_file_path, TMPDIR, "tmp", MYF(MY_WME));
1308
  if (fd < 0)
1 by brian
clean slate
1309
    die("Failed to create temporary file for ds");
1310
1311
  /* Write ds to temporary file and set file pos to beginning*/
2318.5.23 by Olaf van der Spek
Refactor
1312
  if (internal::my_write(fd, (unsigned char *) ds.data(), ds.length(), MYF(MY_FNABP | MY_WME)) ||
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
1313
      lseek(fd, 0, SEEK_SET) == MY_FILEPOS_ERROR)
1 by brian
clean slate
1314
  {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1315
    internal::my_close(fd, MYF(0));
1 by brian
clean slate
1316
    /* Remove the temporary file */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1317
    internal::my_delete(temp_file_path, MYF(0));
1 by brian
clean slate
1318
    die("Failed to write file '%s'", temp_file_path);
1319
  }
1320
2318.4.14 by Olaf van der Spek
Refactor
1321
  int error= compare_files2(fd, fname);
1 by brian
clean slate
1322
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1323
  internal::my_close(fd, MYF(0));
1 by brian
clean slate
1324
  /* Remove the temporary file */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1325
  internal::my_delete(temp_file_path, MYF(0));
1 by brian
clean slate
1326
2318.4.14 by Olaf van der Spek
Refactor
1327
  return error;
1 by brian
clean slate
1328
}
1329
1330
1331
/*
1332
  Check the content of ds against result file
1333
1334
  SYNOPSIS
1335
  check_result
1336
  ds - content to be checked
1337
1338
  RETURN VALUES
1339
  error - the function will not return
1340
1341
*/
1342
2318.5.23 by Olaf van der Spek
Refactor
1343
static void check_result(string& ds)
1 by brian
clean slate
1344
{
1345
  const char* mess= "Result content mismatch\n";
1346
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
1347
  if (access(result_file_name.c_str(), F_OK) != 0)
1348
    die("The specified result file does not exist: '%s'", result_file_name.c_str());
1349
2318.4.12 by Olaf van der Spek
Refactor
1350
  switch (string_cmp(ds, result_file_name.c_str())) 
1351
  {
1 by brian
clean slate
1352
  case RESULT_OK:
1353
    break; /* ok */
1354
  case RESULT_LENGTH_MISMATCH:
1355
    mess= "Result length mismatch\n";
1356
    /* Fallthrough */
1357
  case RESULT_CONTENT_MISMATCH:
1358
  {
1359
    /*
1360
      Result mismatched, dump results to .reject file
1361
      and then show the diff
1362
    */
1363
    char reject_file[FN_REFLEN];
1364
    size_t reject_length;
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
1365
    internal::dirname_part(reject_file, result_file_name.c_str(), &reject_length);
1 by brian
clean slate
1366
1367
    if (access(reject_file, W_OK) == 0)
1368
    {
1369
      /* Result file directory is writable, save reject file there */
2318.4.14 by Olaf van der Spek
Refactor
1370
      internal::fn_format(reject_file, result_file_name.c_str(), NULL, ".reject", MY_REPLACE_EXT);
1 by brian
clean slate
1371
    }
1372
    else
1373
    {
1374
      /* Put reject file in opt_logdir */
2318.4.14 by Olaf van der Spek
Refactor
1375
      internal::fn_format(reject_file, result_file_name.c_str(), opt_logdir.c_str(), ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1 by brian
clean slate
1376
    }
2318.5.23 by Olaf van der Spek
Refactor
1377
    str_to_file(reject_file, ds.data(), ds.length());
1 by brian
clean slate
1378
2318.5.23 by Olaf van der Spek
Refactor
1379
    ds.erase(); /* Don't create a .log file */
1 by brian
clean slate
1380
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
1381
    show_diff(NULL, result_file_name.c_str(), reject_file);
512.1.1 by Stewart Smith
a few warnings that show up on ubuntu 8.10: unchecked return codes, not fromat string
1382
    die("%s",mess);
1 by brian
clean slate
1383
    break;
1384
  }
1385
  default: /* impossible */
1386
    die("Unknown error code from dyn_string_cmp()");
1387
  }
1388
}
1389
1390
1391
/*
1392
  Check the content of ds against a require file
1393
  If match fails, abort the test with special error code
1394
  indicating that test is not supported
1395
1396
  SYNOPSIS
1397
  check_require
1398
  ds - content to be checked
1399
  fname - name of file to check against
1400
1401
  RETURN VALUES
1402
  error - the function will not return
1403
1404
*/
1405
2318.5.23 by Olaf van der Spek
Refactor
1406
static void check_require(const string& ds, const string& fname)
1 by brian
clean slate
1407
{
1134.1.3 by Monty Taylor
Fixed up drizzletest.cc
1408
  if (string_cmp(ds, fname.c_str()))
1 by brian
clean slate
1409
  {
1410
    char reason[FN_REFLEN];
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1411
    internal::fn_format(reason, fname.c_str(), "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1 by brian
clean slate
1412
    abort_not_supported_test("Test requires: '%s'", reason);
1413
  }
1414
}
1415
1416
1417
/*
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1418
  Remove surrounding chars from string
1 by brian
clean slate
1419
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1420
  Return 1 if first character is found but not last
1 by brian
clean slate
1421
*/
1422
static int strip_surrounding(char* str, char c1, char c2)
1423
{
1424
  char* ptr= str;
1425
1426
  /* Check if the first non space character is c1 */
2445.1.3 by Olaf van der Spek
Refactor
1427
  while (*ptr && charset_info->isspace(*ptr))
1 by brian
clean slate
1428
    ptr++;
1429
  if (*ptr == c1)
1430
  {
1431
    /* Replace it with a space */
1432
    *ptr= ' ';
1433
1434
    /* Last non space charecter should be c2 */
376 by Brian Aker
strend remove
1435
    ptr= strchr(str, '\0')-1;
2445.1.3 by Olaf van der Spek
Refactor
1436
    while (*ptr && charset_info->isspace(*ptr))
1 by brian
clean slate
1437
      ptr--;
1438
    if (*ptr == c2)
1439
    {
1440
      /* Replace it with \0 */
1441
      *ptr= 0;
1442
    }
1443
    else
1444
    {
1445
      /* Mismatch detected */
1446
      return 1;
1447
    }
1448
  }
1449
  return 0;
1450
}
1451
1452
2318.4.6 by Olaf van der Spek
Refactor
1453
static void strip_parentheses(st_command* command)
1 by brian
clean slate
1454
{
1455
  if (strip_surrounding(command->first_argument, '(', ')'))
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1456
    die("%.*s - argument list started with '%c' must be ended with '%c'",
1457
        command->first_word_len, command->query, '(', ')');
1 by brian
clean slate
1458
}
1459
1460
1461
1462
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1463
              int val_len)
1464
{
1465
  if (!name_len && name)
1466
    name_len = strlen(name);
1467
  if (!val_len && val)
1468
    val_len = strlen(val) ;
2151.2.25 by Olaf van der Spek
refactor
1469
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
1 by brian
clean slate
1470
2151.2.25 by Olaf van der Spek
refactor
1471
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
1 by brian
clean slate
1472
  tmp_var->alloced = (v == 0);
1473
2151.2.25 by Olaf van der Spek
refactor
1474
  int val_alloc_len = val_len + 16; /* room to grow */
1475
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
1 by brian
clean slate
1476
1477
  memcpy(tmp_var->name, name, name_len);
1478
  if (val)
1479
  {
1480
    memcpy(tmp_var->str_val, val, val_len);
1481
    tmp_var->str_val[val_len]= 0;
1482
  }
1483
  tmp_var->name_len = name_len;
1484
  tmp_var->str_val_len = val_len;
1485
  tmp_var->alloced_len = val_alloc_len;
2151.2.25 by Olaf van der Spek
refactor
1486
  tmp_var->int_val = val ? atoi(val) : 0;
1487
  tmp_var->int_dirty = false;
1 by brian
clean slate
1488
  tmp_var->env_s = 0;
1489
  return tmp_var;
1490
}
1491
1492
VAR* var_from_env(const char *name, const char *def_val)
1493
{
2151.2.26 by Olaf van der Spek
refactor
1494
  const char *tmp= getenv(name);
1495
  if (!tmp)
1 by brian
clean slate
1496
    tmp = def_val;
2151.2.26 by Olaf van der Spek
refactor
1497
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
1 by brian
clean slate
1498
}
1499
143 by Brian Aker
Bool cleanup.
1500
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1501
             bool ignore_not_existing)
1 by brian
clean slate
1502
{
1503
  int digit;
1504
  VAR *v;
1505
  if (*var_name != '$')
1506
    goto err;
1507
  digit = *++var_name - '0';
1508
  if (digit < 0 || digit >= 10)
1509
  {
1510
    const char *save_var_name = var_name, *end;
893 by Brian Aker
First pass of stripping uint
1511
    uint32_t length;
1 by brian
clean slate
1512
    end = (var_name_end) ? *var_name_end : 0;
2445.1.3 by Olaf van der Spek
Refactor
1513
    while (charset_info->isvar(*var_name) && var_name != end)
1 by brian
clean slate
1514
      var_name++;
1515
    if (var_name == save_var_name)
1516
    {
1517
      if (ignore_not_existing)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1518
        return(0);
1 by brian
clean slate
1519
      die("Empty variable");
1520
    }
895 by Brian Aker
Completion (?) of uint conversion.
1521
    length= (uint32_t) (var_name - save_var_name);
1 by brian
clean slate
1522
    if (length >= MAX_VAR_NAME_LENGTH)
1523
      die("Too long variable name: %s", save_var_name);
1524
1126.15.5 by Monty Taylor
Replaced drizzletests's copy of HASH with drizzled::hash_map
1525
    string save_var_name_str(save_var_name, length);
2192.5.8 by Olaf van der Spek
Use ptr instead of i
1526
    if (var_hash_t::mapped_type* ptr= find_ptr(var_hash, save_var_name_str))
1527
      v= *ptr;
2192.5.1 by Olaf van der Spek
Use find_ptr
1528
    else
1 by brian
clean slate
1529
    {
1530
      char buff[MAX_VAR_NAME_LENGTH+1];
629.5.5 by Toru Maesaka
Fifth pass of replacing MySQL's strmake() with libc calls
1531
      strncpy(buff, save_var_name, length);
1532
      buff[length]= '\0';
1 by brian
clean slate
1533
      v= var_from_env(buff, "");
1534
    }
206.3.1 by Patrick Galbraith
Most everything working with client rename
1535
    var_name--;  /* Point at last character */
1 by brian
clean slate
1536
  }
1537
  else
2151.2.22 by Olaf van der Spek
refactor
1538
    v = &var_reg[digit];
1 by brian
clean slate
1539
1540
  if (!raw && v->int_dirty)
1541
  {
1542
    sprintf(v->str_val, "%d", v->int_val);
1543
    v->int_dirty = 0;
1544
    v->str_val_len = strlen(v->str_val);
1545
  }
1546
  if (var_name_end)
1547
    *var_name_end = var_name  ;
142.1.1 by Patrick
Removing DBUG from client
1548
  return(v);
1 by brian
clean slate
1549
err:
1550
  if (var_name_end)
1551
    *var_name_end = 0;
1552
  die("Unsupported variable name: %s", var_name);
142.1.1 by Patrick
Removing DBUG from client
1553
  return(0);
1 by brian
clean slate
1554
}
1555
1556
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
1557
static VAR *var_obtain(const char *name, int len)
1 by brian
clean slate
1558
{
1126.15.5 by Monty Taylor
Replaced drizzletests's copy of HASH with drizzled::hash_map
1559
  string var_name(name, len);
2192.5.8 by Olaf van der Spek
Use ptr instead of i
1560
  if (var_hash_t::mapped_type* ptr= find_ptr(var_hash, var_name))
1561
    return *ptr;
2151.2.24 by Olaf van der Spek
refactor
1562
  return var_hash[var_name] = var_init(0, name, len, "", 0);
1 by brian
clean slate
1563
}
1564
1565
1566
/*
1567
  - if variable starts with a $ it is regarded as a local test varable
1568
  - if not it is treated as a environment variable, and the corresponding
1569
  environment variable will be updated
1570
*/
1571
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
1572
static void var_set(const char *var_name, const char *var_name_end,
1573
                    const char *var_val, const char *var_val_end)
1 by brian
clean slate
1574
{
1575
  int digit, env_var= 0;
1576
  VAR *v;
1577
1578
  if (*var_name != '$')
1579
    env_var= 1;
1580
  else
1581
    var_name++;
1582
1583
  digit= *var_name - '0';
1584
  if (!(digit < 10 && digit >= 0))
1585
  {
895 by Brian Aker
Completion (?) of uint conversion.
1586
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1 by brian
clean slate
1587
  }
1588
  else
2151.2.22 by Olaf van der Spek
refactor
1589
    v= &var_reg[digit];
1 by brian
clean slate
1590
1591
  eval_expr(v, var_val, (const char**) &var_val_end);
1592
1593
  if (env_var)
1594
  {
1595
    char buf[1024], *old_env_s= v->env_s;
1596
    if (v->int_dirty)
1597
    {
1598
      sprintf(v->str_val, "%d", v->int_val);
1599
      v->int_dirty= 0;
1600
      v->str_val_len= strlen(v->str_val);
1601
    }
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
1602
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1603
             v->name_len, v->name,
1604
             v->str_val_len, v->str_val);
2318.4.5 by Olaf van der Spek
Refactor
1605
    v->env_s= strdup(buf);
1 by brian
clean slate
1606
    putenv(v->env_s);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1607
    free(old_env_s);
1 by brian
clean slate
1608
  }
142.1.1 by Patrick
Removing DBUG from client
1609
  return;
1 by brian
clean slate
1610
}
1611
1612
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
1613
static void var_set_string(const char* name, const char* value)
1 by brian
clean slate
1614
{
1615
  var_set(name, name + strlen(name), value, value + strlen(value));
1616
}
1617
1618
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
1619
static void var_set_int(const char* name, int value)
1 by brian
clean slate
1620
{
1621
  char buf[21];
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
1622
  snprintf(buf, sizeof(buf), "%d", value);
1 by brian
clean slate
1623
  var_set_string(name, buf);
1624
}
1625
1626
1627
/*
1628
  Store an integer (typically the returncode of the last SQL)
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
1629
  statement in the drizzletest builtin variable $drizzleclient_errno
1 by brian
clean slate
1630
*/
1631
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
1632
static void var_set_errno(int sql_errno)
1 by brian
clean slate
1633
{
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
1634
  var_set_int("$drizzleclient_errno", sql_errno);
1 by brian
clean slate
1635
}
1636
1637
1638
/*
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
1639
  Update $drizzleclient_get_server_version variable with version
1 by brian
clean slate
1640
  of the currently connected server
1641
*/
1642
928.1.6 by Eric Day
All utilities done except slap.
1643
static void var_set_drizzleclient_get_server_version(drizzle_con_st *con)
1 by brian
clean slate
1644
{
928.1.6 by Eric Day
All utilities done except slap.
1645
  var_set_int("$drizzle_con_server_version", drizzle_con_server_version_number(con));
1 by brian
clean slate
1646
}
1647
1648
1649
/*
1650
  Set variable from the result of a query
1651
1652
  SYNOPSIS
1653
  var_query_set()
206.3.1 by Patrick Galbraith
Most everything working with client rename
1654
  var          variable to set from query
1 by brian
clean slate
1655
  query       start of query string to execute
1656
  query_end   end of the query string to execute
1657
1658
1659
  DESCRIPTION
1660
  let @<var_name> = `<query>`
1661
1662
  Execute the query and assign the first row of result to var as
1663
  a tab separated strings
1664
1665
  Also assign each column of the result set to
1666
  variable "$<var_name>_<column_name>"
1667
  Thus the tab separated output can be read from $<var_name> and
1668
  and each individual column can be read as $<var_name>_<col_name>
1669
1670
*/
1671
2318.5.36 by Olaf van der Spek
Refactor
1672
static void dt_query(drizzle::connection_c& con, drizzle::result_c& res, const std::string& query)
1673
{
1674
  if (drizzle_return_t ret= con.query(res, query))
1675
  {
1676
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
1677
    {
1678
      die("Error running query '%s': %d %s", query.c_str(), res.error_code(), res.error());
1679
    }
1680
    else
1681
    {
1682
      die("Error running query '%s': %d %s", query.c_str(), ret, con.error());
1683
    }
1684
  }
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
1685
2318.5.36 by Olaf van der Spek
Refactor
1686
  if (res.column_count() == 0)
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
1687
  {
2318.5.36 by Olaf van der Spek
Refactor
1688
    die("Query '%s' didn't return a result set", query.c_str());
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
1689
  }
2318.5.36 by Olaf van der Spek
Refactor
1690
}
1691
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
1692
static void var_query_set(VAR *var, const char *query, const char** query_end)
1 by brian
clean slate
1693
{
2318.5.8 by Olaf van der Spek
Refactor
1694
  const char *end = ((query_end && *query_end) ? *query_end : query + strlen(query));
2318.5.33 by Olaf van der Spek
Refactor
1695
  drizzle::connection_c& con= *cur_con;
1 by brian
clean slate
1696
1697
  while (end > query && *end != '`')
1698
    --end;
1699
  if (query == end)
1700
    die("Syntax error in query, missing '`'");
1701
  ++query;
1702
2318.5.33 by Olaf van der Spek
Refactor
1703
  string ds_query;
1 by brian
clean slate
1704
  /* Eval the query, thus replacing all environment variables */
163 by Brian Aker
Merge Monty's code.
1705
  do_eval(&ds_query, query, end, false);
1 by brian
clean slate
1706
2318.5.8 by Olaf van der Spek
Refactor
1707
  drizzle::result_c res;
2318.5.36 by Olaf van der Spek
Refactor
1708
  dt_query(con, res, ds_query);
1 by brian
clean slate
1709
2318.5.8 by Olaf van der Spek
Refactor
1710
  drizzle_row_t row= res.row_next();
1711
  if (row && row[0])
1 by brian
clean slate
1712
  {
1713
    /*
1714
      Concatenate all fields in the first row with tab in between
1715
      and assign that string to the $variable
1716
    */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1717
    string result;
2318.5.12 by Olaf van der Spek
Refactor
1718
    size_t* lengths= res.row_field_sizes();
2318.5.8 by Olaf van der Spek
Refactor
1719
    for (uint32_t i= 0; i < res.column_count(); i++)
1 by brian
clean slate
1720
    {
1721
      if (row[i])
1722
      {
1723
        /* Add column to tab separated string */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1724
        result.append(row[i], lengths[i]);
1 by brian
clean slate
1725
      }
2318.5.8 by Olaf van der Spek
Refactor
1726
      result += "\t";
1 by brian
clean slate
1727
    }
2318.5.8 by Olaf van der Spek
Refactor
1728
    end= result.c_str() + result.length() - 1;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1729
    eval_expr(var, result.c_str(), (const char**) &end);
1 by brian
clean slate
1730
  }
1731
  else
1732
    eval_expr(var, "", 0);
1733
}
1734
1735
1736
/*
1737
  Set variable from the result of a field in a query
1738
1739
  This function is useful when checking for a certain value
1740
  in the output from a query that can't be restricted to only
1741
  return some values. A very good example of that is most SHOW
1742
  commands.
1743
1744
  SYNOPSIS
1745
  var_set_query_get_value()
1746
1747
  DESCRIPTION
1748
  let $variable= query_get_value(<query to run>,<column name>,<row no>);
1749
1750
  <query to run> -    The query that should be sent to the server
1751
  <column name> -     Name of the column that holds the field be compared
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1752
  against the expected value
1 by brian
clean slate
1753
  <row no> -          Number of the row that holds the field to be
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1754
  compared against the expected value
1 by brian
clean slate
1755
1756
*/
1757
2318.4.6 by Olaf van der Spek
Refactor
1758
static void var_set_query_get_value(st_command* command, VAR *var)
1 by brian
clean slate
1759
{
1760
  int col_no= -1;
2318.5.34 by Olaf van der Spek
Refactor
1761
  drizzle::connection_c& con= *cur_con;
1 by brian
clean slate
1762
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1763
  string ds_query;
1764
  string ds_col;
1765
  string ds_row;
1 by brian
clean slate
1766
  const struct command_arg query_get_value_args[] = {
163 by Brian Aker
Merge Monty's code.
1767
    {"query", ARG_STRING, true, &ds_query, "Query to run"},
1768
    {"column name", ARG_STRING, true, &ds_col, "Name of column"},
1769
    {"row number", ARG_STRING, true, &ds_row, "Number for row"}
1 by brian
clean slate
1770
  };
1771
142.1.1 by Patrick
Removing DBUG from client
1772
1 by brian
clean slate
1773
1774
  strip_parentheses(command);
1775
  check_command_args(command, command->first_argument, query_get_value_args,
1776
                     sizeof(query_get_value_args)/sizeof(struct command_arg),
1777
                     ',');
1778
1779
  /* Convert row number to int */
2318.4.14 by Olaf van der Spek
Refactor
1780
  long row_no= atoi(ds_row.c_str());
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.
1781
  
1782
  istringstream buff(ds_row);
1783
  if ((buff >> row_no).fail())
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1784
    die("Invalid row number: '%s'", ds_row.c_str());
1 by brian
clean slate
1785
1786
  /* Remove any surrounding "'s from the query - if there is any */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1787
  // (Don't get me started on this)
2318.4.14 by Olaf van der Spek
Refactor
1788
  char* unstripped_query= strdup(ds_query.c_str());
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1789
  if (strip_surrounding(unstripped_query, '"', '"'))
1790
    die("Mismatched \"'s around query '%s'", ds_query.c_str());
2318.4.14 by Olaf van der Spek
Refactor
1791
  ds_query= unstripped_query;
1 by brian
clean slate
1792
2318.5.9 by Olaf van der Spek
Refactor
1793
  drizzle::result_c res;
2318.5.36 by Olaf van der Spek
Refactor
1794
  dt_query(con, res, ds_query);
1 by brian
clean slate
1795
1796
  {
1797
    /* Find column number from the given column name */
2318.5.9 by Olaf van der Spek
Refactor
1798
    uint32_t num_fields= res.column_count();
2318.4.14 by Olaf van der Spek
Refactor
1799
    for (uint32_t i= 0; i < num_fields; i++)
1 by brian
clean slate
1800
    {
2318.5.12 by Olaf van der Spek
Refactor
1801
      drizzle_column_st* column= res.column_next();
928.1.6 by Eric Day
All utilities done except slap.
1802
      if (strcmp(drizzle_column_name(column), ds_col.c_str()) == 0 &&
1803
          strlen(drizzle_column_name(column)) == ds_col.length())
1 by brian
clean slate
1804
      {
1805
        col_no= i;
1806
        break;
1807
      }
1808
    }
1809
    if (col_no == -1)
1810
    {
2318.5.9 by Olaf van der Spek
Refactor
1811
      die("Could not find column '%s' in the result of '%s'", ds_col.c_str(), ds_query.c_str());
1 by brian
clean slate
1812
    }
1813
  }
1814
1815
  {
1816
    /* Get the value */
1817
    long rows= 0;
1818
    const char* value= "No such row";
1819
2318.5.9 by Olaf van der Spek
Refactor
1820
    while (drizzle_row_t row= res.row_next())
1 by brian
clean slate
1821
    {
1822
      if (++rows == row_no)
1823
      {
1824
        /* Found the row to get */
2318.5.9 by Olaf van der Spek
Refactor
1825
        value= row[col_no] ? row[col_no] : "NULL";
1 by brian
clean slate
1826
        break;
1827
      }
1828
    }
1829
    eval_expr(var, value, 0);
1830
  }
1831
}
1832
1833
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
1834
static void var_copy(VAR *dest, VAR *src)
1 by brian
clean slate
1835
{
1836
  dest->int_val= src->int_val;
1837
  dest->int_dirty= src->int_dirty;
1838
1839
  /* Alloc/realloc data for str_val in dest */
670.1.2 by Monty Taylor
Removed two (foo) ? realloc(foo, len) : malloc (len) instances.
1840
  if (dest->alloced_len < src->alloced_len)
1841
  {
670.2.1 by Monty Taylor
Moved pthread keys
1842
    char *tmpptr= (char *)realloc(dest->str_val, src->alloced_len);
670.1.2 by Monty Taylor
Removed two (foo) ? realloc(foo, len) : malloc (len) instances.
1843
    dest->str_val= tmpptr;
1844
  }
1 by brian
clean slate
1845
  else
1846
    dest->alloced_len= src->alloced_len;
1847
1848
  /* Copy str_val data to dest */
1849
  dest->str_val_len= src->str_val_len;
1850
  if (src->str_val_len)
1851
    memcpy(dest->str_val, src->str_val, src->str_val_len);
1852
}
1853
1854
1855
void eval_expr(VAR *v, const char *p, const char **p_end)
1856
{
1857
  if (*p == '$')
1858
  {
2151.2.27 by Olaf van der Spek
refactor
1859
    VAR *vp= var_get(p, p_end, 0, 0);
1860
    if (vp)
1 by brian
clean slate
1861
      var_copy(v, vp);
142.1.1 by Patrick
Removing DBUG from client
1862
    return;
1 by brian
clean slate
1863
  }
1864
1865
  if (*p == '`')
1866
  {
1867
    var_query_set(v, p, p_end);
142.1.1 by Patrick
Removing DBUG from client
1868
    return;
1 by brian
clean slate
1869
  }
1870
1871
  {
1872
    /* Check if this is a "let $var= query_get_value()" */
1873
    const char* get_value_str= "query_get_value";
1874
    const size_t len= strlen(get_value_str);
1875
    if (strncmp(p, get_value_str, len)==0)
1876
    {
1134.1.3 by Monty Taylor
Fixed up drizzletest.cc
1877
      st_command command;
1 by brian
clean slate
1878
      command.query= (char*)p;
1879
      command.first_word_len= len;
1880
      command.first_argument= command.query + len;
1881
      command.end= (char*)*p_end;
1882
      var_set_query_get_value(&command, v);
142.1.1 by Patrick
Removing DBUG from client
1883
      return;
1 by brian
clean slate
1884
    }
1885
  }
1886
1887
  {
1888
    int new_val_len = (p_end && *p_end) ?
1889
      (int) (*p_end - p) : (int) strlen(p);
1890
    if (new_val_len + 1 >= v->alloced_len)
1891
    {
1892
      static int MIN_VAR_ALLOC= 32;
1893
      v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
1894
        MIN_VAR_ALLOC : new_val_len + 1;
670.1.2 by Monty Taylor
Removed two (foo) ? realloc(foo, len) : malloc (len) instances.
1895
      char *tmpptr= (char *)realloc(v->str_val, v->alloced_len+1);
1896
      v->str_val= tmpptr;
1 by brian
clean slate
1897
    }
1898
    v->str_val_len = new_val_len;
1899
    memcpy(v->str_val, p, new_val_len);
1900
    v->str_val[new_val_len] = 0;
1901
    v->int_val=atoi(p);
1902
    v->int_dirty=0;
1903
  }
142.1.1 by Patrick
Removing DBUG from client
1904
  return;
1 by brian
clean slate
1905
}
1906
1907
2318.4.5 by Olaf van der Spek
Refactor
1908
static void open_file(const char *name)
1 by brian
clean slate
1909
{
1910
  char buff[FN_REFLEN];
142.1.1 by Patrick
Removing DBUG from client
1911
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1912
  if (!internal::test_if_hard_path(name))
1 by brian
clean slate
1913
  {
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
1914
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),name);
1 by brian
clean slate
1915
    name=buff;
1916
  }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1917
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
1 by brian
clean slate
1918
2151.2.27 by Olaf van der Spek
refactor
1919
  cur_file++;
1920
  if (cur_file == &*file_stack.end())
1 by brian
clean slate
1921
    die("Source directives are nesting too deep");
910.1.3 by Brian Aker
Remove my_fopen() and key_map.cc file (thanks to Jay's lcov)
1922
  if (!(cur_file->file= fopen(buff, "r")))
1 by brian
clean slate
1923
  {
1924
    cur_file--;
1925
    die("Could not open '%s' for reading", buff);
1926
  }
2318.4.5 by Olaf van der Spek
Refactor
1927
  cur_file->file_name= strdup(buff);
1 by brian
clean slate
1928
  cur_file->lineno=1;
1929
}
1930
1931
1932
/*
1933
  Source and execute the given file
1934
1935
  SYNOPSIS
1936
  do_source()
206.3.1 by Patrick Galbraith
Most everything working with client rename
1937
  query  called command
1 by brian
clean slate
1938
1939
  DESCRIPTION
1940
  source <file_name>
1941
1942
  Open the file <file_name> and execute it
1943
1944
*/
1945
2318.4.6 by Olaf van der Spek
Refactor
1946
static void do_source(st_command* command)
1 by brian
clean slate
1947
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1948
  string ds_filename;
1 by brian
clean slate
1949
  const struct command_arg source_args[] = {
163 by Brian Aker
Merge Monty's code.
1950
    { "filename", ARG_STRING, true, &ds_filename, "File to source" }
1 by brian
clean slate
1951
  };
142.1.1 by Patrick
Removing DBUG from client
1952
1 by brian
clean slate
1953
1954
  check_command_args(command, command->first_argument, source_args,
1955
                     sizeof(source_args)/sizeof(struct command_arg),
1956
                     ' ');
1957
1958
  /*
1959
    If this file has already been sourced, don't source it again.
1960
    It's already available in the q_lines cache.
1961
  */
1962
  if (parser.current_line < (parser.read_lines - 1))
1963
    ; /* Do nothing */
1964
  else
1965
  {
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
1966
    if (! opt_testdir.empty())
685.1.22 by Monty Taylor
Added testdir setting support to drizzletest.
1967
    {
1968
      string testdir(opt_testdir);
1969
      if (testdir[testdir.length()] != '/')
2318.6.9 by Olaf van der Spek
Refactor
1970
        testdir += "/";
1971
      testdir += ds_filename;
685.1.22 by Monty Taylor
Added testdir setting support to drizzletest.
1972
      ds_filename.swap(testdir);
1973
    }
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1974
    open_file(ds_filename.c_str());
1 by brian
clean slate
1975
  }
1976
}
1977
1978
2151.2.17 by Olaf van der Spek
drizzletest refactoring
1979
static void init_builtin_echo()
1 by brian
clean slate
1980
{
1981
  builtin_echo[0]= 0;
1982
}
1983
1984
1985
/*
1986
  Replace a substring
1987
1988
  SYNOPSIS
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1989
  replace
1990
  ds_str      The string to search and perform the replace in
1991
  search_str  The string to search for
1992
  search_len  Length of the string to search for
1993
  replace_str The string to replace with
1994
  replace_len Length of the string to replace with
1 by brian
clean slate
1995
1996
  RETURN
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
1997
  0 String replaced
1998
  1 Could not find search_str in str
1 by brian
clean slate
1999
*/
2000
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2001
static int replace(string *ds_str,
297 by Brian Aker
Final ulong cleanup in clients
2002
                   const char *search_str, uint32_t search_len,
2003
                   const char *replace_str, uint32_t replace_len)
1 by brian
clean slate
2004
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2005
  string ds_tmp;
2006
  const char *start= strstr(ds_str->c_str(), search_str);
1 by brian
clean slate
2007
  if (!start)
2008
    return 1;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2009
  ds_tmp.append(ds_str->c_str(), start - ds_str->c_str());
2010
  ds_tmp.append(replace_str, replace_len);
2011
  ds_tmp.append(start + search_len);
2012
  *ds_str= ds_tmp;
1 by brian
clean slate
2013
  return 0;
2014
}
2015
2016
2017
/*
2018
  Execute given command.
2019
2020
  SYNOPSIS
2021
  do_exec()
206.3.1 by Patrick Galbraith
Most everything working with client rename
2022
  query  called command
1 by brian
clean slate
2023
2024
  DESCRIPTION
2025
  exec <command>
2026
2027
  Execute the text between exec and end of line in a subprocess.
2028
  The error code returned from the subprocess is checked against the
2029
  expected error array, previously set with the --error command.
2030
  It can thus be used to execute a command that shall fail.
2031
2032
  NOTE
206.3.1 by Patrick Galbraith
Most everything working with client rename
2033
  Although drizzletest is executed from cygwin shell, the command will be
1 by brian
clean slate
2034
  executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
206.3.1 by Patrick Galbraith
Most everything working with client rename
2035
  drizzletest commmand(s) like "remove_file" for that
1 by brian
clean slate
2036
*/
2037
2318.4.6 by Olaf van der Spek
Refactor
2038
static void do_exec(st_command* command)
1 by brian
clean slate
2039
{
2040
  int error;
2041
  char buf[512];
2042
  FILE *res_file;
2043
  char *cmd= command->first_argument;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2044
  string ds_cmd;
1 by brian
clean slate
2045
2046
  /* Skip leading space */
2445.1.3 by Olaf van der Spek
Refactor
2047
  while (*cmd && charset_info->isspace(*cmd))
1 by brian
clean slate
2048
    cmd++;
2049
  if (!*cmd)
2050
    die("Missing argument in exec");
2051
  command->last_argument= command->end;
2052
2053
  /* Eval the command, thus replacing all environment variables */
2054
  do_eval(&ds_cmd, cmd, command->end, !is_windows);
2055
2056
  /* Check if echo should be replaced with "builtin" echo */
2057
  if (builtin_echo[0] && strncmp(cmd, "echo", 4) == 0)
2058
  {
2059
    /* Replace echo with our "builtin" echo */
2060
    replace(&ds_cmd, "echo", 4, builtin_echo, strlen(builtin_echo));
2061
  }
2062
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2063
  if (!(res_file= popen(ds_cmd.c_str(), "r")) && command->abort_on_error)
1 by brian
clean slate
2064
  {
2065
    die("popen(\"%s\", \"r\") failed", command->first_argument);
2066
  }
2067
2068
  while (fgets(buf, sizeof(buf), res_file))
2069
  {
2070
    if (disable_result_log)
2071
    {
2072
      buf[strlen(buf)-1]=0;
2073
    }
2074
    else
2075
    {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2076
      replace_append(&ds_res, buf);
1 by brian
clean slate
2077
    }
2078
  }
2079
  error= pclose(res_file);
2080
  if (error > 0)
2081
  {
893 by Brian Aker
First pass of stripping uint
2082
    uint32_t status= WEXITSTATUS(error), i;
143 by Brian Aker
Bool cleanup.
2083
    bool ok= 0;
1 by brian
clean slate
2084
2085
    if (command->abort_on_error)
2086
    {
2318.5.37 by Olaf van der Spek
Refactor
2087
      log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d", ds_cmd.c_str(), error, status, errno);
1 by brian
clean slate
2088
      die("command \"%s\" failed", command->first_argument);
2089
    }
2090
2091
    for (i= 0; i < command->expected_errors.count; i++)
2092
    {
2093
      if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
2094
          (command->expected_errors.err[i].code.errnum == status))
2095
      {
2096
        ok= 1;
2097
      }
2098
    }
2099
    if (!ok)
2100
    {
2101
      die("command \"%s\" failed with wrong error: %d",
2102
          command->first_argument, status);
2103
    }
2104
  }
2105
  else if (command->expected_errors.err[0].type == ERR_ERRNO &&
2106
           command->expected_errors.err[0].code.errnum != 0)
2107
  {
2108
    /* Error code we wanted was != 0, i.e. not an expected success */
2318.5.37 by Olaf van der Spek
Refactor
2109
    log_msg("exec of '%s failed, error: %d, errno: %d", ds_cmd.c_str(), error, errno);
1 by brian
clean slate
2110
    die("command \"%s\" succeeded - should have failed with errno %d...",
2111
        command->first_argument, command->expected_errors.err[0].code.errnum);
2112
  }
2113
142.1.1 by Patrick
Removing DBUG from client
2114
  return;
1 by brian
clean slate
2115
}
2116
2117
enum enum_operator
2118
{
2119
  DO_DEC,
2120
  DO_INC
2121
};
2122
2123
2124
/*
2125
  Decrease or increase the value of a variable
2126
2127
  SYNOPSIS
2128
  do_modify_var()
206.3.1 by Patrick Galbraith
Most everything working with client rename
2129
  query  called command
1 by brian
clean slate
2130
  operator    operation to perform on the var
2131
2132
  DESCRIPTION
2133
  dec $var_name
2134
  inc $var_name
2135
2136
*/
2137
2318.4.6 by Olaf van der Spek
Refactor
2138
static int do_modify_var(st_command* command,
77.1.31 by Monty Taylor
Replaced regex lib with pcre. Reworked mysqltest to use it.
2139
                         enum enum_operator op)
1 by brian
clean slate
2140
{
2141
  const char *p= command->first_argument;
2142
  VAR* v;
2143
  if (!*p)
2144
    die("Missing argument to %.*s", command->first_word_len, command->query);
2145
  if (*p != '$')
2146
    die("The argument to %.*s must be a variable (start with $)",
2147
        command->first_word_len, command->query);
2148
  v= var_get(p, &p, 1, 0);
77.1.31 by Monty Taylor
Replaced regex lib with pcre. Reworked mysqltest to use it.
2149
  switch (op) {
1 by brian
clean slate
2150
  case DO_DEC:
2151
    v->int_val--;
2152
    break;
2153
  case DO_INC:
2154
    v->int_val++;
2155
    break;
2156
  default:
2157
    die("Invalid operator to do_modify_var");
2158
    break;
2159
  }
2160
  v->int_dirty= 1;
2161
  command->last_argument= (char*)++p;
2162
  return 0;
2163
}
2164
2165
2166
/*
2167
  SYNOPSIS
2168
  do_system
206.3.1 by Patrick Galbraith
Most everything working with client rename
2169
  command  called command
1 by brian
clean slate
2170
2171
  DESCRIPTION
2172
  system <command>
2173
2174
  Eval the query to expand any $variables in the command.
2175
  Execute the command with the "system" command.
2176
2177
*/
2178
2318.4.6 by Olaf van der Spek
Refactor
2179
static void do_system(st_command* command)
1 by brian
clean slate
2180
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2181
  string ds_cmd;
142.1.1 by Patrick
Removing DBUG from client
2182
1 by brian
clean slate
2183
2184
  if (strlen(command->first_argument) == 0)
2185
    die("Missing arguments to system, nothing to do!");
2186
2187
  /* Eval the system command, thus replacing all environment variables */
2188
  do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2189
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2190
  if (system(ds_cmd.c_str()))
1 by brian
clean slate
2191
  {
2192
    if (command->abort_on_error)
2193
      die("system command '%s' failed", command->first_argument);
2194
2195
    /* If ! abort_on_error, log message and continue */
2318.6.9 by Olaf van der Spek
Refactor
2196
    ds_res += "system command '";
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2197
    replace_append(&ds_res, command->first_argument);
2318.6.9 by Olaf van der Spek
Refactor
2198
    ds_res += "' failed\n";
1 by brian
clean slate
2199
  }
2200
2201
  command->last_argument= command->end;
142.1.1 by Patrick
Removing DBUG from client
2202
  return;
1 by brian
clean slate
2203
}
2204
2205
2206
/*
2207
  SYNOPSIS
2208
  do_remove_file
206.3.1 by Patrick Galbraith
Most everything working with client rename
2209
  command  called command
1 by brian
clean slate
2210
2211
  DESCRIPTION
2212
  remove_file <file_name>
2213
  Remove the file <file_name>
2214
*/
2215
2318.4.6 by Olaf van der Spek
Refactor
2216
static void do_remove_file(st_command* command)
1 by brian
clean slate
2217
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2218
  string ds_filename;
1 by brian
clean slate
2219
  const struct command_arg rm_args[] = {
163 by Brian Aker
Merge Monty's code.
2220
    { "filename", ARG_STRING, true, &ds_filename, "File to delete" }
1 by brian
clean slate
2221
  };
142.1.1 by Patrick
Removing DBUG from client
2222
1 by brian
clean slate
2223
2224
  check_command_args(command, command->first_argument,
2225
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2226
                     ' ');
2227
2318.4.12 by Olaf van der Spek
Refactor
2228
  int error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
1 by brian
clean slate
2229
  handle_command_error(command, error);
2230
}
2231
2232
2233
/*
2234
  SYNOPSIS
2235
  do_copy_file
206.3.1 by Patrick Galbraith
Most everything working with client rename
2236
  command  command handle
1 by brian
clean slate
2237
2238
  DESCRIPTION
2239
  copy_file <from_file> <to_file>
2240
  Copy <from_file> to <to_file>
2241
2242
  NOTE! Will fail if <to_file> exists
2243
*/
2244
2318.4.6 by Olaf van der Spek
Refactor
2245
static void do_copy_file(st_command* command)
1 by brian
clean slate
2246
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2247
  string ds_from_file;
2248
  string ds_to_file;
1 by brian
clean slate
2249
  const struct command_arg copy_file_args[] = {
163 by Brian Aker
Merge Monty's code.
2250
    { "from_file", ARG_STRING, true, &ds_from_file, "Filename to copy from" },
2251
    { "to_file", ARG_STRING, true, &ds_to_file, "Filename to copy to" }
1 by brian
clean slate
2252
  };
142.1.1 by Patrick
Removing DBUG from client
2253
1 by brian
clean slate
2254
2255
  check_command_args(command, command->first_argument,
2256
                     copy_file_args,
2257
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2258
                     ' ');
2259
2318.4.12 by Olaf van der Spek
Refactor
2260
  int error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
1 by brian
clean slate
2261
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2262
  handle_command_error(command, error);
2263
}
2264
2265
2266
/*
2267
  SYNOPSIS
2268
  do_chmod_file
206.3.1 by Patrick Galbraith
Most everything working with client rename
2269
  command  command handle
1 by brian
clean slate
2270
2271
  DESCRIPTION
2272
  chmod <octal> <file_name>
2273
  Change file permission of <file_name>
2274
2275
*/
2276
2318.4.6 by Olaf van der Spek
Refactor
2277
static void do_chmod_file(st_command* command)
1 by brian
clean slate
2278
{
2279
  long mode= 0;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2280
  string ds_mode;
2281
  string ds_file;
1 by brian
clean slate
2282
  const struct command_arg chmod_file_args[] = {
206.3.1 by Patrick Galbraith
Most everything working with client rename
2283
    { "mode", ARG_STRING, true, &ds_mode, "Mode of file(octal) ex. 0660"},
163 by Brian Aker
Merge Monty's code.
2284
    { "filename", ARG_STRING, true, &ds_file, "Filename of file to modify" }
1 by brian
clean slate
2285
  };
142.1.1 by Patrick
Removing DBUG from client
2286
1 by brian
clean slate
2287
2288
  check_command_args(command, command->first_argument,
2289
                     chmod_file_args,
2290
                     sizeof(chmod_file_args)/sizeof(struct command_arg),
2291
                     ' ');
2292
2293
  /* Parse what mode to set */
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.
2294
  istringstream buff(ds_mode);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2295
  if (ds_mode.length() != 4 ||
1119.2.5 by Monty Taylor
Fixed a namespace style thing.
2296
      (buff >> oct >> mode).fail())
1 by brian
clean slate
2297
    die("You must write a 4 digit octal number for mode");
2298
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2299
  handle_command_error(command, chmod(ds_file.c_str(), mode));
1 by brian
clean slate
2300
}
2301
2302
2303
/*
2304
  SYNOPSIS
2305
  do_file_exists
206.3.1 by Patrick Galbraith
Most everything working with client rename
2306
  command  called command
1 by brian
clean slate
2307
2308
  DESCRIPTION
2309
  fiile_exist <file_name>
2310
  Check if file <file_name> exists
2311
*/
2312
2318.4.6 by Olaf van der Spek
Refactor
2313
static void do_file_exist(st_command* command)
1 by brian
clean slate
2314
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2315
  string ds_filename;
1 by brian
clean slate
2316
  const struct command_arg file_exist_args[] = {
163 by Brian Aker
Merge Monty's code.
2317
    { "filename", ARG_STRING, true, &ds_filename, "File to check if it exist" }
1 by brian
clean slate
2318
  };
142.1.1 by Patrick
Removing DBUG from client
2319
1 by brian
clean slate
2320
2321
  check_command_args(command, command->first_argument,
2322
                     file_exist_args,
2323
                     sizeof(file_exist_args)/sizeof(struct command_arg),
2324
                     ' ');
2325
2318.4.12 by Olaf van der Spek
Refactor
2326
  int error= access(ds_filename.c_str(), F_OK) != 0;
1 by brian
clean slate
2327
  handle_command_error(command, error);
2328
}
2329
2330
2331
/*
2332
  SYNOPSIS
2333
  do_mkdir
206.3.1 by Patrick Galbraith
Most everything working with client rename
2334
  command  called command
1 by brian
clean slate
2335
2336
  DESCRIPTION
2337
  mkdir <dir_name>
2338
  Create the directory <dir_name>
2339
*/
2340
2318.4.6 by Olaf van der Spek
Refactor
2341
static void do_mkdir(st_command* command)
1 by brian
clean slate
2342
{
685.3.1 by Toru Maesaka
Removed my_mkdir() and my_sleep()
2343
  string ds_dirname;
1 by brian
clean slate
2344
  const struct command_arg mkdir_args[] = {
163 by Brian Aker
Merge Monty's code.
2345
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
1 by brian
clean slate
2346
  };
142.1.1 by Patrick
Removing DBUG from client
2347
1 by brian
clean slate
2348
2349
  check_command_args(command, command->first_argument,
2350
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2351
                     ' ');
2352
2318.4.12 by Olaf van der Spek
Refactor
2353
  int error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
1 by brian
clean slate
2354
  handle_command_error(command, error);
2355
}
2356
2357
/*
2358
  SYNOPSIS
2359
  do_rmdir
206.3.1 by Patrick Galbraith
Most everything working with client rename
2360
  command  called command
1 by brian
clean slate
2361
2362
  DESCRIPTION
2363
  rmdir <dir_name>
2364
  Remove the empty directory <dir_name>
2365
*/
2366
2318.4.6 by Olaf van der Spek
Refactor
2367
static void do_rmdir(st_command* command)
1 by brian
clean slate
2368
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2369
  string ds_dirname;
1 by brian
clean slate
2370
  const struct command_arg rmdir_args[] = {
163 by Brian Aker
Merge Monty's code.
2371
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to remove"}
1 by brian
clean slate
2372
  };
142.1.1 by Patrick
Removing DBUG from client
2373
1 by brian
clean slate
2374
2375
  check_command_args(command, command->first_argument,
2376
                     rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
2377
                     ' ');
2378
2318.4.12 by Olaf van der Spek
Refactor
2379
  int error= rmdir(ds_dirname.c_str()) != 0;
1 by brian
clean slate
2380
  handle_command_error(command, error);
2381
}
2382
2383
2384
/*
2385
  Read characters from line buffer or file. This is needed to allow
2386
  my_ungetc() to buffer MAX_DELIMITER_LENGTH characters for a file
2387
2388
  NOTE:
2389
  This works as long as one doesn't change files (with 'source file_name')
2390
  when there is things pushed into the buffer.  This should however not
2391
  happen for any tests in the test suite.
2392
*/
2393
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
2394
static int my_getc(FILE *file)
1 by brian
clean slate
2395
{
2396
  if (line_buffer_pos == line_buffer)
2397
    return fgetc(file);
2398
  return *--line_buffer_pos;
2399
}
2400
2401
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
2402
static void my_ungetc(int c)
1 by brian
clean slate
2403
{
2404
  *line_buffer_pos++= (char) c;
2405
}
2406
2407
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2408
static void read_until_delimiter(string *ds,
2409
                                 string *ds_delimiter)
1 by brian
clean slate
2410
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2411
  if (ds_delimiter->length() > MAX_DELIMITER_LENGTH)
1 by brian
clean slate
2412
    die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
2413
2414
  /* Read from file until delimiter is found */
2415
  while (1)
2416
  {
2318.4.12 by Olaf van der Spek
Refactor
2417
    char c= my_getc(cur_file->file);
1 by brian
clean slate
2418
2419
    if (c == '\n')
2420
    {
2421
      cur_file->lineno++;
2422
2423
      /* Skip newline from the same line as the command */
2424
      if (start_lineno == (cur_file->lineno - 1))
2425
        continue;
2426
    }
2427
    else if (start_lineno == cur_file->lineno)
2428
    {
2429
      /*
2430
        No characters except \n are allowed on
2431
        the same line as the command
2432
      */
2433
      die("Trailing characters found after command");
2434
    }
2435
2436
    if (feof(cur_file->file))
2437
      die("End of file encountered before '%s' delimiter was found",
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2438
          ds_delimiter->c_str());
1 by brian
clean slate
2439
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2440
    if (match_delimiter(c, ds_delimiter->c_str(), ds_delimiter->length()))
1 by brian
clean slate
2441
      break;
142.1.1 by Patrick
Removing DBUG from client
2442
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2443
    ds->push_back(c);
1 by brian
clean slate
2444
  }
2445
}
2446
2447
2318.4.6 by Olaf van der Spek
Refactor
2448
static void do_write_file_command(st_command* command, bool append)
1 by brian
clean slate
2449
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2450
  string ds_content;
2451
  string ds_filename;
2452
  string ds_delimiter;
1 by brian
clean slate
2453
  const struct command_arg write_file_args[] = {
163 by Brian Aker
Merge Monty's code.
2454
    { "filename", ARG_STRING, true, &ds_filename, "File to write to" },
2455
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
1 by brian
clean slate
2456
  };
142.1.1 by Patrick
Removing DBUG from client
2457
1 by brian
clean slate
2458
2459
  check_command_args(command,
2460
                     command->first_argument,
2461
                     write_file_args,
2462
                     sizeof(write_file_args)/sizeof(struct command_arg),
2463
                     ' ');
2464
2465
  /* If no delimiter was provided, use EOF */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2466
  if (ds_delimiter.length() == 0)
2318.6.9 by Olaf van der Spek
Refactor
2467
    ds_delimiter += "EOF";
1 by brian
clean slate
2468
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2469
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
1 by brian
clean slate
2470
  {
2471
    /* The file should not be overwritten */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2472
    die("File already exist: '%s'", ds_filename.c_str());
1 by brian
clean slate
2473
  }
2474
2475
  read_until_delimiter(&ds_content, &ds_delimiter);
2318.4.12 by Olaf van der Spek
Refactor
2476
  str_to_file2(ds_filename.c_str(), ds_content.c_str(), ds_content.length(), append);
1 by brian
clean slate
2477
}
2478
2479
2480
/*
2481
  SYNOPSIS
2482
  do_write_file
206.3.1 by Patrick Galbraith
Most everything working with client rename
2483
  command  called command
1 by brian
clean slate
2484
2485
  DESCRIPTION
2486
  write_file <file_name> [<delimiter>];
2487
  <what to write line 1>
2488
  <...>
2489
  < what to write line n>
2490
  EOF
2491
2492
  --write_file <file_name>;
2493
  <what to write line 1>
2494
  <...>
2495
  < what to write line n>
2496
  EOF
2497
2498
  Write everything between the "write_file" command and 'delimiter'
2499
  to "file_name"
2500
2501
  NOTE! Will fail if <file_name> exists
2502
2503
  Default <delimiter> is EOF
2504
2505
*/
2506
2318.4.6 by Olaf van der Spek
Refactor
2507
static void do_write_file(st_command* command)
1 by brian
clean slate
2508
{
163 by Brian Aker
Merge Monty's code.
2509
  do_write_file_command(command, false);
1 by brian
clean slate
2510
}
2511
2512
2513
/*
2514
  SYNOPSIS
2515
  do_append_file
206.3.1 by Patrick Galbraith
Most everything working with client rename
2516
  command  called command
1 by brian
clean slate
2517
2518
  DESCRIPTION
2519
  append_file <file_name> [<delimiter>];
2520
  <what to write line 1>
2521
  <...>
2522
  < what to write line n>
2523
  EOF
2524
2525
  --append_file <file_name>;
2526
  <what to write line 1>
2527
  <...>
2528
  < what to write line n>
2529
  EOF
2530
2531
  Append everything between the "append_file" command
2532
  and 'delimiter' to "file_name"
2533
2534
  Default <delimiter> is EOF
2535
2536
*/
2537
2318.4.6 by Olaf van der Spek
Refactor
2538
static void do_append_file(st_command* command)
1 by brian
clean slate
2539
{
163 by Brian Aker
Merge Monty's code.
2540
  do_write_file_command(command, true);
1 by brian
clean slate
2541
}
2542
2543
2544
/*
2545
  SYNOPSIS
2546
  do_cat_file
206.3.1 by Patrick Galbraith
Most everything working with client rename
2547
  command  called command
1 by brian
clean slate
2548
2549
  DESCRIPTION
2550
  cat_file <file_name>;
2551
2552
  Print the given file to result log
2553
2554
*/
2555
2318.4.6 by Olaf van der Spek
Refactor
2556
static void do_cat_file(st_command* command)
1 by brian
clean slate
2557
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2558
  static string ds_filename;
1 by brian
clean slate
2559
  const struct command_arg cat_file_args[] = {
163 by Brian Aker
Merge Monty's code.
2560
    { "filename", ARG_STRING, true, &ds_filename, "File to read from" }
1 by brian
clean slate
2561
  };
142.1.1 by Patrick
Removing DBUG from client
2562
1 by brian
clean slate
2563
2564
  check_command_args(command,
2565
                     command->first_argument,
2566
                     cat_file_args,
2567
                     sizeof(cat_file_args)/sizeof(struct command_arg),
2568
                     ' ');
2569
2318.5.22 by Olaf van der Spek
Refactor
2570
  cat_file(ds_res, ds_filename.c_str());
1 by brian
clean slate
2571
}
2572
2573
2574
/*
2575
  SYNOPSIS
2576
  do_diff_files
206.3.1 by Patrick Galbraith
Most everything working with client rename
2577
  command  called command
1 by brian
clean slate
2578
2579
  DESCRIPTION
2580
  diff_files <file1> <file2>;
2581
2582
  Fails if the two files differ.
2583
2584
*/
2585
2318.4.6 by Olaf van der Spek
Refactor
2586
static void do_diff_files(st_command* command)
1 by brian
clean slate
2587
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2588
  string ds_filename;
2589
  string ds_filename2;
1 by brian
clean slate
2590
  const struct command_arg diff_file_args[] = {
163 by Brian Aker
Merge Monty's code.
2591
    { "file1", ARG_STRING, true, &ds_filename, "First file to diff" },
2592
    { "file2", ARG_STRING, true, &ds_filename2, "Second file to diff" }
1 by brian
clean slate
2593
  };
142.1.1 by Patrick
Removing DBUG from client
2594
1 by brian
clean slate
2595
2596
  check_command_args(command,
2597
                     command->first_argument,
2598
                     diff_file_args,
2599
                     sizeof(diff_file_args)/sizeof(struct command_arg),
2600
                     ' ');
2601
2318.4.12 by Olaf van der Spek
Refactor
2602
  int error= compare_files(ds_filename.c_str(), ds_filename2.c_str());
2603
  if (error)
1 by brian
clean slate
2604
  {
2605
    /* Compare of the two files failed, append them to output
2606
       so the failure can be analyzed
2607
    */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2608
    show_diff(&ds_res, ds_filename.c_str(), ds_filename2.c_str());
1 by brian
clean slate
2609
  }
2610
2611
  handle_command_error(command, error);
2612
}
2613
2614
/*
2615
  SYNOPSIS
2616
  do_send_quit
206.3.1 by Patrick Galbraith
Most everything working with client rename
2617
  command  called command
1 by brian
clean slate
2618
2619
  DESCRIPTION
2620
  Sends a simple quit command to the server for the named connection.
2621
2622
*/
2623
2318.4.6 by Olaf van der Spek
Refactor
2624
static void do_send_quit(st_command* command)
1 by brian
clean slate
2625
{
2318.5.4 by Olaf van der Spek
Refactor
2626
  char* p= command->first_argument;
2627
2628
  if (not *p)
2629
    die("Missing connection name in send_quit");
2630
  char* name= p;
2445.1.3 by Olaf van der Spek
Refactor
2631
  while (*p && !charset_info->isspace(*p))
2318.5.4 by Olaf van der Spek
Refactor
2632
    p++;
2633
2634
  if (*p)
2635
    *p++= 0;
2636
  command->last_argument= p;
2637
2318.5.25 by Olaf van der Spek
Refactor
2638
  st_connection* con= find_ptr2(g_connections, name);
2318.5.4 by Olaf van der Spek
Refactor
2639
  if (not con)
2640
    die("connection '%s' not found in connection pool", name);
2641
2318.5.19 by Olaf van der Spek
Refactor
2642
  drizzle::result_c result;
928.1.6 by Eric Day
All utilities done except slap.
2643
  drizzle_return_t ret;
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
2644
  drizzle_quit(*con, result, &ret);
1 by brian
clean slate
2645
}
2646
2647
2648
/*
2649
  SYNOPSIS
2650
  do_change_user
2651
  command       called command
2652
2653
  DESCRIPTION
2654
  change_user [<user>], [<passwd>], [<db>]
2655
  <user> - user to change to
2656
  <passwd> - user password
2657
  <db> - default database
2658
2659
  Changes the user and causes the database specified by db to become
2660
  the default (current) database for the the current connection.
2661
2662
*/
2663
2318.5.23 by Olaf van der Spek
Refactor
2664
static void do_change_user(st_command *)
1 by brian
clean slate
2665
{
923.1.5 by Brian Aker
Remove Change User code.
2666
  assert(0);
1 by brian
clean slate
2667
}
2668
2669
/*
2670
  SYNOPSIS
2671
  do_perl
206.3.1 by Patrick Galbraith
Most everything working with client rename
2672
  command  command handle
1 by brian
clean slate
2673
2674
  DESCRIPTION
2675
  perl [<delimiter>];
2676
  <perlscript line 1>
2677
  <...>
2678
  <perlscript line n>
2679
  EOF
2680
2681
  Execute everything after "perl" until <delimiter> as perl.
2682
  Useful for doing more advanced things
2683
  but still being able to execute it on all platforms.
2684
2685
  Default <delimiter> is EOF
2686
*/
2687
2318.4.6 by Olaf van der Spek
Refactor
2688
static void do_perl(st_command* command)
1 by brian
clean slate
2689
{
2690
  char buf[FN_REFLEN];
2691
  char temp_file_path[FN_REFLEN];
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2692
  string ds_script;
2693
  string ds_delimiter;
2318.5.19 by Olaf van der Spek
Refactor
2694
  const command_arg perl_args[] = {
163 by Brian Aker
Merge Monty's code.
2695
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
1 by brian
clean slate
2696
  };
142.1.1 by Patrick
Removing DBUG from client
2697
1 by brian
clean slate
2698
2699
  check_command_args(command,
2700
                     command->first_argument,
2701
                     perl_args,
2702
                     sizeof(perl_args)/sizeof(struct command_arg),
2703
                     ' ');
2704
2705
  /* If no delimiter was provided, use EOF */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2706
  if (ds_delimiter.length() == 0)
2318.6.9 by Olaf van der Spek
Refactor
2707
    ds_delimiter += "EOF";
1 by brian
clean slate
2708
2709
  read_until_delimiter(&ds_script, &ds_delimiter);
2710
2711
  /* Create temporary file name */
2318.5.19 by Olaf van der Spek
Refactor
2712
  int fd= internal::create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"), "tmp", MYF(MY_WME));
2713
  if (fd < 0)
1 by brian
clean slate
2714
    die("Failed to create temporary file for perl command");
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
2715
  internal::my_close(fd, MYF(0));
1 by brian
clean slate
2716
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2717
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
1 by brian
clean slate
2718
2719
  /* Format the "perl <filename>" command */
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
2720
  snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
1 by brian
clean slate
2721
2318.5.19 by Olaf van der Spek
Refactor
2722
  FILE* res_file= popen(buf, "r");
2723
  if (not res_file && command->abort_on_error)
1 by brian
clean slate
2724
    die("popen(\"%s\", \"r\") failed", buf);
2725
2726
  while (fgets(buf, sizeof(buf), res_file))
2727
  {
2728
    if (disable_result_log)
2729
      buf[strlen(buf)-1]=0;
2730
    else
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2731
      replace_append(&ds_res, buf);
1 by brian
clean slate
2732
  }
2318.5.19 by Olaf van der Spek
Refactor
2733
  int error= pclose(res_file);
1 by brian
clean slate
2734
2735
  /* Remove the temporary file */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
2736
  internal::my_delete(temp_file_path, MYF(0));
1 by brian
clean slate
2737
2738
  handle_command_error(command, WEXITSTATUS(error));
2739
}
2740
2741
2742
/*
2743
  Print the content between echo and <delimiter> to result file.
2744
  Evaluate all variables in the string before printing, allow
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2745
  for variable names to be escaped using        \
1 by brian
clean slate
2746
2747
  SYNOPSIS
2748
  do_echo()
2749
  command  called command
2750
2751
  DESCRIPTION
2752
  echo text
2753
  Print the text after echo until end of command to result file
2754
2755
  echo $<var_name>
2756
  Print the content of the variable <var_name> to result file
2757
2758
  echo Some text $<var_name>
2759
  Print "Some text" plus the content of the variable <var_name> to
2760
  result file
2761
2762
  echo Some text \$<var_name>
2763
  Print "Some text" plus $<var_name> to result file
2764
*/
2765
2318.4.6 by Olaf van der Spek
Refactor
2766
static void do_echo(st_command* command)
1 by brian
clean slate
2767
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2768
  string ds_echo;
163 by Brian Aker
Merge Monty's code.
2769
  do_eval(&ds_echo, command->first_argument, command->end, false);
2318.6.9 by Olaf van der Spek
Refactor
2770
  ds_res += ds_echo;
2771
  ds_res += "\n";
1 by brian
clean slate
2772
  command->last_argument= command->end;
2773
}
2774
2318.4.6 by Olaf van der Spek
Refactor
2775
static void do_wait_for_slave_to_stop()
1 by brian
clean slate
2776
{
2777
  static int SLAVE_POLL_INTERVAL= 300000;
2318.5.34 by Olaf van der Spek
Refactor
2778
  drizzle::connection_c& con= *cur_con;
1 by brian
clean slate
2779
  for (;;)
2780
  {
2318.5.9 by Olaf van der Spek
Refactor
2781
    drizzle::result_c res;
2318.5.37 by Olaf van der Spek
Refactor
2782
    dt_query(con, res, "show status like 'Slave_running'");
2318.5.9 by Olaf van der Spek
Refactor
2783
    drizzle_row_t row= res.row_next();
2784
    if (!row || !row[1])
1 by brian
clean slate
2785
    {
2786
      die("Strange result from query while probing slave for stop");
2787
    }
2318.5.9 by Olaf van der Spek
Refactor
2788
    if (!strcmp(row[1], "OFF"))
1 by brian
clean slate
2789
      break;
685.3.1 by Toru Maesaka
Removed my_mkdir() and my_sleep()
2790
    usleep(SLAVE_POLL_INTERVAL);
1 by brian
clean slate
2791
  }
2792
}
2793
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
2794
static void do_sync_with_master2(long offset)
1 by brian
clean slate
2795
{
2318.5.32 by Olaf van der Spek
Refactor
2796
  drizzle::connection_c& con= *cur_con;
1 by brian
clean slate
2797
2798
  if (!master_pos.file[0])
2799
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
2800
2385.3.32 by Olaf van der Spek
cppcheck
2801
  char query_buf[FN_REFLEN+128];
2385.2.4 by Olaf van der Spek
cppcheck
2802
  snprintf(query_buf, sizeof(query_buf), "select master_pos_wait('%s', %ld)", master_pos.file, master_pos.pos + offset);
2385.3.33 by Olaf van der Spek
Oops
2803
  for (int tries= 0; tries < 30; tries++)
2385.3.32 by Olaf van der Spek
cppcheck
2804
  {
2805
    drizzle::result_c res;
2806
    dt_query(con, res, query_buf);
2807
2808
    drizzle_row_t row= res.row_next();
2809
    if (not row)
2810
      die("empty result in %s", query_buf);
2811
    if (row[0])
2812
      return;
1 by brian
clean slate
2813
    /*
2385.3.32 by Olaf van der Spek
cppcheck
2814
    It may be that the slave SQL thread has not started yet, though START
2815
    SLAVE has been issued ?
1 by brian
clean slate
2816
    */
2817
    sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
2818
  }
2385.3.32 by Olaf van der Spek
cppcheck
2819
  show_query(con, "SHOW MASTER STATUS");
2820
  show_query(con, "SHOW SLAVE STATUS");
2821
  die("could not sync with master ('%s' returned NULL)", query_buf);
1 by brian
clean slate
2822
}
2823
2318.4.6 by Olaf van der Spek
Refactor
2824
static void do_sync_with_master(st_command* command)
1 by brian
clean slate
2825
{
2826
  long offset= 0;
2827
  char *p= command->first_argument;
2828
  const char *offset_start= p;
2829
  if (*offset_start)
2830
  {
2445.1.3 by Olaf van der Spek
Refactor
2831
    for (; charset_info->isdigit(*p); p++)
1 by brian
clean slate
2832
      offset = offset * 10 + *p - '0';
2833
2445.1.3 by Olaf van der Spek
Refactor
2834
    if(*p && !charset_info->isspace(*p))
1 by brian
clean slate
2835
      die("Invalid integer argument \"%s\"", offset_start);
2836
    command->last_argument= p;
2837
  }
2838
  do_sync_with_master2(offset);
2839
  return;
2840
}
2841
2842
2843
/*
2844
  when ndb binlog is on, this call will wait until last updated epoch
206.3.1 by Patrick Galbraith
Most everything working with client rename
2845
  (locally in the drizzled) has been received into the binlog
1 by brian
clean slate
2846
*/
2318.4.6 by Olaf van der Spek
Refactor
2847
static void do_save_master_pos()
1 by brian
clean slate
2848
{
2318.5.10 by Olaf van der Spek
Refactor
2849
  drizzle::result_c res;
2318.6.1 by Olaf van der Spek
Refactor
2850
  dt_query(*cur_con, res, "show master status");
2318.5.10 by Olaf van der Spek
Refactor
2851
  drizzle_row_t row= res.row_next();
2852
  if (!row)
1 by brian
clean slate
2853
    die("empty result in show master status");
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
2854
  strncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
1 by brian
clean slate
2855
  master_pos.pos = strtoul(row[1], (char**) 0, 10);
2856
}
2857
2858
2859
/*
2860
  Assign the variable <var_name> with <var_val>
2861
2862
  SYNOPSIS
2863
  do_let()
206.3.1 by Patrick Galbraith
Most everything working with client rename
2864
  query  called command
1 by brian
clean slate
2865
2866
  DESCRIPTION
2867
  let $<var_name>=<var_val><delimiter>
2868
2869
  <var_name>  - is the string string found between the $ and =
2870
  <var_val>   - is the content between the = and <delimiter>, it may span
2871
  multiple line and contain any characters except <delimiter>
2872
  <delimiter> - is a string containing of one or more chars, default is ;
2873
2874
  RETURN VALUES
2875
  Program will die if error detected
2876
*/
2877
2318.4.6 by Olaf van der Spek
Refactor
2878
static void do_let(st_command* command)
1 by brian
clean slate
2879
{
2880
  char *p= command->first_argument;
2881
  char *var_name, *var_name_end;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2882
  string let_rhs_expr;
2883
1 by brian
clean slate
2884
2885
  /* Find <var_name> */
2886
  if (!*p)
2887
    die("Missing arguments to let");
2888
  var_name= p;
2445.1.3 by Olaf van der Spek
Refactor
2889
  while (*p && (*p != '=') && !charset_info->isspace(*p))
1 by brian
clean slate
2890
    p++;
2891
  var_name_end= p;
2892
  if (var_name == var_name_end ||
2893
      (var_name+1 == var_name_end && *var_name == '$'))
2894
    die("Missing variable name in let");
2445.1.3 by Olaf van der Spek
Refactor
2895
  while (charset_info->isspace(*p))
1 by brian
clean slate
2896
    p++;
2897
  if (*p++ != '=')
2898
    die("Missing assignment operator in let");
2899
2900
  /* Find start of <var_val> */
2445.1.3 by Olaf van der Spek
Refactor
2901
  while (*p && charset_info->isspace(*p))
1 by brian
clean slate
2902
    p++;
2903
163 by Brian Aker
Merge Monty's code.
2904
  do_eval(&let_rhs_expr, p, command->end, false);
1 by brian
clean slate
2905
2906
  command->last_argument= command->end;
2907
  /* Assign var_val to var_name */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2908
  var_set(var_name, var_name_end, let_rhs_expr.c_str(),
2909
          (let_rhs_expr.c_str() + let_rhs_expr.length()));
142.1.1 by Patrick
Removing DBUG from client
2910
  return;
1 by brian
clean slate
2911
}
2912
2913
2914
/*
2915
  Sleep the number of specified seconds
2916
2917
  SYNOPSIS
2918
  do_sleep()
206.3.1 by Patrick Galbraith
Most everything working with client rename
2919
  q         called command
1 by brian
clean slate
2920
  real_sleep   use the value from opt_sleep as number of seconds to sleep
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
2921
  if real_sleep is false
1 by brian
clean slate
2922
2923
  DESCRIPTION
2924
  sleep <seconds>
2925
  real_sleep <seconds>
2926
2927
  The difference between the sleep and real_sleep commands is that sleep
2928
  uses the delay from the --sleep command-line option if there is one.
2929
  (If the --sleep option is not given, the sleep command uses the delay
2930
  specified by its argument.) The real_sleep command always uses the
2931
  delay specified by its argument.  The logic is that sometimes delays are
2932
  cpu-dependent, and --sleep can be used to set this delay.  real_sleep is
2933
  used for cpu-independent delays.
2934
*/
2935
2318.4.6 by Olaf van der Spek
Refactor
2936
static void do_sleep(st_command* command, bool real_sleep)
1 by brian
clean slate
2937
{
2938
  char *p= command->first_argument;
2939
  char *sleep_start, *sleep_end= command->end;
1883.3.1 by Andrew Hutchings
Cleanup drizzledump and drizzle for cppcheck
2940
  double sleep_val= 0;
1 by brian
clean slate
2941
2445.1.3 by Olaf van der Spek
Refactor
2942
  while (charset_info->isspace(*p))
1 by brian
clean slate
2943
    p++;
2944
  if (!*p)
2945
    die("Missing argument to %.*s", command->first_word_len, command->query);
2946
  sleep_start= p;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
2947
  /* Check that arg starts with a digit, not handled by internal::my_strtod */
2445.1.3 by Olaf van der Spek
Refactor
2948
  if (!charset_info->isdigit(*sleep_start))
1 by brian
clean slate
2949
    die("Invalid argument to %.*s \"%s\"", command->first_word_len,
2950
        command->query,command->first_argument);
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.
2951
  string buff_str(sleep_start, sleep_end-sleep_start);
2952
  istringstream buff(buff_str);
2318.4.6 by Olaf van der Spek
Refactor
2953
  buff >> sleep_val;
2954
  if (buff.fail())
2955
    die("Invalid argument to %.*s \"%s\"", command->first_word_len, command->query, command->first_argument);
1 by brian
clean slate
2956
2957
  /* Fixed sleep time selected by --sleep option */
2958
  if (opt_sleep >= 0 && !real_sleep)
2959
    sleep_val= opt_sleep;
2960
2961
  if (sleep_val)
2151.2.22 by Olaf van der Spek
refactor
2962
    usleep(sleep_val * 1000000);
1 by brian
clean slate
2963
  command->last_argument= sleep_end;
2964
}
2965
2966
2318.4.6 by Olaf van der Spek
Refactor
2967
static void do_get_file_name(st_command* command, string &dest)
1 by brian
clean slate
2968
{
2151.2.27 by Olaf van der Spek
refactor
2969
  char *p= command->first_argument;
1 by brian
clean slate
2970
  if (!*p)
2971
    die("Missing file name argument");
2151.2.27 by Olaf van der Spek
refactor
2972
  char *name= p;
2445.1.3 by Olaf van der Spek
Refactor
2973
  while (*p && !charset_info->isspace(*p))
1 by brian
clean slate
2974
    p++;
2975
  if (*p)
2976
    *p++= 0;
2977
  command->last_argument= p;
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
2978
  if (! opt_testdir.empty())
1134.1.2 by Monty Taylor
Append opt_testdir to result files being required.
2979
  {
2980
    dest= opt_testdir;
2981
    if (dest[dest.length()] != '/')
2318.6.9 by Olaf van der Spek
Refactor
2982
      dest += "/";
1134.1.2 by Monty Taylor
Append opt_testdir to result files being required.
2983
  }
2984
  dest.append(name);
1 by brian
clean slate
2985
}
2986
2987
2318.4.6 by Olaf van der Spek
Refactor
2988
static void do_set_charset(st_command* command)
1 by brian
clean slate
2989
{
2990
  char *charset_name= command->first_argument;
2991
  char *p;
2992
2993
  if (!charset_name || !*charset_name)
2994
    die("Missing charset name in 'character_set'");
2995
  /* Remove end space */
2996
  p= charset_name;
2445.1.3 by Olaf van der Spek
Refactor
2997
  while (*p && !charset_info->isspace(*p))
1 by brian
clean slate
2998
    p++;
2999
  if(*p)
3000
    *p++= 0;
3001
  command->last_argument= p;
862 by Brian Aker
Remove charset directory code.
3002
  charset_info= get_charset_by_csname(charset_name, MY_CS_PRIMARY);
1 by brian
clean slate
3003
  if (!charset_info)
3004
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3005
}
3006
1996.3.7 by Monty Taylor
Replaced static error code mapping with a query of data_dictionary.errors.
3007
static void fill_global_error_names()
3008
{
2318.5.33 by Olaf van der Spek
Refactor
3009
  drizzle::connection_c& con= *cur_con;
1996.3.7 by Monty Taylor
Replaced static error code mapping with a query of data_dictionary.errors.
3010
3011
  global_error_names.clear();
3012
2318.5.10 by Olaf van der Spek
Refactor
3013
  drizzle::result_c res;
2318.5.37 by Olaf van der Spek
Refactor
3014
  dt_query(con, res, "select error_name, error_code from data_dictionary.errors");
2318.5.10 by Olaf van der Spek
Refactor
3015
  while (drizzle_row_t row= res.row_next())
1996.3.7 by Monty Taylor
Replaced static error code mapping with a query of data_dictionary.errors.
3016
  {
2318.4.6 by Olaf van der Spek
Refactor
3017
    if (not row[0])
3018
      break;
1996.3.7 by Monty Taylor
Replaced static error code mapping with a query of data_dictionary.errors.
3019
    /*
3020
      Concatenate all fields in the first row with tab in between
3021
      and assign that string to the $variable
3022
    */
2318.5.12 by Olaf van der Spek
Refactor
3023
    size_t *lengths= res.row_field_sizes();
1996.3.7 by Monty Taylor
Replaced static error code mapping with a query of data_dictionary.errors.
3024
    try
3025
    {
2151.2.26 by Olaf van der Spek
refactor
3026
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
1996.3.7 by Monty Taylor
Replaced static error code mapping with a query of data_dictionary.errors.
3027
    }
3028
    catch (boost::bad_lexical_cast &ex)
3029
    {
3030
      die("Invalid error_code from Drizzle: %s", ex.what());
3031
    }
3032
  }
1999.1.3 by Brian Aker
Merge in Monty. Two changes were made:
3033
}
3034
2192.5.1 by Olaf van der Spek
Use find_ptr
3035
static uint32_t get_errcode_from_name(const char *error_name, const char *error_end)
1 by brian
clean slate
3036
{
2192.5.1 by Olaf van der Spek
Use find_ptr
3037
  string error_name_s(error_name, error_end);
1090.2.1 by Robert Klahn
convert global_error_names from a c array to a c++ std::map
3038
2192.5.8 by Olaf van der Spek
Use ptr instead of i
3039
  if (ErrorCodes::mapped_type* ptr= find_ptr(global_error_names, error_name_s))
3040
    return *ptr;
1996.3.7 by Monty Taylor
Replaced static error code mapping with a query of data_dictionary.errors.
3041
3042
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3043
  return 0;
1 by brian
clean slate
3044
}
3045
2318.4.6 by Olaf van der Spek
Refactor
3046
static void do_get_errcodes(st_command* command)
1 by brian
clean slate
3047
{
3048
  struct st_match_err *to= saved_expected_errors.err;
3049
  char *p= command->first_argument;
893 by Brian Aker
First pass of stripping uint
3050
  uint32_t count= 0;
1 by brian
clean slate
3051
142.1.1 by Patrick
Removing DBUG from client
3052
1 by brian
clean slate
3053
3054
  if (!*p)
3055
    die("Missing argument(s) to 'error'");
3056
3057
  do
3058
  {
3059
    char *end;
3060
3061
    /* Skip leading spaces */
3062
    while (*p && *p == ' ')
3063
      p++;
3064
3065
    /* Find end */
3066
    end= p;
3067
    while (*end && *end != ',' && *end != ' ')
3068
      end++;
3069
3070
    if (*p == 'S')
3071
    {
3072
      char *to_ptr= to->code.sqlstate;
3073
3074
      /*
3075
        SQLSTATE string
928.1.6 by Eric Day
All utilities done except slap.
3076
        - Must be DRIZZLE_MAX_SQLSTATE_SIZE long
1 by brian
clean slate
3077
        - May contain only digits[0-9] and _uppercase_ letters
3078
      */
3079
      p++; /* Step past the S */
928.1.6 by Eric Day
All utilities done except slap.
3080
      if ((end - p) != DRIZZLE_MAX_SQLSTATE_SIZE)
3081
        die("The sqlstate must be exactly %d chars long", DRIZZLE_MAX_SQLSTATE_SIZE);
1 by brian
clean slate
3082
3083
      /* Check sqlstate string validity */
3084
      while (*p && p < end)
3085
      {
2445.1.3 by Olaf van der Spek
Refactor
3086
        if (charset_info->isdigit(*p) || charset_info->isupper(*p))
1 by brian
clean slate
3087
          *to_ptr++= *p++;
3088
        else
2445.1.3 by Olaf van der Spek
Refactor
3089
          die("The sqlstate may only consist of digits[0-9] and _uppercase_ letters");
1 by brian
clean slate
3090
      }
3091
3092
      *to_ptr= 0;
3093
      to->type= ERR_SQLSTATE;
3094
    }
3095
    else if (*p == 's')
3096
    {
3097
      die("The sqlstate definition must start with an uppercase S");
3098
    }
3099
    else if (*p == 'E')
3100
    {
3101
      /* Error name string */
3102
3103
      to->code.errnum= get_errcode_from_name(p, end);
3104
      to->type= ERR_ERRNO;
3105
    }
3106
    else if (*p == 'e')
3107
    {
3108
      die("The error name definition must start with an uppercase E");
3109
    }
2132.1.5 by Brian Aker
Fix lookup for HA error codes.
3110
    else if (*p == 'H')
3111
    {
3112
      /* Error name string */
3113
3114
      to->code.errnum= get_errcode_from_name(p, end);
3115
      to->type= ERR_ERRNO;
3116
    }
1 by brian
clean slate
3117
    else
3118
    {
2141.1.1 by kalebral at gmail
remove remaining error numbers for tests, fail if test has error numbers
3119
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
1 by brian
clean slate
3120
    }
3121
    to++;
3122
    count++;
3123
3124
    if (count >= (sizeof(saved_expected_errors.err) /
3125
                  sizeof(struct st_match_err)))
3126
      die("Too many errorcodes specified");
3127
3128
    /* Set pointer to the end of the last error code */
3129
    p= end;
3130
3131
    /* Find next ',' */
3132
    while (*p && *p != ',')
3133
      p++;
3134
3135
    if (*p)
3136
      p++; /* Step past ',' */
3137
3138
  } while (*p);
3139
3140
  command->last_argument= p;
3141
  to->type= ERR_EMPTY;                        /* End of data */
3142
3143
  saved_expected_errors.count= count;
142.1.1 by Patrick
Removing DBUG from client
3144
  return;
1 by brian
clean slate
3145
}
3146
3147
3148
/*
3149
  Get a string;  Return ptr to end of string
3150
  Strings may be surrounded by " or '
3151
3152
  If string is a '$variable', return the value of the variable.
3153
*/
3154
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
3155
static char *get_string(char **to_ptr, char **from_ptr,
2318.4.6 by Olaf van der Spek
Refactor
3156
                        st_command* command)
1 by brian
clean slate
3157
{
3158
  char c, sep;
3159
  char *to= *to_ptr, *from= *from_ptr, *start=to;
142.1.1 by Patrick
Removing DBUG from client
3160
1 by brian
clean slate
3161
3162
  /* Find separator */
3163
  if (*from == '"' || *from == '\'')
3164
    sep= *from++;
3165
  else
206.3.1 by Patrick Galbraith
Most everything working with client rename
3166
    sep=' ';        /* Separated with space */
1 by brian
clean slate
3167
3168
  for ( ; (c=*from) ; from++)
3169
  {
3170
    if (c == '\\' && from[1])
206.3.1 by Patrick Galbraith
Most everything working with client rename
3171
    {          /* Escaped character */
1 by brian
clean slate
3172
      /* We can't translate \0 -> ASCII 0 as replace can't handle ASCII 0 */
3173
      switch (*++from) {
3174
      case 'n':
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3175
        *to++= '\n';
3176
        break;
1 by brian
clean slate
3177
      case 't':
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3178
        *to++= '\t';
3179
        break;
1 by brian
clean slate
3180
      case 'r':
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3181
        *to++ = '\r';
3182
        break;
1 by brian
clean slate
3183
      case 'b':
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3184
        *to++ = '\b';
3185
        break;
206.3.1 by Patrick Galbraith
Most everything working with client rename
3186
      case 'Z':        /* ^Z must be escaped on Win32 */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3187
        *to++='\032';
3188
        break;
1 by brian
clean slate
3189
      default:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3190
        *to++ = *from;
3191
        break;
1 by brian
clean slate
3192
      }
3193
    }
3194
    else if (c == sep)
3195
    {
3196
      if (c == ' ' || c != *++from)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3197
        break;        /* Found end of string */
206.3.1 by Patrick Galbraith
Most everything working with client rename
3198
      *to++=c;        /* Copy duplicated separator */
1 by brian
clean slate
3199
    }
3200
    else
3201
      *to++=c;
3202
  }
3203
  if (*from != ' ' && *from)
3204
    die("Wrong string argument in %s", command->query);
3205
2445.1.3 by Olaf van der Spek
Refactor
3206
  while (charset_info->isspace(*from))  /* Point to next string */
1 by brian
clean slate
3207
    from++;
3208
206.3.1 by Patrick Galbraith
Most everything working with client rename
3209
  *to =0;        /* End of string marker */
3210
  *to_ptr= to+1;      /* Store pointer to end */
1 by brian
clean slate
3211
  *from_ptr= from;
3212
3213
  /* Check if this was a variable */
3214
  if (*start == '$')
3215
  {
3216
    const char *end= to;
3217
    VAR *var=var_get(start, &end, 0, 1);
3218
    if (var && to == (char*) end+1)
206.3.1 by Patrick Galbraith
Most everything working with client rename
3219
      return(var->str_val);  /* return found variable value */
1 by brian
clean slate
3220
  }
142.1.1 by Patrick
Removing DBUG from client
3221
  return(start);
1 by brian
clean slate
3222
}
3223
3224
928.1.6 by Eric Day
All utilities done except slap.
3225
static void set_reconnect(drizzle_con_st *con, int val)
1 by brian
clean slate
3226
{
928.1.6 by Eric Day
All utilities done except slap.
3227
  (void) con;
3228
  (void) val;
3229
/* XXX
143 by Brian Aker
Bool cleanup.
3230
  bool reconnect= val;
142.1.1 by Patrick
Removing DBUG from client
3231
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
3232
  drizzleclient_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
928.1.6 by Eric Day
All utilities done except slap.
3233
*/
1 by brian
clean slate
3234
}
3235
3236
2318.5.25 by Olaf van der Spek
Refactor
3237
static void select_connection_name(const char *name)
1 by brian
clean slate
3238
{
2318.5.25 by Olaf van der Spek
Refactor
3239
  if (!(cur_con= find_ptr2(g_connections, name)))
1 by brian
clean slate
3240
    die("connection '%s' not found in connection pool", name);
3241
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
3242
  /* Update $drizzleclient_get_server_version to that of current connection */
2318.5.26 by Olaf van der Spek
Refactor
3243
  var_set_drizzleclient_get_server_version(*cur_con);
1 by brian
clean slate
3244
}
3245
3246
2318.5.25 by Olaf van der Spek
Refactor
3247
static void select_connection(st_command* command)
1 by brian
clean slate
3248
{
3249
  char *p= command->first_argument;
3250
  if (!*p)
3251
    die("Missing connection name in connect");
2318.5.25 by Olaf van der Spek
Refactor
3252
  char* name= p;
2445.1.3 by Olaf van der Spek
Refactor
3253
  while (*p && !charset_info->isspace(*p))
1 by brian
clean slate
3254
    p++;
3255
  if (*p)
3256
    *p++= 0;
3257
  command->last_argument= p;
2318.5.25 by Olaf van der Spek
Refactor
3258
  select_connection_name(name);
1 by brian
clean slate
3259
}
3260
3261
2318.4.6 by Olaf van der Spek
Refactor
3262
static void do_close_connection(st_command* command)
1 by brian
clean slate
3263
{
2318.5.24 by Olaf van der Spek
Refactor
3264
  char* p= command->first_argument;
1 by brian
clean slate
3265
  if (!*p)
3266
    die("Missing connection name in disconnect");
2318.5.24 by Olaf van der Spek
Refactor
3267
  char* name= p;
2445.1.3 by Olaf van der Spek
Refactor
3268
  while (*p && !charset_info->isspace(*p))
1 by brian
clean slate
3269
    p++;
3270
3271
  if (*p)
3272
    *p++= 0;
3273
  command->last_argument= p;
3274
2318.5.25 by Olaf van der Spek
Refactor
3275
  st_connection* con= find_ptr2(g_connections, name);
2318.5.24 by Olaf van der Spek
Refactor
3276
  if (!con)
1 by brian
clean slate
3277
    die("connection '%s' not found in connection pool", name);
2318.5.24 by Olaf van der Spek
Refactor
3278
  g_connections.erase(name);
3279
  delete con;
1 by brian
clean slate
3280
}
3281
3282
3283
/*
3284
  Connect to a server doing several retries if needed.
3285
3286
  SYNOPSIS
3287
  safe_connect()
3288
  con               - connection structure to be used
3289
  host, user, pass, - connection parameters
3290
  db, port, sock
3291
3292
  NOTE
3293
3294
  Sometimes in a test the client starts before
3295
  the server - to solve the problem, we try again
3296
  after some sleep if connection fails the first
3297
  time
3298
3299
  This function will try to connect to the given server
3300
  "opt_max_connect_retries" times and sleep "connection_retry_sleep"
3301
  seconds between attempts before finally giving up.
3302
  This helps in situation when the client starts
3303
  before the server (which happens sometimes).
3304
  It will only ignore connection errors during these retries.
3305
3306
*/
3307
2318.5.25 by Olaf van der Spek
Refactor
3308
static st_connection* safe_connect(const char *name, const string host, const string user, const char *pass, const string db, uint32_t port)
1 by brian
clean slate
3309
{
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
3310
  uint32_t failed_attempts= 0;
2318.5.25 by Olaf van der Spek
Refactor
3311
  st_connection* con0= new st_connection;
2318.5.26 by Olaf van der Spek
Refactor
3312
  drizzle_con_st* con= *con0;
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
3313
  drizzle_con_set_tcp(con, host.c_str(), port);
1608.5.3 by Vijay Samuel
Merge fixes for password.
3314
  drizzle_con_set_auth(con, user.c_str(), pass);
2318.5.24 by Olaf van der Spek
Refactor
3315
  while (drizzle_return_t ret= drizzle_con_connect(con))
1 by brian
clean slate
3316
  {
3317
    /*
3318
      Connect failed
3319
3320
      Only allow retry if this was an error indicating the server
3321
      could not be contacted. Error code differs depending
3322
      on protocol/connection type
3323
    */
3324
928.1.6 by Eric Day
All utilities done except slap.
3325
    if ((ret == DRIZZLE_RETURN_GETADDRINFO ||
3326
         ret == DRIZZLE_RETURN_COULD_NOT_CONNECT) &&
1 by brian
clean slate
3327
        failed_attempts < opt_max_connect_retries)
3328
    {
2318.5.24 by Olaf van der Spek
Refactor
3329
      verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts, opt_max_connect_retries, ret, drizzle_con_error(con));
2318.5.25 by Olaf van der Spek
Refactor
3330
      usleep(100000);
1 by brian
clean slate
3331
    }
3332
    else
3333
    {
3334
      if (failed_attempts > 0)
2318.5.24 by Olaf van der Spek
Refactor
3335
        die("Could not open connection '%s' after %d attempts: %d %s", name, failed_attempts, ret, drizzle_con_error(con));
1 by brian
clean slate
3336
      else
2318.5.24 by Olaf van der Spek
Refactor
3337
        die("Could not open connection '%s': %d %s", name, ret, drizzle_con_error(con));
1 by brian
clean slate
3338
    }
3339
    failed_attempts++;
3340
  }
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
3341
3342
  {
3343
    std::string sql_string("CREATE SCHEMA IF NOT EXISTS mysql");
3344
    drizzle_return_t ret;
3345
    drizzle_result_st *result= drizzle_query(con, NULL, sql_string.c_str(), sql_string.size(), &ret);
3346
    if (ret != DRIZZLE_RETURN_OK)
3347
    {
3348
      die("Failed to create schema '%s': %d %s", db.c_str(), ret, drizzle_con_error(con));
3349
    }
3350
3351
    if (result)
3352
    {
3353
      drizzle_result_free(result);
3354
    }
3355
  }
3356
3357
  {
3358
    std::string sql_string("CREATE SCHEMA IF NOT EXISTS ");
3359
    sql_string+= db;
3360
    drizzle_return_t ret;
3361
    drizzle_result_st *result= drizzle_query(con, NULL, sql_string.c_str(), sql_string.size(), &ret);
3362
    if (ret != DRIZZLE_RETURN_OK)
3363
    {
3364
      die("Failed to create schema '%s': %d %s", db.c_str(), ret, drizzle_con_error(con));
3365
    }
3366
3367
    if (result)
3368
    {
3369
      drizzle_result_free(result);
3370
    }
3371
  }
3372
3373
  {
3374
    std::string sql_string("USE ");
3375
    sql_string+= db;
3376
    drizzle_return_t ret;
3377
    drizzle_result_st *result= drizzle_query(con, NULL, sql_string.c_str(), sql_string.size(), &ret);
3378
    if (ret != DRIZZLE_RETURN_OK)
3379
    {
3380
      die("Failed to use schema '%s': %d %s", db.c_str(), ret, drizzle_con_error(con));
3381
    }
3382
3383
    if (result)
3384
    {
3385
      drizzle_result_free(result);
3386
    }
3387
  }
3388
2318.5.25 by Olaf van der Spek
Refactor
3389
  return con0;
1 by brian
clean slate
3390
}
3391
3392
3393
/*
3394
  Connect to a server and handle connection errors in case they occur.
3395
3396
  SYNOPSIS
3397
  connect_n_handle_errors()
3398
  q                 - context of connect "query" (command)
3399
  con               - connection structure to be used
3400
  host, user, pass, - connection parameters
3401
  db, port, sock
3402
3403
  DESCRIPTION
3404
  This function will try to establish a connection to server and handle
3405
  possible errors in the same manner as if "connect" was usual SQL-statement
3406
  (If error is expected it will ignore it once it occurs and log the
3407
  "statement" to the query log).
3408
  Unlike safe_connect() it won't do several attempts.
3409
3410
  RETURN VALUES
3411
  1 - Connected
3412
  0 - Not connected
3413
3414
*/
3415
2318.4.6 by Olaf van der Spek
Refactor
3416
static int connect_n_handle_errors(st_command* command,
928.1.6 by Eric Day
All utilities done except slap.
3417
                                   drizzle_con_st *con, const char* host,
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3418
                                   const char* user, const char* pass,
3419
                                   const char* db, int port, const char* sock)
1 by brian
clean slate
3420
{
3421
  /* Only log if an error is expected */
3422
  if (!command->abort_on_error &&
3423
      !disable_query_log)
3424
  {
3425
    /*
3426
      Log the connect to result log
3427
    */
2318.6.9 by Olaf van der Spek
Refactor
3428
    ds_res += "connect(";
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3429
    replace_append(&ds_res, host);
2318.6.9 by Olaf van der Spek
Refactor
3430
    ds_res += ",";
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3431
    replace_append(&ds_res, user);
2318.6.9 by Olaf van der Spek
Refactor
3432
    ds_res += ",";
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3433
    replace_append(&ds_res, pass);
2318.6.9 by Olaf van der Spek
Refactor
3434
    ds_res += ",";
1 by brian
clean slate
3435
    if (db)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3436
      replace_append(&ds_res, db);
2318.6.9 by Olaf van der Spek
Refactor
3437
    ds_res += ",";
2318.6.1 by Olaf van der Spek
Refactor
3438
    replace_append_uint(ds_res, port);
2318.6.9 by Olaf van der Spek
Refactor
3439
    ds_res += ",";
1 by brian
clean slate
3440
    if (sock)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3441
      replace_append(&ds_res, sock);
2318.6.9 by Olaf van der Spek
Refactor
3442
    ds_res += ")";
3443
    ds_res += delimiter;
3444
    ds_res += "\n";
1 by brian
clean slate
3445
  }
928.1.6 by Eric Day
All utilities done except slap.
3446
  drizzle_con_set_tcp(con, host, port);
3447
  drizzle_con_set_auth(con, user, pass);
3448
  drizzle_con_set_db(con, db);
2318.5.25 by Olaf van der Spek
Refactor
3449
  if (drizzle_return_t ret= drizzle_con_connect(con))
1 by brian
clean slate
3450
  {
971.3.42 by Eric Day
Fixed return code reporting with new libdrizzle for drizzletest.
3451
    if (ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
3452
    {
3453
      var_set_errno(drizzle_con_error_code(con));
2318.5.3 by Olaf van der Spek
Refactor
3454
      handle_error(command, drizzle_con_error_code(con), drizzle_con_error(con), drizzle_con_sqlstate(con), &ds_res);
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
3455
    }
3456
    else
3457
    {
3458
      var_set_errno(ret);
3459
      handle_error(command, ret, drizzle_con_error(con), "", &ds_res);
3460
    }
1 by brian
clean slate
3461
    return 0; /* Not connected */
3462
  }
3463
  var_set_errno(0);
3464
  handle_no_error(command);
3465
  return 1; /* Connected */
3466
}
3467
3468
3469
/*
206.3.1 by Patrick Galbraith
Most everything working with client rename
3470
  Open a new connection to DRIZZLE Server with the parameters
1 by brian
clean slate
3471
  specified. Make the new connection the current connection.
3472
3473
  SYNOPSIS
3474
  do_connect()
206.3.1 by Patrick Galbraith
Most everything working with client rename
3475
  q         called command
1 by brian
clean slate
3476
3477
  DESCRIPTION
3478
  connect(<name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]]);
3479
  connect <name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]];
3480
3481
  <name> - name of the new connection
3482
  <host> - hostname of server
3483
  <user> - user to connect as
3484
  <pass> - password used when connecting
3485
  <db>   - initial db when connected
3486
  <port> - server port
3487
  <sock> - server socket
3488
  <opts> - options to use for the connection
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3489
  * SSL - use SSL if available
3490
  * COMPRESS - use compression if available
1 by brian
clean slate
3491
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3492
  */
1 by brian
clean slate
3493
2318.4.6 by Olaf van der Spek
Refactor
3494
static void do_connect(st_command* command)
1 by brian
clean slate
3495
{
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
3496
  uint32_t con_port= opt_port;
1 by brian
clean slate
3497
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3498
  string ds_connection_name;
3499
  string ds_host;
3500
  string ds_user;
3501
  string ds_password;
3502
  string ds_database;
3503
  string ds_port;
3504
  string ds_sock;
3505
  string ds_options;
1 by brian
clean slate
3506
  const struct command_arg connect_args[] = {
163 by Brian Aker
Merge Monty's code.
3507
    { "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3508
    { "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3509
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
3510
    { "passsword", ARG_STRING, false, &ds_password, "Password used when connecting" },
3511
    { "database", ARG_STRING, false, &ds_database, "Database to select after connect" },
3512
    { "port", ARG_STRING, false, &ds_port, "Port to connect to" },
3513
    { "socket", ARG_STRING, false, &ds_sock, "Socket to connect with" },
3514
    { "options", ARG_STRING, false, &ds_options, "Options to use while connecting" }
1 by brian
clean slate
3515
  };
3516
3517
  strip_parentheses(command);
3518
  check_command_args(command, command->first_argument, connect_args,
3519
                     sizeof(connect_args)/sizeof(struct command_arg),
3520
                     ',');
3521
3522
  /* Port */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3523
  if (ds_port.length())
1 by brian
clean slate
3524
  {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3525
    con_port= atoi(ds_port.c_str());
1 by brian
clean slate
3526
    if (con_port == 0)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3527
      die("Illegal argument for port: '%s'", ds_port.c_str());
1 by brian
clean slate
3528
  }
3529
3530
  /* Sock */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3531
  if (!ds_sock.empty())
1 by brian
clean slate
3532
  {
3533
    /*
3534
      If the socket is specified just as a name without path
3535
      append tmpdir in front
3536
    */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3537
    if (*ds_sock.c_str() != FN_LIBCHAR)
1 by brian
clean slate
3538
    {
3539
      char buff[FN_REFLEN];
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
3540
      internal::fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
2318.5.4 by Olaf van der Spek
Refactor
3541
      ds_sock= buff;
1 by brian
clean slate
3542
    }
3543
  }
3544
3545
  /* Options */
2318.5.3 by Olaf van der Spek
Refactor
3546
  const char* con_options= ds_options.c_str();
1 by brian
clean slate
3547
  while (*con_options)
3548
  {
3549
    /* Step past any spaces in beginning of option*/
2445.1.3 by Olaf van der Spek
Refactor
3550
    while (*con_options && charset_info->isspace(*con_options))
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3551
      con_options++;
1 by brian
clean slate
3552
    /* Find end of this option */
2318.5.4 by Olaf van der Spek
Refactor
3553
    const char* end= con_options;
2445.1.3 by Olaf van der Spek
Refactor
3554
    while (*end && !charset_info->isspace(*end))
1 by brian
clean slate
3555
      end++;
2318.5.4 by Olaf van der Spek
Refactor
3556
    die("Illegal option to connect: %.*s", (int) (end - con_options), con_options);
1 by brian
clean slate
3557
    /* Process next option */
3558
    con_options= end;
3559
  }
3560
2318.5.25 by Olaf van der Spek
Refactor
3561
  if (find_ptr2(g_connections, ds_connection_name))
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3562
    die("Connection %s already exists", ds_connection_name.c_str());
3563
2318.5.24 by Olaf van der Spek
Refactor
3564
  st_connection* con_slot= new st_connection;
1 by brian
clean slate
3565
3566
  /* Use default db name */
2318.5.3 by Olaf van der Spek
Refactor
3567
  if (ds_database.empty())
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
3568
  {
2318.5.3 by Olaf van der Spek
Refactor
3569
    ds_database= opt_db;
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
3570
  }
1 by brian
clean slate
3571
3572
  /* Special database to allow one to connect without a database name */
2318.5.3 by Olaf van der Spek
Refactor
3573
  if (ds_database == "*NO-ONE*")
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
3574
  {
632.1.12 by Monty Taylor
Fixed more sun studio warnings.
3575
    ds_database.clear();
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
3576
  }
1 by brian
clean slate
3577
2318.5.26 by Olaf van der Spek
Refactor
3578
  if (connect_n_handle_errors(command, *con_slot, ds_host.c_str(), ds_user.c_str(), 
2318.5.3 by Olaf van der Spek
Refactor
3579
    ds_password.c_str(), ds_database.c_str(), con_port, ds_sock.c_str()))
1 by brian
clean slate
3580
  {
2318.5.24 by Olaf van der Spek
Refactor
3581
    g_connections[ds_connection_name]= con_slot;
1 by brian
clean slate
3582
    cur_con= con_slot;
3583
  }
3584
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
3585
  /* Update $drizzleclient_get_server_version to that of current connection */
2318.5.26 by Olaf van der Spek
Refactor
3586
  var_set_drizzleclient_get_server_version(*cur_con);
1 by brian
clean slate
3587
}
3588
3589
2318.5.4 by Olaf van der Spek
Refactor
3590
static void do_done(st_command* command)
1 by brian
clean slate
3591
{
3592
  /* Check if empty block stack */
3593
  if (cur_block == block_stack)
3594
  {
3595
    if (*command->query != '}')
3596
      die("Stray 'end' command - end of block before beginning");
3597
    die("Stray '}' - end of block before beginning");
3598
  }
3599
3600
  /* Test if inner block has been executed */
3601
  if (cur_block->ok && cur_block->cmd == cmd_while)
3602
  {
3603
    /* Pop block from stack, re-execute outer block */
3604
    cur_block--;
3605
    parser.current_line = cur_block->line;
3606
  }
3607
  else
3608
  {
3609
    /* Pop block from stack, goto next line */
3610
    cur_block--;
3611
    parser.current_line++;
3612
  }
3613
}
3614
3615
3616
/*
3617
  Process start of a "if" or "while" statement
3618
3619
  SYNOPSIS
3620
  do_block()
3621
  cmd        Type of block
206.3.1 by Patrick Galbraith
Most everything working with client rename
3622
  q         called command
1 by brian
clean slate
3623
3624
  DESCRIPTION
3625
  if ([!]<expr>)
3626
  {
3627
  <block statements>
3628
  }
3629
3630
  while ([!]<expr>)
3631
  {
3632
  <block statements>
3633
  }
3634
3635
  Evaluates the <expr> and if it evaluates to
3636
  greater than zero executes the following code block.
3637
  A '!' can be used before the <expr> to indicate it should
3638
  be executed if it evaluates to zero.
3639
3640
*/
3641
2318.5.23 by Olaf van der Spek
Refactor
3642
static void do_block(enum block_cmd cmd, st_command* command)
1 by brian
clean slate
3643
{
3644
  char *p= command->first_argument;
3645
  const char *expr_start, *expr_end;
3646
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
144 by Brian Aker
Merging in Patrick's work.
3647
  bool not_expr= false;
1 by brian
clean slate
3648
3649
  /* Check stack overflow */
3650
  if (cur_block == block_stack_end)
3651
    die("Nesting too deeply");
3652
3653
  /* Set way to find outer block again, increase line counter */
3654
  cur_block->line= parser.current_line++;
3655
3656
  /* If this block is ignored */
3657
  if (!cur_block->ok)
3658
  {
3659
    /* Inner block should be ignored too */
3660
    cur_block++;
3661
    cur_block->cmd= cmd;
163 by Brian Aker
Merge Monty's code.
3662
    cur_block->ok= false;
142.1.1 by Patrick
Removing DBUG from client
3663
    return;
1 by brian
clean slate
3664
  }
3665
3666
  /* Parse and evaluate test expression */
3667
  expr_start= strchr(p, '(');
3668
  if (!expr_start++)
3669
    die("missing '(' in %s", cmd_name);
3670
3671
  /* Check for !<expr> */
3672
  if (*expr_start == '!')
3673
  {
163 by Brian Aker
Merge Monty's code.
3674
    not_expr= true;
1 by brian
clean slate
3675
    expr_start++; /* Step past the '!' */
3676
  }
3677
  /* Find ending ')' */
3678
  expr_end= strrchr(expr_start, ')');
3679
  if (!expr_end)
3680
    die("missing ')' in %s", cmd_name);
3681
  p= (char*)expr_end+1;
3682
2445.1.3 by Olaf van der Spek
Refactor
3683
  while (*p && charset_info->isspace(*p))
1 by brian
clean slate
3684
    p++;
3685
  if (*p && *p != '{')
3686
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
3687
2151.2.25 by Olaf van der Spek
refactor
3688
  VAR v;
1 by brian
clean slate
3689
  var_init(&v,0,0,0,0);
3690
  eval_expr(&v, expr_start, &expr_end);
3691
3692
  /* Define inner block */
3693
  cur_block++;
3694
  cur_block->cmd= cmd;
163 by Brian Aker
Merge Monty's code.
3695
  cur_block->ok= (v.int_val ? true : false);
1 by brian
clean slate
3696
3697
  if (not_expr)
3698
    cur_block->ok = !cur_block->ok;
3699
1022.4.1 by Monty Taylor
First attempt at supporting gcc-4.4.
3700
  free(v.str_val);
3701
  free(v.env_s);
1 by brian
clean slate
3702
}
3703
3704
2318.5.23 by Olaf van der Spek
Refactor
3705
static void do_delimiter(st_command* command)
1 by brian
clean slate
3706
{
3707
  char* p= command->first_argument;
3708
2445.1.3 by Olaf van der Spek
Refactor
3709
  while (*p && charset_info->isspace(*p))
1 by brian
clean slate
3710
    p++;
3711
3712
  if (!(*p))
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
3713
  {
1 by brian
clean slate
3714
    die("Can't set empty delimiter");
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
3715
  }
1 by brian
clean slate
3716
629.5.5 by Toru Maesaka
Fifth pass of replacing MySQL's strmake() with libc calls
3717
  strncpy(delimiter, p, sizeof(delimiter) - 1);
1 by brian
clean slate
3718
  delimiter_length= strlen(delimiter);
3719
3720
  command->last_argument= p + delimiter_length;
3721
}
3722
3723
893 by Brian Aker
First pass of stripping uint
3724
bool match_delimiter(int c, const char *delim, uint32_t length)
1 by brian
clean slate
3725
{
893 by Brian Aker
First pass of stripping uint
3726
  uint32_t i;
1 by brian
clean slate
3727
  char tmp[MAX_DELIMITER_LENGTH];
3728
3729
  if (c != *delim)
3730
    return 0;
3731
3732
  for (i= 1; i < length &&
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3733
         (c= my_getc(cur_file->file)) == *(delim + i);
1 by brian
clean slate
3734
       i++)
3735
    tmp[i]= c;
3736
3737
  if (i == length)
206.3.1 by Patrick Galbraith
Most everything working with client rename
3738
    return 1;          /* Found delimiter */
1 by brian
clean slate
3739
3740
  /* didn't find delimiter, push back things that we read */
3741
  my_ungetc(c);
3742
  while (i > 1)
3743
    my_ungetc(tmp[--i]);
3744
  return 0;
3745
}
3746
3747
143 by Brian Aker
Bool cleanup.
3748
static bool end_of_query(int c)
1 by brian
clean slate
3749
{
3750
  return match_delimiter(c, delimiter, delimiter_length);
3751
}
3752
3753
3754
/*
3755
  Read one "line" from the file
3756
3757
  SYNOPSIS
3758
  read_line
3759
  buf     buffer for the read line
3760
  size    size of the buffer i.e max size to read
3761
3762
  DESCRIPTION
3763
  This function actually reads several lines and adds them to the
3764
  buffer buf. It continues to read until it finds what it believes
3765
  is a complete query.
3766
3767
  Normally that means it will read lines until it reaches the
3768
  "delimiter" that marks end of query. Default delimiter is ';'
3769
  The function should be smart enough not to detect delimiter's
3770
  found inside strings surrounded with '"' and '\'' escaped strings.
3771
3772
  If the first line in a query starts with '#' or '-' this line is treated
3773
  as a comment. A comment is always terminated when end of line '\n' is
3774
  reached.
3775
3776
*/
3777
1237.6.10 by Brian Aker
Pass through charsets to remove dead code.
3778
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
3779
static int my_strnncoll_simple(const charset_info_st * const  cs, const unsigned char *s, size_t slen,
1237.6.10 by Brian Aker
Pass through charsets to remove dead code.
3780
                               const unsigned char *t, size_t tlen,
3781
                               bool t_is_prefix)
3782
{
3783
  size_t len = ( slen > tlen ) ? tlen : slen;
3784
  unsigned char *map= cs->sort_order;
3785
  if (t_is_prefix && slen > tlen)
3786
    slen=tlen;
3787
  while (len--)
3788
  {
3789
    if (map[*s++] != map[*t++])
3790
      return ((int) map[s[-1]] - (int) map[t[-1]]);
3791
  }
3792
  /*
3793
    We can't use (slen - tlen) here as the result may be outside of the
3794
    precision of a signed int
3795
  */
3796
  return slen > tlen ? 1 : slen < tlen ? -1 : 0 ;
3797
}
3798
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
3799
static int read_line(char *buf, int size)
1 by brian
clean slate
3800
{
3801
  char c, last_quote= 0;
3802
  char *p= buf, *buf_end= buf + size - 1;
3803
  int skip_char= 0;
3804
  enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
3805
        R_COMMENT, R_LINE_START} state= R_LINE_START;
142.1.1 by Patrick
Removing DBUG from client
3806
1 by brian
clean slate
3807
3808
  start_lineno= cur_file->lineno;
3809
  for (; p < buf_end ;)
3810
  {
3811
    skip_char= 0;
3812
    c= my_getc(cur_file->file);
3813
    if (feof(cur_file->file))
3814
    {
3815
  found_eof:
3816
      if (cur_file->file != stdin)
3817
      {
910.1.3 by Brian Aker
Remove my_fopen() and key_map.cc file (thanks to Jay's lcov)
3818
        fclose(cur_file->file);
1 by brian
clean slate
3819
        cur_file->file= 0;
3820
      }
481 by Brian Aker
Remove all of uchar.
3821
      free((unsigned char*) cur_file->file_name);
1 by brian
clean slate
3822
      cur_file->file_name= 0;
2151.2.27 by Olaf van der Spek
refactor
3823
      if (cur_file == file_stack.data())
1 by brian
clean slate
3824
      {
3825
        /* We're back at the first file, check if
3826
           all { have matching }
3827
        */
3828
        if (cur_block != block_stack)
3829
          die("Missing end of block");
3830
3831
        *p= 0;
142.1.1 by Patrick
Removing DBUG from client
3832
        return(1);
1 by brian
clean slate
3833
      }
3834
      cur_file--;
3835
      start_lineno= cur_file->lineno;
3836
      continue;
3837
    }
3838
3839
    if (c == '\n')
3840
    {
3841
      /* Line counting is independent of state */
3842
      cur_file->lineno++;
3843
3844
      /* Convert cr/lf to lf */
3845
      if (p != buf && *(p-1) == '\r')
3846
        p--;
3847
    }
3848
3849
    switch(state) {
3850
    case R_NORMAL:
3851
      if (end_of_query(c))
3852
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3853
        *p= 0;
3854
        return(0);
1 by brian
clean slate
3855
      }
3856
      else if ((c == '{' &&
481 by Brian Aker
Remove all of uchar.
3857
                (!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
1067.4.14 by Nathan Williams
Fixed type differences for min/max calls on OSX.
3858
                                      (unsigned char*) buf, min((ptrdiff_t)5, p - buf), 0) ||
481 by Brian Aker
Remove all of uchar.
3859
                 !my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
1067.4.14 by Nathan Williams
Fixed type differences for min/max calls on OSX.
3860
                                      (unsigned char*) buf, min((ptrdiff_t)2, p - buf), 0))))
1 by brian
clean slate
3861
      {
3862
        /* Only if and while commands can be terminated by { */
3863
        *p++= c;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3864
        *p= 0;
3865
        return(0);
1 by brian
clean slate
3866
      }
3867
      else if (c == '\'' || c == '"' || c == '`')
3868
      {
3869
        last_quote= c;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3870
        state= R_Q;
1 by brian
clean slate
3871
      }
3872
      break;
3873
3874
    case R_COMMENT:
3875
      if (c == '\n')
3876
      {
3877
        /* Comments are terminated by newline */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3878
        *p= 0;
3879
        return(0);
1 by brian
clean slate
3880
      }
3881
      break;
3882
3883
    case R_LINE_START:
3884
      if (c == '#' || c == '-')
3885
      {
3886
        /* A # or - in the first position of the line - this is a comment */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3887
        state = R_COMMENT;
1 by brian
clean slate
3888
      }
2445.1.3 by Olaf van der Spek
Refactor
3889
      else if (charset_info->isspace(c))
1 by brian
clean slate
3890
      {
3891
        /* Skip all space at begining of line */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3892
        if (c == '\n')
1 by brian
clean slate
3893
        {
3894
          /* Query hasn't started yet */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3895
          start_lineno= cur_file->lineno;
1 by brian
clean slate
3896
        }
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3897
        skip_char= 1;
1 by brian
clean slate
3898
      }
3899
      else if (end_of_query(c))
3900
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3901
        *p= 0;
3902
        return(0);
1 by brian
clean slate
3903
      }
3904
      else if (c == '}')
3905
      {
3906
        /* A "}" need to be by itself in the begining of a line to terminate */
3907
        *p++= c;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3908
        *p= 0;
3909
        return(0);
1 by brian
clean slate
3910
      }
3911
      else if (c == '\'' || c == '"' || c == '`')
3912
      {
3913
        last_quote= c;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3914
        state= R_Q;
1 by brian
clean slate
3915
      }
3916
      else
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3917
        state= R_NORMAL;
1 by brian
clean slate
3918
      break;
3919
3920
    case R_Q:
3921
      if (c == last_quote)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3922
        state= R_NORMAL;
1 by brian
clean slate
3923
      else if (c == '\\')
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3924
        state= R_SLASH_IN_Q;
1 by brian
clean slate
3925
      break;
3926
3927
    case R_SLASH_IN_Q:
3928
      state= R_Q;
3929
      break;
3930
3931
    }
3932
3933
    if (!skip_char)
3934
    {
3935
      /* Could be a multibyte character */
3936
      /* This code is based on the code in "sql_load.cc" */
3937
      int charlen = my_mbcharlen(charset_info, c);
3938
      /* We give up if multibyte character is started but not */
3939
      /* completed before we pass buf_end */
3940
      if ((charlen > 1) && (p + charlen) <= buf_end)
3941
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3942
        int i;
3943
        char* mb_start = p;
3944
3945
        *p++ = c;
3946
3947
        for (i= 1; i < charlen; i++)
3948
        {
3949
          if (feof(cur_file->file))
3950
            goto found_eof;
3951
          c= my_getc(cur_file->file);
3952
          *p++ = c;
3953
        }
3954
        if (! my_ismbchar(charset_info, mb_start, p))
3955
        {
3956
          /* It was not a multiline char, push back the characters */
3957
          /* We leave first 'c', i.e. pretend it was a normal char */
3958
          while (p > mb_start)
3959
            my_ungetc(*--p);
3960
        }
1 by brian
clean slate
3961
      }
3962
      else
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3963
        *p++= c;
1 by brian
clean slate
3964
    }
3965
  }
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
3966
  die("The input buffer is too small for this query.x\n"        \
1 by brian
clean slate
3967
      "check your query or increase MAX_QUERY and recompile");
142.1.1 by Patrick
Removing DBUG from client
3968
  return(0);
1 by brian
clean slate
3969
}
3970
3971
3972
/*
3973
  Convert the read query to result format version 1
3974
3975
  That is: After newline, all spaces need to be skipped
3976
  unless the previous char was a quote
3977
3978
  This is due to an old bug that has now been fixed, but the
3979
  version 1 output format is preserved by using this function
3980
3981
*/
3982
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
3983
static void convert_to_format_v1(char* query)
1 by brian
clean slate
3984
{
3985
  int last_c_was_quote= 0;
3986
  char *p= query, *to= query;
376 by Brian Aker
strend remove
3987
  char *end= strchr(query, '\0');
1 by brian
clean slate
3988
  char last_c;
3989
3990
  while (p <= end)
3991
  {
3992
    if (*p == '\n' && !last_c_was_quote)
3993
    {
3994
      *to++ = *p++; /* Save the newline */
3995
3996
      /* Skip any spaces on next line */
2445.1.3 by Olaf van der Spek
Refactor
3997
      while (*p && charset_info->isspace(*p))
1 by brian
clean slate
3998
        p++;
3999
4000
      last_c_was_quote= 0;
4001
    }
4002
    else if (*p == '\'' || *p == '"' || *p == '`')
4003
    {
4004
      last_c= *p;
4005
      *to++ = *p++;
4006
4007
      /* Copy anything until the next quote of same type */
4008
      while (*p && *p != last_c)
4009
        *to++ = *p++;
4010
4011
      *to++ = *p++;
4012
4013
      last_c_was_quote= 1;
4014
    }
4015
    else
4016
    {
4017
      *to++ = *p++;
4018
      last_c_was_quote= 0;
4019
    }
4020
  }
4021
}
4022
4023
4024
/*
4025
  Check a command that is about to be sent (or should have been
206.3.1 by Patrick Galbraith
Most everything working with client rename
4026
  sent if parsing was enabled) to DRIZZLE server for
1 by brian
clean slate
4027
  suspicious things and generate warnings.
4028
*/
4029
2318.4.6 by Olaf van der Spek
Refactor
4030
static void scan_command_for_warnings(st_command* command)
1 by brian
clean slate
4031
{
4032
  const char *ptr= command->query;
4033
2318.5.3 by Olaf van der Spek
Refactor
4034
  while (*ptr)
1 by brian
clean slate
4035
  {
4036
    /*
4037
      Look for query's that lines that start with a -- comment
206.3.1 by Patrick Galbraith
Most everything working with client rename
4038
      and has a drizzletest command
1 by brian
clean slate
4039
    */
4040
    if (ptr[0] == '\n' &&
4041
        ptr[1] && ptr[1] == '-' &&
4042
        ptr[2] && ptr[2] == '-' &&
4043
        ptr[3])
4044
    {
893 by Brian Aker
First pass of stripping uint
4045
      uint32_t type;
1 by brian
clean slate
4046
      char save;
4047
      char *end, *start= (char*)ptr+3;
4048
      /* Skip leading spaces */
2445.1.3 by Olaf van der Spek
Refactor
4049
      while (*start && charset_info->isspace(*start))
1 by brian
clean slate
4050
        start++;
4051
      end= start;
4052
      /* Find end of command(next space) */
2445.1.3 by Olaf van der Spek
Refactor
4053
      while (*end && !charset_info->isspace(*end))
1 by brian
clean slate
4054
        end++;
4055
      save= *end;
4056
      *end= 0;
2275.2.20 by Olaf van der Spek
Typelib Options
4057
      type= command_typelib.find_type(start, TYPELIB::e_default);
1 by brian
clean slate
4058
      if (type)
2318.5.3 by Olaf van der Spek
Refactor
4059
        warning_msg("Embedded drizzletest command '--%s' detected in query '%s' was this intentional? ", start, command->query);
1 by brian
clean slate
4060
      *end= save;
4061
    }
4062
    ptr++;
4063
  }
4064
}
4065
4066
/*
4067
  Check for unexpected "junk" after the end of query
4068
  This is normally caused by missing delimiters or when
4069
  switching between different delimiters
4070
*/
4071
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
4072
static void check_eol_junk_line(const char *line)
1 by brian
clean slate
4073
{
4074
  const char *p= line;
4075
4076
  /* Check for extra delimiter */
4077
  if (*p && !strncmp(p, delimiter, delimiter_length))
4078
    die("Extra delimiter \"%s\" found", delimiter);
4079
4080
  /* Allow trailing # comment */
4081
  if (*p && *p != '#')
4082
  {
4083
    if (*p == '\n')
4084
      die("Missing delimiter");
4085
    die("End of line junk detected: \"%s\"", p);
4086
  }
142.1.1 by Patrick
Removing DBUG from client
4087
  return;
1 by brian
clean slate
4088
}
4089
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
4090
static void check_eol_junk(const char *eol)
1 by brian
clean slate
4091
{
4092
  const char *p= eol;
4093
4094
  /* Skip past all spacing chars and comments */
2445.1.3 by Olaf van der Spek
Refactor
4095
  while (*p && (charset_info->isspace(*p) || *p == '#' || *p == '\n'))
1 by brian
clean slate
4096
  {
4097
    /* Skip past comments started with # and ended with newline */
4098
    if (*p && *p == '#')
4099
    {
4100
      p++;
4101
      while (*p && *p != '\n')
4102
        p++;
4103
    }
4104
4105
    /* Check this line */
4106
    if (*p && *p == '\n')
4107
      check_eol_junk_line(p);
4108
4109
    if (*p)
4110
      p++;
4111
  }
4112
4113
  check_eol_junk_line(p);
4114
142.1.1 by Patrick
Removing DBUG from client
4115
  return;
1 by brian
clean slate
4116
}
4117
4118
/*
4119
  Create a command from a set of lines
4120
4121
  SYNOPSIS
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4122
  read_command()
4123
  command_ptr pointer where to return the new query
1 by brian
clean slate
4124
4125
  DESCRIPTION
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4126
  Converts lines returned by read_line into a command, this involves
4127
  parsing the first word in the read line to find the command type.
1 by brian
clean slate
4128
4129
  A -- comment may contain a valid query as the first word after the
4130
  comment start. Thus it's always checked to see if that is the case.
4131
  The advantage with this approach is to be able to execute commands
4132
  terminated by new line '\n' regardless how many "delimiter" it contain.
4133
*/
4134
1579.3.8 by Stewart Smith
we need to increase MAX_QUERY size in drizzletest to run a query to test if we can properly create an ENUM column that has more than the maximum number of elements
4135
#define MAX_QUERY (768*1024*2) /* 256K -- a test in sp-big is >128K */
1 by brian
clean slate
4136
static char read_command_buf[MAX_QUERY];
4137
2318.5.23 by Olaf van der Spek
Refactor
4138
static int read_command(st_command** command_ptr)
1 by brian
clean slate
4139
{
4140
  char *p= read_command_buf;
2318.5.23 by Olaf van der Spek
Refactor
4141
  st_command* command;
142.1.1 by Patrick
Removing DBUG from client
4142
1 by brian
clean slate
4143
4144
  if (parser.current_line < parser.read_lines)
4145
  {
373.1.6 by Monty Taylor
Moved q_lines to vector.
4146
    *command_ptr= q_lines[parser.current_line];
142.1.1 by Patrick
Removing DBUG from client
4147
    return(0);
1 by brian
clean slate
4148
  }
2318.6.90 by Olaf van der Spek
Refactor
4149
  *command_ptr= command= new st_command;
373.1.6 by Monty Taylor
Moved q_lines to vector.
4150
  q_lines.push_back(command);
1 by brian
clean slate
4151
  command->type= Q_UNKNOWN;
4152
4153
  read_command_buf[0]= 0;
4154
  if (read_line(read_command_buf, sizeof(read_command_buf)))
4155
  {
4156
    check_eol_junk(read_command_buf);
142.1.1 by Patrick
Removing DBUG from client
4157
    return(1);
1 by brian
clean slate
4158
  }
4159
4160
  convert_to_format_v1(read_command_buf);
4161
4162
  if (*p == '#')
4163
  {
4164
    command->type= Q_COMMENT;
4165
  }
4166
  else if (p[0] == '-' && p[1] == '-')
4167
  {
4168
    command->type= Q_COMMENT_WITH_COMMAND;
4169
    p+= 2; /* Skip past -- */
4170
  }
4171
4172
  /* Skip leading spaces */
2445.1.3 by Olaf van der Spek
Refactor
4173
  while (*p && charset_info->isspace(*p))
1 by brian
clean slate
4174
    p++;
4175
2318.4.5 by Olaf van der Spek
Refactor
4176
  command->query_buf= command->query= strdup(p);
1 by brian
clean slate
4177
4178
  /* Calculate first word length(the command), terminated by space or ( */
4179
  p= command->query;
2445.1.3 by Olaf van der Spek
Refactor
4180
  while (*p && !charset_info->isspace(*p) && *p != '(')
1 by brian
clean slate
4181
    p++;
895 by Brian Aker
Completion (?) of uint conversion.
4182
  command->first_word_len= (uint32_t) (p - command->query);
1 by brian
clean slate
4183
4184
  /* Skip spaces between command and first argument */
2445.1.3 by Olaf van der Spek
Refactor
4185
  while (*p && charset_info->isspace(*p))
1 by brian
clean slate
4186
    p++;
4187
  command->first_argument= p;
4188
376 by Brian Aker
strend remove
4189
  command->end= strchr(command->query, '\0');
1 by brian
clean slate
4190
  command->query_len= (command->end - command->query);
4191
  parser.read_lines++;
2392.1.2 by Brian Aker
This fixes up the valgrind issues (ie path, and the testing of drizzletest)
4192
142.1.1 by Patrick
Removing DBUG from client
4193
  return(0);
1 by brian
clean slate
4194
}
4195
4196
/*
4197
  Write the content of str into file
4198
4199
  SYNOPSIS
4200
  str_to_file2
4201
  fname - name of file to truncate/create and write to
4202
  str - content to write to file
4203
  size - size of content witten to file
4204
  append - append to file instead of overwriting old file
4205
*/
4206
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4207
void str_to_file2(const char *fname, const char *str, int size, bool append)
1 by brian
clean slate
4208
{
4209
  char buff[FN_REFLEN];
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
4210
  if (!internal::test_if_hard_path(fname))
1 by brian
clean slate
4211
  {
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4212
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),fname);
1 by brian
clean slate
4213
    fname= buff;
4214
  }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
4215
  internal::fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
1 by brian
clean slate
4216
2318.5.4 by Olaf van der Spek
Refactor
4217
  int flags= O_WRONLY | O_CREAT;
1 by brian
clean slate
4218
  if (!append)
4219
    flags|= O_TRUNC;
2318.5.4 by Olaf van der Spek
Refactor
4220
  int fd= internal::my_open(buff, flags, MYF(MY_WME | MY_FFNF));
4221
  if (fd < 0)
1 by brian
clean slate
4222
    die("Could not open '%s' for writing: errno = %d", buff, errno);
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
4223
  if (append && lseek(fd, 0, SEEK_END) == MY_FILEPOS_ERROR)
1 by brian
clean slate
4224
    die("Could not find end of file '%s': errno = %d", buff, errno);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
4225
  if (internal::my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
1 by brian
clean slate
4226
    die("write failed");
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
4227
  internal::my_close(fd, MYF(0));
1 by brian
clean slate
4228
}
4229
4230
/*
4231
  Write the content of str into file
4232
4233
  SYNOPSIS
4234
  str_to_file
4235
  fname - name of file to truncate/create and write to
4236
  str - content to write to file
4237
  size - size of content witten to file
4238
*/
4239
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4240
void str_to_file(const char *fname, const char *str, int size)
1 by brian
clean slate
4241
{
163 by Brian Aker
Merge Monty's code.
4242
  str_to_file2(fname, str, size, false);
1 by brian
clean slate
4243
}
4244
4245
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4246
void dump_result_to_log_file(const char *buf, int size)
1 by brian
clean slate
4247
{
4248
  char log_file[FN_REFLEN];
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4249
  str_to_file(internal::fn_format(log_file, result_file_name.c_str(), opt_logdir.c_str(), ".log",
4250
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
1 by brian
clean slate
4251
                        MY_REPLACE_EXT),
4252
              buf, size);
2318.5.4 by Olaf van der Spek
Refactor
4253
  fprintf(stderr, "\nMore results from queries before failure can be found in %s\n", log_file);
1 by brian
clean slate
4254
}
4255
2151.2.17 by Olaf van der Spek
drizzletest refactoring
4256
void dump_progress()
1 by brian
clean slate
4257
{
4258
  char progress_file[FN_REFLEN];
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4259
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4260
                        opt_logdir.c_str(), ".progress",
4261
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
1 by brian
clean slate
4262
                        MY_REPLACE_EXT),
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4263
              ds_progress.c_str(), ds_progress.length());
1 by brian
clean slate
4264
}
4265
2151.2.17 by Olaf van der Spek
drizzletest refactoring
4266
void dump_warning_messages()
1 by brian
clean slate
4267
{
4268
  char warn_file[FN_REFLEN];
4269
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4270
  str_to_file(internal::fn_format(warn_file, result_file_name.c_str(), opt_logdir.c_str(), ".warnings",
4271
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
1 by brian
clean slate
4272
                        MY_REPLACE_EXT),
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4273
              ds_warning_messages.c_str(), ds_warning_messages.length());
1 by brian
clean slate
4274
}
4275
4276
4277
/*
4278
  Append the result for one field to the dynamic string ds
4279
*/
4280
928.1.6 by Eric Day
All utilities done except slap.
4281
static void append_field(string *ds, uint32_t col_idx, drizzle_column_st *column,
151 by Brian Aker
Ulonglong to uint64_t
4282
                         const char* val, uint64_t len, bool is_null)
1 by brian
clean slate
4283
{
4284
  if (col_idx < max_replace_column && replace_column[col_idx])
4285
  {
4286
    val= replace_column[col_idx];
4287
    len= strlen(val);
4288
  }
4289
  else if (is_null)
4290
  {
4291
    val= "NULL";
4292
    len= 4;
4293
  }
4294
4295
  if (!display_result_vertically)
4296
  {
4297
    if (col_idx)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4298
      ds->append("\t");
2318.5.22 by Olaf van der Spek
Refactor
4299
    replace_append_mem(*ds, val, (int)len);
1 by brian
clean slate
4300
  }
4301
  else
4302
  {
928.1.6 by Eric Day
All utilities done except slap.
4303
    ds->append(drizzle_column_name(column));
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4304
    ds->append("\t");
2318.5.22 by Olaf van der Spek
Refactor
4305
    replace_append_mem(*ds, val, (int)len);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4306
    ds->append("\n");
1 by brian
clean slate
4307
  }
4308
}
4309
4310
4311
/*
4312
  Append all results to the dynamic string separated with '\t'
4313
  Values may be converted with 'replace_column'
4314
*/
4315
2318.5.21 by Olaf van der Spek
Refactor
4316
static void append_result(string *ds, drizzle::result_c& res)
1 by brian
clean slate
4317
{
2318.5.21 by Olaf van der Spek
Refactor
4318
  uint32_t num_fields= res.column_count();
4319
  while (drizzle_row_t row = res.row_next())
1 by brian
clean slate
4320
  {
2318.5.21 by Olaf van der Spek
Refactor
4321
    size_t* lengths = res.row_field_sizes();
4322
    res.column_seek(0);
2318.5.4 by Olaf van der Spek
Refactor
4323
    for (uint32_t i = 0; i < num_fields; i++)
928.1.8 by Eric Day
All tests now passing now, fixed a few more client utility bugs.
4324
    {
2318.5.21 by Olaf van der Spek
Refactor
4325
      drizzle_column_st* column= res.column_next();
4326
      if (row[i] && drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
2187.3.1 by Monty Taylor
Make boolean return as tinyint through the mysql_protocol, so that php and
4327
      {
4328
        if (boost::lexical_cast<uint32_t>(row[i]))
4329
        {
2318.5.21 by Olaf van der Spek
Refactor
4330
          if (drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED)
2187.3.5 by Monty Taylor
Getting closer.
4331
          {
4332
            append_field(ds, i, column, "YES", 3, false);
4333
          }
4334
          else
4335
          {
4336
            append_field(ds, i, column, "TRUE", 4, false);
4337
          }
2187.3.1 by Monty Taylor
Make boolean return as tinyint through the mysql_protocol, so that php and
4338
        }
4339
        else
4340
        {
2318.5.21 by Olaf van der Spek
Refactor
4341
          if (drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED)
2187.3.5 by Monty Taylor
Getting closer.
4342
          {
4343
            append_field(ds, i, column, "NO", 2, false);
4344
          }
4345
          else
4346
          {
4347
            append_field(ds, i, column, "FALSE", 5, false);
4348
          }
2187.3.1 by Monty Taylor
Make boolean return as tinyint through the mysql_protocol, so that php and
4349
        }
4350
      }
4351
      else
4352
      {
2318.5.4 by Olaf van der Spek
Refactor
4353
        append_field(ds, i, column, (const char*)row[i], lengths[i], !row[i]);
2187.3.1 by Monty Taylor
Make boolean return as tinyint through the mysql_protocol, so that php and
4354
      }
928.1.8 by Eric Day
All tests now passing now, fixed a few more client utility bugs.
4355
    }
1 by brian
clean slate
4356
    if (!display_result_vertically)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4357
      ds->append("\n");
1 by brian
clean slate
4358
  }
4359
}
4360
4361
4362
/*
4363
  Append metadata for fields to output
4364
*/
4365
2318.6.1 by Olaf van der Spek
Refactor
4366
static void append_metadata(string& ds, drizzle::result_c& res)
1 by brian
clean slate
4367
{
2318.6.1 by Olaf van der Spek
Refactor
4368
  ds += "Catalog\tDatabase\tTable\tTable_alias\tColumn\tColumn_alias\tType\tLength\tMax length\tIs_null\tFlags\tDecimals\tCharsetnr\n";
2318.5.21 by Olaf van der Spek
Refactor
4369
  res.column_seek(0);
4370
  while (drizzle_column_st* column= res.column_next())
1 by brian
clean slate
4371
  {
2318.6.1 by Olaf van der Spek
Refactor
4372
    ds += drizzle_column_catalog(column);
4373
    ds += "\t";
4374
    ds += drizzle_column_db(column);
4375
    ds += "\t";
4376
    ds += drizzle_column_orig_table(column);
4377
    ds += "\t";
4378
    ds += drizzle_column_table(column);
4379
    ds += "\t";
4380
    ds += drizzle_column_orig_name(column);
4381
    ds += "\t";
4382
    ds += drizzle_column_name(column);
4383
    ds += "\t";
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4384
    replace_append_uint(ds, drizzle_column_type_drizzle(column));
2318.6.1 by Olaf van der Spek
Refactor
4385
    ds += "\t";
928.1.6 by Eric Day
All utilities done except slap.
4386
    replace_append_uint(ds, drizzle_column_size(column));
2318.6.1 by Olaf van der Spek
Refactor
4387
    ds += "\t";
2318.5.21 by Olaf van der Spek
Refactor
4388
    replace_append_uint(ds, drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY ? 1 : drizzle_column_max_size(column));
2318.6.1 by Olaf van der Spek
Refactor
4389
    ds += "\t";
2318.6.9 by Olaf van der Spek
Refactor
4390
    ds += drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL ? "N" : "Y";
2318.6.1 by Olaf van der Spek
Refactor
4391
    ds += "\t";
928.1.6 by Eric Day
All utilities done except slap.
4392
    replace_append_uint(ds, drizzle_column_flags(column));
2318.6.1 by Olaf van der Spek
Refactor
4393
    ds += "\t";
928.1.6 by Eric Day
All utilities done except slap.
4394
    replace_append_uint(ds, drizzle_column_decimals(column));
2318.6.1 by Olaf van der Spek
Refactor
4395
    ds += "\t";
928.1.6 by Eric Day
All utilities done except slap.
4396
    replace_append_uint(ds, drizzle_column_charset(column));
2318.6.1 by Olaf van der Spek
Refactor
4397
    ds += "\n";
1 by brian
clean slate
4398
  }
4399
}
4400
4401
4402
/*
4403
  Append affected row count and other info to output
4404
*/
4405
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4406
static void append_info(string *ds, uint64_t affected_rows,
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
4407
                        const char *info)
1 by brian
clean slate
4408
{
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.
4409
  ostringstream buf;
4410
  buf << "affected rows: " << affected_rows << endl;
4411
  ds->append(buf.str());
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4412
  if (info && strcmp(info, ""))
1 by brian
clean slate
4413
  {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4414
    ds->append("info: ");
4415
    ds->append(info);
4416
    ds->append("\n", 1);
1 by brian
clean slate
4417
  }
4418
}
4419
4420
4421
/*
4422
  Display the table headings with the names tab separated
4423
*/
4424
2318.5.21 by Olaf van der Spek
Refactor
4425
static void append_table_headings(string& ds, drizzle::result_c& res)
1 by brian
clean slate
4426
{
928.1.6 by Eric Day
All utilities done except slap.
4427
  uint32_t col_idx= 0;
2318.5.21 by Olaf van der Spek
Refactor
4428
  res.column_seek(0);
4429
  while (drizzle_column_st* column= res.column_next())
1 by brian
clean slate
4430
  {
4431
    if (col_idx)
2318.5.11 by Olaf van der Spek
Refactor
4432
      ds += "\t";
4433
    replace_append(&ds, drizzle_column_name(column));
928.1.6 by Eric Day
All utilities done except slap.
4434
    col_idx++;
1 by brian
clean slate
4435
  }
2318.5.11 by Olaf van der Spek
Refactor
4436
  ds += "\n";
1 by brian
clean slate
4437
}
4438
4439
/*
4440
  Fetch warnings from server and append to ds
4441
4442
  RETURN VALUE
4443
  Number of warnings appended to ds
4444
*/
4445
2318.5.34 by Olaf van der Spek
Refactor
4446
static int append_warnings(string& ds, drizzle::connection_c& con, drizzle::result_c& res)
1 by brian
clean slate
4447
{
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4448
  uint32_t count= drizzle_result_warning_count(res);
2318.5.11 by Olaf van der Spek
Refactor
4449
  if (!count)
4450
    return 0;
4451
4452
  drizzle::result_c warn_res;
2318.5.37 by Olaf van der Spek
Refactor
4453
  dt_query(con, warn_res, "show warnings");
2318.5.21 by Olaf van der Spek
Refactor
4454
  append_result(&ds, warn_res);
2318.5.11 by Olaf van der Spek
Refactor
4455
  return count;
1 by brian
clean slate
4456
}
4457
4458
4459
/*
206.3.1 by Patrick Galbraith
Most everything working with client rename
4460
  Run query using DRIZZLE C API
1 by brian
clean slate
4461
4462
  SYNOPSIS
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4463
  run_query_normal()
4464
  drizzle  DRIZZLE handle
4465
  command  current command pointer
4466
  flags  flags indicating if we should SEND and/or REAP
4467
  query  query string to execute
4468
  query_len  length query string to execute
4469
  ds    output buffer where to store result form query
1 by brian
clean slate
4470
*/
4471
2318.5.34 by Olaf van der Spek
Refactor
4472
static void run_query_normal(st_connection& cn,
2318.4.6 by Olaf van der Spek
Refactor
4473
                             st_command* command,
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
4474
                             int flags, char *query, int query_len,
2318.5.21 by Olaf van der Spek
Refactor
4475
                             string *ds, string& ds_warnings)
1 by brian
clean slate
4476
{
928.1.6 by Eric Day
All utilities done except slap.
4477
  drizzle_return_t ret;
2318.5.34 by Olaf van der Spek
Refactor
4478
  drizzle_con_st *con= cn;
928.1.6 by Eric Day
All utilities done except slap.
4479
  int err= 0;
1 by brian
clean slate
4480
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4481
  drizzle_con_add_options(con, DRIZZLE_CON_NO_RESULT_READ);
4482
2318.5.20 by Olaf van der Spek
Refactor
4483
  drizzle::result_c res;
1 by brian
clean slate
4484
  if (flags & QUERY_SEND_FLAG)
4485
  {
4486
    /*
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4487
     * Send the query
4488
     */
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4489
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4490
    (void) drizzle_query(con, res, query, query_len, &ret);
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4491
    if (ret != DRIZZLE_RETURN_OK)
1 by brian
clean slate
4492
    {
971.3.42 by Eric Day
Fixed return code reporting with new libdrizzle for drizzletest.
4493
      if (ret == DRIZZLE_RETURN_ERROR_CODE ||
4494
          ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
928.1.6 by Eric Day
All utilities done except slap.
4495
      {
2318.5.20 by Olaf van der Spek
Refactor
4496
        err= res.error_code();
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4497
        handle_error(command, err, res.error(), drizzle_result_sqlstate(res), ds);
928.1.6 by Eric Day
All utilities done except slap.
4498
      }
4499
      else
4500
      {
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4501
        handle_error(command, ret, drizzle_con_error(con), "", ds);
928.1.6 by Eric Day
All utilities done except slap.
4502
        err= ret;
4503
      }
1 by brian
clean slate
4504
      goto end;
4505
    }
4506
  }
4507
  if (!(flags & QUERY_REAP_FLAG))
142.1.1 by Patrick
Removing DBUG from client
4508
    return;
1 by brian
clean slate
4509
4510
  {
4511
    /*
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4512
     * Read the result packet
4513
     */
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4514
    if (drizzle_result_read(con, res, &ret) == NULL ||
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4515
        ret != DRIZZLE_RETURN_OK)
4516
    {
4517
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
4518
      {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4519
        handle_error(command, res.error_code(), res.error(), drizzle_result_sqlstate(res), ds);
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4520
      }
4521
      else
4522
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4523
      err= ret;
4524
      goto end;
4525
    }
4526
4527
    /*
1 by brian
clean slate
4528
      Store the result of the query if it will return any fields
4529
    */
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4530
    if (res.column_count() && (ret= drizzle_result_buffer(res)) != DRIZZLE_RETURN_OK)
1 by brian
clean slate
4531
    {
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4532
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
4533
      {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4534
        handle_error(command, res.error_code(), res.error(), drizzle_result_sqlstate(res), ds);
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4535
      }
4536
      else
4537
        handle_error(command, ret, drizzle_con_error(con), "", ds);
928.1.6 by Eric Day
All utilities done except slap.
4538
      err= ret;
1 by brian
clean slate
4539
      goto end;
4540
    }
4541
4542
    if (!disable_result_log)
4543
    {
151 by Brian Aker
Ulonglong to uint64_t
4544
      uint64_t affected_rows= 0;    /* Ok to be undef if 'disable_info' is set */
1 by brian
clean slate
4545
2318.5.20 by Olaf van der Spek
Refactor
4546
      if (res.column_count())
1 by brian
clean slate
4547
      {
236.3.5 by Andrey Hristov
Constify libdrizzle functions
4548
        if (display_metadata)
2318.6.1 by Olaf van der Spek
Refactor
4549
          append_metadata(*ds, res);
1 by brian
clean slate
4550
236.3.5 by Andrey Hristov
Constify libdrizzle functions
4551
        if (!display_result_vertically)
2318.5.21 by Olaf van der Spek
Refactor
4552
          append_table_headings(*ds, res);
1 by brian
clean slate
4553
2318.5.21 by Olaf van der Spek
Refactor
4554
        append_result(ds, res);
1 by brian
clean slate
4555
      }
4556
4557
      /*
1165.1.17 by Stewart Smith
remove unused oldlibdrizzle drizzleclient_affected_rows()
4558
        Need to call drizzle_result_affected_rows() before the "new"
1 by brian
clean slate
4559
        query to find the warnings
4560
      */
4561
      if (!disable_info)
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4562
        affected_rows= drizzle_result_affected_rows(res);
1 by brian
clean slate
4563
4564
      /*
4565
        Add all warnings to the result. We can't do this if we are in
4566
        the middle of processing results from multi-statement, because
4567
        this will break protocol.
4568
      */
928.1.6 by Eric Day
All utilities done except slap.
4569
      if (!disable_warnings)
1 by brian
clean slate
4570
      {
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4571
        drizzle_con_remove_options(con, DRIZZLE_CON_NO_RESULT_READ);
2318.5.34 by Olaf van der Spek
Refactor
4572
        if (append_warnings(ds_warnings, cn, res) || not ds_warnings.empty())
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4573
        {
4574
          ds->append("Warnings:\n", 10);
2318.5.21 by Olaf van der Spek
Refactor
4575
          *ds += ds_warnings;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4576
        }
1 by brian
clean slate
4577
      }
4578
4579
      if (!disable_info)
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
4580
        append_info(ds, affected_rows, drizzle_result_info(res));
1 by brian
clean slate
4581
    }
4582
4583
  }
4584
4585
  /* If we come here the query is both executed and read successfully */
4586
  handle_no_error(command);
4587
4588
end:
4589
4590
  /*
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
4591
    We save the return code (drizzleclient_errno(drizzle)) from the last call sent
4592
    to the server into the drizzletest builtin variable $drizzleclient_errno. This
1 by brian
clean slate
4593
    variable then can be used from the test case itself.
4594
  */
928.1.7 by Eric Day
Tools mostly converted, still fixing bugs from test suite.
4595
  drizzle_con_remove_options(con, DRIZZLE_CON_NO_RESULT_READ);
928.1.6 by Eric Day
All utilities done except slap.
4596
  var_set_errno(err);
1 by brian
clean slate
4597
}
4598
4599
4600
/*
4601
  Handle errors which occurred during execution
4602
4603
  SYNOPSIS
4604
  handle_error()
4605
  q     - query context
4606
  err_errno - error number
4607
  err_error - error message
4608
  err_sqlstate - sql state
4609
  ds    - dynamic string which is used for output buffer
4610
4611
  NOTE
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4612
  If there is an unexpected error this function will abort drizzletest
4613
  immediately.
1 by brian
clean slate
4614
*/
4615
2318.4.6 by Olaf van der Spek
Refactor
4616
void handle_error(st_command* command,
1 by brian
clean slate
4617
                  unsigned int err_errno, const char *err_error,
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4618
                  const char *err_sqlstate, string *ds)
1 by brian
clean slate
4619
{
1134.1.3 by Monty Taylor
Fixed up drizzletest.cc
4620
  if (! command->require_file.empty())
1 by brian
clean slate
4621
  {
4622
    /*
4623
      The query after a "--require" failed. This is fine as long the server
4624
      returned a valid reponse. Don't allow 2013 or 2006 to trigger an
4625
      abort_not_supported_test
4626
    */
2367.2.6 by Olaf van der Spek
Remove old defines
4627
    if (err_errno == DRIZZLE_RETURN_LOST_CONNECTION)
2318.5.4 by Olaf van der Spek
Refactor
4628
      die("require query '%s' failed: %d: %s", command->query, err_errno, err_error);
1 by brian
clean slate
4629
4630
    /* Abort the run of this test, pass the failed query as reason */
2318.5.4 by Olaf van der Spek
Refactor
4631
    abort_not_supported_test("Query '%s' failed, required functionality not supported", command->query);
1 by brian
clean slate
4632
  }
4633
4634
  if (command->abort_on_error)
4635
    die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
4636
2318.5.4 by Olaf van der Spek
Refactor
4637
  uint32_t i= 0;
4638
  for (; i < command->expected_errors.count; i++)
1 by brian
clean slate
4639
  {
4640
    if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
4641
         (command->expected_errors.err[i].code.errnum == err_errno)) ||
4642
        ((command->expected_errors.err[i].type == ERR_SQLSTATE) &&
4643
         (strncmp(command->expected_errors.err[i].code.sqlstate,
928.1.6 by Eric Day
All utilities done except slap.
4644
                  err_sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE) == 0)))
1 by brian
clean slate
4645
    {
4646
      if (!disable_result_log)
4647
      {
4648
        if (command->expected_errors.count == 1)
4649
        {
4650
          /* Only log error if there is one possible error */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4651
          ds->append("ERROR ", 6);
4652
          replace_append(ds, err_sqlstate);
4653
          ds->append(": ", 2);
4654
          replace_append(ds, err_error);
4655
          ds->append("\n",1);
1 by brian
clean slate
4656
        }
4657
        /* Don't log error if we may not get an error */
4658
        else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
4659
                 (command->expected_errors.err[0].type == ERR_ERRNO &&
4660
                  command->expected_errors.err[0].code.errnum != 0))
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4661
          ds->append("Got one of the listed errors\n");
1 by brian
clean slate
4662
      }
4663
      /* OK */
142.1.1 by Patrick
Removing DBUG from client
4664
      return;
1 by brian
clean slate
4665
    }
4666
  }
4667
4668
  if (!disable_result_log)
4669
  {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4670
    ds->append("ERROR ",6);
4671
    replace_append(ds, err_sqlstate);
4672
    ds->append(": ", 2);
4673
    replace_append(ds, err_error);
4674
    ds->append("\n", 1);
1 by brian
clean slate
4675
  }
4676
4677
  if (i)
4678
  {
4679
    if (command->expected_errors.err[0].type == ERR_ERRNO)
4680
      die("query '%s' failed with wrong errno %d: '%s', instead of %d...",
4681
          command->query, err_errno, err_error,
4682
          command->expected_errors.err[0].code.errnum);
4683
    else
4684
      die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
4685
          command->query, err_sqlstate, err_error,
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4686
          command->expected_errors.err[0].code.sqlstate);
1 by brian
clean slate
4687
  }
4688
}
4689
4690
4691
/*
4692
  Handle absence of errors after execution
4693
4694
  SYNOPSIS
4695
  handle_no_error()
4696
  q - context of query
4697
4698
  RETURN VALUE
4699
  error - function will not return
4700
*/
4701
2318.4.6 by Olaf van der Spek
Refactor
4702
void handle_no_error(st_command* command)
1 by brian
clean slate
4703
{
4704
  if (command->expected_errors.err[0].type == ERR_ERRNO &&
4705
      command->expected_errors.err[0].code.errnum != 0)
4706
  {
4707
    /* Error code we wanted was != 0, i.e. not an expected success */
2318.5.4 by Olaf van der Spek
Refactor
4708
    die("query '%s' succeeded - should have failed with errno %d...", command->query, command->expected_errors.err[0].code.errnum);
1 by brian
clean slate
4709
  }
4710
  else if (command->expected_errors.err[0].type == ERR_SQLSTATE &&
4711
           strcmp(command->expected_errors.err[0].code.sqlstate,"00000") != 0)
4712
  {
4713
    /* SQLSTATE we wanted was != "00000", i.e. not an expected success */
2318.5.4 by Olaf van der Spek
Refactor
4714
    die("query '%s' succeeded - should have failed with sqlstate %s...", command->query, command->expected_errors.err[0].code.sqlstate);
1 by brian
clean slate
4715
  }
4716
}
4717
4718
4719
/*
4720
  Run query
4721
4722
  SYNPOSIS
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4723
  run_query()
4724
  drizzle  DRIZZLE handle
4725
  command  currrent command pointer
1 by brian
clean slate
4726
4727
  flags control the phased/stages of query execution to be performed
4728
  if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
4729
  is on the result will be read - for regular query, both bits must be on
4730
*/
4731
2318.5.34 by Olaf van der Spek
Refactor
4732
static void run_query(st_connection& cn,
2318.4.6 by Olaf van der Spek
Refactor
4733
                      st_command* command,
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
4734
                      int flags)
1 by brian
clean slate
4735
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4736
  string eval_query;
1 by brian
clean slate
4737
  char *query;
4738
  int query_len;
142.1.1 by Patrick
Removing DBUG from client
4739
1 by brian
clean slate
4740
4741
  /* Scan for warning before sending to server */
4742
  scan_command_for_warnings(command);
4743
4744
  /*
4745
    Evaluate query if this is an eval command
4746
  */
4747
  if (command->type == Q_EVAL)
4748
  {
163 by Brian Aker
Merge Monty's code.
4749
    do_eval(&eval_query, command->query, command->end, false);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4750
    query = strdup(eval_query.c_str());
4751
    query_len = eval_query.length();
1 by brian
clean slate
4752
  }
4753
  else
4754
  {
4755
    query = command->query;
4756
    query_len = strlen(query);
4757
  }
4758
4759
  /*
4760
    When command->require_file is set the output of _this_ query
4761
    should be compared with an already existing file
4762
    Create a temporary dynamic string to contain the output from
4763
    this query.
4764
  */
2318.5.34 by Olaf van der Spek
Refactor
4765
  string ds_result;
2318.5.13 by Olaf van der Spek
Refactor
4766
  string* ds= command->require_file.empty() ? &ds_res : &ds_result;
1 by brian
clean slate
4767
  /*
4768
    Log the query into the output buffer
4769
  */
4770
  if (!disable_query_log && (flags & QUERY_SEND_FLAG))
4771
  {
2318.5.22 by Olaf van der Spek
Refactor
4772
    replace_append_mem(*ds, query, query_len);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4773
    ds->append(delimiter, delimiter_length);
4774
    ds->append("\n");
1 by brian
clean slate
4775
  }
4776
2318.5.34 by Olaf van der Spek
Refactor
4777
  string* save_ds= NULL;
4778
  string ds_sorted;
1 by brian
clean slate
4779
  if (display_result_sorted)
4780
  {
4781
    /*
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4782
      Collect the query output in a separate string
4783
      that can be sorted before it's added to the
4784
      global result string
1 by brian
clean slate
4785
    */
4786
    save_ds= ds; /* Remember original ds */
4787
    ds= &ds_sorted;
4788
  }
4789
4790
  /*
4791
    Always run with normal C API if it's not a complete
4792
    SEND + REAP
4793
  */
2318.5.34 by Olaf van der Spek
Refactor
4794
  string ds_warnings;
2318.5.21 by Olaf van der Spek
Refactor
4795
  run_query_normal(cn, command, flags, query, query_len, ds, ds_warnings);
1 by brian
clean slate
4796
4797
  if (display_result_sorted)
4798
  {
4799
    /* Sort the result set and append it to result */
2318.5.22 by Olaf van der Spek
Refactor
4800
    append_sorted(*save_ds, ds_sorted);
1 by brian
clean slate
4801
    ds= save_ds;
4802
  }
4803
1134.1.3 by Monty Taylor
Fixed up drizzletest.cc
4804
  if (! command->require_file.empty())
1 by brian
clean slate
4805
  {
4806
    /* A result file was specified for _this_ query
4807
       and the output should be checked against an already
4808
       existing file which has been specified using --require or --result
4809
    */
2318.5.23 by Olaf van der Spek
Refactor
4810
    check_require(*ds, command->require_file);
1 by brian
clean slate
4811
  }
4812
}
4813
4814
4815
/****************************************************************************/
4816
2318.5.23 by Olaf van der Spek
Refactor
4817
static void get_command_type(st_command* command)
1 by brian
clean slate
4818
{
4819
  if (*command->query == '}')
4820
  {
4821
    command->type = Q_END_BLOCK;
142.1.1 by Patrick
Removing DBUG from client
4822
    return;
1 by brian
clean slate
4823
  }
4824
2318.5.4 by Olaf van der Spek
Refactor
4825
  char save= command->query[command->first_word_len];
1 by brian
clean slate
4826
  command->query[command->first_word_len]= 0;
2318.5.4 by Olaf van der Spek
Refactor
4827
  uint32_t type= command_typelib.find_type(command->query, TYPELIB::e_default);
1 by brian
clean slate
4828
  command->query[command->first_word_len]= save;
4829
  if (type > 0)
4830
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
4831
    command->type=(enum enum_commands) type;    /* Found command */
1 by brian
clean slate
4832
4833
    /*
4834
      Look for case where "query" was explicitly specified to
4835
      force command being sent to server
4836
    */
4837
    if (type == Q_QUERY)
4838
    {
4839
      /* Skip the "query" part */
4840
      command->query= command->first_argument;
4841
    }
4842
  }
4843
  else
4844
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
4845
    /* No drizzletest command matched */
1 by brian
clean slate
4846
4847
    if (command->type != Q_COMMENT_WITH_COMMAND)
4848
    {
206.3.1 by Patrick Galbraith
Most everything working with client rename
4849
      /* A query that will sent to drizzled */
1 by brian
clean slate
4850
      command->type= Q_QUERY;
4851
    }
4852
    else
4853
    {
206.3.1 by Patrick Galbraith
Most everything working with client rename
4854
      /* -- comment that didn't contain a drizzletest command */
1 by brian
clean slate
4855
      command->type= Q_COMMENT;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
4856
      warning_msg("Suspicious command '--%s' detected, was this intentional? " \
1 by brian
clean slate
4857
                  "Use # instead of -- to avoid this warning",
4858
                  command->query);
4859
4860
      if (command->first_word_len &&
4861
          strcmp(command->query + command->first_word_len - 1, delimiter) == 0)
4862
      {
4863
        /*
4864
          Detect comment with command using extra delimiter
4865
          Ex --disable_query_log;
4866
          ^ Extra delimiter causing the command
4867
          to be skipped
4868
        */
4869
        save= command->query[command->first_word_len-1];
4870
        command->query[command->first_word_len-1]= 0;
2275.2.20 by Olaf van der Spek
Typelib Options
4871
        if (command_typelib.find_type(command->query, TYPELIB::e_default) > 0)
1 by brian
clean slate
4872
          die("Extra delimiter \";\" found");
4873
        command->query[command->first_word_len-1]= save;
4874
4875
      }
4876
    }
4877
  }
4878
4879
  /* Set expected error on command */
2318.5.4 by Olaf van der Spek
Refactor
4880
  memcpy(&command->expected_errors, &saved_expected_errors, sizeof(saved_expected_errors));
4881
  command->abort_on_error= (command->expected_errors.count == 0 && abort_on_error);
1 by brian
clean slate
4882
}
4883
4884
4885
4886
/*
4887
  Record how many milliseconds it took to execute the test file
4888
  up until the current line and save it in the dynamic string ds_progress.
4889
4890
  The ds_progress will be dumped to <test_name>.progress when
4891
  test run completes
4892
4893
*/
4894
2318.5.23 by Olaf van der Spek
Refactor
4895
static void mark_progress(st_command*, int line)
1 by brian
clean slate
4896
{
151 by Brian Aker
Ulonglong to uint64_t
4897
  uint64_t timer= timer_now();
1 by brian
clean slate
4898
  if (!progress_start)
4899
    progress_start= timer;
4900
  timer-= progress_start;
4901
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.
4902
  ostringstream buf;
1 by brian
clean slate
4903
  /* Milliseconds since start */
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.
4904
  buf << timer << "\t";
1 by brian
clean slate
4905
4906
  /* Parser line number */
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.
4907
  buf << line << "\t";
1 by brian
clean slate
4908
4909
  /* Filename */
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.
4910
  buf << cur_file->file_name << ":";
1 by brian
clean slate
4911
4912
  /* Line in file */
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.
4913
  buf << cur_file->lineno << endl;
4914
2318.6.9 by Olaf van der Spek
Refactor
4915
  ds_progress += buf.str();
1 by brian
clean slate
4916
4917
}
4918
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4919
static void check_retries(uint32_t in_opt_max_connect_retries)
4920
{
4921
  if (in_opt_max_connect_retries > 10000 || opt_max_connect_retries<1)
4922
  {
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
4923
    cout << N_("Error: Invalid Value for opt_max_connect_retries"); 
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4924
    exit(-1);
4925
  }
4926
  opt_max_connect_retries= in_opt_max_connect_retries;
4927
}
4928
4929
static void check_tail_lines(uint32_t in_opt_tail_lines)
4930
{
4931
  if (in_opt_tail_lines > 10000)
4932
  {
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
4933
    cout << N_("Error: Invalid Value for opt_tail_lines"); 
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4934
    exit(-1);
4935
  }
4936
  opt_tail_lines= in_opt_tail_lines;
4937
}
4938
4939
static void check_sleep(int32_t in_opt_sleep)
4940
{
4941
  if (in_opt_sleep < -1)
4942
  {
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
4943
    cout << N_("Error: Invalid Value for opt_sleep"); 
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4944
    exit(-1);
4945
  }
4946
  opt_sleep= in_opt_sleep;
4947
}
4948
1 by brian
clean slate
4949
int main(int argc, char **argv)
4950
{
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4951
try
4952
{
143 by Brian Aker
Bool cleanup.
4953
  bool q_send_flag= 0, abort_flag= 0;
893 by Brian Aker
First pass of stripping uint
4954
  uint32_t command_executed= 0, last_command_executed= 0;
2318.5.4 by Olaf van der Spek
Refactor
4955
  string save_file;
1 by brian
clean slate
4956
4957
  TMPDIR[0]= 0;
4958
1639.4.1 by Stewart Smith
drizzletest was calling my_end but not my_init, which means we were destroying a pthread COND variable that wsan't created. naughty.
4959
  internal::my_init();
4960
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4961
  po::options_description commandline_options("Options used only in command line");
4962
  commandline_options.add_options()
4963
  ("help,?", "Display this help and exit.")
4964
  ("mark-progress", po::value<bool>(&opt_mark_progress)->default_value(false)->zero_tokens(),
4965
  "Write linenumber and elapsed time to <testname>.progress ")
4966
  ("sleep,T", po::value<int32_t>(&opt_sleep)->default_value(-1)->notifier(&check_sleep),
4967
  "Sleep always this many seconds on sleep commands.")
4968
  ("test-file,x", po::value<string>(),
4969
  "Read test from/in this file (default stdin).")
4970
  ("timer-file,f", po::value<string>(),
4971
  "File where the timing in micro seconds is stored.")
4972
  ("tmpdir,t", po::value<string>(),
4973
  "Temporary directory where sockets are put.")
4974
  ("verbose,v", po::value<bool>(&verbose)->default_value(false),
4975
  "Write more.")
4976
  ("version,V", "Output version information and exit.")
4977
  ("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
4978
  "Configuration file defaults are not used if no-defaults is set")
4979
  ;
4980
4981
  po::options_description test_options("Options specific to the drizzleimport");
4982
  test_options.add_options()
4983
  ("basedir,b", po::value<string>(&opt_basedir)->default_value(""),
4984
  "Basedir for tests.")
4985
  ("character-sets-dir", po::value<string>(&opt_charsets_dir)->default_value(""),
4986
  "Directory where character sets are.")
4987
  ("database,D", po::value<string>(&opt_db)->default_value(""),
4988
  "Database to use.")
4989
  ("include,i", po::value<string>(&opt_include)->default_value(""),
4990
  "Include SQL before each test case.")  
4991
  ("testdir", po::value<string>(&opt_testdir)->default_value(""),
4992
  "Path to use to search for test files")
4993
  ("logdir", po::value<string>(&opt_logdir)->default_value(""),
4994
  "Directory for log files")
4995
  ("max-connect-retries", po::value<uint32_t>(&opt_max_connect_retries)->default_value(500)->notifier(&check_retries),
4996
  "Max number of connection attempts when connecting to server")
1757.5.1 by Andrew Hutchings
Rework the boolean options so that true-by-default options change to --disable-option.
4997
  ("quiet,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
4998
  "Suppress all normal output.")
4999
  ("record,r", "Record output of test_file into result file.")
5000
  ("result-file,R", po::value<string>(&result_file_name)->default_value(""),
5001
  "Read/Store result from/in this file.")
5002
  ("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5003
  "Suppress all normal output. Synonym for --quiet.")
5004
  ("tail-lines", po::value<uint32_t>(&opt_tail_lines)->default_value(0)->notifier(&check_tail_lines),
5005
  "Number of lines of the resul to include in a failure report")
5006
  ;
5007
5008
  po::options_description client_options("Options specific to the client");
5009
  client_options.add_options()
5010
5011
  ("host,h", po::value<string>(&opt_host)->default_value("localhost"),
5012
  "Connect to host.")
1608.5.3 by Vijay Samuel
Merge fixes for password.
5013
  ("password,P", po::value<string>(&password)->default_value("PASSWORD_SENTINEL"),
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5014
  "Password to use when connecting to server.")
5015
  ("port,p", po::value<uint32_t>(&opt_port)->default_value(0),
5016
  "Port number to use for connection or 0 for default")
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
5017
  ("protocol", po::value<string>(&opt_protocol),
5018
  "The protocol of connection (mysql or drizzle).")
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5019
  ("user,u", po::value<string>(&opt_user)->default_value(""),
5020
  "User for login.")
5021
  ;
5022
5023
  po::positional_options_description p;
5024
  p.add("database", 1);
5025
5026
  po::options_description long_options("Allowed Options");
5027
  long_options.add(commandline_options).add(test_options).add(client_options);
5028
5029
  std::string system_config_dir_test(SYSCONFDIR); 
2318.6.9 by Olaf van der Spek
Refactor
5030
  system_config_dir_test += "/drizzle/drizzletest.cnf";
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5031
5032
  std::string system_config_dir_client(SYSCONFDIR); 
2318.6.9 by Olaf van der Spek
Refactor
5033
  system_config_dir_client += "/drizzle/client.cnf";
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5034
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
5035
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
5036
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)
5037
  if (user_config_dir.compare(0, 2, "~/") == 0)
5038
  {
2367.2.7 by Olaf van der Spek
Refactor
5039
    if (const char *homedir= getenv("HOME"))
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)
5040
      user_config_dir.replace(0, 1, homedir);
5041
  }
5042
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5043
  po::variables_map vm;
5044
1793.3.1 by Andrew Hutchings
Disable boost:po allow_guessing which was making some wrong assumptions
5045
  // Disable allow_guessing
5046
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
5047
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5048
  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
5049
            style(style).positional(p).extra_parser(parse_password_arg).run(),
5050
            vm);
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5051
5052
  if (! vm["no-defaults"].as<bool>())
5053
  {
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
5054
    std::string user_config_dir_test(user_config_dir);
2318.6.9 by Olaf van der Spek
Refactor
5055
    user_config_dir_test += "/drizzle/drizzletest.cnf"; 
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
5056
5057
    std::string user_config_dir_client(user_config_dir);
2318.6.9 by Olaf van der Spek
Refactor
5058
    user_config_dir_client += "/drizzle/client.cnf";
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
5059
5060
    ifstream user_test_ifs(user_config_dir_test.c_str());
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5061
    po::store(parse_config_file(user_test_ifs, test_options), vm);
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
5062
5063
    ifstream user_client_ifs(user_config_dir_client.c_str());
5064
    po::store(parse_config_file(user_client_ifs, client_options), vm);
5065
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5066
    ifstream system_test_ifs(system_config_dir_test.c_str());
5067
    store(parse_config_file(system_test_ifs, test_options), vm);
5068
5069
    ifstream system_client_ifs(system_config_dir_client.c_str());
5070
    po::store(parse_config_file(system_client_ifs, client_options), vm);
5071
  }
5072
5073
  po::notify(vm);
5074
1 by brian
clean slate
5075
  /* Init expected errors */
5076
  memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
5077
5078
  /* Init file stack */
2151.2.27 by Olaf van der Spek
refactor
5079
  memset(file_stack.data(), 0, sizeof(file_stack));
5080
  cur_file= file_stack.data();
1 by brian
clean slate
5081
5082
  /* Init block stack */
5083
  memset(block_stack, 0, sizeof(block_stack));
5084
  block_stack_end=
5085
    block_stack + (sizeof(block_stack)/sizeof(struct st_block)) - 1;
5086
  cur_block= block_stack;
163 by Brian Aker
Merge Monty's code.
5087
  cur_block->ok= true; /* Outer block should always be executed */
1 by brian
clean slate
5088
  cur_block->cmd= cmd_none;
5089
928.1.6 by Eric Day
All utilities done except slap.
5090
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_version());
1 by brian
clean slate
5091
5092
  memset(&master_pos, 0, sizeof(master_pos));
5093
5094
  parser.current_line= parser.read_lines= 0;
5095
  memset(&var_reg, 0, sizeof(var_reg));
5096
5097
  init_builtin_echo();
5098
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5099
  ds_res.reserve(65536);
5100
  ds_progress.reserve(2048);
5101
  ds_warning_messages.reserve(2048);
5102
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5103
 
5104
  if (vm.count("record"))
5105
  {
5106
    record = 1;
5107
  }
5108
5109
  if (vm.count("test-file"))
5110
  {
5111
    string tmp= vm["test-file"].as<string>();
5112
    char buff[FN_REFLEN];
5113
    if (!internal::test_if_hard_path(tmp.c_str()))
5114
    {
5115
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5116
      tmp= buff;
5117
    }
5118
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
2151.2.27 by Olaf van der Spek
refactor
5119
    assert(cur_file == file_stack.data() && cur_file->file == 0);
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5120
    if (!(cur_file->file= fopen(buff, "r")))
5121
    {
5122
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5123
      return EXIT_ARGUMENT_INVALID;
5124
    }
2318.4.5 by Olaf van der Spek
Refactor
5125
    cur_file->file_name= strdup(buff);
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5126
    cur_file->lineno= 1;
5127
  }
5128
5129
  if (vm.count("timer-file"))
5130
  {
5131
    string tmp= vm["timer-file"].as<string>().c_str();
5132
    static char buff[FN_REFLEN];
5133
    if (!internal::test_if_hard_path(tmp.c_str()))
5134
    {
5135
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5136
      tmp= buff;
5137
    }
5138
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5139
    timer_file= buff;
5140
    unlink(timer_file);       /* Ignore error, may not exist */
5141
  }
5142
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
5143
  if (vm.count("protocol"))
5144
  {
2318.7.21 by Olaf van der Spek
Use boost::to_lower
5145
    boost::to_lower(opt_protocol);
1750.4.2 by Patrick Crews
Moved transaction_log tests into updated non-publisher-based tree
5146
    if (not opt_protocol.compare("mysql"))
5147
      use_drizzle_protocol=false;
5148
    else if (not opt_protocol.compare("drizzle"))
5149
      use_drizzle_protocol=true;
5150
    else
5151
    {
5152
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
5153
      exit(-1);
5154
    }
5155
  }
5156
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5157
  if (vm.count("port"))
5158
  {
5159
    /* If the port number is > 65535 it is not a valid port
5160
       This also helps with potential data loss casting unsigned long to a
5161
       uint32_t. */
5162
    if (opt_port > 65535)
5163
    {
5164
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
5165
      exit(EXIT_ARGUMENT_INVALID);
5166
    }
5167
  }
5168
1633.5.3 by Vijay Samuel
Merge password fix for client.
5169
  if( vm.count("password") )
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5170
  {
5171
    if (!opt_password.empty())
5172
      opt_password.erase();
1608.5.3 by Vijay Samuel
Merge fixes for password.
5173
    if (password == PASSWORD_SENTINEL)
5174
    {
5175
      opt_password= "";
5176
    }
5177
    else
5178
    {
5179
      opt_password= password;
5180
      tty_password= false;
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5181
    }
5182
  }
5183
  else
5184
  {
5185
      tty_password= true;
5186
  }
5187
5188
  if (vm.count("tmpdir"))
5189
  {
5190
    strncpy(TMPDIR, vm["tmpdir"].as<string>().c_str(), sizeof(TMPDIR));
5191
  }
5192
5193
  if (vm.count("version"))
5194
  {
5195
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5196
    drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5197
    exit(0);
5198
  }
5199
  
5200
  if (vm.count("help"))
5201
  {
5202
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5203
    drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5204
    printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
5205
    printf("Drizzle version modified by Brian, Jay, Monty Taylor, PatG and Stewart\n");
5206
    printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
5207
    printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
5208
    printf("Usage: %s [OPTIONS] [database] < test_file\n", internal::my_progname);
5209
    exit(0);
5210
  }
5211
5212
  if (tty_password)
5213
  {
5214
    opt_pass= client_get_tty_password(NULL);          /* purify tested */
5215
  }
1 by brian
clean slate
5216
2429.1.1 by Brian Aker
Remove the schema copy in test-run.pl
5217
  server_initialized= true;
2151.2.27 by Olaf van der Spek
refactor
5218
  if (cur_file == file_stack.data() && cur_file->file == 0)
1 by brian
clean slate
5219
  {
5220
    cur_file->file= stdin;
656.1.20 by Monty Taylor
Removed my_strdup, my_malloc, my_realloc from client/
5221
    cur_file->file_name= strdup("<stdin>");
1 by brian
clean slate
5222
    cur_file->lineno= 1;
5223
  }
2318.5.25 by Olaf van der Spek
Refactor
5224
  cur_con= safe_connect("default", opt_host, opt_user, opt_pass, opt_db, opt_port);
2318.5.24 by Olaf van der Spek
Refactor
5225
  g_connections["default"] = cur_con;
1 by brian
clean slate
5226
1996.3.8 by Monty Taylor
Resolve error messages earlier, so that we can avoid clashes with
5227
  fill_global_error_names();
5228
1 by brian
clean slate
5229
  /* Use all time until exit if no explicit 'start_timer' */
5230
  timer_start= timer_now();
5231
5232
  /*
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
5233
    Initialize $drizzleclient_errno with -1, so we can
1 by brian
clean slate
5234
    - distinguish it from valid values ( >= 0 ) and
5235
    - detect if there was never a command sent to the server
5236
  */
5237
  var_set_errno(-1);
5238
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
5239
  /* Update $drizzleclient_get_server_version to that of current connection */
2318.5.26 by Olaf van der Spek
Refactor
5240
  var_set_drizzleclient_get_server_version(*cur_con);
1 by brian
clean slate
5241
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5242
  if (! opt_include.empty())
1 by brian
clean slate
5243
  {
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5244
    open_file(opt_include.c_str());
1 by brian
clean slate
5245
  }
5246
2318.5.4 by Olaf van der Spek
Refactor
5247
  st_command* command;
1 by brian
clean slate
5248
  while (!read_command(&command) && !abort_flag)
5249
  {
5250
    int current_line_inc = 1, processed = 0;
5251
    if (command->type == Q_UNKNOWN || command->type == Q_COMMENT_WITH_COMMAND)
5252
      get_command_type(command);
5253
5254
    if (parsing_disabled &&
5255
        command->type != Q_ENABLE_PARSING &&
5256
        command->type != Q_DISABLE_PARSING)
5257
    {
5258
      command->type= Q_COMMENT;
5259
      scan_command_for_warnings(command);
5260
    }
5261
5262
    if (cur_block->ok)
5263
    {
5264
      command->last_argument= command->first_argument;
5265
      processed = 1;
5266
      switch (command->type) {
5267
      case Q_CONNECT:
5268
        do_connect(command);
5269
        break;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5270
      case Q_CONNECTION:
5271
        select_connection(command);
5272
        break;
1 by brian
clean slate
5273
      case Q_DISCONNECT:
5274
      case Q_DIRTY_CLOSE:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5275
        do_close_connection(command); break;
1 by brian
clean slate
5276
      case Q_ENABLE_QUERY_LOG:   disable_query_log=0; break;
5277
      case Q_DISABLE_QUERY_LOG:  disable_query_log=1; break;
5278
      case Q_ENABLE_ABORT_ON_ERROR:  abort_on_error=1; break;
5279
      case Q_DISABLE_ABORT_ON_ERROR: abort_on_error=0; break;
5280
      case Q_ENABLE_RESULT_LOG:  disable_result_log=0; break;
5281
      case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
5282
      case Q_ENABLE_WARNINGS:    disable_warnings=0; break;
5283
      case Q_DISABLE_WARNINGS:   disable_warnings=1; break;
5284
      case Q_ENABLE_INFO:        disable_info=0; break;
5285
      case Q_DISABLE_INFO:       disable_info=1; break;
5286
      case Q_ENABLE_METADATA:    display_metadata=1; break;
5287
      case Q_DISABLE_METADATA:   display_metadata=0; break;
5288
      case Q_SOURCE: do_source(command); break;
5289
      case Q_SLEEP: do_sleep(command, 0); break;
5290
      case Q_REAL_SLEEP: do_sleep(command, 1); break;
2318.4.6 by Olaf van der Spek
Refactor
5291
      case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(); break;
1 by brian
clean slate
5292
      case Q_INC: do_modify_var(command, DO_INC); break;
5293
      case Q_DEC: do_modify_var(command, DO_DEC); break;
5294
      case Q_ECHO: do_echo(command); command_executed++; break;
5295
      case Q_SYSTEM: do_system(command); break;
5296
      case Q_REMOVE_FILE: do_remove_file(command); break;
5297
      case Q_MKDIR: do_mkdir(command); break;
5298
      case Q_RMDIR: do_rmdir(command); break;
5299
      case Q_FILE_EXIST: do_file_exist(command); break;
5300
      case Q_WRITE_FILE: do_write_file(command); break;
5301
      case Q_APPEND_FILE: do_append_file(command); break;
5302
      case Q_DIFF_FILES: do_diff_files(command); break;
5303
      case Q_SEND_QUIT: do_send_quit(command); break;
5304
      case Q_CHANGE_USER: do_change_user(command); break;
5305
      case Q_CAT_FILE: do_cat_file(command); break;
5306
      case Q_COPY_FILE: do_copy_file(command); break;
5307
      case Q_CHMOD_FILE: do_chmod_file(command); break;
5308
      case Q_PERL: do_perl(command); break;
5309
      case Q_DELIMITER:
5310
        do_delimiter(command);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5311
        break;
1 by brian
clean slate
5312
      case Q_DISPLAY_VERTICAL_RESULTS:
163 by Brian Aker
Merge Monty's code.
5313
        display_result_vertically= true;
1 by brian
clean slate
5314
        break;
5315
      case Q_DISPLAY_HORIZONTAL_RESULTS:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5316
        display_result_vertically= false;
1 by brian
clean slate
5317
        break;
5318
      case Q_SORTED_RESULT:
5319
        /*
5320
          Turn on sorting of result set, will be reset after next
5321
          command
5322
        */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5323
        display_result_sorted= true;
1 by brian
clean slate
5324
        break;
5325
      case Q_LET: do_let(command); break;
5326
      case Q_EVAL_RESULT:
5327
        die("'eval_result' command  is deprecated");
5328
      case Q_EVAL:
5329
      case Q_QUERY_VERTICAL:
5330
      case Q_QUERY_HORIZONTAL:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5331
        if (command->query == command->query_buf)
1 by brian
clean slate
5332
        {
5333
          /* Skip the first part of command, i.e query_xxx */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5334
          command->query= command->first_argument;
1 by brian
clean slate
5335
          command->first_word_len= 0;
5336
        }
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5337
        /* fall through */
1 by brian
clean slate
5338
      case Q_QUERY:
5339
      case Q_REAP:
5340
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5341
        bool old_display_result_vertically= display_result_vertically;
1 by brian
clean slate
5342
        /* Default is full query, both reap and send  */
5343
        int flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
5344
5345
        if (q_send_flag)
5346
        {
5347
          /* Last command was an empty 'send' */
5348
          flags= QUERY_SEND_FLAG;
5349
          q_send_flag= 0;
5350
        }
5351
        else if (command->type == Q_REAP)
5352
        {
5353
          flags= QUERY_REAP_FLAG;
5354
        }
5355
5356
        /* Check for special property for this query */
5357
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5358
1134.1.2 by Monty Taylor
Append opt_testdir to result files being required.
5359
        if (! save_file.empty())
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5360
        {
1134.1.3 by Monty Taylor
Fixed up drizzletest.cc
5361
          command->require_file= save_file;
1134.1.2 by Monty Taylor
Append opt_testdir to result files being required.
5362
          save_file.clear();
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5363
        }
2318.5.34 by Olaf van der Spek
Refactor
5364
        run_query(*cur_con, command, flags);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5365
        command_executed++;
1 by brian
clean slate
5366
        command->last_argument= command->end;
5367
5368
        /* Restore settings */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5369
        display_result_vertically= old_display_result_vertically;
1 by brian
clean slate
5370
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5371
        break;
1 by brian
clean slate
5372
      }
5373
      case Q_SEND:
5374
        if (!*command->first_argument)
5375
        {
5376
          /*
5377
            This is a send without arguments, it indicates that _next_ query
5378
            should be send only
5379
          */
5380
          q_send_flag= 1;
5381
          break;
5382
        }
5383
5384
        /* Remove "send" if this is first iteration */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5385
        if (command->query == command->query_buf)
5386
          command->query= command->first_argument;
1 by brian
clean slate
5387
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5388
        /*
5389
          run_query() can execute a query partially, depending on the flags.
5390
          QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
1 by brian
clean slate
5391
          the query and read the result some time later when reap instruction
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5392
          is given on this connection.
1 by brian
clean slate
5393
        */
2318.5.34 by Olaf van der Spek
Refactor
5394
        run_query(*cur_con, command, QUERY_SEND_FLAG);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5395
        command_executed++;
1 by brian
clean slate
5396
        command->last_argument= command->end;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5397
        break;
1 by brian
clean slate
5398
      case Q_REQUIRE:
1134.1.2 by Monty Taylor
Append opt_testdir to result files being required.
5399
        do_get_file_name(command, save_file);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5400
        break;
1 by brian
clean slate
5401
      case Q_ERROR:
5402
        do_get_errcodes(command);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5403
        break;
1 by brian
clean slate
5404
      case Q_REPLACE:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5405
        do_get_replace(command);
5406
        break;
1 by brian
clean slate
5407
      case Q_REPLACE_REGEX:
5408
        do_get_replace_regex(command);
5409
        break;
5410
      case Q_REPLACE_COLUMN:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5411
        do_get_replace_column(command);
5412
        break;
1 by brian
clean slate
5413
      case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5414
      case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5415
      case Q_SYNC_SLAVE_WITH_MASTER:
5416
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5417
        do_save_master_pos();
5418
        if (*command->first_argument)
5419
          select_connection(command);
5420
        else
5421
          select_connection_name("slave");
5422
        do_sync_with_master2(0);
5423
        break;
1 by brian
clean slate
5424
      }
206.3.1 by Patrick Galbraith
Most everything working with client rename
5425
      case Q_COMMENT:        /* Ignore row */
1 by brian
clean slate
5426
        command->last_argument= command->end;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5427
        break;
1 by brian
clean slate
5428
      case Q_PING:
928.1.6 by Eric Day
All utilities done except slap.
5429
        {
2318.5.19 by Olaf van der Spek
Refactor
5430
          drizzle::result_c result;
928.1.6 by Eric Day
All utilities done except slap.
5431
          drizzle_return_t ret;
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
5432
          (void) drizzle_ping(*cur_con, result, &ret);
928.1.6 by Eric Day
All utilities done except slap.
5433
        }
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5434
        break;
1 by brian
clean slate
5435
      case Q_EXEC:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5436
        do_exec(command);
5437
        command_executed++;
5438
        break;
1 by brian
clean slate
5439
      case Q_START_TIMER:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5440
        /* Overwrite possible earlier start of timer */
5441
        timer_start= timer_now();
5442
        break;
1 by brian
clean slate
5443
      case Q_END_TIMER:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5444
        /* End timer before ending drizzletest */
5445
        timer_output();
5446
        break;
1 by brian
clean slate
5447
      case Q_CHARACTER_SET:
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5448
        do_set_charset(command);
5449
        break;
1 by brian
clean slate
5450
      case Q_DISABLE_RECONNECT:
2318.5.26 by Olaf van der Spek
Refactor
5451
        set_reconnect(*cur_con, 0);
1 by brian
clean slate
5452
        break;
5453
      case Q_ENABLE_RECONNECT:
2318.5.26 by Olaf van der Spek
Refactor
5454
        set_reconnect(*cur_con, 1);
1 by brian
clean slate
5455
        break;
5456
      case Q_DISABLE_PARSING:
5457
        if (parsing_disabled == 0)
5458
          parsing_disabled= 1;
5459
        else
5460
          die("Parsing is already disabled");
5461
        break;
5462
      case Q_ENABLE_PARSING:
5463
        /*
5464
          Ensure we don't get parsing_disabled < 0 as this would accidentally
5465
          disable code we don't want to have disabled
5466
        */
5467
        if (parsing_disabled == 1)
5468
          parsing_disabled= 0;
5469
        else
5470
          die("Parsing is already enabled");
5471
        break;
5472
      case Q_DIE:
5473
        /* Abort test with error code and error message */
5474
        die("%s", command->first_argument);
5475
        break;
5476
      case Q_EXIT:
5477
        /* Stop processing any more commands */
5478
        abort_flag= 1;
5479
        break;
5480
      case Q_SKIP:
5481
        abort_not_supported_test("%s", command->first_argument);
5482
        break;
5483
5484
      case Q_RESULT:
5485
        die("result, deprecated command");
5486
        break;
5487
5488
      default:
5489
        processed= 0;
5490
        break;
5491
      }
5492
    }
5493
5494
    if (!processed)
5495
    {
5496
      current_line_inc= 0;
5497
      switch (command->type) {
5498
      case Q_WHILE: do_block(cmd_while, command); break;
5499
      case Q_IF: do_block(cmd_if, command); break;
5500
      case Q_END_BLOCK: do_done(command); break;
5501
      default: current_line_inc = 1; break;
5502
      }
5503
    }
5504
    else
5505
      check_eol_junk(command->last_argument);
5506
5507
    if (command->type != Q_ERROR &&
5508
        command->type != Q_COMMENT)
5509
    {
5510
      /*
5511
        As soon as any non "error" command or comment has been executed,
5512
        the array with expected errors should be cleared
5513
      */
5514
      memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
5515
    }
5516
5517
    if (command_executed != last_command_executed)
5518
    {
5519
      /*
5520
        As soon as any command has been executed,
5521
        the replace structures should be cleared
5522
      */
5523
      free_all_replace();
5524
5525
      /* Also reset "sorted_result" */
163 by Brian Aker
Merge Monty's code.
5526
      display_result_sorted= false;
1 by brian
clean slate
5527
    }
5528
    last_command_executed= command_executed;
5529
5530
    parser.current_line += current_line_inc;
5531
    if ( opt_mark_progress )
5532
      mark_progress(command, parser.current_line);
5533
  }
5534
5535
  start_lineno= 0;
5536
5537
  if (parsing_disabled)
5538
    die("Test ended with parsing disabled");
5539
5540
  /*
5541
    The whole test has been executed _sucessfully_.
5542
    Time to compare result or save it to record file.
5543
    The entire output from test is now kept in ds_res.
5544
  */
2367.2.7 by Olaf van der Spek
Refactor
5545
  if (ds_res.empty())
1 by brian
clean slate
5546
    die("The test didn't produce any output");
2367.2.7 by Olaf van der Spek
Refactor
5547
  if (result_file_name.empty())
5548
  {
5549
    /* No result_file_name specified to compare with, print to stdout */
5550
    printf("%s", ds_res.c_str());
5551
  }
5552
  else if (record)
5553
  {
5554
    /* Recording - dump the output from test to result file */
5555
    str_to_file(result_file_name.c_str(), ds_res.c_str(), ds_res.length());
5556
  }
5557
  else
5558
  {
5559
    /* Check that the output from test is equal to result file
5560
    - detect missing result file
5561
    - detect zero size result file
5562
    */
5563
    check_result(ds_res);
1 by brian
clean slate
5564
  }
5565
2318.5.4 by Olaf van der Spek
Refactor
5566
  struct stat res_info;
2367.2.7 by Olaf van der Spek
Refactor
5567
  if (not command_executed && not result_file_name.empty() && not stat(result_file_name.c_str(), &res_info))
1 by brian
clean slate
5568
  {
5569
    /*
5570
      my_stat() successful on result file. Check if we have not run a
5571
      single query, but we do have a result file that contains data.
5572
      Note that we don't care, if my_stat() fails. For example, for a
5573
      non-existing or non-readable file, we assume it's fine to have
5574
      no query output from the test file, e.g. regarded as no error.
5575
    */
5576
    die("No queries executed but result file found!");
5577
  }
5578
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5579
  if ( opt_mark_progress && ! result_file_name.empty() )
1 by brian
clean slate
5580
    dump_progress();
5581
5582
  /* Dump warning messages */
2367.2.7 by Olaf van der Spek
Refactor
5583
  if (not result_file_name.empty() && ds_warning_messages.length())
1 by brian
clean slate
5584
    dump_warning_messages();
5585
5586
  timer_output();
5587
  /* Yes, if we got this far the test has suceeded! Sakila smiles */
5588
  cleanup_and_exit(0);
1608.5.1 by Vijay Samuel
Merge refactor drizzletest
5589
}
5590
5591
  catch(exception &err)
5592
  {
5593
    cerr<<err.what()<<endl;
5594
  }
5595
2367.2.7 by Olaf van der Spek
Refactor
5596
  return 0;
1 by brian
clean slate
5597
}
5598
5599
5600
/*
5601
  A primitive timer that give results in milliseconds if the
5602
  --timer-file=<filename> is given. The timer result is written
5603
  to that file when the result is available. To not confuse
5604
  mysql-test-run with an old obsolete result, we remove the file
5605
  before executing any commands. The time we measure is
5606
5607
  - If no explicit 'start_timer' or 'end_timer' is given in the
206.3.1 by Patrick Galbraith
Most everything working with client rename
5608
  test case, the timer measure how long we execute in drizzletest.
1 by brian
clean slate
5609
5610
  - If only 'start_timer' is given we measure how long we execute
206.3.1 by Patrick Galbraith
Most everything working with client rename
5611
  from that point until we terminate drizzletest.
1 by brian
clean slate
5612
5613
  - If only 'end_timer' is given we measure how long we execute
206.3.1 by Patrick Galbraith
Most everything working with client rename
5614
  from that we enter drizzletest to the 'end_timer' is command is
1 by brian
clean slate
5615
  executed.
5616
5617
  - If both 'start_timer' and 'end_timer' are given we measure
5618
  the time between executing the two commands.
5619
*/
5620
2151.2.17 by Olaf van der Spek
drizzletest refactoring
5621
void timer_output()
1 by brian
clean slate
5622
{
5623
  if (timer_file)
5624
  {
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.
5625
    ostringstream buf;
151 by Brian Aker
Ulonglong to uint64_t
5626
    uint64_t timer= timer_now() - timer_start;
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.
5627
    buf << timer;
5628
    str_to_file(timer_file,buf.str().c_str(), buf.str().size() );
1 by brian
clean slate
5629
    /* Timer has been written to the file, don't use it anymore */
5630
    timer_file= 0;
5631
  }
5632
}
5633
5634
2151.2.17 by Olaf van der Spek
drizzletest refactoring
5635
uint64_t timer_now()
1 by brian
clean slate
5636
{
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
5637
#if defined(HAVE_GETHRTIME)
5638
  return gethrtime()/1000/1000;
5639
#else
5640
  uint64_t newtime;
5641
  struct timeval t;
5642
  /*
5643
    The following loop is here because gettimeofday may fail on some systems
5644
  */
5645
  while (gettimeofday(&t, NULL) != 0)
5646
  {}
5647
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
5648
  return newtime/1000;
5649
#endif  /* defined(HAVE_GETHRTIME) */
1 by brian
clean slate
5650
}
5651
5652
5653
/*
5654
  Get arguments for replace_columns. The syntax is:
5655
  replace-column column_number to_string [column_number to_string ...]
5656
  Where each argument may be quoted with ' or "
5657
  A argument may also be a variable, in which case the value of the
5658
  variable is replaced.
5659
*/
5660
2318.4.6 by Olaf van der Spek
Refactor
5661
void do_get_replace_column(st_command* command)
1 by brian
clean slate
5662
{
5663
  char *from= command->first_argument;
5664
  char *buff, *start;
142.1.1 by Patrick
Removing DBUG from client
5665
1 by brian
clean slate
5666
5667
  free_replace_column();
5668
  if (!*from)
5669
    die("Missing argument in %s", command->query);
5670
5671
  /* Allocate a buffer for results */
656.1.20 by Monty Taylor
Removed my_strdup, my_malloc, my_realloc from client/
5672
  start= buff= (char *)malloc(strlen(from)+1);
1 by brian
clean slate
5673
  while (*from)
5674
  {
893 by Brian Aker
First pass of stripping uint
5675
    uint32_t column_number;
1 by brian
clean slate
5676
2151.2.17 by Olaf van der Spek
drizzletest refactoring
5677
    char *to= get_string(&buff, &from, command);
1 by brian
clean slate
5678
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
5679
      die("Wrong column number to replace_column in '%s'", command->query);
5680
    if (!*from)
5681
      die("Wrong number of arguments to replace_column in '%s'", command->query);
5682
    to= get_string(&buff, &from, command);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
5683
    free(replace_column[column_number-1]);
656.1.20 by Monty Taylor
Removed my_strdup, my_malloc, my_realloc from client/
5684
    replace_column[column_number-1]= strdup(to);
1 by brian
clean slate
5685
    set_if_bigger(max_replace_column, column_number);
5686
  }
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
5687
  free(start);
1 by brian
clean slate
5688
  command->last_argument= command->end;
5689
}
5690
5691
5692
void free_replace_column()
5693
{
2318.5.4 by Olaf van der Spek
Refactor
5694
  for (uint32_t i= 0; i < max_replace_column; i++)
1 by brian
clean slate
5695
  {
2151.2.17 by Olaf van der Spek
drizzletest refactoring
5696
    free(replace_column[i]);
5697
    replace_column[i]= 0;
1 by brian
clean slate
5698
  }
5699
  max_replace_column= 0;
5700
}
5701
5702
5703
/****************************************************************************/
5704
/*
5705
  Replace functions
5706
*/
5707
5708
/* Definitions for replace result */
5709
2198.4.1 by Olaf van der Spek
Refactor
5710
class POINTER_ARRAY
5711
{    /* when using array-strings */
5712
public:
2198.4.2 by Olaf van der Spek
Refactor
5713
  ~POINTER_ARRAY();
2198.4.1 by Olaf van der Spek
Refactor
5714
  int insert(char* name);
5715
2198.4.2 by Olaf van der Spek
Refactor
5716
  POINTER_ARRAY()
5717
  {
5718
    memset(this, 0, sizeof(*this));
5719
  }
5720
206.3.1 by Patrick Galbraith
Most everything working with client rename
5721
  TYPELIB typelib;        /* Pointer to strings */
2198.4.1 by Olaf van der Spek
Refactor
5722
  unsigned char *str;          /* Strings is here */
5723
  uint8_t* flag;          /* Flag about each var. */
5724
  uint32_t array_allocs;
5725
  uint32_t max_count;
5726
  uint32_t length;
5727
  uint32_t max_length;
5728
};
1 by brian
clean slate
5729
5730
struct st_replace;
2151.2.20 by Olaf van der Spek
refactor
5731
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
2151.5.5 by Olaf van der Spek
char* -> const char*
5732
                                char *word_end_chars);
2198.4.1 by Olaf van der Spek
Refactor
5733
2318.5.22 by Olaf van der Spek
Refactor
5734
void replace_strings_append(struct st_replace *rep, string& ds, const char *from, int len);
1 by brian
clean slate
5735
2151.2.21 by Olaf van der Spek
refactor
5736
st_replace *glob_replace= NULL;
5737
// boost::scoped_ptr<st_replace> glob_replace;
1 by brian
clean slate
5738
5739
/*
5740
  Get arguments for replace. The syntax is:
5741
  replace from to [from to ...]
5742
  Where each argument may be quoted with ' or "
5743
  A argument may also be a variable, in which case the value of the
5744
  variable is replaced.
5745
*/
5746
2198.4.2 by Olaf van der Spek
Refactor
5747
POINTER_ARRAY::~POINTER_ARRAY()
2151.2.20 by Olaf van der Spek
refactor
5748
{
2198.4.1 by Olaf van der Spek
Refactor
5749
  if (!typelib.count)
2151.2.20 by Olaf van der Spek
refactor
5750
    return;
2198.4.1 by Olaf van der Spek
Refactor
5751
  typelib.count= 0;
5752
  free((char*) typelib.type_names);
5753
  typelib.type_names=0;
5754
  free(str);
2151.2.20 by Olaf van der Spek
refactor
5755
}
5756
2318.4.6 by Olaf van der Spek
Refactor
5757
void do_get_replace(st_command* command)
1 by brian
clean slate
5758
{
5759
  char *from= command->first_argument;
2198.4.2 by Olaf van der Spek
Refactor
5760
  if (!*from)
5761
    die("Missing argument in %s", command->query);
5762
  free_replace();
1 by brian
clean slate
5763
  POINTER_ARRAY to_array, from_array;
2198.4.2 by Olaf van der Spek
Refactor
5764
  char* start= (char*)malloc(strlen(from) + 1);
5765
  char* buff= start;
1 by brian
clean slate
5766
  while (*from)
5767
  {
2198.4.2 by Olaf van der Spek
Refactor
5768
    char *to= get_string(&buff, &from, command);
1 by brian
clean slate
5769
    if (!*from)
2198.4.2 by Olaf van der Spek
Refactor
5770
      die("Wrong number of arguments to replace_result in '%s'", command->query);
2198.4.1 by Olaf van der Spek
Refactor
5771
    from_array.insert(to);
1 by brian
clean slate
5772
    to= get_string(&buff, &from, command);
2198.4.1 by Olaf van der Spek
Refactor
5773
    to_array.insert(to);
1 by brian
clean slate
5774
  }
2198.4.2 by Olaf van der Spek
Refactor
5775
  char word_end_chars[256];
5776
  char* pos= word_end_chars;
5777
  for (int i= 1; i < 256; i++)
5778
  {
2445.1.3 by Olaf van der Spek
Refactor
5779
    if (charset_info->isspace(i))
1 by brian
clean slate
5780
      *pos++= i;
2198.4.2 by Olaf van der Spek
Refactor
5781
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
5782
  *pos=0;          /* End pointer */
2151.5.5 by Olaf van der Spek
char* -> const char*
5783
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
2151.2.20 by Olaf van der Spek
refactor
5784
                                   to_array.typelib.type_names,
5785
                                   from_array.typelib.count,
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
5786
                                   word_end_chars)))
1 by brian
clean slate
5787
    die("Can't initialize replace from '%s'", command->query);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
5788
  free(start);
1 by brian
clean slate
5789
  command->last_argument= command->end;
142.1.1 by Patrick
Removing DBUG from client
5790
  return;
1 by brian
clean slate
5791
}
5792
5793
5794
void free_replace()
5795
{
2151.2.13 by Olaf van der Spek
drizzletest refactoring
5796
  free(glob_replace);
5797
  glob_replace=0;
1 by brian
clean slate
5798
}
5799
5800
5801
typedef struct st_replace {
143 by Brian Aker
Bool cleanup.
5802
  bool found;
1 by brian
clean slate
5803
  struct st_replace *next[256];
5804
} REPLACE;
5805
5806
typedef struct st_replace_found {
143 by Brian Aker
Bool cleanup.
5807
  bool found;
1 by brian
clean slate
5808
  char *replace_string;
893 by Brian Aker
First pass of stripping uint
5809
  uint32_t to_offset;
1 by brian
clean slate
5810
  int from_offset;
5811
} REPLACE_STRING;
5812
5813
2318.5.22 by Olaf van der Spek
Refactor
5814
void replace_strings_append(REPLACE *rep, string& ds, const char *str, int len)
1 by brian
clean slate
5815
{
2151.2.17 by Olaf van der Spek
drizzletest refactoring
5816
  REPLACE_STRING *rep_str;
2318.5.22 by Olaf van der Spek
Refactor
5817
  const char* start= str;
5818
  const char* from= str;
5819
5820
  REPLACE* rep_pos=rep+1;
1 by brian
clean slate
5821
  for (;;)
5822
  {
5823
    /* Loop through states */
5824
    while (!rep_pos->found)
481 by Brian Aker
Remove all of uchar.
5825
      rep_pos= rep_pos->next[(unsigned char) *from++];
1 by brian
clean slate
5826
5827
    /* Does this state contain a string to be replaced */
5828
    if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
5829
    {
5830
      /* No match found */
2318.5.22 by Olaf van der Spek
Refactor
5831
      ds.append(start, from - start - 1);
142.1.1 by Patrick
Removing DBUG from client
5832
      return;
1 by brian
clean slate
5833
    }
5834
5835
    /* Append part of original string before replace string */
2318.5.22 by Olaf van der Spek
Refactor
5836
    ds.append(start, (from - rep_str->to_offset) - start);
1 by brian
clean slate
5837
5838
    /* Append replace string */
2318.5.22 by Olaf van der Spek
Refactor
5839
    ds.append(rep_str->replace_string, strlen(rep_str->replace_string));
1 by brian
clean slate
5840
5841
    if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
142.1.1 by Patrick
Removing DBUG from client
5842
      return;
5843
142.1.2 by Patrick
All DBUG_x removed from client/
5844
    assert(from <= str+len);
1 by brian
clean slate
5845
    start= from;
5846
    rep_pos=rep;
5847
  }
5848
}
5849
5850
5851
/*
5852
  Regex replace  functions
5853
*/
5854
5855
5856
/* Stores regex substitutions */
5857
5858
struct st_regex
5859
{
5860
  char* pattern; /* Pattern to be replaced */
5861
  char* replace; /* String or expression to replace the pattern with */
5862
  int icase; /* true if the match is case insensitive */
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
5863
  int global; /* true if the match should be global -- 
5864
                 i.e. repeat the matching until the end of the string */
1 by brian
clean slate
5865
};
5866
2151.2.18 by Olaf van der Spek
refactor
5867
class st_replace_regex
1 by brian
clean slate
5868
{
2151.2.18 by Olaf van der Spek
refactor
5869
public:
5870
  st_replace_regex(char* expr);
2151.2.19 by Olaf van der Spek
refactor
5871
  int multi_reg_replace(char* val);
1 by brian
clean slate
5872
5873
  /*
5874
    Temporary storage areas for substitutions. To reduce unnessary copying
5875
    and memory freeing/allocation, we pre-allocate two buffers, and alternate
5876
    their use, one for input/one for output, the roles changing on the next
5877
    st_regex substition. At the end of substitutions  buf points to the
5878
    one containing the final result.
5879
  */
2151.2.28 by Olaf van der Spek
refactor
5880
  typedef vector<st_regex> regex_arr_t;
5881
2151.2.18 by Olaf van der Spek
refactor
5882
  char* buf_;
1 by brian
clean slate
5883
  char* even_buf;
5884
  char* odd_buf;
5885
  int even_buf_len;
5886
  int odd_buf_len;
2151.2.19 by Olaf van der Spek
refactor
5887
  boost::array<char, 8 << 10> buf0_;
5888
  boost::array<char, 8 << 10> buf1_;
2151.2.28 by Olaf van der Spek
refactor
5889
  regex_arr_t regex_arr;
1 by brian
clean slate
5890
};
5891
2151.2.21 by Olaf van der Spek
refactor
5892
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
1 by brian
clean slate
5893
5894
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
5895
                char *string, int icase, int global);
1 by brian
clean slate
5896
5897
5898
5899
/*
5900
  Finds the next (non-escaped) '/' in the expression.
5901
  (If the character '/' is needed, it can be escaped using '\'.)
5902
*/
5903
5904
#define PARSE_REGEX_ARG                         \
5905
  while (p < expr_end)                          \
5906
  {                                             \
5907
    char c= *p;                                 \
5908
    if (c == '/')                               \
5909
    {                                           \
5910
      if (last_c == '\\')                       \
5911
      {                                         \
5912
        buf_p[-1]= '/';                         \
5913
      }                                         \
5914
      else                                      \
5915
      {                                         \
5916
        *buf_p++ = 0;                           \
5917
        break;                                  \
5918
      }                                         \
5919
    }                                           \
5920
    else                                        \
5921
      *buf_p++ = c;                             \
5922
                                                \
5923
    last_c= c;                                  \
5924
    p++;                                        \
5925
  }                                             \
5926
                                                \
5927
/*
5928
  Initializes the regular substitution expression to be used in the
5929
  result output of test.
5930
5931
  Returns: st_replace_regex struct with pairs of substitutions
5932
*/
5933
2151.2.18 by Olaf van der Spek
refactor
5934
st_replace_regex::st_replace_regex(char* expr)
1 by brian
clean slate
5935
{
893 by Brian Aker
First pass of stripping uint
5936
  uint32_t expr_len= strlen(expr);
1 by brian
clean slate
5937
  char last_c = 0;
2151.2.11 by Olaf van der Spek
drizzletest refactoring
5938
  st_regex reg;
1 by brian
clean slate
5939
2151.2.14 by Olaf van der Spek
drizzletest refactoring
5940
  char* buf= new char[expr_len];
2151.2.11 by Olaf van der Spek
drizzletest refactoring
5941
  char* expr_end= expr + expr_len;
5942
  char* p= expr;
5943
  char* buf_p= buf;
1 by brian
clean slate
5944
5945
  /* for each regexp substitution statement */
5946
  while (p < expr_end)
5947
  {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
5948
    memset(&reg, 0, sizeof(reg));
1 by brian
clean slate
5949
    /* find the start of the statement */
5950
    while (p < expr_end)
5951
    {
5952
      if (*p == '/')
5953
        break;
5954
      p++;
5955
    }
5956
5957
    if (p == expr_end || ++p == expr_end)
5958
    {
2151.2.18 by Olaf van der Spek
refactor
5959
      if (!regex_arr.empty())
1 by brian
clean slate
5960
        break;
5961
      else
5962
        goto err;
5963
    }
5964
    /* we found the start */
5965
    reg.pattern= buf_p;
5966
5967
    /* Find first argument -- pattern string to be removed */
5968
    PARSE_REGEX_ARG
5969
5970
      if (p == expr_end || ++p == expr_end)
5971
        goto err;
5972
5973
    /* buf_p now points to the replacement pattern terminated with \0 */
5974
    reg.replace= buf_p;
5975
5976
    /* Find second argument -- replace string to replace pattern */
5977
    PARSE_REGEX_ARG
5978
5979
      if (p == expr_end)
5980
        goto err;
5981
5982
    /* skip the ending '/' in the statement */
5983
    p++;
5984
5985
    /* Check if we should do matching case insensitive */
5986
    if (p < expr_end && *p == 'i')
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
5987
    {
5988
      p++;
1 by brian
clean slate
5989
      reg.icase= 1;
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
5990
    }
5991
5992
    /* Check if we should do matching globally */
5993
    if (p < expr_end && *p == 'g')
5994
    {
5995
      p++;
5996
      reg.global= 1;
5997
    }
2151.2.18 by Olaf van der Spek
refactor
5998
    regex_arr.push_back(reg);
1 by brian
clean slate
5999
  }
2151.2.19 by Olaf van der Spek
refactor
6000
  odd_buf_len= even_buf_len= buf0_.size();
6001
  even_buf= buf0_.data();
6002
  odd_buf= buf1_.data();
2151.2.18 by Olaf van der Spek
refactor
6003
  buf_= even_buf;
1 by brian
clean slate
6004
2151.2.15 by Olaf van der Spek
drizzletest refactoring
6005
  return;
1 by brian
clean slate
6006
6007
err:
6008
  die("Error parsing replace_regex \"%s\"", expr);
6009
}
6010
6011
/*
6012
  Execute all substitutions on val.
6013
6014
  Returns: true if substituition was made, false otherwise
6015
  Side-effect: Sets r->buf to be the buffer with all substitutions done.
6016
6017
  IN:
6018
  struct st_replace_regex* r
6019
  char* val
6020
  Out:
6021
  struct st_replace_regex* r
6022
  r->buf points at the resulting buffer
6023
  r->even_buf and r->odd_buf might have been reallocated
6024
  r->even_buf_len and r->odd_buf_len might have been changed
6025
6026
  TODO:  at some point figure out if there is a way to do everything
6027
  in one pass
6028
*/
6029
2151.2.19 by Olaf van der Spek
refactor
6030
int st_replace_regex::multi_reg_replace(char* val)
1 by brian
clean slate
6031
{
2151.2.28 by Olaf van der Spek
refactor
6032
  char* in_buf= val;
6033
  char* out_buf= even_buf;
6034
  int* buf_len_p= &even_buf_len;
6035
  buf_= 0;
1 by brian
clean slate
6036
6037
  /* For each substitution, do the replace */
2151.2.28 by Olaf van der Spek
refactor
6038
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
1 by brian
clean slate
6039
  {
6040
    char* save_out_buf= out_buf;
2151.2.28 by Olaf van der Spek
refactor
6041
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6042
                     in_buf, i.icase, i.global))
1 by brian
clean slate
6043
    {
6044
      /* if the buffer has been reallocated, make adjustements */
6045
      if (save_out_buf != out_buf)
6046
      {
2151.2.28 by Olaf van der Spek
refactor
6047
        if (save_out_buf == even_buf)
6048
          even_buf= out_buf;
1 by brian
clean slate
6049
        else
2151.2.28 by Olaf van der Spek
refactor
6050
          odd_buf= out_buf;
1 by brian
clean slate
6051
      }
2151.2.28 by Olaf van der Spek
refactor
6052
      buf_= out_buf;
1 by brian
clean slate
6053
      if (in_buf == val)
2151.2.28 by Olaf van der Spek
refactor
6054
        in_buf= odd_buf;
2151.2.18 by Olaf van der Spek
refactor
6055
      std::swap(in_buf, out_buf);
2151.2.28 by Olaf van der Spek
refactor
6056
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
1 by brian
clean slate
6057
    }
6058
  }
2151.2.28 by Olaf van der Spek
refactor
6059
  return buf_ == 0;
1 by brian
clean slate
6060
}
6061
6062
/*
6063
  Parse the regular expression to be used in all result files
6064
  from now on.
6065
6066
  The syntax is --replace_regex /from/to/i /from/to/i ...
6067
  i means case-insensitive match. If omitted, the match is
6068
  case-sensitive
6069
6070
*/
2318.4.6 by Olaf van der Spek
Refactor
6071
void do_get_replace_regex(st_command* command)
1 by brian
clean slate
6072
{
6073
  char *expr= command->first_argument;
2151.2.21 by Olaf van der Spek
refactor
6074
  glob_replace_regex.reset(new st_replace_regex(expr));
1 by brian
clean slate
6075
  command->last_argument= command->end;
6076
}
6077
6078
/*
6079
  Performs a regex substitution
6080
6081
  IN:
6082
6083
  buf_p - result buffer pointer. Will change if reallocated
6084
  buf_len_p - result buffer length. Will change if the buffer is reallocated
6085
  pattern - regexp pattern to match
6086
  replace - replacement expression
6087
  string - the string to perform substituions in
6088
  icase - flag, if set to 1 the match is case insensitive
6089
*/
6090
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6091
                char *replace, char *in_string, int icase, int global)
1 by brian
clean slate
6092
{
612.2.7 by Monty Taylor
Switched from pcrecpp to plain pcre - mainly so that we can build on OpenSolaris without dealing with G++ vs. SunStudio C++. This all goes away with new test framework - so I did not write pretty replacement code.
6093
  const char *error= NULL;
6094
  int erroffset;
6095
  int ovector[3];
6096
  pcre *re= pcre_compile(pattern,
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6097
                         icase ? PCRE_CASELESS | PCRE_MULTILINE : PCRE_MULTILINE,
612.2.7 by Monty Taylor
Switched from pcrecpp to plain pcre - mainly so that we can build on OpenSolaris without dealing with G++ vs. SunStudio C++. This all goes away with new test framework - so I did not write pretty replacement code.
6098
                         &error, &erroffset, NULL);
6099
  if (re == NULL)
6100
    return 1;
6101
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6102
  if (! global)
6103
  {
6104
6105
    int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
6106
                      0, 0, ovector, 3);
6107
    if (rc < 0)
6108
    {
6109
      pcre_free(re);
6110
      return 1;
6111
    }
6112
6113
    char *substring_to_replace= in_string + ovector[0];
6114
    int substring_length= ovector[1] - ovector[0];
6115
    *buf_len_p= strlen(in_string) - substring_length + strlen(replace);
2318.4.8 by Olaf van der Spek
Remove malloc NULL check. Just die.
6116
    char* new_buf= (char*)malloc(*buf_len_p+1);
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6117
6118
    memset(new_buf, 0, *buf_len_p+1);
6119
    strncpy(new_buf, in_string, substring_to_replace-in_string);
6120
    strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
6121
    strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
6122
            substring_to_replace + substring_length,
6123
            strlen(in_string)
6124
              - substring_length
6125
              - (substring_to_replace-in_string));
6126
    *buf_p= new_buf;
6127
6128
    pcre_free(re);
6129
    return 0;
6130
  }
6131
  else
6132
  {
6133
    /* Repeatedly replace the string with the matched regex */
6134
    string subject(in_string);
6135
    size_t replace_length= strlen(replace);
1750.4.1 by Patrick Crews
Moving transaction_log_tests' new tests into a new branch -\n movement has occurred in the test suite since these were created and merging creates a gnarly mess
6136
    size_t length_of_replacement= strlen(replace);
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6137
    size_t current_position= 0;
6138
    int rc= 0;
1750.4.1 by Patrick Crews
Moving transaction_log_tests' new tests into a new branch -\n movement has occurred in the test suite since these were created and merging creates a gnarly mess
6139
6140
    while (true) 
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6141
    {
1750.4.1 by Patrick Crews
Moving transaction_log_tests' new tests into a new branch -\n movement has occurred in the test suite since these were created and merging creates a gnarly mess
6142
      rc= pcre_exec(re, NULL, subject.c_str(), subject.length(), 
6143
                    current_position, 0, ovector, 3);
6144
      if (rc < 0)
6145
      {
6146
        break;
6147
      }
6148
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6149
      current_position= static_cast<size_t>(ovector[0]);
6150
      replace_length= static_cast<size_t>(ovector[1] - ovector[0]);
1750.4.1 by Patrick Crews
Moving transaction_log_tests' new tests into a new branch -\n movement has occurred in the test suite since these were created and merging creates a gnarly mess
6151
      subject.replace(current_position, replace_length, replace, length_of_replacement);
6152
      current_position= current_position + length_of_replacement;
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6153
    }
6154
2318.4.8 by Olaf van der Spek
Remove malloc NULL check. Just die.
6155
    char* new_buf = (char*) malloc(subject.length() + 1);
1143.3.4 by Jay Pipes
Adds INFORMATION_SCHEMA views for the transaction log:
6156
    memset(new_buf, 0, subject.length() + 1);
6157
    strncpy(new_buf, subject.c_str(), subject.length());
6158
    *buf_len_p= subject.length() + 1;
6159
    *buf_p= new_buf;
6160
          
6161
    pcre_free(re);
6162
    return 0;
6163
  }
1 by brian
clean slate
6164
}
6165
6166
6167
#ifndef WORD_BIT
895 by Brian Aker
Completion (?) of uint conversion.
6168
#define WORD_BIT (8*sizeof(uint32_t))
1 by brian
clean slate
6169
#endif
6170
6171
#define SET_MALLOC_HUNC 64
6172
#define LAST_CHAR_CODE 259
6173
2151.2.33 by Olaf van der Spek
refactor
6174
class REP_SET
2151.2.30 by Olaf van der Spek
refactor
6175
{
2151.2.33 by Olaf van der Spek
refactor
6176
public:
6177
  void internal_set_bit(uint32_t bit);
6178
  void internal_clear_bit(uint32_t bit);
2151.2.34 by Olaf van der Spek
refactor
6179
  void or_bits(const REP_SET *from);
6180
  void copy_bits(const REP_SET *from);
2151.2.36 by Olaf van der Spek
refactor
6181
  int cmp_bits(const REP_SET *set2) const;
6182
  int get_next_bit(uint32_t lastpos) const;
2151.2.33 by Olaf van der Spek
refactor
6183
893 by Brian Aker
First pass of stripping uint
6184
  uint32_t  *bits;        /* Pointer to used sets */
206.3.1 by Patrick Galbraith
Most everything working with client rename
6185
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
893 by Brian Aker
First pass of stripping uint
6186
  uint32_t  found_len;      /* Best match to date */
206.3.1 by Patrick Galbraith
Most everything working with client rename
6187
  int  found_offset;
893 by Brian Aker
First pass of stripping uint
6188
  uint32_t  table_offset;
6189
  uint32_t  size_of_bits;      /* For convinience */
2151.2.30 by Olaf van der Spek
refactor
6190
};
1 by brian
clean slate
6191
2151.2.31 by Olaf van der Spek
refactor
6192
class REP_SETS
2151.2.30 by Olaf van der Spek
refactor
6193
{
2151.2.31 by Olaf van der Spek
refactor
6194
public:
2151.2.32 by Olaf van der Spek
refactor
6195
  int find_set(const REP_SET *find);
2151.2.31 by Olaf van der Spek
refactor
6196
  void free_last_set();
6197
  void free_sets();
2151.2.34 by Olaf van der Spek
refactor
6198
  void make_sets_invisible();
2151.2.31 by Olaf van der Spek
refactor
6199
893 by Brian Aker
First pass of stripping uint
6200
  uint32_t    count;      /* Number of sets */
6201
  uint32_t    extra;      /* Extra sets in buffer */
2151.2.31 by Olaf van der Spek
refactor
6202
  uint32_t    invisible;    /* Sets not shown */
893 by Brian Aker
First pass of stripping uint
6203
  uint32_t    size_of_bits;
206.3.1 by Patrick Galbraith
Most everything working with client rename
6204
  REP_SET  *set,*set_buffer;
893 by Brian Aker
First pass of stripping uint
6205
  uint32_t    *bit_buffer;
2151.2.30 by Olaf van der Spek
refactor
6206
};
1 by brian
clean slate
6207
2151.2.30 by Olaf van der Spek
refactor
6208
struct FOUND_SET 
6209
{
893 by Brian Aker
First pass of stripping uint
6210
  uint32_t table_offset;
1 by brian
clean slate
6211
  int found_offset;
2151.2.30 by Olaf van der Spek
refactor
6212
};
1 by brian
clean slate
6213
2151.2.30 by Olaf van der Spek
refactor
6214
struct FOLLOWS
6215
{
1 by brian
clean slate
6216
  int chr;
893 by Brian Aker
First pass of stripping uint
6217
  uint32_t table_offset;
6218
  uint32_t len;
2151.2.30 by Olaf van der Spek
refactor
6219
};
1 by brian
clean slate
6220
2318.4.8 by Olaf van der Spek
Remove malloc NULL check. Just die.
6221
void init_sets(REP_SETS *sets, uint32_t states);
1 by brian
clean slate
6222
REP_SET *make_new_set(REP_SETS *sets);
2151.2.36 by Olaf van der Spek
refactor
6223
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6224
6225
static uint32_t found_sets= 0;
893 by Brian Aker
First pass of stripping uint
6226
2151.5.5 by Olaf van der Spek
char* -> const char*
6227
static uint32_t replace_len(const char *str)
1 by brian
clean slate
6228
{
893 by Brian Aker
First pass of stripping uint
6229
  uint32_t len=0;
1 by brian
clean slate
6230
  while (*str)
6231
  {
6232
    if (str[0] == '\\' && str[1])
6233
      str++;
6234
    str++;
6235
    len++;
6236
  }
6237
  return len;
6238
}
6239
2151.2.20 by Olaf van der Spek
refactor
6240
/* Return 1 if regexp starts with \b or ends with \b*/
6241
6242
static bool start_at_word(const char *pos)
6243
{
2318.5.2 by Olaf van der Spek
Refactor
6244
  return (!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2);
2151.2.20 by Olaf van der Spek
refactor
6245
}
6246
6247
static bool end_of_word(const char *pos)
6248
{
6249
  const char *end= strchr(pos, '\0');
6250
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6251
}
6252
1 by brian
clean slate
6253
/* Init a replace structure for further calls */
6254
2151.2.20 by Olaf van der Spek
refactor
6255
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
1 by brian
clean slate
6256
{
2151.2.29 by Olaf van der Spek
refactor
6257
  const int SPACE_CHAR= 256;
6258
  const int START_OF_LINE= 257;
6259
  const int END_OF_LINE= 258;
1 by brian
clean slate
6260
893 by Brian Aker
First pass of stripping uint
6261
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
1 by brian
clean slate
6262
  int used_sets,chr,default_state;
6263
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
2151.5.5 by Olaf van der Spek
char* -> const char*
6264
  char *to_pos, **to_array;
1 by brian
clean slate
6265
6266
  /* Count number of states */
2318.5.4 by Olaf van der Spek
Refactor
6267
  for (i=result_len=max_length=0 , states=2; i < count; i++)
1 by brian
clean slate
6268
  {
6269
    len=replace_len(from[i]);
6270
    if (!len)
6271
    {
6272
      errno=EINVAL;
142.1.1 by Patrick
Removing DBUG from client
6273
      return(0);
1 by brian
clean slate
6274
    }
6275
    states+=len+1;
895 by Brian Aker
Completion (?) of uint conversion.
6276
    result_len+=(uint32_t) strlen(to[i])+1;
1 by brian
clean slate
6277
    if (len > max_length)
6278
      max_length=len;
6279
  }
212.6.10 by Mats Kindahl
Removing redundant use of casts in client/ for memcmp(), memcpy(), memset(), and memmove().
6280
  memset(is_word_end, 0, sizeof(is_word_end));
2318.5.4 by Olaf van der Spek
Refactor
6281
  for (i=0; word_end_chars[i]; i++)
481 by Brian Aker
Remove all of uchar.
6282
    is_word_end[(unsigned char) word_end_chars[i]]=1;
1 by brian
clean slate
6283
2151.2.31 by Olaf van der Spek
refactor
6284
  REP_SETS sets;
6285
  REP_SET *set,*start_states,*word_states,*new_set;
6286
  REPLACE_STRING *rep_str;
2318.4.8 by Olaf van der Spek
Remove malloc NULL check. Just die.
6287
  init_sets(&sets, states);
1 by brian
clean slate
6288
  found_sets=0;
2151.2.29 by Olaf van der Spek
refactor
6289
  vector<FOUND_SET> found_set(max_length * count);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
6290
  make_new_set(&sets);      /* Set starting set */
2151.2.34 by Olaf van der Spek
refactor
6291
  sets.make_sets_invisible();      /* Hide previus sets */
1 by brian
clean slate
6292
  used_sets=-1;
206.3.1 by Patrick Galbraith
Most everything working with client rename
6293
  word_states=make_new_set(&sets);    /* Start of new word */
6294
  start_states=make_new_set(&sets);    /* This is first state */
2151.2.31 by Olaf van der Spek
refactor
6295
  vector<FOLLOWS> follow(states + 2);
2151.2.38 by Olaf van der Spek
Use &vector::front() insetad of data()
6296
  FOLLOWS *follow_ptr= &follow[1];
1 by brian
clean slate
6297
  /* Init follow_ptr[] */
2151.2.31 by Olaf van der Spek
refactor
6298
  for (i=0, states=1; i < count; i++)
1 by brian
clean slate
6299
  {
6300
    if (from[i][0] == '\\' && from[i][1] == '^')
6301
    {
2151.2.33 by Olaf van der Spek
refactor
6302
      start_states->internal_set_bit(states + 1);
1 by brian
clean slate
6303
      if (!from[i][2])
6304
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6305
        start_states->table_offset=i;
6306
        start_states->found_offset=1;
1 by brian
clean slate
6307
      }
6308
    }
6309
    else if (from[i][0] == '\\' && from[i][1] == '$')
6310
    {
2151.2.33 by Olaf van der Spek
refactor
6311
      start_states->internal_set_bit(states);
6312
      word_states->internal_set_bit(states);
365.2.7 by Monty Taylor
INT32_MAX stuff.
6313
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
1 by brian
clean slate
6314
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6315
        start_states->table_offset=i;
6316
        start_states->found_offset=0;
1 by brian
clean slate
6317
      }
6318
    }
6319
    else
6320
    {
2151.2.33 by Olaf van der Spek
refactor
6321
      word_states->internal_set_bit(states);
1 by brian
clean slate
6322
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
2151.2.33 by Olaf van der Spek
refactor
6323
        start_states->internal_set_bit(states + 1);
1 by brian
clean slate
6324
      else
2151.2.33 by Olaf van der Spek
refactor
6325
        start_states->internal_set_bit(states);
1 by brian
clean slate
6326
    }
2151.2.30 by Olaf van der Spek
refactor
6327
    const char *pos;
2318.5.4 by Olaf van der Spek
Refactor
6328
    for (pos= from[i], len=0; *pos; pos++)
1 by brian
clean slate
6329
    {
6330
      if (*pos == '\\' && *(pos+1))
6331
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6332
        pos++;
6333
        switch (*pos) {
6334
        case 'b':
6335
          follow_ptr->chr = SPACE_CHAR;
6336
          break;
6337
        case '^':
6338
          follow_ptr->chr = START_OF_LINE;
6339
          break;
6340
        case '$':
6341
          follow_ptr->chr = END_OF_LINE;
6342
          break;
6343
        case 'r':
6344
          follow_ptr->chr = '\r';
6345
          break;
6346
        case 't':
6347
          follow_ptr->chr = '\t';
6348
          break;
6349
        case 'v':
6350
          follow_ptr->chr = '\v';
6351
          break;
6352
        default:
481 by Brian Aker
Remove all of uchar.
6353
          follow_ptr->chr = (unsigned char) *pos;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6354
          break;
6355
        }
1 by brian
clean slate
6356
      }
6357
      else
481 by Brian Aker
Remove all of uchar.
6358
        follow_ptr->chr= (unsigned char) *pos;
1 by brian
clean slate
6359
      follow_ptr->table_offset=i;
6360
      follow_ptr->len= ++len;
6361
      follow_ptr++;
6362
    }
6363
    follow_ptr->chr=0;
6364
    follow_ptr->table_offset=i;
6365
    follow_ptr->len=len;
6366
    follow_ptr++;
895 by Brian Aker
Completion (?) of uint conversion.
6367
    states+=(uint32_t) len+1;
1 by brian
clean slate
6368
  }
6369
6370
2318.5.4 by Olaf van der Spek
Refactor
6371
  for (set_nr=0; set_nr < sets.count; set_nr++)
1 by brian
clean slate
6372
  {
6373
    set=sets.set+set_nr;
206.3.1 by Patrick Galbraith
Most everything working with client rename
6374
    default_state= 0;        /* Start from beginning */
1 by brian
clean slate
6375
6376
    /* If end of found-string not found or start-set with current set */
6377
2318.5.4 by Olaf van der Spek
Refactor
6378
    for (i= UINT32_MAX; (i= set->get_next_bit(i));)
1 by brian
clean slate
6379
    {
2151.2.29 by Olaf van der Spek
refactor
6380
      if (!follow[i].chr && !default_state)
2151.2.38 by Olaf van der Spek
Use &vector::front() insetad of data()
6381
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
1 by brian
clean slate
6382
    }
2151.2.34 by Olaf van der Spek
refactor
6383
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
1 by brian
clean slate
6384
    if (!default_state)
2151.2.34 by Olaf van der Spek
refactor
6385
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
1 by brian
clean slate
6386
6387
    /* Find all chars that follows current sets */
212.6.10 by Mats Kindahl
Removing redundant use of casts in client/ for memcmp(), memcpy(), memset(), and memmove().
6388
    memset(used_chars, 0, sizeof(used_chars));
2318.5.4 by Olaf van der Spek
Refactor
6389
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i));)
1 by brian
clean slate
6390
    {
6391
      used_chars[follow[i].chr]=1;
6392
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6393
           follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6394
        used_chars[0]=1;
1 by brian
clean slate
6395
    }
6396
6397
    /* Mark word_chars used if \b is in state */
6398
    if (used_chars[SPACE_CHAR])
2318.5.4 by Olaf van der Spek
Refactor
6399
      for (const char *pos= word_end_chars; *pos; pos++)
481 by Brian Aker
Remove all of uchar.
6400
        used_chars[(int) (unsigned char) *pos] = 1;
1 by brian
clean slate
6401
6402
    /* Handle other used characters */
2318.5.4 by Olaf van der Spek
Refactor
6403
    for (chr= 0; chr < 256; chr++)
1 by brian
clean slate
6404
    {
6405
      if (! used_chars[chr])
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6406
        set->next[chr]= chr ? default_state : -1;
1 by brian
clean slate
6407
      else
6408
      {
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6409
        new_set=make_new_set(&sets);
6410
        set=sets.set+set_nr;      /* if realloc */
6411
        new_set->table_offset=set->table_offset;
6412
        new_set->found_len=set->found_len;
6413
        new_set->found_offset=set->found_offset+1;
6414
        found_end=0;
1 by brian
clean slate
6415
2318.5.4 by Olaf van der Spek
Refactor
6416
        for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i));)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6417
        {
6418
          if (!follow[i].chr || follow[i].chr == chr ||
6419
              (follow[i].chr == SPACE_CHAR &&
6420
               (is_word_end[chr] ||
6421
                (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6422
              (follow[i].chr == END_OF_LINE && ! chr))
6423
          {
6424
            if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6425
                follow[i].len > found_end)
6426
              found_end=follow[i].len;
6427
            if (chr && follow[i].chr)
2151.2.33 by Olaf van der Spek
refactor
6428
              new_set->internal_set_bit(i + 1);    /* To next set */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6429
            else
2151.2.33 by Olaf van der Spek
refactor
6430
              new_set->internal_set_bit(i);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6431
          }
6432
        }
6433
        if (found_end)
6434
        {
6435
          new_set->found_len=0;      /* Set for testing if first */
6436
          bits_set=0;
2318.5.4 by Olaf van der Spek
Refactor
6437
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i));)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6438
          {
6439
            if ((follow[i].chr == SPACE_CHAR ||
6440
                 follow[i].chr == END_OF_LINE) && ! chr)
6441
              bit_nr=i+1;
6442
            else
6443
              bit_nr=i;
6444
            if (follow[bit_nr-1].len < found_end ||
6445
                (new_set->found_len &&
6446
                 (chr == 0 || !follow[bit_nr].chr)))
2151.2.33 by Olaf van der Spek
refactor
6447
              new_set->internal_clear_bit(i);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6448
            else
6449
            {
6450
              if (chr == 0 || !follow[bit_nr].chr)
6451
              {          /* best match  */
6452
                new_set->table_offset=follow[bit_nr].table_offset;
6453
                if (chr || (follow[i].chr == SPACE_CHAR ||
6454
                            follow[i].chr == END_OF_LINE))
6455
                  new_set->found_offset=found_end;  /* New match */
6456
                new_set->found_len=found_end;
6457
              }
6458
              bits_set++;
6459
            }
6460
          }
6461
          if (bits_set == 1)
6462
          {
2151.2.38 by Olaf van der Spek
Use &vector::front() insetad of data()
6463
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
2151.2.31 by Olaf van der Spek
refactor
6464
            sets.free_last_set();
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6465
          }
6466
          else
2151.2.32 by Olaf van der Spek
refactor
6467
            set->next[chr] = sets.find_set(new_set);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6468
        }
6469
        else
2151.2.32 by Olaf van der Spek
refactor
6470
          set->next[chr] = sets.find_set(new_set);
1 by brian
clean slate
6471
      }
6472
    }
6473
  }
6474
6475
  /* Alloc replace structure for the replace-state-machine */
6476
2151.2.30 by Olaf van der Spek
refactor
6477
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
2151.2.29 by Olaf van der Spek
refactor
6478
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
1 by brian
clean slate
6479
  {
656.1.20 by Monty Taylor
Removed my_strdup, my_malloc, my_realloc from client/
6480
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
6481
                       sizeof(REPLACE_STRING)*(found_sets+1)+
6482
                       sizeof(char *)*count+result_len);
1 by brian
clean slate
6483
    rep_str=(REPLACE_STRING*) (replace+sets.count);
6484
    to_array= (char **) (rep_str+found_sets+1);
6485
    to_pos=(char *) (to_array+count);
2318.5.4 by Olaf van der Spek
Refactor
6486
    for (i=0; i < count; i++)
1 by brian
clean slate
6487
    {
6488
      to_array[i]=to_pos;
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
6489
      to_pos=strcpy(to_pos,to[i])+strlen(to[i])+1;
1 by brian
clean slate
6490
    }
6491
    rep_str[0].found=1;
6492
    rep_str[0].replace_string=0;
2318.5.4 by Olaf van der Spek
Refactor
6493
    for (i=1; i <= found_sets; i++)
1 by brian
clean slate
6494
    {
2151.2.30 by Olaf van der Spek
refactor
6495
      const char *pos= from[found_set[i-1].table_offset];
212.6.10 by Mats Kindahl
Removing redundant use of casts in client/ for memcmp(), memcpy(), memset(), and memmove().
6496
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
2151.2.30 by Olaf van der Spek
refactor
6497
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
6498
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
6499
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
1 by brian
clean slate
6500
    }
2318.5.4 by Olaf van der Spek
Refactor
6501
    for (i=0; i < sets.count; i++)
1 by brian
clean slate
6502
    {
2318.5.4 by Olaf van der Spek
Refactor
6503
      for (j=0; j < 256; j++)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6504
        if (sets.set[i].next[j] >= 0)
6505
          replace[i].next[j]=replace+sets.set[i].next[j];
6506
        else
6507
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
1 by brian
clean slate
6508
    }
6509
  }
2151.2.31 by Olaf van der Spek
refactor
6510
  sets.free_sets();
2151.2.29 by Olaf van der Spek
refactor
6511
  return replace;
1 by brian
clean slate
6512
}
6513
6514
2318.4.8 by Olaf van der Spek
Remove malloc NULL check. Just die.
6515
void init_sets(REP_SETS *sets,uint32_t states)
1 by brian
clean slate
6516
{
212.6.10 by Mats Kindahl
Removing redundant use of casts in client/ for memcmp(), memcpy(), memset(), and memmove().
6517
  memset(sets, 0, sizeof(*sets));
1 by brian
clean slate
6518
  sets->size_of_bits=((states+7)/8);
2318.4.8 by Olaf van der Spek
Remove malloc NULL check. Just die.
6519
  sets->set_buffer=(REP_SET*) malloc(sizeof(REP_SET) * SET_MALLOC_HUNC);
6520
  sets->bit_buffer=(uint*) malloc(sizeof(uint32_t) * sets->size_of_bits * SET_MALLOC_HUNC);
1 by brian
clean slate
6521
}
6522
6523
/* Make help sets invisible for nicer codeing */
6524
2151.2.34 by Olaf van der Spek
refactor
6525
void REP_SETS::make_sets_invisible()
1 by brian
clean slate
6526
{
2151.2.34 by Olaf van der Spek
refactor
6527
  invisible= count;
6528
  set += count;
6529
  count= 0;
1 by brian
clean slate
6530
}
6531
6532
REP_SET *make_new_set(REP_SETS *sets)
6533
{
6534
  REP_SET *set;
6535
  if (sets->extra)
6536
  {
6537
    sets->extra--;
6538
    set=sets->set+ sets->count++;
895 by Brian Aker
Completion (?) of uint conversion.
6539
    memset(set->bits, 0, sizeof(uint32_t)*sets->size_of_bits);
212.6.10 by Mats Kindahl
Removing redundant use of casts in client/ for memcmp(), memcpy(), memset(), and memmove().
6540
    memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
1 by brian
clean slate
6541
    set->found_offset=0;
6542
    set->found_len=0;
365.2.7 by Monty Taylor
INT32_MAX stuff.
6543
    set->table_offset= UINT32_MAX;
1 by brian
clean slate
6544
    set->size_of_bits=sets->size_of_bits;
6545
    return set;
6546
  }
2318.4.7 by Olaf van der Spek
Refactor
6547
  uint32_t count= sets->count + sets->invisible + SET_MALLOC_HUNC;
6548
  set= (REP_SET*) realloc((unsigned char*) sets->set_buffer, sizeof(REP_SET)*count);
1 by brian
clean slate
6549
  sets->set_buffer=set;
6550
  sets->set=set+sets->invisible;
2318.4.7 by Olaf van der Spek
Refactor
6551
  uint32_t* bit_buffer= (uint*) realloc((unsigned char*) sets->bit_buffer, (sizeof(uint32_t)*sets->size_of_bits)*count);
1 by brian
clean slate
6552
  sets->bit_buffer=bit_buffer;
2318.4.7 by Olaf van der Spek
Refactor
6553
  for (uint32_t i= 0; i < count; i++)
1 by brian
clean slate
6554
  {
6555
    sets->set_buffer[i].bits=bit_buffer;
6556
    bit_buffer+=sets->size_of_bits;
6557
  }
6558
  sets->extra=SET_MALLOC_HUNC;
6559
  return make_new_set(sets);
6560
}
6561
2151.2.31 by Olaf van der Spek
refactor
6562
void REP_SETS::free_last_set()
1 by brian
clean slate
6563
{
2151.2.31 by Olaf van der Spek
refactor
6564
  count--;
6565
  extra++;
1 by brian
clean slate
6566
}
6567
2151.2.31 by Olaf van der Spek
refactor
6568
void REP_SETS::free_sets()
1 by brian
clean slate
6569
{
2151.2.31 by Olaf van der Spek
refactor
6570
  free(set_buffer);
6571
  free(bit_buffer);
1 by brian
clean slate
6572
}
6573
2151.2.33 by Olaf van der Spek
refactor
6574
void REP_SET::internal_set_bit(uint32_t bit)
1 by brian
clean slate
6575
{
2151.2.33 by Olaf van der Spek
refactor
6576
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
1 by brian
clean slate
6577
}
6578
2151.2.33 by Olaf van der Spek
refactor
6579
void REP_SET::internal_clear_bit(uint32_t bit)
1 by brian
clean slate
6580
{
2151.2.33 by Olaf van der Spek
refactor
6581
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
1 by brian
clean slate
6582
}
6583
6584
2151.2.34 by Olaf van der Spek
refactor
6585
void REP_SET::or_bits(const REP_SET *from)
1 by brian
clean slate
6586
{
2318.5.4 by Olaf van der Spek
Refactor
6587
  for (uint32_t i= 0; i < size_of_bits; i++)
2151.2.34 by Olaf van der Spek
refactor
6588
    bits[i]|=from->bits[i];
1 by brian
clean slate
6589
}
6590
2151.2.34 by Olaf van der Spek
refactor
6591
void REP_SET::copy_bits(const REP_SET *from)
1 by brian
clean slate
6592
{
2151.2.34 by Olaf van der Spek
refactor
6593
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
1 by brian
clean slate
6594
}
6595
2151.2.36 by Olaf van der Spek
refactor
6596
int REP_SET::cmp_bits(const REP_SET *set2) const
1 by brian
clean slate
6597
{
2151.2.36 by Olaf van der Spek
refactor
6598
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
1 by brian
clean slate
6599
}
6600
6601
/* Get next set bit from set. */
6602
2151.2.36 by Olaf van der Spek
refactor
6603
int REP_SET::get_next_bit(uint32_t lastpos) const
1 by brian
clean slate
6604
{
2151.2.36 by Olaf van der Spek
refactor
6605
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
6606
  uint32_t *end= bits + size_of_bits;
6607
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
2151.2.35 by Olaf van der Spek
refactor
6608
6609
  while (!bits0 && ++start < end)
6610
    bits0= start[0];
6611
  if (!bits0)
1 by brian
clean slate
6612
    return 0;
2151.2.36 by Olaf van der Spek
refactor
6613
  uint32_t pos= (start - bits) * WORD_BIT;
2151.2.35 by Olaf van der Spek
refactor
6614
  while (!(bits0 & 1))
1 by brian
clean slate
6615
  {
2151.2.35 by Olaf van der Spek
refactor
6616
    bits0 >>=1;
1 by brian
clean slate
6617
    pos++;
6618
  }
6619
  return pos;
6620
}
6621
6622
/* find if there is a same set in sets. If there is, use it and
6623
   free given set, else put in given set in sets and return its
6624
   position */
6625
2151.2.32 by Olaf van der Spek
refactor
6626
int REP_SETS::find_set(const REP_SET *find)
1 by brian
clean slate
6627
{
2151.2.31 by Olaf van der Spek
refactor
6628
  uint32_t i= 0;
2151.2.32 by Olaf van der Spek
refactor
6629
  for (; i < count - 1; i++)
1 by brian
clean slate
6630
  {
2151.2.36 by Olaf van der Spek
refactor
6631
    if (!set[i].cmp_bits(find))
1 by brian
clean slate
6632
    {
2151.2.32 by Olaf van der Spek
refactor
6633
      free_last_set();
1 by brian
clean slate
6634
      return i;
6635
    }
6636
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
6637
  return i;        /* return new postion */
1 by brian
clean slate
6638
}
6639
6640
/* find if there is a found_set with same table_offset & found_offset
6641
   If there is return offset to it, else add new offset and return pos.
6642
   Pos returned is -offset-2 in found_set_structure because it is
6643
   saved in set->next and set->next[] >= 0 points to next set and
6644
   set->next[] == -1 is reserved for end without replaces.
6645
*/
6646
2151.2.29 by Olaf van der Spek
refactor
6647
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
1 by brian
clean slate
6648
{
2151.2.29 by Olaf van der Spek
refactor
6649
  uint32_t i= 0;
6650
  for (; i < found_sets; i++)
6651
  {
1 by brian
clean slate
6652
    if (found_set[i].table_offset == table_offset &&
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6653
        found_set[i].found_offset == found_offset)
2151.2.29 by Olaf van der Spek
refactor
6654
      return - i - 2;
6655
  }
6656
  found_set[i].table_offset= table_offset;
6657
  found_set[i].found_offset= found_offset;
1 by brian
clean slate
6658
  found_sets++;
2151.2.29 by Olaf van der Spek
refactor
6659
  return - i - 2; // return new postion
1 by brian
clean slate
6660
}
6661
6662
/****************************************************************************
6663
 * Handle replacement of strings
6664
 ****************************************************************************/
6665
206.3.1 by Patrick Galbraith
Most everything working with client rename
6666
#define PC_MALLOC    256  /* Bytes for pointers */
6667
#define PS_MALLOC    512  /* Bytes for data */
1 by brian
clean slate
6668
2198.4.1 by Olaf van der Spek
Refactor
6669
static int insert_pointer_name(POINTER_ARRAY* pa, char* name)
1 by brian
clean slate
6670
{
893 by Brian Aker
First pass of stripping uint
6671
  uint32_t i,length,old_count;
481 by Brian Aker
Remove all of uchar.
6672
  unsigned char *new_pos;
1 by brian
clean slate
6673
  const char **new_array;
142.1.1 by Patrick
Removing DBUG from client
6674
1 by brian
clean slate
6675
6676
  if (! pa->typelib.count)
6677
  {
2318.4.8 by Olaf van der Spek
Remove malloc NULL check. Just die.
6678
    pa->typelib.type_names=(const char **)
656.1.20 by Monty Taylor
Removed my_strdup, my_malloc, my_realloc from client/
6679
          malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6680
                     (sizeof(char *)+sizeof(*pa->flag))*
2318.4.8 by Olaf van der Spek
Remove malloc NULL check. Just die.
6681
                     (sizeof(char *)+sizeof(*pa->flag))));
6682
    pa->str= (unsigned char*) malloc(PS_MALLOC-MALLOC_OVERHEAD);
481 by Brian Aker
Remove all of uchar.
6683
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(unsigned char*)+
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6684
                                               sizeof(*pa->flag));
428 by Monty Taylor
Removed int7 and int15 and non-stdbool bool def.
6685
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
1 by brian
clean slate
6686
    pa->length=0;
6687
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6688
    pa->array_allocs=1;
6689
  }
895 by Brian Aker
Completion (?) of uint conversion.
6690
  length=(uint32_t) strlen(name)+1;
1 by brian
clean slate
6691
  if (pa->length+length >= pa->max_length)
6692
  {
2318.4.7 by Olaf van der Spek
Refactor
6693
    new_pos= (unsigned char*)realloc((unsigned char*)pa->str, (size_t)(pa->max_length+PS_MALLOC));
1 by brian
clean slate
6694
    if (new_pos != pa->str)
6695
    {
1130.3.31 by Monty Taylor
Fixed an equals sign issue on a changed line.
6696
      ptrdiff_t diff= PTR_BYTE_DIFF(new_pos,pa->str);
2318.5.4 by Olaf van der Spek
Refactor
6697
      for (i=0; i < pa->typelib.count; i++)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6698
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
6699
                                              char*);
1 by brian
clean slate
6700
      pa->str=new_pos;
6701
    }
6702
    pa->max_length+=PS_MALLOC;
6703
  }
6704
  if (pa->typelib.count >= pa->max_count-1)
6705
  {
656.1.20 by Monty Taylor
Removed my_strdup, my_malloc, my_realloc from client/
6706
    size_t len;
1 by brian
clean slate
6707
    pa->array_allocs++;
6708
    len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
2318.4.7 by Olaf van der Spek
Refactor
6709
    new_array= (const char **)realloc((unsigned char*) pa->typelib.type_names,
656.1.20 by Monty Taylor
Removed my_strdup, my_malloc, my_realloc from client/
6710
                                 len/
6711
                                  (sizeof(unsigned char*)+sizeof(*pa->flag))*
2318.4.7 by Olaf van der Spek
Refactor
6712
                                  (sizeof(unsigned char*)+sizeof(*pa->flag)));
1 by brian
clean slate
6713
    pa->typelib.type_names=new_array;
6714
    old_count=pa->max_count;
481 by Brian Aker
Remove all of uchar.
6715
    pa->max_count=len/(sizeof(unsigned char*) + sizeof(*pa->flag));
428 by Monty Taylor
Removed int7 and int15 and non-stdbool bool def.
6716
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
212.6.10 by Mats Kindahl
Removing redundant use of casts in client/ for memcmp(), memcpy(), memset(), and memmove().
6717
    memcpy(pa->flag, pa->typelib.type_names+old_count,
6718
           old_count*sizeof(*pa->flag));
1 by brian
clean slate
6719
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
6720
  pa->flag[pa->typelib.count]=0;      /* Reset flag */
1 by brian
clean slate
6721
  pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
461 by Monty Taylor
Removed NullS. bu-bye.
6722
  pa->typelib.type_names[pa->typelib.count]= NULL;  /* Put end-mark */
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
6723
  strcpy((char*) pa->str+pa->length,name);
1 by brian
clean slate
6724
  pa->length+=length;
142.1.1 by Patrick
Removing DBUG from client
6725
  return(0);
1 by brian
clean slate
6726
} /* insert_pointer_name */
6727
2198.4.1 by Olaf van der Spek
Refactor
6728
int POINTER_ARRAY::insert(char* name)
6729
{
6730
  return insert_pointer_name(this, name);
6731
}
6732
1 by brian
clean slate
6733
6734
/* Functions that uses replace and replace_regex */
6735
6736
/* Append the string to ds, with optional replace */
2318.5.22 by Olaf van der Spek
Refactor
6737
void replace_append_mem(string& ds, const char *val, int len)
1 by brian
clean slate
6738
{
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6739
  char *v= strdup(val);
6740
2151.2.19 by Olaf van der Spek
refactor
6741
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
1 by brian
clean slate
6742
  {
2151.2.19 by Olaf van der Spek
refactor
6743
    v= glob_replace_regex->buf_;
6744
    len= strlen(v);
1 by brian
clean slate
6745
  }
6746
  if (glob_replace)
6747
  {
6748
    /* Normal replace */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6749
    replace_strings_append(glob_replace, ds, v, len);
1 by brian
clean slate
6750
  }
6751
  else
2318.5.22 by Olaf van der Spek
Refactor
6752
    ds.append(v, len);
1 by brian
clean slate
6753
}
6754
6755
6756
/* Append zero-terminated string to ds, with optional replace */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6757
void replace_append(string *ds, const char *val)
1 by brian
clean slate
6758
{
2318.5.22 by Olaf van der Spek
Refactor
6759
  replace_append_mem(*ds, val, strlen(val));
1 by brian
clean slate
6760
}
6761
893 by Brian Aker
First pass of stripping uint
6762
/* Append uint32_t to ds, with optional replace */
2318.6.1 by Olaf van der Spek
Refactor
6763
void replace_append_uint(string& ds, uint32_t val)
1 by brian
clean slate
6764
{
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.
6765
  ostringstream buff;
6766
  buff << val;
2318.6.1 by Olaf van der Spek
Refactor
6767
  replace_append_mem(ds, buff.str().c_str(), buff.str().size());
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6768
1 by brian
clean slate
6769
}
6770
6771
6772
6773
/*
6774
  Build a list of pointer to each line in ds_input, sort
6775
  the list and use the sorted list to append the strings
6776
  sorted to the output ds
6777
6778
  SYNOPSIS
6779
  dynstr_append_sorted
6780
  ds - string where the sorted output will be appended
6781
  ds_input - string to be sorted
6782
6783
*/
6784
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6785
2318.5.22 by Olaf van der Spek
Refactor
6786
void append_sorted(string& ds, const string& ds_input)
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6787
{
496.1.6 by Paul McCullagh
Fixed the --sorted_result command and changed to sorting accending
6788
  priority_queue<string, vector<string>, greater<string> > lines;
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6789
2318.5.22 by Olaf van der Spek
Refactor
6790
  if (ds_input.empty())
142.1.1 by Patrick
Removing DBUG from client
6791
    return;  /* No input */
1 by brian
clean slate
6792
2318.5.22 by Olaf van der Spek
Refactor
6793
  unsigned long eol_pos= ds_input.find_first_of('\n', 0);
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6794
  if (eol_pos == string::npos)
6795
    return; // We should have at least one header here
6796
2318.5.22 by Olaf van der Spek
Refactor
6797
  ds.append(ds_input.substr(0, eol_pos+1));
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6798
6799
  unsigned long start_pos= eol_pos+1;
1 by brian
clean slate
6800
6801
  /* Insert line(s) in array */
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6802
  do {
1 by brian
clean slate
6803
2318.5.22 by Olaf van der Spek
Refactor
6804
    eol_pos= ds_input.find_first_of('\n', start_pos);
1 by brian
clean slate
6805
    /* Find end of line */
2318.5.22 by Olaf van der Spek
Refactor
6806
    lines.push(ds_input.substr(start_pos, eol_pos-start_pos+1));
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6807
    start_pos= eol_pos+1;
6808
6809
  } while ( eol_pos != string::npos);
1 by brian
clean slate
6810
6811
  /* Create new result */
2318.5.2 by Olaf van der Spek
Refactor
6812
  while (!lines.empty()) 
6813
  {
2318.5.22 by Olaf van der Spek
Refactor
6814
    ds.append(lines.top());
373.1.8 by Monty Taylor
Removed DYNAMIC_STRING.
6815
    lines.pop();
1 by brian
clean slate
6816
  }
6817
}
2151.2.21 by Olaf van der Spek
refactor
6818
6819
static void free_all_replace()
6820
{
6821
  free_replace();
6822
  glob_replace_regex.reset();
6823
  free_replace_column();
6824
}