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