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