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