~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqltest.c

  • Committer: Monty Taylor
  • Date: 2008-07-01 14:33:36 UTC
  • mto: (28.1.12 backport_patch)
  • mto: This revision was merged to the branch mainline in revision 34.
  • Revision ID: monty@inaugust.com-20080701143336-8uihm7dhpu92rt0q
Somehow missed moving password.c. Duh.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
/* Copyright (C) 2000 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
20
15
 
21
16
/*
22
 
  drizzletest
 
17
  mysqltest
23
18
 
24
19
  Tool used for executing a .test file
25
20
 
26
 
  See the "DRIZZLE Test framework manual" for more information
27
 
  http://dev.mysql.com/doc/drizzletest/en/index.html
 
21
  See the "MySQL Test framework manual" for more information
 
22
  http://dev.mysql.com/doc/mysqltest/en/index.html
28
23
 
29
24
  Please keep the test framework tools identical in all versions!
30
25
 
38
33
 
39
34
#define MTEST_VERSION "3.3"
40
35
 
41
 
#include "config.h"
42
36
#include "client_priv.h"
43
 
 
44
 
#include <queue>
45
 
#include <map>
46
 
#include <string>
47
 
#include <vector>
48
 
 
49
 
#include <pcrecpp.h>
50
 
 
51
 
#include <mysys/hash.h>
 
37
#include <mysql_version.h>
 
38
#include <mysqld_error.h>
 
39
#include <m_ctype.h>
 
40
#include <my_dir.h>
 
41
#include <hash.h>
52
42
#include <stdarg.h>
53
 
 
54
 
#include "errname.h"
55
 
 
56
 
using namespace std;
 
43
#include <violite.h>
 
44
#include "my_regex.h" /* Our own version of regex */
 
45
#ifdef HAVE_SYS_WAIT_H
 
46
#include <sys/wait.h>
 
47
#endif
 
48
 
 
49
 
57
50
 
58
51
#define MAX_VAR_NAME_LENGTH    256
59
52
#define MAX_COLUMNS            256
65
58
#define QUERY_REAP_FLAG  2
66
59
 
67
60
enum {
 
61
  OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
68
62
  OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
69
63
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
70
64
};
76
70
const char *opt_include= 0, *opt_charsets_dir;
77
71
static int opt_port= 0;
78
72
static int opt_max_connect_retries;
79
 
static bool opt_compress= 0, silent= 0, verbose= 0;
80
 
static bool debug_info_flag= 0, debug_check_flag= 0;
81
 
static bool tty_password= 0;
82
 
static bool opt_mark_progress= 0;
83
 
static bool parsing_disabled= 0;
84
 
static bool display_result_vertically= false,
85
 
  display_metadata= false, display_result_sorted= false;
86
 
static bool disable_query_log= 0, disable_result_log= 0;
87
 
static bool disable_warnings= 0;
88
 
static bool disable_info= 1;
89
 
static bool abort_on_error= 1;
90
 
static bool server_initialized= 0;
91
 
static bool is_windows= 0;
 
73
static my_bool opt_compress= 0, silent= 0, verbose= 0;
 
74
static my_bool debug_info_flag= 0, debug_check_flag= 0;
 
75
static my_bool tty_password= 0;
 
76
static my_bool opt_mark_progress= 0;
 
77
static my_bool ps_protocol= 0, ps_protocol_enabled= 0;
 
78
static my_bool sp_protocol= 0, sp_protocol_enabled= 0;
 
79
static my_bool view_protocol= 0, view_protocol_enabled= 0;
 
80
static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0;
 
81
static my_bool parsing_disabled= 0;
 
82
static my_bool display_result_vertically= FALSE,
 
83
  display_metadata= FALSE, display_result_sorted= FALSE;
 
84
static my_bool disable_query_log= 0, disable_result_log= 0;
 
85
static my_bool disable_warnings= 0;
 
86
static my_bool disable_info= 1;
 
87
static my_bool abort_on_error= 1;
 
88
static my_bool server_initialized= 0;
 
89
static my_bool is_windows= 0;
92
90
static char **default_argv;
93
 
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
 
91
static const char *load_default_groups[]= { "mysqltest", "client", 0 };
94
92
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
95
93
 
96
94
static uint start_lineno= 0; /* Start line of current command */
114
112
struct st_block
115
113
{
116
114
  int             line; /* Start line of block */
117
 
  bool         ok;   /* Should block be executed */
 
115
  my_bool         ok;   /* Should block be executed */
118
116
  enum block_cmd  cmd;  /* Command owning the block */
119
117
};
120
118
 
134
132
static struct st_test_file* file_stack_end;
135
133
 
136
134
 
137
 
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
 
135
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
 
136
 
 
137
static const char *embedded_server_groups[]=
 
138
{
 
139
  "server",
 
140
  "embedded",
 
141
  "mysqltest_SERVER",
 
142
  NullS
 
143
};
138
144
 
139
145
static int embedded_server_arg_count=0;
140
146
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
144
150
  See the timer_output() definition for details
145
151
*/
146
152
static char *timer_file = NULL;
147
 
static uint64_t timer_start;
 
153
static ulonglong timer_start;
148
154
static void timer_output(void);
149
 
static uint64_t timer_now(void);
150
 
 
151
 
static uint64_t progress_start= 0;
152
 
 
153
 
vector<struct st_command*> q_lines;
154
 
 
155
 
typedef struct {
 
155
static ulonglong timer_now(void);
 
156
 
 
157
static ulonglong progress_start= 0;
 
158
 
 
159
/* Precompiled re's */
 
160
static my_regex_t ps_re;     /* the query can be run using PS protocol */
 
161
static my_regex_t sp_re;     /* the query can be run as a SP */
 
162
static my_regex_t view_re;   /* the query can be run as a view*/
 
163
 
 
164
static void init_re(void);
 
165
static int match_re(my_regex_t *, char *);
 
166
static void free_re(void);
 
167
 
 
168
DYNAMIC_ARRAY q_lines;
 
169
 
 
170
struct
 
171
{
156
172
  int read_lines,current_line;
157
 
} parser_st;
158
 
parser_st parser;
 
173
} parser;
159
174
 
160
 
typedef struct
 
175
struct
161
176
{
162
177
  char file[FN_REFLEN];
163
 
  uint32_t pos;
164
 
} master_pos_st;
165
 
 
166
 
master_pos_st master_pos;
 
178
  ulong pos;
 
179
} master_pos;
167
180
 
168
181
/* if set, all results are concated and compared against this file */
169
182
const char *result_file_name= 0;
188
201
 
189
202
struct st_connection
190
203
{
191
 
  DRIZZLE drizzle;
 
204
  MYSQL mysql;
192
205
  /* Used when creating views and sp, to avoid implicit commit */
193
 
  DRIZZLE *util_drizzle;
 
206
  MYSQL* util_mysql;
194
207
  char *name;
 
208
  MYSQL_STMT* stmt;
 
209
 
 
210
#ifdef EMBEDDED_LIBRARY
 
211
  const char *cur_query;
 
212
  int cur_query_len;
 
213
  pthread_mutex_t mutex;
 
214
  pthread_cond_t cond;
 
215
  int query_done;
 
216
#endif /*EMBEDDED_LIBRARY*/
195
217
};
196
218
struct st_connection connections[128];
197
219
struct st_connection* cur_con= NULL, *next_con, *connections_end;
198
220
 
199
221
/*
200
 
  List of commands in drizzletest
 
222
  List of commands in mysqltest
201
223
  Must match the "command_names" array
202
224
  Add new commands before Q_UNKNOWN!
203
225
*/
204
226
enum enum_commands {
205
227
  Q_CONNECTION=1,     Q_QUERY,
206
 
  Q_CONNECT,      Q_SLEEP, Q_REAL_SLEEP,
207
 
  Q_INC,        Q_DEC,
208
 
  Q_SOURCE,      Q_DISCONNECT,
209
 
  Q_LET,        Q_ECHO,
210
 
  Q_WHILE,      Q_END_BLOCK,
211
 
  Q_SYSTEM,      Q_RESULT,
212
 
  Q_REQUIRE,      Q_SAVE_MASTER_POS,
 
228
  Q_CONNECT,        Q_SLEEP, Q_REAL_SLEEP,
 
229
  Q_INC,                    Q_DEC,
 
230
  Q_SOURCE,         Q_DISCONNECT,
 
231
  Q_LET,                    Q_ECHO,
 
232
  Q_WHILE,          Q_END_BLOCK,
 
233
  Q_SYSTEM,         Q_RESULT,
 
234
  Q_REQUIRE,        Q_SAVE_MASTER_POS,
213
235
  Q_SYNC_WITH_MASTER,
214
236
  Q_SYNC_SLAVE_WITH_MASTER,
215
237
  Q_ERROR,
216
 
  Q_SEND,        Q_REAP,
217
 
  Q_DIRTY_CLOSE,      Q_REPLACE, Q_REPLACE_COLUMN,
218
 
  Q_PING,        Q_EVAL,
 
238
  Q_SEND,                   Q_REAP,
 
239
  Q_DIRTY_CLOSE,            Q_REPLACE, Q_REPLACE_COLUMN,
 
240
  Q_PING,                   Q_EVAL,
219
241
  Q_EVAL_RESULT,
220
242
  Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
221
243
  Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
228
250
  Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
229
251
  Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
230
252
  Q_START_TIMER, Q_END_TIMER,
231
 
  Q_CHARACTER_SET,
 
253
  Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
232
254
  Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
233
255
  Q_IF,
234
256
  Q_DISABLE_PARSING, Q_ENABLE_PARSING,
237
259
  Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
238
260
  Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
239
261
 
240
 
  Q_UNKNOWN,             /* Unknown command.   */
241
 
  Q_COMMENT,             /* Comments, ignored. */
 
262
  Q_UNKNOWN,                           /* Unknown command.   */
 
263
  Q_COMMENT,                           /* Comments, ignored. */
242
264
  Q_COMMENT_WITH_COMMAND
243
265
};
244
266
 
298
320
  "start_timer",
299
321
  "end_timer",
300
322
  "character_set",
 
323
  "disable_ps_protocol",
 
324
  "enable_ps_protocol",
301
325
  "disable_reconnect",
302
326
  "enable_reconnect",
303
327
  "if",
310
334
  "copy_file",
311
335
  "perl",
312
336
  "die",
313
 
 
 
337
               
314
338
  /* Don't execute any more commands, compare result */
315
339
  "exit",
316
340
  "skip",
362
386
{
363
387
  char *query, *query_buf,*first_argument,*last_argument,*end;
364
388
  int first_word_len, query_len;
365
 
  bool abort_on_error;
 
389
  my_bool abort_on_error;
366
390
  struct st_expected_errors expected_errors;
367
391
  char require_file[FN_REFLEN];
368
392
  enum enum_commands type;
369
393
};
370
394
 
371
395
TYPELIB command_typelib= {array_elements(command_names),"",
372
 
                          command_names, 0};
 
396
                          command_names, 0};
373
397
 
374
 
string ds_res, ds_progress, ds_warning_messages;
 
398
DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
375
399
 
376
400
char builtin_echo[FN_REFLEN];
377
401
 
378
402
void die(const char *fmt, ...)
379
 
  __attribute__((format(printf, 1, 2)));
 
403
  ATTRIBUTE_FORMAT(printf, 1, 2);
380
404
void abort_not_supported_test(const char *fmt, ...)
381
 
  __attribute__((format(printf, 1, 2)));
 
405
  ATTRIBUTE_FORMAT(printf, 1, 2);
382
406
void verbose_msg(const char *fmt, ...)
383
 
  __attribute__((format(printf, 1, 2)));
 
407
  ATTRIBUTE_FORMAT(printf, 1, 2);
384
408
void warning_msg(const char *fmt, ...)
385
 
  __attribute__((format(printf, 1, 2)));
 
409
  ATTRIBUTE_FORMAT(printf, 1, 2);
386
410
void log_msg(const char *fmt, ...)
387
 
  __attribute__((format(printf, 1, 2)));
 
411
  ATTRIBUTE_FORMAT(printf, 1, 2);
388
412
 
389
413
VAR* var_from_env(const char *, const char *);
390
414
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
391
415
              int val_len);
392
416
void var_free(void* v);
393
417
VAR* var_get(const char *var_name, const char** var_name_end,
394
 
             bool raw, bool ignore_not_existing);
 
418
             my_bool raw, my_bool ignore_not_existing);
395
419
void eval_expr(VAR* v, const char *p, const char** p_end);
396
 
bool match_delimiter(int c, const char *delim, uint length);
 
420
my_bool match_delimiter(int c, const char *delim, uint length);
397
421
void dump_result_to_reject_file(char *buf, int size);
398
 
void dump_result_to_log_file(const char *buf, int size);
399
 
void dump_warning_messages(void);
400
 
void dump_progress(void);
 
422
void dump_result_to_log_file(char *buf, int size);
 
423
void dump_warning_messages();
 
424
void dump_progress();
401
425
 
402
 
void do_eval(string *query_eval, const char *query,
403
 
             const char *query_end, bool pass_through_escape_chars);
404
 
void str_to_file(const char *fname, const char *str, int size);
405
 
void str_to_file2(const char *fname, const char *str, int size, bool append);
 
426
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
 
427
             const char *query_end, my_bool pass_through_escape_chars);
 
428
void str_to_file(const char *fname, char *str, int size);
 
429
void str_to_file2(const char *fname, char *str, int size, my_bool append);
406
430
 
407
431
/* For replace_column */
408
432
static char *replace_column[MAX_COLUMNS];
409
433
static uint max_replace_column= 0;
410
434
void do_get_replace_column(struct st_command*);
411
 
void free_replace_column(void);
 
435
void free_replace_column();
412
436
 
413
437
/* For replace */
414
438
void do_get_replace(struct st_command *command);
415
 
void free_replace(void);
 
439
void free_replace();
416
440
 
417
441
/* For replace_regex */
418
442
void do_get_replace_regex(struct st_command *command);
419
 
void free_replace_regex(void);
420
 
 
421
 
 
422
 
void free_all_replace(void);
423
 
 
424
 
 
425
 
void free_all_replace(void){
 
443
void free_replace_regex();
 
444
 
 
445
 
 
446
void free_all_replace(){
426
447
  free_replace();
427
448
  free_replace_regex();
428
449
  free_replace_column();
429
450
}
430
451
 
431
 
void replace_append_mem(string *ds, const char *val,
432
 
                        int len);
433
 
void replace_append(string *ds, const char *val);
434
 
void replace_append_uint(string *ds, uint val);
435
 
void append_sorted(string* ds, string* ds_input);
 
452
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
 
453
                               int len);
 
454
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
 
455
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
 
456
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input);
436
457
 
437
458
void handle_error(struct st_command*,
438
459
                  unsigned int err_errno, const char *err_error,
439
 
                  const char *err_sqlstate, string *ds);
 
460
                  const char *err_sqlstate, DYNAMIC_STRING *ds);
440
461
void handle_no_error(struct st_command*);
441
462
 
442
 
 
443
 
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
444
 
 
445
 
void do_eval(string *query_eval, const char *query,
446
 
             const char *query_end, bool pass_through_escape_chars)
 
463
#ifdef EMBEDDED_LIBRARY
 
464
 
 
465
/* attributes of the query thread */
 
466
pthread_attr_t cn_thd_attrib;
 
467
 
 
468
/*
 
469
  send_one_query executes query in separate thread, which is
 
470
  necessary in embedded library to run 'send' in proper way.
 
471
  This implementation doesn't handle errors returned
 
472
  by mysql_send_query. It's technically possible, though
 
473
  I don't see where it is needed.
 
474
*/
 
475
pthread_handler_t send_one_query(void *arg)
 
476
{
 
477
  struct st_connection *cn= (struct st_connection*)arg;
 
478
 
 
479
  mysql_thread_init();
 
480
  VOID(mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len));
 
481
 
 
482
  mysql_thread_end();
 
483
  pthread_mutex_lock(&cn->mutex);
 
484
  cn->query_done= 1;
 
485
  VOID(pthread_cond_signal(&cn->cond));
 
486
  pthread_mutex_unlock(&cn->mutex);
 
487
  pthread_exit(0);
 
488
  return 0;
 
489
}
 
490
 
 
491
static int do_send_query(struct st_connection *cn, const char *q, int q_len,
 
492
                         int flags)
 
493
{
 
494
  pthread_t tid;
 
495
 
 
496
  if (flags & QUERY_REAP_FLAG)
 
497
    return mysql_send_query(&cn->mysql, q, q_len);
 
498
 
 
499
  if (pthread_mutex_init(&cn->mutex, NULL) ||
 
500
      pthread_cond_init(&cn->cond, NULL))
 
501
    die("Error in the thread library");
 
502
 
 
503
  cn->cur_query= q;
 
504
  cn->cur_query_len= q_len;
 
505
  cn->query_done= 0;
 
506
  if (pthread_create(&tid, &cn_thd_attrib, send_one_query, (void*)cn))
 
507
    die("Cannot start new thread for query");
 
508
 
 
509
  return 0;
 
510
}
 
511
 
 
512
static void wait_query_thread_end(struct st_connection *con)
 
513
{
 
514
  if (!con->query_done)
 
515
  {
 
516
    pthread_mutex_lock(&con->mutex);
 
517
    while (!con->query_done)
 
518
      pthread_cond_wait(&con->cond, &con->mutex);
 
519
    pthread_mutex_unlock(&con->mutex);
 
520
  }
 
521
}
 
522
 
 
523
#else /*EMBEDDED_LIBRARY*/
 
524
 
 
525
#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q, q_len)
 
526
 
 
527
#endif /*EMBEDDED_LIBRARY*/
 
528
 
 
529
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
 
530
             const char *query_end, my_bool pass_through_escape_chars)
447
531
{
448
532
  const char *p;
449
533
  register char c, next_c;
450
534
  register int escaped = 0;
451
535
  VAR *v;
452
 
 
 
536
  DBUG_ENTER("do_eval");
453
537
 
454
538
  for (p= query; (c= *p) && p < query_end; ++p)
455
539
  {
457
541
    case '$':
458
542
      if (escaped)
459
543
      {
460
 
        escaped= 0;
461
 
        query_eval->append(p, 1);
 
544
        escaped= 0;
 
545
        dynstr_append_mem(query_eval, p, 1);
462
546
      }
463
547
      else
464
548
      {
465
 
        if (!(v= var_get(p, &p, 0, 0)))
466
 
          die("Bad variable in eval");
467
 
        query_eval->append(v->str_val, v->str_val_len);
 
549
        if (!(v= var_get(p, &p, 0, 0)))
 
550
          die("Bad variable in eval");
 
551
        dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
468
552
      }
469
553
      break;
470
554
    case '\\':
471
555
      next_c= *(p+1);
472
556
      if (escaped)
473
557
      {
474
 
        escaped= 0;
475
 
        query_eval->append(p, 1);
 
558
        escaped= 0;
 
559
        dynstr_append_mem(query_eval, p, 1);
476
560
      }
477
561
      else if (next_c == '\\' || next_c == '$' || next_c == '"')
478
562
      {
479
563
        /* Set escaped only if next char is \, " or $ */
480
 
        escaped= 1;
 
564
        escaped= 1;
481
565
 
482
566
        if (pass_through_escape_chars)
483
567
        {
484
568
          /* The escape char should be added to the output string. */
485
 
          query_eval->append(p, 1);
 
569
          dynstr_append_mem(query_eval, p, 1);
486
570
        }
487
571
      }
488
572
      else
489
 
        query_eval->append(p, 1);
 
573
        dynstr_append_mem(query_eval, p, 1);
490
574
      break;
491
575
    default:
492
576
      escaped= 0;
493
 
      query_eval->append(p, 1);
 
577
      dynstr_append_mem(query_eval, p, 1);
494
578
      break;
495
579
    }
496
580
  }
497
 
  return;
498
 
}
499
 
 
500
 
 
501
 
/*
502
 
  Concatenates any number of strings, escapes any OS quote in the result then
503
 
  surround the whole affair in another set of quotes which is finally appended
504
 
  to specified string.  This function is especially useful when
505
 
  building strings to be executed with the system() function.
506
 
 
507
 
  @param str string which will have addtional strings appended.
508
 
  @param append string to be appended.
509
 
  @param ... Optional. Additional string(s) to be appended.
510
 
 
511
 
  @note The final argument in the list must be NULL even if no additional
512
 
  options are passed.
513
 
*/
514
 
 
515
 
void append_os_quoted(string *str, const char *append, ...)
516
 
{
517
 
  const char *quote_str= "\'";
518
 
  const uint  quote_len= 1;
519
 
 
520
 
  va_list dirty_text;
521
 
 
522
 
  str->append(quote_str, quote_len); /* Leading quote */
523
 
  va_start(dirty_text, append);
524
 
  while (append != NULL)
525
 
  {
526
 
    const char  *cur_pos= append;
527
 
    const char *next_pos= cur_pos;
528
 
 
529
 
    /* Search for quote in each string and replace with escaped quote */
530
 
    while((next_pos= strrchr(cur_pos, quote_str[0])) != NULL)
531
 
    {
532
 
      str->append(cur_pos, next_pos - cur_pos);
533
 
      str->append("\\", 1);
534
 
      str->append(quote_str, quote_len);
535
 
      cur_pos= next_pos + 1;
536
 
    }
537
 
    str->append(cur_pos);
538
 
    append= va_arg(dirty_text, char *);
539
 
  }
540
 
  va_end(dirty_text);
541
 
  str->append(quote_str, quote_len); /* Trailing quote */
 
581
  DBUG_VOID_RETURN;
542
582
}
543
583
 
544
584
 
550
590
 
551
591
  SYNOPSIS
552
592
  show_query
553
 
  drizzle - connection to use
 
593
  mysql - connection to use
554
594
  query - query to run
555
595
 
556
596
*/
557
597
 
558
 
static void show_query(DRIZZLE *drizzle, const char* query)
 
598
static void show_query(MYSQL* mysql, const char* query)
559
599
{
560
 
  DRIZZLE_RES* res;
561
 
 
562
 
 
563
 
  if (!drizzle)
564
 
    return;
565
 
 
566
 
  if (drizzle_query(drizzle, query))
 
600
  MYSQL_RES* res;
 
601
  DBUG_ENTER("show_query");
 
602
 
 
603
  if (!mysql)
 
604
    DBUG_VOID_RETURN;
 
605
 
 
606
  if (mysql_query(mysql, query))
567
607
  {
568
608
    log_msg("Error running query '%s': %d %s",
569
 
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
570
 
    return;
 
609
            query, mysql_errno(mysql), mysql_error(mysql));
 
610
    DBUG_VOID_RETURN;
571
611
  }
572
612
 
573
 
  if ((res= drizzle_store_result(drizzle)) == NULL)
 
613
  if ((res= mysql_store_result(mysql)) == NULL)
574
614
  {
575
615
    /* No result set returned */
576
 
    return;
 
616
    DBUG_VOID_RETURN;
577
617
  }
578
618
 
579
619
  {
580
 
    DRIZZLE_ROW row;
 
620
    MYSQL_ROW row;
581
621
    unsigned int i;
582
622
    unsigned int row_num= 0;
583
 
    unsigned int num_fields= drizzle_num_fields(res);
584
 
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
623
    unsigned int num_fields= mysql_num_fields(res);
 
624
    MYSQL_FIELD *fields= mysql_fetch_fields(res);
585
625
 
586
626
    fprintf(stderr, "=== %s ===\n", query);
587
 
    while ((row= drizzle_fetch_row(res)))
 
627
    while ((row= mysql_fetch_row(res)))
588
628
    {
589
 
      uint32_t *lengths= drizzle_fetch_lengths(res);
 
629
      unsigned long *lengths= mysql_fetch_lengths(res);
590
630
      row_num++;
591
631
 
592
632
      fprintf(stderr, "---- %d. ----\n", row_num);
601
641
      fprintf(stderr, "=");
602
642
    fprintf(stderr, "\n\n");
603
643
  }
604
 
  drizzle_free_result(res);
 
644
  mysql_free_result(res);
605
645
 
606
 
  return;
 
646
  DBUG_VOID_RETURN;
607
647
}
608
648
 
609
649
 
616
656
 
617
657
  SYNOPSIS
618
658
  show_warnings_before_error
619
 
  drizzle - connection to use
 
659
  mysql - connection to use
620
660
 
621
661
*/
622
662
 
623
 
static void show_warnings_before_error(DRIZZLE *drizzle)
 
663
static void show_warnings_before_error(MYSQL* mysql)
624
664
{
625
 
  DRIZZLE_RES* res;
 
665
  MYSQL_RES* res;
626
666
  const char* query= "SHOW WARNINGS";
627
 
 
628
 
 
629
 
  if (!drizzle)
630
 
    return;
631
 
 
632
 
  if (drizzle_query(drizzle, query))
 
667
  DBUG_ENTER("show_warnings_before_error");
 
668
 
 
669
  if (!mysql)
 
670
    DBUG_VOID_RETURN;
 
671
 
 
672
  if (mysql_query(mysql, query))
633
673
  {
634
674
    log_msg("Error running query '%s': %d %s",
635
 
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
636
 
    return;
 
675
            query, mysql_errno(mysql), mysql_error(mysql));
 
676
    DBUG_VOID_RETURN;
637
677
  }
638
678
 
639
 
  if ((res= drizzle_store_result(drizzle)) == NULL)
 
679
  if ((res= mysql_store_result(mysql)) == NULL)
640
680
  {
641
681
    /* No result set returned */
642
 
    return;
 
682
    DBUG_VOID_RETURN;
643
683
  }
644
684
 
645
 
  if (drizzle_num_rows(res) <= 1)
 
685
  if (mysql_num_rows(res) <= 1)
646
686
  {
647
687
    /* Don't display the last row, it's "last error" */
648
688
  }
649
689
  else
650
690
  {
651
 
    DRIZZLE_ROW row;
 
691
    MYSQL_ROW row;
652
692
    unsigned int row_num= 0;
653
 
    unsigned int num_fields= drizzle_num_fields(res);
 
693
    unsigned int num_fields= mysql_num_fields(res);
654
694
 
655
695
    fprintf(stderr, "\nWarnings from just before the error:\n");
656
 
    while ((row= drizzle_fetch_row(res)))
 
696
    while ((row= mysql_fetch_row(res)))
657
697
    {
658
 
      uint32_t i;
659
 
      uint32_t *lengths= drizzle_fetch_lengths(res);
 
698
      unsigned int i;
 
699
      unsigned long *lengths= mysql_fetch_lengths(res);
660
700
 
661
 
      if (++row_num >= drizzle_num_rows(res))
 
701
      if (++row_num >= mysql_num_rows(res))
662
702
      {
663
703
        /* Don't display the last row, it's "last error" */
664
704
        break;
672
712
      fprintf(stderr, "\n");
673
713
    }
674
714
  }
675
 
  drizzle_free_result(res);
 
715
  mysql_free_result(res);
676
716
 
677
 
  return;
 
717
  DBUG_VOID_RETURN;
678
718
}
679
719
 
680
720
 
687
727
struct command_arg {
688
728
  const char *argname;       /* Name of argument   */
689
729
  enum arg_type type;        /* Type of argument   */
690
 
  bool required;          /* Argument required  */
691
 
  string *ds;        /* Storage for argument */
 
730
  my_bool required;          /* Argument required  */
 
731
  DYNAMIC_STRING *ds;        /* Storage for argument */
692
732
  const char *description;   /* Description of the argument */
693
733
};
694
734
 
695
735
 
696
 
static void check_command_args(struct st_command *command,
697
 
                               const char *arguments,
698
 
                               const struct command_arg *args,
699
 
                               int num_args, const char delimiter_arg)
 
736
void check_command_args(struct st_command *command,
 
737
                        const char *arguments,
 
738
                        const struct command_arg *args,
 
739
                        int num_args, const char delimiter_arg)
700
740
{
701
741
  int i;
702
742
  const char *ptr= arguments;
703
743
  const char *start;
 
744
  DBUG_ENTER("check_command_args");
 
745
  DBUG_PRINT("enter", ("num_args: %d", num_args));
704
746
 
705
747
  for (i= 0; i < num_args; i++)
706
748
  {
718
760
        ptr++;
719
761
      if (ptr > start)
720
762
      {
721
 
        do_eval(arg->ds, start, ptr, false);
 
763
        init_dynamic_string(arg->ds, 0, ptr-start, 32);
 
764
        do_eval(arg->ds, start, ptr, FALSE);
722
765
      }
723
766
      else
724
767
      {
725
768
        /* Empty string */
726
 
        arg->ds->erase();
 
769
        init_dynamic_string(arg->ds, "", 0, 0);
727
770
      }
728
771
      command->last_argument= (char*)ptr;
729
772
 
730
773
      /* Step past the delimiter */
731
774
      if (*ptr && *ptr == delimiter_arg)
732
775
        ptr++;
 
776
      DBUG_PRINT("info", ("val: %s", arg->ds->str));
733
777
      break;
734
778
 
735
779
      /* Rest of line */
736
780
    case ARG_REST:
737
781
      start= ptr;
738
 
      do_eval(arg->ds, start, command->end, false);
 
782
      init_dynamic_string(arg->ds, 0, command->query_len, 256);
 
783
      do_eval(arg->ds, start, command->end, FALSE);
739
784
      command->last_argument= command->end;
 
785
      DBUG_PRINT("info", ("val: %s", arg->ds->str));
740
786
      break;
741
787
 
742
788
    default:
743
 
      assert("Unknown argument type");
 
789
      DBUG_ASSERT("Unknown argument type");
744
790
      break;
745
791
    }
746
792
 
747
793
    /* Check required arg */
748
 
    if (arg->ds->length() == 0 && arg->required)
 
794
    if (arg->ds->length == 0 && arg->required)
749
795
      die("Missing required argument '%s' to command '%.*s'", arg->argname,
750
796
          command->first_word_len, command->query);
751
797
 
759
805
          ptr, command->first_word_len, command->query);
760
806
    ptr++;
761
807
  }
762
 
  return;
 
808
  DBUG_VOID_RETURN;
763
809
}
764
810
 
765
811
 
766
 
static void handle_command_error(struct st_command *command, uint error)
 
812
void handle_command_error(struct st_command *command, uint error)
767
813
{
768
 
 
 
814
  DBUG_ENTER("handle_command_error");
 
815
  DBUG_PRINT("enter", ("error: %d", error));
769
816
  if (error != 0)
770
817
  {
771
818
    uint i;
775
822
          command->first_word_len, command->query, error);
776
823
    for (i= 0; i < command->expected_errors.count; i++)
777
824
    {
 
825
      DBUG_PRINT("info", ("expected error: %d",
 
826
                          command->expected_errors.err[i].code.errnum));
778
827
      if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
779
828
          (command->expected_errors.err[i].code.errnum == error))
780
829
      {
781
 
        return;
 
830
        DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d",
 
831
                            command->first_word_len, command->query, error));
 
832
        DBUG_VOID_RETURN;
782
833
      }
783
834
    }
784
835
    die("command \"%.*s\" failed with wrong error: %d",
792
843
        command->first_word_len, command->query,
793
844
        command->expected_errors.err[0].code.errnum);
794
845
  }
795
 
  return;
 
846
  DBUG_VOID_RETURN;
796
847
}
797
848
 
798
849
 
799
 
static void close_connections(void)
 
850
void close_connections()
800
851
{
801
 
 
 
852
  DBUG_ENTER("close_connections");
802
853
  for (--next_con; next_con >= connections; --next_con)
803
854
  {
804
 
    drizzle_close(&next_con->drizzle);
805
 
    if (next_con->util_drizzle)
806
 
      drizzle_close(next_con->util_drizzle);
807
 
    free(next_con->name);
808
 
  }
809
 
  return;
810
 
}
811
 
 
812
 
 
813
 
static void close_files(void)
814
 
{
815
 
 
 
855
    if (next_con->stmt)
 
856
      mysql_stmt_close(next_con->stmt);
 
857
    next_con->stmt= 0;
 
858
    mysql_close(&next_con->mysql);
 
859
    if (next_con->util_mysql)
 
860
      mysql_close(next_con->util_mysql);
 
861
    my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
 
862
  }
 
863
  DBUG_VOID_RETURN;
 
864
}
 
865
 
 
866
 
 
867
void close_statements()
 
868
{
 
869
  struct st_connection *con;
 
870
  DBUG_ENTER("close_statements");
 
871
  for (con= connections; con < next_con; con++)
 
872
  {
 
873
    if (con->stmt)
 
874
      mysql_stmt_close(con->stmt);
 
875
    con->stmt= 0;
 
876
  }
 
877
  DBUG_VOID_RETURN;
 
878
}
 
879
 
 
880
 
 
881
void close_files()
 
882
{
 
883
  DBUG_ENTER("close_files");
816
884
  for (; cur_file >= file_stack; cur_file--)
817
885
  {
818
886
    if (cur_file->file && cur_file->file != stdin)
819
887
    {
 
888
      DBUG_PRINT("info", ("closing file: %s", cur_file->file_name));
820
889
      my_fclose(cur_file->file, MYF(0));
821
890
    }
822
 
    free((unsigned char*) cur_file->file_name);
 
891
    my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
823
892
    cur_file->file_name= 0;
824
893
  }
825
 
  return;
 
894
  DBUG_VOID_RETURN;
826
895
}
827
896
 
828
897
 
829
 
static void free_used_memory(void)
 
898
void free_used_memory()
830
899
{
831
900
  uint i;
832
 
 
 
901
  DBUG_ENTER("free_used_memory");
833
902
 
834
903
  close_connections();
835
904
  close_files();
836
905
  hash_free(&var_hash);
837
906
 
838
 
  vector<struct st_command *>::iterator iter;
839
 
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
 
907
  for (i= 0 ; i < q_lines.elements ; i++)
840
908
  {
841
 
    struct st_command * q_line= *(iter.base());
842
 
    if (q_line->query_buf != NULL)
843
 
    {
844
 
      free(q_line->query_buf);
845
 
    }
846
 
    free(q_line);
 
909
    struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
 
910
    my_free((*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
 
911
    my_free((*q),MYF(0));
847
912
  }
848
 
 
849
913
  for (i= 0; i < 10; i++)
850
914
  {
851
915
    if (var_reg[i].alloced_len)
852
 
      free(var_reg[i].str_val);
 
916
      my_free(var_reg[i].str_val, MYF(MY_WME));
853
917
  }
854
918
  while (embedded_server_arg_count > 1)
855
 
    free(embedded_server_args[--embedded_server_arg_count]);
856
 
 
 
919
    my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
 
920
  delete_dynamic(&q_lines);
 
921
  dynstr_free(&ds_res);
 
922
  dynstr_free(&ds_progress);
 
923
  dynstr_free(&ds_warning_messages);
857
924
  free_all_replace();
858
 
  free(opt_pass);
 
925
  my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
859
926
  free_defaults(default_argv);
860
 
 
 
927
  free_re();
 
928
 
 
929
  /* Only call mysql_server_end if mysql_server_init has been called */
 
930
  if (server_initialized)
 
931
    mysql_server_end();
 
932
 
 
933
  /* Don't use DBUG after mysql_server_end() */
861
934
  return;
862
935
}
863
936
 
877
950
      break;
878
951
    case 62:
879
952
      printf("skipped\n");
880
 
      break;
 
953
    break;
881
954
    default:
882
955
      printf("unknown exit code: %d\n", exit_code);
883
 
      assert(0);
 
956
      DBUG_ASSERT(0);
884
957
    }
885
958
  }
886
959
 
891
964
{
892
965
  static int dying= 0;
893
966
  va_list args;
 
967
  DBUG_ENTER("die");
 
968
  DBUG_PRINT("enter", ("start_lineno: %d", start_lineno));
894
969
 
895
970
  /*
896
971
    Protect against dying twice
902
977
  dying= 1;
903
978
 
904
979
  /* Print the error message */
905
 
  fprintf(stderr, "drizzletest: ");
 
980
  fprintf(stderr, "mysqltest: ");
906
981
  if (cur_file && cur_file != file_stack)
907
982
    fprintf(stderr, "In included file \"%s\": ",
908
983
            cur_file->file_name);
920
995
  fflush(stderr);
921
996
 
922
997
  /* Show results from queries just before failure */
923
 
  if (ds_res.length() && opt_tail_lines)
 
998
  if (ds_res.length && opt_tail_lines)
924
999
  {
925
1000
    int tail_lines= opt_tail_lines;
926
 
    const char* show_from= ds_res.c_str() + ds_res.length() - 1;
927
 
    while(show_from > ds_res.c_str() && tail_lines > 0 )
 
1001
    char* show_from= ds_res.str + ds_res.length - 1;
 
1002
    while(show_from > ds_res.str && tail_lines > 0 )
928
1003
    {
929
1004
      show_from--;
930
1005
      if (*show_from == '\n')
931
1006
        tail_lines--;
932
1007
    }
933
1008
    fprintf(stderr, "\nThe result from queries just before the failure was:\n");
934
 
    if (show_from > ds_res.c_str())
 
1009
    if (show_from > ds_res.str)
935
1010
      fprintf(stderr, "< snip >");
936
1011
    fprintf(stderr, "%s", show_from);
937
1012
    fflush(stderr);
938
1013
  }
939
1014
 
940
1015
  /* Dump the result that has been accumulated so far to .log file */
941
 
  if (result_file_name && ds_res.length())
942
 
    dump_result_to_log_file(ds_res.c_str(), ds_res.length());
 
1016
  if (result_file_name && ds_res.length)
 
1017
    dump_result_to_log_file(ds_res.str, ds_res.length);
943
1018
 
944
1019
  /* Dump warning messages */
945
 
  if (result_file_name && ds_warning_messages.length())
 
1020
  if (result_file_name && ds_warning_messages.length)
946
1021
    dump_warning_messages();
947
1022
 
948
1023
  /*
950
1025
    been produced prior to the error
951
1026
  */
952
1027
  if (cur_con)
953
 
    show_warnings_before_error(&cur_con->drizzle);
 
1028
    show_warnings_before_error(&cur_con->mysql);
954
1029
 
955
1030
  cleanup_and_exit(1);
956
1031
}
960
1035
{
961
1036
  va_list args;
962
1037
  struct st_test_file* err_file= cur_file;
963
 
 
 
1038
  DBUG_ENTER("abort_not_supported_test");
964
1039
 
965
1040
  /* Print include filestack */
966
1041
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
989
1064
}
990
1065
 
991
1066
 
 
1067
void abort_not_in_this_version()
 
1068
{
 
1069
  die("Not available in this version of mysqltest");
 
1070
}
 
1071
 
 
1072
 
 
1073
void deprecated(struct st_command *command)
 
1074
{
 
1075
  die("'%.*s'has been deprecated",
 
1076
      command->first_word_len, command->query);
 
1077
}
 
1078
 
 
1079
 
992
1080
void verbose_msg(const char *fmt, ...)
993
1081
{
994
1082
  va_list args;
995
 
 
 
1083
  DBUG_ENTER("verbose_msg");
996
1084
  if (!verbose)
997
 
    return;
 
1085
    DBUG_VOID_RETURN;
998
1086
 
999
1087
  va_start(args, fmt);
1000
 
  fprintf(stderr, "drizzletest: ");
 
1088
  fprintf(stderr, "mysqltest: ");
1001
1089
  if (cur_file && cur_file != file_stack)
1002
1090
    fprintf(stderr, "In included file \"%s\": ",
1003
1091
            cur_file->file_name);
1007
1095
  fprintf(stderr, "\n");
1008
1096
  va_end(args);
1009
1097
 
1010
 
  return;
 
1098
  DBUG_VOID_RETURN;
1011
1099
}
1012
1100
 
1013
1101
 
1016
1104
  va_list args;
1017
1105
  char buff[512];
1018
1106
  size_t len;
1019
 
 
 
1107
  DBUG_ENTER("warning_msg");
1020
1108
 
1021
1109
  va_start(args, fmt);
1022
 
  ds_warning_messages.append("drizzletest: ");
 
1110
  dynstr_append(&ds_warning_messages, "mysqltest: ");
1023
1111
  if (start_lineno != 0)
1024
1112
  {
1025
 
    ds_warning_messages.append("Warning detected ");
 
1113
    dynstr_append(&ds_warning_messages, "Warning detected ");
1026
1114
    if (cur_file && cur_file != file_stack)
1027
1115
    {
1028
 
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1029
 
                    cur_file->file_name);
1030
 
      ds_warning_messages.append(buff, len);
 
1116
      len= my_snprintf(buff, sizeof(buff), "in included file %s ",
 
1117
                       cur_file->file_name);
 
1118
      dynstr_append_mem(&ds_warning_messages,
 
1119
                        buff, len);
1031
1120
    }
1032
 
    len= snprintf(buff, sizeof(buff), "at line %d: ",
1033
 
                  start_lineno);
1034
 
    ds_warning_messages.append(buff, len);
 
1121
    len= my_snprintf(buff, sizeof(buff), "at line %d: ",
 
1122
                     start_lineno);
 
1123
    dynstr_append_mem(&ds_warning_messages,
 
1124
                      buff, len);
1035
1125
  }
1036
1126
 
1037
 
  len= vsnprintf(buff, sizeof(buff), fmt, args);
1038
 
  ds_warning_messages.append(buff, len);
 
1127
  len= my_vsnprintf(buff, sizeof(buff), fmt, args);
 
1128
  dynstr_append_mem(&ds_warning_messages, buff, len);
1039
1129
 
1040
 
  ds_warning_messages.append("\n");
 
1130
  dynstr_append(&ds_warning_messages, "\n");
1041
1131
  va_end(args);
1042
1132
 
1043
 
  return;
 
1133
  DBUG_VOID_RETURN;
1044
1134
}
1045
1135
 
1046
1136
 
1049
1139
  va_list args;
1050
1140
  char buff[1024];
1051
1141
  size_t len;
1052
 
 
 
1142
  DBUG_ENTER("log_msg");
1053
1143
 
1054
1144
  va_start(args, fmt);
1055
 
  len= vsnprintf(buff, sizeof(buff)-1, fmt, args);
 
1145
  len= my_vsnprintf(buff, sizeof(buff)-1, fmt, args);
1056
1146
  va_end(args);
1057
1147
 
1058
 
  ds_res.append(buff, len);
1059
 
  ds_res.append("\n");
 
1148
  dynstr_append_mem(&ds_res, buff, len);
 
1149
  dynstr_append(&ds_res, "\n");
1060
1150
 
1061
 
  return;
 
1151
  DBUG_VOID_RETURN;
1062
1152
}
1063
1153
 
1064
1154
 
1072
1162
 
1073
1163
*/
1074
1164
 
1075
 
static void cat_file(string* ds, const char* filename)
 
1165
void cat_file(DYNAMIC_STRING* ds, const char* filename)
1076
1166
{
1077
1167
  int fd;
1078
1168
  uint len;
1080
1170
 
1081
1171
  if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
1082
1172
    die("Failed to open file '%s'", filename);
1083
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1173
  while((len= my_read(fd, (uchar*)&buff,
1084
1174
                      sizeof(buff), MYF(0))) > 0)
1085
1175
  {
1086
1176
    char *p= buff, *start= buff;
1092
1182
        /* Add fake newline instead of cr and output the line */
1093
1183
        *p= '\n';
1094
1184
        p++; /* Step past the "fake" newline */
1095
 
        ds->append(start, p-start);
 
1185
        dynstr_append_mem(ds, start, p-start);
1096
1186
        p++; /* Step past the "fake" newline */
1097
1187
        start= p;
1098
1188
      }
1099
1189
      else
1100
1190
        p++;
1101
1191
    }
1102
 
    /* Output any chars that might be left */
1103
 
    ds->append(start, p-start);
 
1192
    /* Output any chars that migh be left */
 
1193
    dynstr_append_mem(ds, start, p-start);
1104
1194
  }
1105
1195
  my_close(fd, MYF(0));
1106
1196
}
1112
1202
  SYNOPSIS
1113
1203
  run_command
1114
1204
  cmd - command to execute(should be properly quoted
1115
 
  result - pointer to string where to store the result
 
1205
  ds_res- pointer to dynamic string where to store the result
1116
1206
 
1117
1207
*/
1118
1208
 
1119
 
static int run_command(const char * cmd, string * result)
 
1209
static int run_command(char* cmd,
 
1210
                       DYNAMIC_STRING *ds_res)
1120
1211
{
1121
 
  assert(result!=NULL);
1122
1212
  char buf[512]= {0};
1123
1213
  FILE *res_file;
1124
1214
  int error;
1128
1218
 
1129
1219
  while (fgets(buf, sizeof(buf), res_file))
1130
1220
  {
1131
 
    /* Save the output of this command in the supplied string */
1132
 
    result->append(buf);
 
1221
    DBUG_PRINT("info", ("buf: %s", buf));
 
1222
    if(ds_res)
 
1223
    {
 
1224
      /* Save the output of this command in the supplied string */
 
1225
      dynstr_append(ds_res, buf);
 
1226
    }
 
1227
    else
 
1228
    {
 
1229
      /* Print it directly on screen */
 
1230
      fprintf(stdout, "%s", buf);
 
1231
    }
1133
1232
  }
1134
1233
 
1135
1234
  error= pclose(res_file);
1143
1242
  SYNOPSIS
1144
1243
  run_tool
1145
1244
  tool_path - the name of the tool to run
1146
 
  result - pointer to dynamic string where to store the result
 
1245
  ds_res - pointer to dynamic string where to store the result
1147
1246
  ... - variable number of arguments that will be properly
1148
 
  quoted and appended after the tool's name
 
1247
        quoted and appended after the tool's name
1149
1248
 
1150
1249
*/
1151
1250
 
1152
 
static int run_tool(const char *tool_path, string * result, ...)
 
1251
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1153
1252
{
1154
1253
  int ret;
1155
1254
  const char* arg;
1156
1255
  va_list args;
1157
 
  string ds_cmdline;
1158
 
 
1159
 
 
1160
 
  append_os_quoted(&ds_cmdline, tool_path, NULL);
1161
 
  ds_cmdline.append(" ");
1162
 
 
1163
 
  va_start(args, result);
 
1256
  DYNAMIC_STRING ds_cmdline;
 
1257
 
 
1258
  DBUG_ENTER("run_tool");
 
1259
  DBUG_PRINT("enter", ("tool_path: %s", tool_path));
 
1260
 
 
1261
  if (init_dynamic_string(&ds_cmdline, "", FN_REFLEN, FN_REFLEN))
 
1262
    die("Out of memory");
 
1263
 
 
1264
  dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
 
1265
  dynstr_append(&ds_cmdline, " ");
 
1266
 
 
1267
  va_start(args, ds_res);
1164
1268
 
1165
1269
  while ((arg= va_arg(args, char *)))
1166
1270
  {
1167
1271
    /* Options should be os quoted */
1168
1272
    if (strncmp(arg, "--", 2) == 0)
1169
 
      append_os_quoted(&ds_cmdline, arg, NULL);
 
1273
      dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1170
1274
    else
1171
 
      ds_cmdline.append(arg);
1172
 
    ds_cmdline.append(" ");
 
1275
      dynstr_append(&ds_cmdline, arg);
 
1276
    dynstr_append(&ds_cmdline, " ");
1173
1277
  }
1174
1278
 
1175
1279
  va_end(args);
1176
1280
 
1177
 
  ret= run_command(ds_cmdline.c_str(), result);
1178
 
  return(ret);
 
1281
  DBUG_PRINT("info", ("Running: %s", ds_cmdline.str));
 
1282
  ret= run_command(ds_cmdline.str, ds_res);
 
1283
  DBUG_PRINT("exit", ("ret: %d", ret));
 
1284
  dynstr_free(&ds_cmdline);
 
1285
  DBUG_RETURN(ret);
1179
1286
}
1180
1287
 
1181
1288
 
1192
1299
 
1193
1300
*/
1194
1301
 
1195
 
static void show_diff(string* ds,
1196
 
                      const char* filename1, const char* filename2)
 
1302
void show_diff(DYNAMIC_STRING* ds,
 
1303
               const char* filename1, const char* filename2)
1197
1304
{
1198
1305
 
1199
 
  string ds_tmp;
 
1306
  DYNAMIC_STRING ds_tmp;
 
1307
 
 
1308
  if (init_dynamic_string(&ds_tmp, "", 256, 256))
 
1309
    die("Out of memory");
1200
1310
 
1201
1311
  /* First try with unified diff */
1202
1312
  if (run_tool("diff",
1207
1317
               "2>&1",
1208
1318
               NULL) > 1) /* Most "diff" tools return >1 if error */
1209
1319
  {
1210
 
    ds_tmp= "";
 
1320
    dynstr_set(&ds_tmp, "");
1211
1321
 
1212
1322
    /* Fallback to context diff with "diff -c" */
1213
1323
    if (run_tool("diff",
1222
1332
        Fallback to dump both files to result file and inform
1223
1333
        about installing "diff"
1224
1334
      */
1225
 
      ds_tmp= "";
1226
 
 
1227
 
      ds_tmp.append(
1228
 
                    "\n"
1229
 
                    "The two files differ but it was not possible to execute 'diff' in\n"
1230
 
                    "order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1231
 
                    "Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
1232
 
                    "To get a better report you should install 'diff' on your system, which you\n"
1233
 
                    "for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1234
 
                    "\n");
1235
 
 
1236
 
      ds_tmp.append(" --- ");
1237
 
      ds_tmp.append(filename1);
1238
 
      ds_tmp.append(" >>>\n");
 
1335
      dynstr_set(&ds_tmp, "");
 
1336
 
 
1337
      dynstr_append(&ds_tmp,
 
1338
"\n"
 
1339
"The two files differ but it was not possible to execute 'diff' in\n"
 
1340
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
 
1341
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
 
1342
"To get a better report you should install 'diff' on your system, which you\n"
 
1343
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
 
1344
"\n");
 
1345
 
 
1346
      dynstr_append(&ds_tmp, " --- ");
 
1347
      dynstr_append(&ds_tmp, filename1);
 
1348
      dynstr_append(&ds_tmp, " >>>\n");
1239
1349
      cat_file(&ds_tmp, filename1);
1240
 
      ds_tmp.append("<<<\n --- ");
1241
 
      ds_tmp.append(filename1);
1242
 
      ds_tmp.append(" >>>\n");
 
1350
      dynstr_append(&ds_tmp, "<<<\n --- ");
 
1351
      dynstr_append(&ds_tmp, filename1);
 
1352
      dynstr_append(&ds_tmp, " >>>\n");
1243
1353
      cat_file(&ds_tmp, filename2);
1244
 
      ds_tmp.append("<<<<\n");
 
1354
      dynstr_append(&ds_tmp, "<<<<\n");
1245
1355
    }
1246
1356
  }
1247
1357
 
1248
1358
  if (ds)
1249
1359
  {
1250
1360
    /* Add the diff to output */
1251
 
    ds->append(ds_tmp.c_str(), ds_tmp.length());
 
1361
    dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1252
1362
  }
1253
1363
  else
1254
1364
  {
1255
1365
    /* Print diff directly to stdout */
1256
 
    fprintf(stderr, "%s\n", ds_tmp.c_str());
 
1366
    fprintf(stderr, "%s\n", ds_tmp.str);
1257
1367
  }
 
1368
 
 
1369
  dynstr_free(&ds_tmp);
1258
1370
 
1259
1371
}
1260
1372
 
1261
1373
 
1262
1374
enum compare_files_result_enum {
1263
 
  RESULT_OK= 0,
1264
 
  RESULT_CONTENT_MISMATCH= 1,
1265
 
  RESULT_LENGTH_MISMATCH= 2
 
1375
   RESULT_OK= 0,
 
1376
   RESULT_CONTENT_MISMATCH= 1,
 
1377
   RESULT_LENGTH_MISMATCH= 2
1266
1378
};
1267
1379
 
1268
1380
/*
1279
1391
 
1280
1392
*/
1281
1393
 
1282
 
static int compare_files2(File fd, const char* filename2)
 
1394
int compare_files2(File fd, const char* filename2)
1283
1395
{
1284
1396
  int error= RESULT_OK;
1285
1397
  File fd2;
1291
1403
    my_close(fd, MYF(0));
1292
1404
    die("Failed to open second file: '%s'", filename2);
1293
1405
  }
1294
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1406
  while((len= my_read(fd, (uchar*)&buff,
1295
1407
                      sizeof(buff), MYF(0))) > 0)
1296
1408
  {
1297
 
    if ((len2= my_read(fd2, (unsigned char*)&buff2,
 
1409
    if ((len2= my_read(fd2, (uchar*)&buff2,
1298
1410
                       sizeof(buff2), MYF(0))) < len)
1299
1411
    {
1300
1412
      /* File 2 was smaller */
1314
1426
      break;
1315
1427
    }
1316
1428
  }
1317
 
  if (!error && my_read(fd2, (unsigned char*)&buff2,
 
1429
  if (!error && my_read(fd2, (uchar*)&buff2,
1318
1430
                        sizeof(buff2), MYF(0)) > 0)
1319
1431
  {
1320
1432
    /* File 1 was smaller */
1340
1452
 
1341
1453
*/
1342
1454
 
1343
 
static int compare_files(const char* filename1, const char* filename2)
 
1455
int compare_files(const char* filename1, const char* filename2)
1344
1456
{
1345
1457
  File fd;
1346
1458
  int error;
1360
1472
  Compare content of the string in ds to content of file fname
1361
1473
 
1362
1474
  SYNOPSIS
1363
 
  string_cmp
 
1475
  dyn_string_cmp
1364
1476
  ds - Dynamic string containing the string o be compared
1365
1477
  fname - Name of file to compare with
1366
1478
 
1368
1480
  See 'compare_files2'
1369
1481
*/
1370
1482
 
1371
 
static int string_cmp(string* ds, const char *fname)
 
1483
int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
1372
1484
{
1373
1485
  int error;
1374
1486
  File fd;
1375
1487
  char temp_file_path[FN_REFLEN];
1376
1488
 
 
1489
  DBUG_ENTER("dyn_string_cmp");
 
1490
  DBUG_PRINT("enter", ("fname: %s", fname));
 
1491
 
1377
1492
  if ((fd= create_temp_file(temp_file_path, NULL,
1378
 
                            "tmp", O_CREAT | O_RDWR,
 
1493
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
1379
1494
                            MYF(MY_WME))) < 0)
1380
1495
    die("Failed to create temporary file for ds");
1381
1496
 
1382
1497
  /* Write ds to temporary file and set file pos to beginning*/
1383
 
  if (my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
 
1498
  if (my_write(fd, (uchar *) ds->str, ds->length,
1384
1499
               MYF(MY_FNABP | MY_WME)) ||
1385
1500
      my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1386
1501
  {
1396
1511
  /* Remove the temporary file */
1397
1512
  my_delete(temp_file_path, MYF(0));
1398
1513
 
1399
 
  return(error);
 
1514
  DBUG_RETURN(error);
1400
1515
}
1401
1516
 
1402
1517
 
1412
1527
 
1413
1528
*/
1414
1529
 
1415
 
static void check_result(string* ds)
 
1530
void check_result(DYNAMIC_STRING* ds)
1416
1531
{
1417
1532
  const char* mess= "Result content mismatch\n";
1418
1533
 
1419
 
 
1420
 
  assert(result_file_name);
 
1534
  DBUG_ENTER("check_result");
 
1535
  DBUG_ASSERT(result_file_name);
 
1536
  DBUG_PRINT("enter", ("result_file_name: %s", result_file_name));
1421
1537
 
1422
1538
  if (access(result_file_name, F_OK) != 0)
1423
1539
    die("The specified result file does not exist: '%s'", result_file_name);
1424
1540
 
1425
 
  switch (string_cmp(ds, result_file_name)) {
 
1541
  switch (dyn_string_cmp(ds, result_file_name)) {
1426
1542
  case RESULT_OK:
1427
1543
    break; /* ok */
1428
1544
  case RESULT_LENGTH_MISMATCH:
1450
1566
      fn_format(reject_file, result_file_name, opt_logdir,
1451
1567
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1452
1568
    }
1453
 
    str_to_file(reject_file, ds->c_str(), ds->length());
 
1569
    str_to_file(reject_file, ds->str, ds->length);
1454
1570
 
1455
 
    ds->erase(); /* Don't create a .log file */
 
1571
    dynstr_set(ds, NULL); /* Don't create a .log file */
1456
1572
 
1457
1573
    show_diff(NULL, result_file_name, reject_file);
1458
1574
    die(mess);
1462
1578
    die("Unknown error code from dyn_string_cmp()");
1463
1579
  }
1464
1580
 
1465
 
  return;
 
1581
  DBUG_VOID_RETURN;
1466
1582
}
1467
1583
 
1468
1584
 
1481
1597
 
1482
1598
*/
1483
1599
 
1484
 
static void check_require(string* ds, const char *fname)
 
1600
void check_require(DYNAMIC_STRING* ds, const char *fname)
1485
1601
{
1486
 
 
1487
 
 
1488
 
  if (string_cmp(ds, fname))
 
1602
  DBUG_ENTER("check_require");
 
1603
 
 
1604
  if (dyn_string_cmp(ds, fname))
1489
1605
  {
1490
1606
    char reason[FN_REFLEN];
1491
1607
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1492
1608
    abort_not_supported_test("Test requires: '%s'", reason);
1493
1609
  }
1494
 
  return;
 
1610
  DBUG_VOID_RETURN;
1495
1611
}
1496
1612
 
1497
1613
 
1498
1614
/*
1499
 
  Remove surrounding chars from string
 
1615
   Remove surrounding chars from string
1500
1616
 
1501
 
  Return 1 if first character is found but not last
 
1617
   Return 1 if first character is found but not last
1502
1618
*/
1503
1619
static int strip_surrounding(char* str, char c1, char c2)
1504
1620
{
1513
1629
    *ptr= ' ';
1514
1630
 
1515
1631
    /* Last non space charecter should be c2 */
1516
 
    ptr= strchr(str, '\0')-1;
 
1632
    ptr= strend(str)-1;
1517
1633
    while(*ptr && my_isspace(charset_info, *ptr))
1518
1634
      ptr--;
1519
1635
    if (*ptr == c2)
1534
1650
static void strip_parentheses(struct st_command *command)
1535
1651
{
1536
1652
  if (strip_surrounding(command->first_argument, '(', ')'))
1537
 
    die("%.*s - argument list started with '%c' must be ended with '%c'",
1538
 
        command->first_word_len, command->query, '(', ')');
 
1653
      die("%.*s - argument list started with '%c' must be ended with '%c'",
 
1654
          command->first_word_len, command->query, '(', ')');
1539
1655
}
1540
1656
 
1541
1657
 
1542
 
static unsigned char *get_var_key(const unsigned char* var, size_t *len,
1543
 
                          bool __attribute__((unused)) t)
 
1658
static uchar *get_var_key(const uchar* var, size_t *len,
 
1659
                          my_bool __attribute__((unused)) t)
1544
1660
{
1545
1661
  register char* key;
1546
1662
  key = ((VAR*)var)->name;
1547
1663
  *len = ((VAR*)var)->name_len;
1548
 
  return (unsigned char*)key;
 
1664
  return (uchar*)key;
1549
1665
}
1550
1666
 
1551
1667
 
1566
1682
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1567
1683
  tmp_var->alloced = (v == 0);
1568
1684
 
1569
 
  if (!(tmp_var->str_val = (char *)my_malloc(val_alloc_len+1, MYF(MY_WME))))
 
1685
  if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME))))
1570
1686
    die("Out of memory");
1571
1687
 
1572
1688
  memcpy(tmp_var->name, name, name_len);
1587
1703
 
1588
1704
void var_free(void *v)
1589
1705
{
1590
 
  free(((VAR*) v)->str_val);
1591
 
  free(((VAR*) v)->env_s);
 
1706
  my_free(((VAR*) v)->str_val, MYF(MY_WME));
 
1707
  my_free(((VAR*) v)->env_s, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
1592
1708
  if (((VAR*)v)->alloced)
1593
 
    free(v);
 
1709
    my_free(v, MYF(MY_WME));
1594
1710
}
1595
1711
 
1596
1712
 
1602
1718
    tmp = def_val;
1603
1719
 
1604
1720
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1605
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1721
  my_hash_insert(&var_hash, (uchar*)v);
1606
1722
  return v;
1607
1723
}
1608
1724
 
1609
1725
 
1610
 
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1611
 
             bool ignore_not_existing)
 
1726
VAR* var_get(const char *var_name, const char **var_name_end, my_bool raw,
 
1727
             my_bool ignore_not_existing)
1612
1728
{
1613
1729
  int digit;
1614
1730
  VAR *v;
 
1731
  DBUG_ENTER("var_get");
 
1732
  DBUG_PRINT("enter", ("var_name: %s",var_name));
1615
1733
 
1616
1734
  if (*var_name != '$')
1617
1735
    goto err;
1626
1744
    if (var_name == save_var_name)
1627
1745
    {
1628
1746
      if (ignore_not_existing)
1629
 
        return(0);
 
1747
        DBUG_RETURN(0);
1630
1748
      die("Empty variable");
1631
1749
    }
1632
1750
    length= (uint) (var_name - save_var_name);
1633
1751
    if (length >= MAX_VAR_NAME_LENGTH)
1634
1752
      die("Too long variable name: %s", save_var_name);
1635
1753
 
1636
 
    if (!(v = (VAR*) hash_search(&var_hash, (const unsigned char*) save_var_name,
1637
 
                                 length)))
 
1754
    if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
 
1755
                                            length)))
1638
1756
    {
1639
1757
      char buff[MAX_VAR_NAME_LENGTH+1];
1640
1758
      strmake(buff, save_var_name, length);
1641
1759
      v= var_from_env(buff, "");
1642
1760
    }
1643
 
    var_name--;  /* Point at last character */
 
1761
    var_name--; /* Point at last character */
1644
1762
  }
1645
1763
  else
1646
1764
    v = var_reg + digit;
1653
1771
  }
1654
1772
  if (var_name_end)
1655
1773
    *var_name_end = var_name  ;
1656
 
  return(v);
 
1774
  DBUG_RETURN(v);
1657
1775
err:
1658
1776
  if (var_name_end)
1659
1777
    *var_name_end = 0;
1660
1778
  die("Unsupported variable name: %s", var_name);
1661
 
  return(0);
 
1779
  DBUG_RETURN(0);
1662
1780
}
1663
1781
 
1664
1782
 
1665
 
static VAR *var_obtain(const char *name, int len)
 
1783
VAR *var_obtain(const char *name, int len)
1666
1784
{
1667
1785
  VAR* v;
1668
 
  if ((v = (VAR*)hash_search(&var_hash, (const unsigned char *) name, len)))
 
1786
  if ((v = (VAR*)hash_search(&var_hash, (const uchar *) name, len)))
1669
1787
    return v;
1670
1788
  v = var_init(0, name, len, "", 0);
1671
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1789
  my_hash_insert(&var_hash, (uchar*)v);
1672
1790
  return v;
1673
1791
}
1674
1792
 
1679
1797
  environment variable will be updated
1680
1798
*/
1681
1799
 
1682
 
static void var_set(const char *var_name, const char *var_name_end,
1683
 
                    const char *var_val, const char *var_val_end)
 
1800
void var_set(const char *var_name, const char *var_name_end,
 
1801
             const char *var_val, const char *var_val_end)
1684
1802
{
1685
1803
  int digit, env_var= 0;
1686
1804
  VAR *v;
 
1805
  DBUG_ENTER("var_set");
 
1806
  DBUG_PRINT("enter", ("var_name: '%.*s' = '%.*s' (length: %d)",
 
1807
                       (int) (var_name_end - var_name), var_name,
 
1808
                       (int) (var_val_end - var_val), var_val,
 
1809
                       (int) (var_val_end - var_val)));
1687
1810
 
1688
1811
  if (*var_name != '$')
1689
1812
    env_var= 1;
1709
1832
      v->int_dirty= 0;
1710
1833
      v->str_val_len= strlen(v->str_val);
1711
1834
    }
1712
 
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
1713
 
             v->name_len, v->name,
1714
 
             v->str_val_len, v->str_val);
 
1835
    my_snprintf(buf, sizeof(buf), "%.*s=%.*s",
 
1836
                v->name_len, v->name,
 
1837
                v->str_val_len, v->str_val);
1715
1838
    if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
1716
1839
      die("Out of memory");
1717
1840
    putenv(v->env_s);
1718
 
    free(old_env_s);
 
1841
    my_free(old_env_s, MYF(MY_ALLOW_ZERO_PTR));
1719
1842
  }
1720
 
  return;
 
1843
  DBUG_VOID_RETURN;
1721
1844
}
1722
1845
 
1723
1846
 
1724
 
static void var_set_string(const char* name, const char* value)
 
1847
void var_set_string(const char* name, const char* value)
1725
1848
{
1726
1849
  var_set(name, name + strlen(name), value, value + strlen(value));
1727
1850
}
1728
1851
 
1729
1852
 
1730
 
static void var_set_int(const char* name, int value)
 
1853
void var_set_int(const char* name, int value)
1731
1854
{
1732
1855
  char buf[21];
1733
 
  snprintf(buf, sizeof(buf), "%d", value);
 
1856
  my_snprintf(buf, sizeof(buf), "%d", value);
1734
1857
  var_set_string(name, buf);
1735
1858
}
1736
1859
 
1737
1860
 
1738
1861
/*
1739
1862
  Store an integer (typically the returncode of the last SQL)
1740
 
  statement in the drizzletest builtin variable $drizzle_errno
 
1863
  statement in the mysqltest builtin variable $mysql_errno
1741
1864
*/
1742
1865
 
1743
 
static void var_set_errno(int sql_errno)
 
1866
void var_set_errno(int sql_errno)
1744
1867
{
1745
 
  var_set_int("$drizzle_errno", sql_errno);
 
1868
  var_set_int("$mysql_errno", sql_errno);
1746
1869
}
1747
1870
 
1748
1871
 
1749
1872
/*
1750
 
  Update $drizzle_get_server_version variable with version
 
1873
  Update $mysql_get_server_version variable with version
1751
1874
  of the currently connected server
1752
1875
*/
1753
1876
 
1754
 
static void var_set_drizzle_get_server_version(DRIZZLE *drizzle)
 
1877
void var_set_mysql_get_server_version(MYSQL* mysql)
1755
1878
{
1756
 
  var_set_int("$drizzle_get_server_version", drizzle_get_server_version(drizzle));
 
1879
  var_set_int("$mysql_get_server_version", mysql_get_server_version(mysql));
1757
1880
}
1758
1881
 
1759
1882
 
1762
1885
 
1763
1886
  SYNOPSIS
1764
1887
  var_query_set()
1765
 
  var          variable to set from query
 
1888
  var           variable to set from query
1766
1889
  query       start of query string to execute
1767
1890
  query_end   end of the query string to execute
1768
1891
 
1780
1903
 
1781
1904
*/
1782
1905
 
1783
 
static void var_query_set(VAR *var, const char *query, const char** query_end)
 
1906
void var_query_set(VAR *var, const char *query, const char** query_end)
1784
1907
{
1785
 
  const char *end = (char*)((query_end && *query_end) ?
1786
 
                            *query_end : query + strlen(query));
1787
 
  DRIZZLE_RES *res;
1788
 
  DRIZZLE_ROW row;
1789
 
  DRIZZLE *drizzle= &cur_con->drizzle;
1790
 
  string ds_query;
1791
 
 
 
1908
  char *end = (char*)((query_end && *query_end) ?
 
1909
                      *query_end : query + strlen(query));
 
1910
  MYSQL_RES *res;
 
1911
  MYSQL_ROW row;
 
1912
  MYSQL* mysql = &cur_con->mysql;
 
1913
  DYNAMIC_STRING ds_query;
 
1914
  DBUG_ENTER("var_query_set");
1792
1915
 
1793
1916
  while (end > query && *end != '`')
1794
1917
    --end;
1797
1920
  ++query;
1798
1921
 
1799
1922
  /* Eval the query, thus replacing all environment variables */
1800
 
  do_eval(&ds_query, query, end, false);
1801
 
 
1802
 
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1803
 
    die("Error running query '%s': %d %s", ds_query.c_str(),
1804
 
        drizzle_errno(drizzle), drizzle_error(drizzle));
1805
 
  if (!(res= drizzle_store_result(drizzle)))
1806
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
1807
 
 
1808
 
  if ((row= drizzle_fetch_row(res)) && row[0])
 
1923
  init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
 
1924
  do_eval(&ds_query, query, end, FALSE);
 
1925
 
 
1926
  if (mysql_real_query(mysql, ds_query.str, ds_query.length))
 
1927
    die("Error running query '%s': %d %s", ds_query.str,
 
1928
        mysql_errno(mysql), mysql_error(mysql));
 
1929
  if (!(res= mysql_store_result(mysql)))
 
1930
    die("Query '%s' didn't return a result set", ds_query.str);
 
1931
  dynstr_free(&ds_query);
 
1932
 
 
1933
  if ((row= mysql_fetch_row(res)) && row[0])
1809
1934
  {
1810
1935
    /*
1811
1936
      Concatenate all fields in the first row with tab in between
1812
1937
      and assign that string to the $variable
1813
1938
    */
1814
 
    string result;
1815
 
    uint32_t i;
1816
 
    uint32_t *lengths;
 
1939
    DYNAMIC_STRING result;
 
1940
    uint i;
 
1941
    ulong *lengths;
1817
1942
 
1818
 
    lengths= drizzle_fetch_lengths(res);
1819
 
    for (i= 0; i < drizzle_num_fields(res); i++)
 
1943
    init_dynamic_string(&result, "", 512, 512);
 
1944
    lengths= mysql_fetch_lengths(res);
 
1945
    for (i= 0; i < mysql_num_fields(res); i++)
1820
1946
    {
1821
1947
      if (row[i])
1822
1948
      {
1823
1949
        /* Add column to tab separated string */
1824
 
        result.append(row[i], lengths[i]);
 
1950
        dynstr_append_mem(&result, row[i], lengths[i]);
1825
1951
      }
1826
 
      result.append("\t", 1);
 
1952
      dynstr_append_mem(&result, "\t", 1);
1827
1953
    }
1828
 
    end= result.c_str() + result.length()-1;
1829
 
    eval_expr(var, result.c_str(), (const char**) &end);
 
1954
    end= result.str + result.length-1;
 
1955
    eval_expr(var, result.str, (const char**) &end);
 
1956
    dynstr_free(&result);
1830
1957
  }
1831
1958
  else
1832
1959
    eval_expr(var, "", 0);
1833
1960
 
1834
 
  drizzle_free_result(res);
1835
 
  return;
 
1961
  mysql_free_result(res);
 
1962
  DBUG_VOID_RETURN;
1836
1963
}
1837
1964
 
1838
1965
 
1852
1979
 
1853
1980
  <query to run> -    The query that should be sent to the server
1854
1981
  <column name> -     Name of the column that holds the field be compared
1855
 
  against the expected value
 
1982
                      against the expected value
1856
1983
  <row no> -          Number of the row that holds the field to be
1857
 
  compared against the expected value
 
1984
                      compared against the expected value
1858
1985
 
1859
1986
*/
1860
1987
 
1861
 
static void var_set_query_get_value(struct st_command *command, VAR *var)
 
1988
void var_set_query_get_value(struct st_command *command, VAR *var)
1862
1989
{
1863
1990
  long row_no;
1864
1991
  int col_no= -1;
1865
 
  DRIZZLE_RES* res;
1866
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
1992
  MYSQL_RES* res;
 
1993
  MYSQL* mysql= &cur_con->mysql;
1867
1994
 
1868
 
  string ds_query;
1869
 
  string ds_col;
1870
 
  string ds_row;
 
1995
  static DYNAMIC_STRING ds_query;
 
1996
  static DYNAMIC_STRING ds_col;
 
1997
  static DYNAMIC_STRING ds_row;
1871
1998
  const struct command_arg query_get_value_args[] = {
1872
 
    {"query", ARG_STRING, true, &ds_query, "Query to run"},
1873
 
    {"column name", ARG_STRING, true, &ds_col, "Name of column"},
1874
 
    {"row number", ARG_STRING, true, &ds_row, "Number for row"}
 
1999
    "query", ARG_STRING, TRUE, &ds_query, "Query to run",
 
2000
    "column name", ARG_STRING, TRUE, &ds_col, "Name of column",
 
2001
    "row number", ARG_STRING, TRUE, &ds_row, "Number for row"
1875
2002
  };
1876
2003
 
1877
 
 
 
2004
  DBUG_ENTER("var_set_query_get_value");
1878
2005
 
1879
2006
  strip_parentheses(command);
 
2007
  DBUG_PRINT("info", ("query: %s", command->query));
1880
2008
  check_command_args(command, command->first_argument, query_get_value_args,
1881
2009
                     sizeof(query_get_value_args)/sizeof(struct command_arg),
1882
2010
                     ',');
1883
2011
 
 
2012
  DBUG_PRINT("info", ("query: %s", ds_query.str));
 
2013
  DBUG_PRINT("info", ("col: %s", ds_col.str));
 
2014
 
1884
2015
  /* Convert row number to int */
1885
 
  if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1886
 
    die("Invalid row number: '%s'", ds_row.c_str());
 
2016
  if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
 
2017
    die("Invalid row number: '%s'", ds_row.str);
 
2018
  DBUG_PRINT("info", ("row: %s, row_no: %ld", ds_row.str, row_no));
 
2019
  dynstr_free(&ds_row);
1887
2020
 
1888
2021
  /* Remove any surrounding "'s from the query - if there is any */
1889
 
  // (Don't get me started on this)
1890
 
  char * unstripped_query= strdup(ds_query.c_str());
1891
 
  if (strip_surrounding(unstripped_query, '"', '"'))
1892
 
    die("Mismatched \"'s around query '%s'", ds_query.c_str());
1893
 
  ds_query= unstripped_query;
 
2022
  if (strip_surrounding(ds_query.str, '"', '"'))
 
2023
    die("Mismatched \"'s around query '%s'", ds_query.str);
1894
2024
 
1895
2025
  /* Run the query */
1896
 
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1897
 
    die("Error running query '%s': %d %s", ds_query.c_str(),
1898
 
        drizzle_errno(drizzle), drizzle_error(drizzle));
1899
 
  if (!(res= drizzle_store_result(drizzle)))
1900
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
 
2026
  if (mysql_real_query(mysql, ds_query.str, ds_query.length))
 
2027
    die("Error running query '%s': %d %s", ds_query.str,
 
2028
        mysql_errno(mysql), mysql_error(mysql));
 
2029
  if (!(res= mysql_store_result(mysql)))
 
2030
    die("Query '%s' didn't return a result set", ds_query.str);
1901
2031
 
1902
2032
  {
1903
2033
    /* Find column number from the given column name */
1904
2034
    uint i;
1905
 
    uint num_fields= drizzle_num_fields(res);
1906
 
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
2035
    uint num_fields= mysql_num_fields(res);
 
2036
    MYSQL_FIELD *fields= mysql_fetch_fields(res);
1907
2037
 
1908
2038
    for (i= 0; i < num_fields; i++)
1909
2039
    {
1910
 
      if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
1911
 
          strlen(fields[i].name) == ds_col.length())
 
2040
      if (strcmp(fields[i].name, ds_col.str) == 0 &&
 
2041
          strlen(fields[i].name) == ds_col.length)
1912
2042
      {
1913
2043
        col_no= i;
1914
2044
        break;
1916
2046
    }
1917
2047
    if (col_no == -1)
1918
2048
    {
1919
 
      drizzle_free_result(res);
 
2049
      mysql_free_result(res);
1920
2050
      die("Could not find column '%s' in the result of '%s'",
1921
 
          ds_col.c_str(), ds_query.c_str());
 
2051
          ds_col.str, ds_query.str);
1922
2052
    }
 
2053
    DBUG_PRINT("info", ("Found column %d with name '%s'",
 
2054
                        i, fields[i].name));
1923
2055
  }
 
2056
  dynstr_free(&ds_col);
1924
2057
 
1925
2058
  {
1926
2059
    /* Get the value */
1927
 
    DRIZZLE_ROW row;
 
2060
    MYSQL_ROW row;
1928
2061
    long rows= 0;
1929
2062
    const char* value= "No such row";
1930
2063
 
1931
 
    while ((row= drizzle_fetch_row(res)))
 
2064
    while ((row= mysql_fetch_row(res)))
1932
2065
    {
1933
2066
      if (++rows == row_no)
1934
2067
      {
1935
2068
 
 
2069
        DBUG_PRINT("info", ("At row %ld, column %d is '%s'",
 
2070
                            row_no, col_no, row[col_no]));
1936
2071
        /* Found the row to get */
1937
2072
        if (row[col_no])
1938
2073
          value= row[col_no];
1944
2079
    }
1945
2080
    eval_expr(var, value, 0);
1946
2081
  }
1947
 
  drizzle_free_result(res);
 
2082
  dynstr_free(&ds_query);
 
2083
  mysql_free_result(res);
1948
2084
 
1949
 
  return;
 
2085
  DBUG_VOID_RETURN;
1950
2086
}
1951
2087
 
1952
2088
 
1953
 
static void var_copy(VAR *dest, VAR *src)
 
2089
void var_copy(VAR *dest, VAR *src)
1954
2090
{
1955
2091
  dest->int_val= src->int_val;
1956
2092
  dest->int_dirty= src->int_dirty;
1958
2094
  /* Alloc/realloc data for str_val in dest */
1959
2095
  if (dest->alloced_len < src->alloced_len &&
1960
2096
      !(dest->str_val= dest->str_val
1961
 
        ? (char *)my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
1962
 
        : (char *)my_malloc(src->alloced_len, MYF(MY_WME))))
 
2097
        ? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
 
2098
        : my_malloc(src->alloced_len, MYF(MY_WME))))
1963
2099
    die("Out of memory");
1964
2100
  else
1965
2101
    dest->alloced_len= src->alloced_len;
1973
2109
 
1974
2110
void eval_expr(VAR *v, const char *p, const char **p_end)
1975
2111
{
 
2112
 
 
2113
  DBUG_ENTER("eval_expr");
 
2114
  DBUG_PRINT("enter", ("p: '%s'", p));
 
2115
 
1976
2116
  if (*p == '$')
1977
2117
  {
1978
2118
    VAR *vp;
1979
2119
    if ((vp= var_get(p, p_end, 0, 0)))
1980
2120
      var_copy(v, vp);
1981
 
    return;
 
2121
    DBUG_VOID_RETURN;
1982
2122
  }
1983
2123
 
1984
2124
  if (*p == '`')
1985
2125
  {
1986
2126
    var_query_set(v, p, p_end);
1987
 
    return;
 
2127
    DBUG_VOID_RETURN;
1988
2128
  }
1989
2129
 
1990
2130
  {
2000
2140
      command.first_argument= command.query + len;
2001
2141
      command.end= (char*)*p_end;
2002
2142
      var_set_query_get_value(&command, v);
2003
 
      return;
 
2143
      DBUG_VOID_RETURN;
2004
2144
    }
2005
2145
  }
2006
2146
 
2013
2153
      v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
2014
2154
        MIN_VAR_ALLOC : new_val_len + 1;
2015
2155
      if (!(v->str_val =
2016
 
            v->str_val ? (char *)my_realloc(v->str_val, v->alloced_len+1,
2017
 
                                            MYF(MY_WME)) :
2018
 
            (char *)my_malloc(v->alloced_len+1, MYF(MY_WME))))
 
2156
            v->str_val ? my_realloc(v->str_val, v->alloced_len+1,
 
2157
                                    MYF(MY_WME)) :
 
2158
            my_malloc(v->alloced_len+1, MYF(MY_WME))))
2019
2159
        die("Out of memory");
2020
2160
    }
2021
2161
    v->str_val_len = new_val_len;
2022
2162
    memcpy(v->str_val, p, new_val_len);
2023
2163
    v->str_val[new_val_len] = 0;
2024
2164
    v->int_val=atoi(p);
 
2165
    DBUG_PRINT("info", ("atoi on '%s', returns: %d", p, v->int_val));
2025
2166
    v->int_dirty=0;
2026
2167
  }
2027
 
  return;
 
2168
  DBUG_VOID_RETURN;
2028
2169
}
2029
2170
 
2030
2171
 
2031
 
static int open_file(const char *name)
 
2172
int open_file(const char *name)
2032
2173
{
2033
2174
  char buff[FN_REFLEN];
2034
 
 
 
2175
  DBUG_ENTER("open_file");
 
2176
  DBUG_PRINT("enter", ("name: %s", name));
2035
2177
  if (!test_if_hard_path(name))
2036
2178
  {
2037
 
    strxmov(buff, opt_basedir, name, NULL);
 
2179
    strxmov(buff, opt_basedir, name, NullS);
2038
2180
    name=buff;
2039
2181
  }
2040
2182
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2042
2184
  if (cur_file == file_stack_end)
2043
2185
    die("Source directives are nesting too deep");
2044
2186
  cur_file++;
2045
 
  if (!(cur_file->file = my_fopen(buff, O_RDONLY, MYF(0))))
 
2187
  if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
2046
2188
  {
2047
2189
    cur_file--;
2048
2190
    die("Could not open '%s' for reading", buff);
2049
2191
  }
2050
2192
  cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
2051
2193
  cur_file->lineno=1;
2052
 
  return(0);
 
2194
  DBUG_RETURN(0);
2053
2195
}
2054
2196
 
2055
2197
 
2058
2200
 
2059
2201
  SYNOPSIS
2060
2202
  do_source()
2061
 
  query  called command
 
2203
  query called command
2062
2204
 
2063
2205
  DESCRIPTION
2064
2206
  source <file_name>
2067
2209
 
2068
2210
*/
2069
2211
 
2070
 
static void do_source(struct st_command *command)
 
2212
void do_source(struct st_command *command)
2071
2213
{
2072
 
  string ds_filename;
 
2214
  static DYNAMIC_STRING ds_filename;
2073
2215
  const struct command_arg source_args[] = {
2074
 
    { "filename", ARG_STRING, true, &ds_filename, "File to source" }
 
2216
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to source" }
2075
2217
  };
2076
 
 
 
2218
  DBUG_ENTER("do_source");
2077
2219
 
2078
2220
  check_command_args(command, command->first_argument, source_args,
2079
2221
                     sizeof(source_args)/sizeof(struct command_arg),
2087
2229
    ; /* Do nothing */
2088
2230
  else
2089
2231
  {
2090
 
    open_file(ds_filename.c_str());
 
2232
    DBUG_PRINT("info", ("sourcing file: %s", ds_filename.str));
 
2233
    open_file(ds_filename.str);
2091
2234
  }
2092
2235
 
 
2236
  dynstr_free(&ds_filename);
2093
2237
  return;
2094
2238
}
2095
2239
 
2096
2240
 
 
2241
FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
 
2242
{
 
2243
  return popen(ds_cmd->str, mode);
 
2244
}
 
2245
 
 
2246
 
2097
2247
static void init_builtin_echo(void)
2098
2248
{
2099
2249
  builtin_echo[0]= 0;
2105
2255
  Replace a substring
2106
2256
 
2107
2257
  SYNOPSIS
2108
 
  replace
2109
 
  ds_str      The string to search and perform the replace in
2110
 
  search_str  The string to search for
2111
 
  search_len  Length of the string to search for
2112
 
  replace_str The string to replace with
2113
 
  replace_len Length of the string to replace with
 
2258
    replace
 
2259
    ds_str      The string to search and perform the replace in
 
2260
    search_str  The string to search for
 
2261
    search_len  Length of the string to search for
 
2262
    replace_str The string to replace with
 
2263
    replace_len Length of the string to replace with
2114
2264
 
2115
2265
  RETURN
2116
 
  0 String replaced
2117
 
  1 Could not find search_str in str
 
2266
    0 String replaced
 
2267
    1 Could not find search_str in str
2118
2268
*/
2119
2269
 
2120
 
static int replace(string *ds_str,
2121
 
                   const char *search_str, uint32_t search_len,
2122
 
                   const char *replace_str, uint32_t replace_len)
 
2270
static int replace(DYNAMIC_STRING *ds_str,
 
2271
                   const char *search_str, ulong search_len,
 
2272
                   const char *replace_str, ulong replace_len)
2123
2273
{
2124
 
  string ds_tmp;
2125
 
  const char *start= strstr(ds_str->c_str(), search_str);
 
2274
  DYNAMIC_STRING ds_tmp;
 
2275
  const char *start= strstr(ds_str->str, search_str);
2126
2276
  if (!start)
2127
2277
    return 1;
2128
 
  ds_tmp.append(ds_str->c_str(), start - ds_str->c_str());
2129
 
  ds_tmp.append(replace_str, replace_len);
2130
 
  ds_tmp.append(start + search_len);
2131
 
  *ds_str= ds_tmp;
 
2278
  init_dynamic_string(&ds_tmp, "",
 
2279
                      ds_str->length + replace_len, 256);
 
2280
  dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
 
2281
  dynstr_append_mem(&ds_tmp, replace_str, replace_len);
 
2282
  dynstr_append(&ds_tmp, start + search_len);
 
2283
  dynstr_set(ds_str, ds_tmp.str);
 
2284
  dynstr_free(&ds_tmp);
2132
2285
  return 0;
2133
2286
}
2134
2287
 
2138
2291
 
2139
2292
  SYNOPSIS
2140
2293
  do_exec()
2141
 
  query  called command
 
2294
  query called command
2142
2295
 
2143
2296
  DESCRIPTION
2144
2297
  exec <command>
2149
2302
  It can thus be used to execute a command that shall fail.
2150
2303
 
2151
2304
  NOTE
2152
 
  Although drizzletest is executed from cygwin shell, the command will be
 
2305
  Although mysqltest is executed from cygwin shell, the command will be
2153
2306
  executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
2154
 
  drizzletest commmand(s) like "remove_file" for that
 
2307
  mysqltest commmand(s) like "remove_file" for that
2155
2308
*/
2156
2309
 
2157
 
static void do_exec(struct st_command *command)
 
2310
void do_exec(struct st_command *command)
2158
2311
{
2159
2312
  int error;
2160
2313
  char buf[512];
2161
2314
  FILE *res_file;
2162
2315
  char *cmd= command->first_argument;
2163
 
  string ds_cmd;
 
2316
  DYNAMIC_STRING ds_cmd;
 
2317
  DBUG_ENTER("do_exec");
 
2318
  DBUG_PRINT("enter", ("cmd: '%s'", cmd));
2164
2319
 
2165
2320
  /* Skip leading space */
2166
2321
  while (*cmd && my_isspace(charset_info, *cmd))
2169
2324
    die("Missing argument in exec");
2170
2325
  command->last_argument= command->end;
2171
2326
 
 
2327
  init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
2172
2328
  /* Eval the command, thus replacing all environment variables */
2173
2329
  do_eval(&ds_cmd, cmd, command->end, !is_windows);
2174
2330
 
2179
2335
    replace(&ds_cmd, "echo", 4, builtin_echo, strlen(builtin_echo));
2180
2336
  }
2181
2337
 
2182
 
  if (!(res_file= popen(ds_cmd.c_str(), "r")) && command->abort_on_error)
 
2338
  DBUG_PRINT("info", ("Executing '%s' as '%s'",
 
2339
                      command->first_argument, ds_cmd.str));
 
2340
 
 
2341
  if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
2183
2342
  {
 
2343
    dynstr_free(&ds_cmd);
2184
2344
    die("popen(\"%s\", \"r\") failed", command->first_argument);
2185
2345
  }
2186
2346
 
2189
2349
    if (disable_result_log)
2190
2350
    {
2191
2351
      buf[strlen(buf)-1]=0;
 
2352
      DBUG_PRINT("exec_result",("%s", buf));
2192
2353
    }
2193
2354
    else
2194
2355
    {
2195
 
      replace_append(&ds_res, buf);
 
2356
      replace_dynstr_append(&ds_res, buf);
2196
2357
    }
2197
2358
  }
2198
2359
  error= pclose(res_file);
2199
2360
  if (error > 0)
2200
2361
  {
2201
2362
    uint status= WEXITSTATUS(error), i;
2202
 
    bool ok= 0;
 
2363
    my_bool ok= 0;
2203
2364
 
2204
2365
    if (command->abort_on_error)
2205
2366
    {
2206
2367
      log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
2207
 
              ds_cmd.c_str(), error, status, errno);
 
2368
              ds_cmd.str, error, status, errno);
 
2369
      dynstr_free(&ds_cmd);
2208
2370
      die("command \"%s\" failed", command->first_argument);
2209
2371
    }
2210
2372
 
 
2373
    DBUG_PRINT("info",
 
2374
               ("error: %d, status: %d", error, status));
2211
2375
    for (i= 0; i < command->expected_errors.count; i++)
2212
2376
    {
 
2377
      DBUG_PRINT("info", ("expected error: %d",
 
2378
                          command->expected_errors.err[i].code.errnum));
2213
2379
      if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
2214
2380
          (command->expected_errors.err[i].code.errnum == status))
2215
2381
      {
2216
2382
        ok= 1;
 
2383
        DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d",
 
2384
                            command->first_argument, status));
2217
2385
      }
2218
2386
    }
2219
2387
    if (!ok)
2220
2388
    {
 
2389
      dynstr_free(&ds_cmd);
2221
2390
      die("command \"%s\" failed with wrong error: %d",
2222
2391
          command->first_argument, status);
2223
2392
    }
2227
2396
  {
2228
2397
    /* Error code we wanted was != 0, i.e. not an expected success */
2229
2398
    log_msg("exec of '%s failed, error: %d, errno: %d",
2230
 
            ds_cmd.c_str(), error, errno);
 
2399
            ds_cmd.str, error, errno);
 
2400
    dynstr_free(&ds_cmd);
2231
2401
    die("command \"%s\" succeeded - should have failed with errno %d...",
2232
2402
        command->first_argument, command->expected_errors.err[0].code.errnum);
2233
2403
  }
2234
2404
 
2235
 
  return;
 
2405
  dynstr_free(&ds_cmd);
 
2406
  DBUG_VOID_RETURN;
2236
2407
}
2237
2408
 
2238
2409
enum enum_operator
2247
2418
 
2248
2419
  SYNOPSIS
2249
2420
  do_modify_var()
2250
 
  query  called command
 
2421
  query called command
2251
2422
  operator    operation to perform on the var
2252
2423
 
2253
2424
  DESCRIPTION
2256
2427
 
2257
2428
*/
2258
2429
 
2259
 
static int do_modify_var(struct st_command *command,
2260
 
                         enum enum_operator op)
 
2430
int do_modify_var(struct st_command *command,
 
2431
                  enum enum_operator operator)
2261
2432
{
2262
2433
  const char *p= command->first_argument;
2263
2434
  VAR* v;
2267
2438
    die("The argument to %.*s must be a variable (start with $)",
2268
2439
        command->first_word_len, command->query);
2269
2440
  v= var_get(p, &p, 1, 0);
2270
 
  switch (op) {
 
2441
  switch (operator) {
2271
2442
  case DO_DEC:
2272
2443
    v->int_val--;
2273
2444
    break;
2285
2456
 
2286
2457
 
2287
2458
/*
 
2459
  Wrapper for 'system' function
 
2460
 
 
2461
  NOTE
 
2462
  If mysqltest is executed from cygwin shell, the command will be
 
2463
  executed in the "windows command interpreter" cmd.exe and we prepend "sh"
 
2464
  to make it be executed by cygwins "bash". Thus commands like "rm",
 
2465
  "mkdir" as well as shellscripts can executed by "system" in Windows.
 
2466
 
 
2467
*/
 
2468
 
 
2469
int my_system(DYNAMIC_STRING* ds_cmd)
 
2470
{
 
2471
  return system(ds_cmd->str);
 
2472
}
 
2473
 
 
2474
 
 
2475
/*
2288
2476
  SYNOPSIS
2289
2477
  do_system
2290
 
  command  called command
 
2478
  command       called command
2291
2479
 
2292
2480
  DESCRIPTION
2293
2481
  system <command>
2297
2485
 
2298
2486
*/
2299
2487
 
2300
 
static void do_system(struct st_command *command)
 
2488
void do_system(struct st_command *command)
2301
2489
{
2302
 
  string ds_cmd;
2303
 
 
 
2490
  DYNAMIC_STRING ds_cmd;
 
2491
  DBUG_ENTER("do_system");
2304
2492
 
2305
2493
  if (strlen(command->first_argument) == 0)
2306
2494
    die("Missing arguments to system, nothing to do!");
2307
2495
 
 
2496
  init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
 
2497
 
2308
2498
  /* Eval the system command, thus replacing all environment variables */
2309
2499
  do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2310
2500
 
2311
 
  if (system(ds_cmd.c_str()))
 
2501
  DBUG_PRINT("info", ("running system command '%s' as '%s'",
 
2502
                      command->first_argument, ds_cmd.str));
 
2503
  if (my_system(&ds_cmd))
2312
2504
  {
2313
2505
    if (command->abort_on_error)
2314
2506
      die("system command '%s' failed", command->first_argument);
2315
2507
 
2316
2508
    /* If ! abort_on_error, log message and continue */
2317
 
    ds_res.append("system command '");
2318
 
    replace_append(&ds_res, command->first_argument);
2319
 
    ds_res.append("' failed\n");
 
2509
    dynstr_append(&ds_res, "system command '");
 
2510
    replace_dynstr_append(&ds_res, command->first_argument);
 
2511
    dynstr_append(&ds_res, "' failed\n");
2320
2512
  }
2321
2513
 
2322
2514
  command->last_argument= command->end;
2323
 
  return;
 
2515
  dynstr_free(&ds_cmd);
 
2516
  DBUG_VOID_RETURN;
2324
2517
}
2325
2518
 
2326
2519
 
2327
2520
/*
2328
2521
  SYNOPSIS
2329
2522
  do_remove_file
2330
 
  command  called command
 
2523
  command       called command
2331
2524
 
2332
2525
  DESCRIPTION
2333
2526
  remove_file <file_name>
2334
2527
  Remove the file <file_name>
2335
2528
*/
2336
2529
 
2337
 
static void do_remove_file(struct st_command *command)
 
2530
void do_remove_file(struct st_command *command)
2338
2531
{
2339
2532
  int error;
2340
 
  string ds_filename;
 
2533
  static DYNAMIC_STRING ds_filename;
2341
2534
  const struct command_arg rm_args[] = {
2342
 
    { "filename", ARG_STRING, true, &ds_filename, "File to delete" }
 
2535
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to delete" }
2343
2536
  };
2344
 
 
 
2537
  DBUG_ENTER("do_remove_file");
2345
2538
 
2346
2539
  check_command_args(command, command->first_argument,
2347
2540
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2348
2541
                     ' ');
2349
2542
 
2350
 
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2543
  DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
 
2544
  error= my_delete(ds_filename.str, MYF(0)) != 0;
2351
2545
  handle_command_error(command, error);
2352
 
  return;
 
2546
  dynstr_free(&ds_filename);
 
2547
  DBUG_VOID_RETURN;
2353
2548
}
2354
2549
 
2355
2550
 
2356
2551
/*
2357
2552
  SYNOPSIS
2358
2553
  do_copy_file
2359
 
  command  command handle
 
2554
  command       command handle
2360
2555
 
2361
2556
  DESCRIPTION
2362
2557
  copy_file <from_file> <to_file>
2365
2560
  NOTE! Will fail if <to_file> exists
2366
2561
*/
2367
2562
 
2368
 
static void do_copy_file(struct st_command *command)
 
2563
void do_copy_file(struct st_command *command)
2369
2564
{
2370
2565
  int error;
2371
 
  string ds_from_file;
2372
 
  string ds_to_file;
 
2566
  static DYNAMIC_STRING ds_from_file;
 
2567
  static DYNAMIC_STRING ds_to_file;
2373
2568
  const struct command_arg copy_file_args[] = {
2374
 
    { "from_file", ARG_STRING, true, &ds_from_file, "Filename to copy from" },
2375
 
    { "to_file", ARG_STRING, true, &ds_to_file, "Filename to copy to" }
 
2569
    { "from_file", ARG_STRING, TRUE, &ds_from_file, "Filename to copy from" },
 
2570
    { "to_file", ARG_STRING, TRUE, &ds_to_file, "Filename to copy to" }
2376
2571
  };
2377
 
 
 
2572
  DBUG_ENTER("do_copy_file");
2378
2573
 
2379
2574
  check_command_args(command, command->first_argument,
2380
2575
                     copy_file_args,
2381
2576
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2382
2577
                     ' ');
2383
2578
 
2384
 
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2579
  DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
 
2580
  error= (my_copy(ds_from_file.str, ds_to_file.str,
2385
2581
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2386
2582
  handle_command_error(command, error);
2387
 
  return;
 
2583
  dynstr_free(&ds_from_file);
 
2584
  dynstr_free(&ds_to_file);
 
2585
  DBUG_VOID_RETURN;
2388
2586
}
2389
2587
 
2390
2588
 
2391
2589
/*
2392
2590
  SYNOPSIS
2393
2591
  do_chmod_file
2394
 
  command  command handle
 
2592
  command       command handle
2395
2593
 
2396
2594
  DESCRIPTION
2397
2595
  chmod <octal> <file_name>
2399
2597
 
2400
2598
*/
2401
2599
 
2402
 
static void do_chmod_file(struct st_command *command)
 
2600
void do_chmod_file(struct st_command *command)
2403
2601
{
2404
2602
  long mode= 0;
2405
 
  string ds_mode;
2406
 
  string ds_file;
 
2603
  static DYNAMIC_STRING ds_mode;
 
2604
  static DYNAMIC_STRING ds_file;
2407
2605
  const struct command_arg chmod_file_args[] = {
2408
 
    { "mode", ARG_STRING, true, &ds_mode, "Mode of file(octal) ex. 0660"},
2409
 
    { "filename", ARG_STRING, true, &ds_file, "Filename of file to modify" }
 
2606
    { "mode", ARG_STRING, TRUE, &ds_mode, "Mode of file(octal) ex. 0660"}, 
 
2607
    { "filename", ARG_STRING, TRUE, &ds_file, "Filename of file to modify" }
2410
2608
  };
2411
 
 
 
2609
  DBUG_ENTER("do_chmod_file");
2412
2610
 
2413
2611
  check_command_args(command, command->first_argument,
2414
2612
                     chmod_file_args,
2416
2614
                     ' ');
2417
2615
 
2418
2616
  /* Parse what mode to set */
2419
 
  if (ds_mode.length() != 4 ||
2420
 
      str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NULL)
 
2617
  if (ds_mode.length != 4 ||
 
2618
      str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
2421
2619
    die("You must write a 4 digit octal number for mode");
2422
2620
 
2423
 
  handle_command_error(command, chmod(ds_file.c_str(), mode));
2424
 
  return;
 
2621
  DBUG_PRINT("info", ("chmod %o %s", (uint)mode, ds_file.str));
 
2622
  handle_command_error(command, chmod(ds_file.str, mode));
 
2623
  dynstr_free(&ds_mode);
 
2624
  dynstr_free(&ds_file);
 
2625
  DBUG_VOID_RETURN;
2425
2626
}
2426
2627
 
2427
2628
 
2428
2629
/*
2429
2630
  SYNOPSIS
2430
2631
  do_file_exists
2431
 
  command  called command
 
2632
  command       called command
2432
2633
 
2433
2634
  DESCRIPTION
2434
2635
  fiile_exist <file_name>
2435
2636
  Check if file <file_name> exists
2436
2637
*/
2437
2638
 
2438
 
static void do_file_exist(struct st_command *command)
 
2639
void do_file_exist(struct st_command *command)
2439
2640
{
2440
2641
  int error;
2441
 
  string ds_filename;
 
2642
  static DYNAMIC_STRING ds_filename;
2442
2643
  const struct command_arg file_exist_args[] = {
2443
 
    { "filename", ARG_STRING, true, &ds_filename, "File to check if it exist" }
 
2644
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to check if it exist" }
2444
2645
  };
2445
 
 
 
2646
  DBUG_ENTER("do_file_exist");
2446
2647
 
2447
2648
  check_command_args(command, command->first_argument,
2448
2649
                     file_exist_args,
2449
2650
                     sizeof(file_exist_args)/sizeof(struct command_arg),
2450
2651
                     ' ');
2451
2652
 
2452
 
  error= (access(ds_filename.c_str(), F_OK) != 0);
 
2653
  DBUG_PRINT("info", ("Checking for existence of file: %s", ds_filename.str));
 
2654
  error= (access(ds_filename.str, F_OK) != 0);
2453
2655
  handle_command_error(command, error);
2454
 
  return;
 
2656
  dynstr_free(&ds_filename);
 
2657
  DBUG_VOID_RETURN;
2455
2658
}
2456
2659
 
2457
2660
 
2458
2661
/*
2459
2662
  SYNOPSIS
2460
2663
  do_mkdir
2461
 
  command  called command
 
2664
  command       called command
2462
2665
 
2463
2666
  DESCRIPTION
2464
2667
  mkdir <dir_name>
2465
2668
  Create the directory <dir_name>
2466
2669
*/
2467
2670
 
2468
 
static void do_mkdir(struct st_command *command)
 
2671
void do_mkdir(struct st_command *command)
2469
2672
{
2470
2673
  int error;
2471
 
  string ds_dirname;
 
2674
  static DYNAMIC_STRING ds_dirname;
2472
2675
  const struct command_arg mkdir_args[] = {
2473
 
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
 
2676
    "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to create"
2474
2677
  };
2475
 
 
 
2678
  DBUG_ENTER("do_mkdir");
2476
2679
 
2477
2680
  check_command_args(command, command->first_argument,
2478
2681
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2479
2682
                     ' ');
2480
2683
 
2481
 
  error= my_mkdir(ds_dirname.c_str(), 0777, MYF(0)) != 0;
 
2684
  DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
 
2685
  error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
2482
2686
  handle_command_error(command, error);
2483
 
  return;
 
2687
  dynstr_free(&ds_dirname);
 
2688
  DBUG_VOID_RETURN;
2484
2689
}
2485
2690
 
2486
2691
/*
2487
2692
  SYNOPSIS
2488
2693
  do_rmdir
2489
 
  command  called command
 
2694
  command       called command
2490
2695
 
2491
2696
  DESCRIPTION
2492
2697
  rmdir <dir_name>
2493
2698
  Remove the empty directory <dir_name>
2494
2699
*/
2495
2700
 
2496
 
static void do_rmdir(struct st_command *command)
 
2701
void do_rmdir(struct st_command *command)
2497
2702
{
2498
2703
  int error;
2499
 
  string ds_dirname;
 
2704
  static DYNAMIC_STRING ds_dirname;
2500
2705
  const struct command_arg rmdir_args[] = {
2501
 
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to remove"}
 
2706
    "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove"
2502
2707
  };
2503
 
 
 
2708
  DBUG_ENTER("do_rmdir");
2504
2709
 
2505
2710
  check_command_args(command, command->first_argument,
2506
2711
                     rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
2507
2712
                     ' ');
2508
2713
 
2509
 
  error= rmdir(ds_dirname.c_str()) != 0;
 
2714
  DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
 
2715
  error= rmdir(ds_dirname.str) != 0;
2510
2716
  handle_command_error(command, error);
2511
 
  return;
 
2717
  dynstr_free(&ds_dirname);
 
2718
  DBUG_VOID_RETURN;
2512
2719
}
2513
2720
 
2514
2721
 
2522
2729
  happen for any tests in the test suite.
2523
2730
*/
2524
2731
 
2525
 
static int my_getc(FILE *file)
 
2732
int my_getc(FILE *file)
2526
2733
{
2527
2734
  if (line_buffer_pos == line_buffer)
2528
2735
    return fgetc(file);
2530
2737
}
2531
2738
 
2532
2739
 
2533
 
static void my_ungetc(int c)
 
2740
void my_ungetc(int c)
2534
2741
{
2535
2742
  *line_buffer_pos++= (char) c;
2536
2743
}
2537
2744
 
2538
2745
 
2539
 
static void read_until_delimiter(string *ds,
2540
 
                                 string *ds_delimiter)
 
2746
void read_until_delimiter(DYNAMIC_STRING *ds,
 
2747
                          DYNAMIC_STRING *ds_delimiter)
2541
2748
{
2542
2749
  char c;
 
2750
  DBUG_ENTER("read_until_delimiter");
 
2751
  DBUG_PRINT("enter", ("delimiter: %s, length: %u",
 
2752
                       ds_delimiter->str, (uint) ds_delimiter->length));
2543
2753
 
2544
 
  if (ds_delimiter->length() > MAX_DELIMITER_LENGTH)
 
2754
  if (ds_delimiter->length > MAX_DELIMITER_LENGTH)
2545
2755
    die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
2546
2756
 
2547
2757
  /* Read from file until delimiter is found */
2568
2778
 
2569
2779
    if (feof(cur_file->file))
2570
2780
      die("End of file encountered before '%s' delimiter was found",
2571
 
          ds_delimiter->c_str());
 
2781
          ds_delimiter->str);
2572
2782
 
2573
 
    if (match_delimiter(c, ds_delimiter->c_str(), ds_delimiter->length()))
 
2783
    if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
 
2784
    {
 
2785
      DBUG_PRINT("exit", ("Found delimiter '%s'", ds_delimiter->str));
2574
2786
      break;
2575
 
 
2576
 
    ds->push_back(c);
 
2787
    }
 
2788
    dynstr_append_mem(ds, (const char*)&c, 1);
2577
2789
  }
2578
 
  return;
 
2790
  DBUG_PRINT("exit", ("ds: %s", ds->str));
 
2791
  DBUG_VOID_RETURN;
2579
2792
}
2580
2793
 
2581
2794
 
2582
 
static void do_write_file_command(struct st_command *command, bool append)
 
2795
void do_write_file_command(struct st_command *command, my_bool append)
2583
2796
{
2584
 
  string ds_content;
2585
 
  string ds_filename;
2586
 
  string ds_delimiter;
 
2797
  static DYNAMIC_STRING ds_content;
 
2798
  static DYNAMIC_STRING ds_filename;
 
2799
  static DYNAMIC_STRING ds_delimiter;
2587
2800
  const struct command_arg write_file_args[] = {
2588
 
    { "filename", ARG_STRING, true, &ds_filename, "File to write to" },
2589
 
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
 
2801
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to write to" },
 
2802
    { "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until" }
2590
2803
  };
2591
 
 
 
2804
  DBUG_ENTER("do_write_file");
2592
2805
 
2593
2806
  check_command_args(command,
2594
2807
                     command->first_argument,
2597
2810
                     ' ');
2598
2811
 
2599
2812
  /* If no delimiter was provided, use EOF */
2600
 
  if (ds_delimiter.length() == 0)
2601
 
    ds_delimiter= "EOF";
 
2813
  if (ds_delimiter.length == 0)
 
2814
    dynstr_set(&ds_delimiter, "EOF");
2602
2815
 
2603
 
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
 
2816
  if (!append && access(ds_filename.str, F_OK) == 0)
2604
2817
  {
2605
2818
    /* The file should not be overwritten */
2606
 
    die("File already exist: '%s'", ds_filename.c_str());
 
2819
    die("File already exist: '%s'", ds_filename.str);
2607
2820
  }
2608
2821
 
 
2822
  init_dynamic_string(&ds_content, "", 1024, 1024);
2609
2823
  read_until_delimiter(&ds_content, &ds_delimiter);
2610
 
  str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2611
 
               ds_content.length(), append);
2612
 
  return;
 
2824
  DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str));
 
2825
  str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
 
2826
  dynstr_free(&ds_content);
 
2827
  dynstr_free(&ds_filename);
 
2828
  dynstr_free(&ds_delimiter);
 
2829
  DBUG_VOID_RETURN;
2613
2830
}
2614
2831
 
2615
2832
 
2616
2833
/*
2617
2834
  SYNOPSIS
2618
2835
  do_write_file
2619
 
  command  called command
 
2836
  command       called command
2620
2837
 
2621
2838
  DESCRIPTION
2622
2839
  write_file <file_name> [<delimiter>];
2640
2857
 
2641
2858
*/
2642
2859
 
2643
 
static void do_write_file(struct st_command *command)
 
2860
void do_write_file(struct st_command *command)
2644
2861
{
2645
 
  do_write_file_command(command, false);
 
2862
  do_write_file_command(command, FALSE);
2646
2863
}
2647
2864
 
2648
2865
 
2649
2866
/*
2650
2867
  SYNOPSIS
2651
2868
  do_append_file
2652
 
  command  called command
 
2869
  command       called command
2653
2870
 
2654
2871
  DESCRIPTION
2655
2872
  append_file <file_name> [<delimiter>];
2671
2888
 
2672
2889
*/
2673
2890
 
2674
 
static void do_append_file(struct st_command *command)
 
2891
void do_append_file(struct st_command *command)
2675
2892
{
2676
 
  do_write_file_command(command, true);
 
2893
  do_write_file_command(command, TRUE);
2677
2894
}
2678
2895
 
2679
2896
 
2680
2897
/*
2681
2898
  SYNOPSIS
2682
2899
  do_cat_file
2683
 
  command  called command
 
2900
  command       called command
2684
2901
 
2685
2902
  DESCRIPTION
2686
2903
  cat_file <file_name>;
2689
2906
 
2690
2907
*/
2691
2908
 
2692
 
static void do_cat_file(struct st_command *command)
 
2909
void do_cat_file(struct st_command *command)
2693
2910
{
2694
 
  static string ds_filename;
 
2911
  static DYNAMIC_STRING ds_filename;
2695
2912
  const struct command_arg cat_file_args[] = {
2696
 
    { "filename", ARG_STRING, true, &ds_filename, "File to read from" }
 
2913
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to read from" }
2697
2914
  };
2698
 
 
 
2915
  DBUG_ENTER("do_cat_file");
2699
2916
 
2700
2917
  check_command_args(command,
2701
2918
                     command->first_argument,
2703
2920
                     sizeof(cat_file_args)/sizeof(struct command_arg),
2704
2921
                     ' ');
2705
2922
 
2706
 
  cat_file(&ds_res, ds_filename.c_str());
2707
 
 
2708
 
  return;
 
2923
  DBUG_PRINT("info", ("Reading from, file: %s", ds_filename.str));
 
2924
 
 
2925
  cat_file(&ds_res, ds_filename.str);
 
2926
 
 
2927
  dynstr_free(&ds_filename);
 
2928
  DBUG_VOID_RETURN;
2709
2929
}
2710
2930
 
2711
2931
 
2712
2932
/*
2713
2933
  SYNOPSIS
2714
2934
  do_diff_files
2715
 
  command  called command
 
2935
  command       called command
2716
2936
 
2717
2937
  DESCRIPTION
2718
2938
  diff_files <file1> <file2>;
2721
2941
 
2722
2942
*/
2723
2943
 
2724
 
static void do_diff_files(struct st_command *command)
 
2944
void do_diff_files(struct st_command *command)
2725
2945
{
2726
2946
  int error= 0;
2727
 
  string ds_filename;
2728
 
  string ds_filename2;
 
2947
  static DYNAMIC_STRING ds_filename;
 
2948
  static DYNAMIC_STRING ds_filename2;
2729
2949
  const struct command_arg diff_file_args[] = {
2730
 
    { "file1", ARG_STRING, true, &ds_filename, "First file to diff" },
2731
 
    { "file2", ARG_STRING, true, &ds_filename2, "Second file to diff" }
 
2950
    { "file1", ARG_STRING, TRUE, &ds_filename, "First file to diff" },
 
2951
    { "file2", ARG_STRING, TRUE, &ds_filename2, "Second file to diff" }
2732
2952
  };
2733
 
 
 
2953
  DBUG_ENTER("do_diff_files");
2734
2954
 
2735
2955
  check_command_args(command,
2736
2956
                     command->first_argument,
2738
2958
                     sizeof(diff_file_args)/sizeof(struct command_arg),
2739
2959
                     ' ');
2740
2960
 
2741
 
  if ((error= compare_files(ds_filename.c_str(), ds_filename2.c_str())))
 
2961
  if ((error= compare_files(ds_filename.str, ds_filename2.str)))
2742
2962
  {
2743
2963
    /* Compare of the two files failed, append them to output
2744
2964
       so the failure can be analyzed
2745
2965
    */
2746
 
    show_diff(&ds_res, ds_filename.c_str(), ds_filename2.c_str());
 
2966
    show_diff(&ds_res, ds_filename.str, ds_filename2.str);
2747
2967
  }
2748
2968
 
 
2969
  dynstr_free(&ds_filename);
 
2970
  dynstr_free(&ds_filename2);
2749
2971
  handle_command_error(command, error);
2750
 
  return;
 
2972
  DBUG_VOID_RETURN;
2751
2973
}
2752
2974
 
2753
2975
 
2754
 
static struct st_connection * find_connection_by_name(const char *name)
 
2976
struct st_connection * find_connection_by_name(const char *name)
2755
2977
{
2756
2978
  struct st_connection *con;
2757
2979
  for (con= connections; con < next_con; con++)
2768
2990
/*
2769
2991
  SYNOPSIS
2770
2992
  do_send_quit
2771
 
  command  called command
 
2993
  command       called command
2772
2994
 
2773
2995
  DESCRIPTION
2774
2996
  Sends a simple quit command to the server for the named connection.
2775
2997
 
2776
2998
*/
2777
2999
 
2778
 
static void do_send_quit(struct st_command *command)
 
3000
void do_send_quit(struct st_command *command)
2779
3001
{
2780
3002
  char *p= command->first_argument, *name;
2781
3003
  struct st_connection *con;
2782
3004
 
 
3005
  DBUG_ENTER("do_send_quit");
 
3006
  DBUG_PRINT("enter",("name: '%s'",p));
 
3007
 
2783
3008
  if (!*p)
2784
3009
    die("Missing connection name in send_quit");
2785
3010
  name= p;
2793
3018
  if (!(con= find_connection_by_name(name)))
2794
3019
    die("connection '%s' not found in connection pool", name);
2795
3020
 
2796
 
  simple_command(&con->drizzle,COM_QUIT,0,0,1);
 
3021
  simple_command(&con->mysql,COM_QUIT,0,0,1);
2797
3022
 
2798
 
  return;
 
3023
  DBUG_VOID_RETURN;
2799
3024
}
2800
3025
 
2801
3026
 
2815
3040
 
2816
3041
*/
2817
3042
 
2818
 
static void do_change_user(struct st_command *command)
 
3043
void do_change_user(struct st_command *command)
2819
3044
{
2820
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3045
  MYSQL *mysql = &cur_con->mysql;
2821
3046
  /* static keyword to make the NetWare compiler happy. */
2822
 
  string ds_user, ds_passwd, ds_db;
 
3047
  static DYNAMIC_STRING ds_user, ds_passwd, ds_db;
2823
3048
  const struct command_arg change_user_args[] = {
2824
 
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
2825
 
    { "password", ARG_STRING, false, &ds_passwd, "Password used when connecting" },
2826
 
    { "database", ARG_STRING, false, &ds_db, "Database to select after connect" },
 
3049
    { "user", ARG_STRING, FALSE, &ds_user, "User to connect as" },
 
3050
    { "password", ARG_STRING, FALSE, &ds_passwd, "Password used when connecting" },
 
3051
    { "database", ARG_STRING, FALSE, &ds_db, "Database to select after connect" },
2827
3052
  };
2828
3053
 
2829
 
 
 
3054
  DBUG_ENTER("do_change_user");
2830
3055
 
2831
3056
  check_command_args(command, command->first_argument,
2832
3057
                     change_user_args,
2833
3058
                     sizeof(change_user_args)/sizeof(struct command_arg),
2834
3059
                     ',');
2835
3060
 
2836
 
  if (!ds_user.length())
2837
 
    ds_user= drizzle->user;
2838
 
 
2839
 
  if (!ds_passwd.length())
2840
 
    ds_passwd= drizzle->passwd;
2841
 
 
2842
 
  if (!ds_db.length())
2843
 
    ds_db= drizzle->db;
2844
 
 
2845
 
  if (drizzle_change_user(drizzle, ds_user.c_str(),
2846
 
                          ds_passwd.c_str(), ds_db.c_str()))
2847
 
    die("change user failed: %s", drizzle_error(drizzle));
2848
 
 
2849
 
 
2850
 
  return;
 
3061
  if (cur_con->stmt)
 
3062
  {
 
3063
    mysql_stmt_close(cur_con->stmt);
 
3064
    cur_con->stmt= NULL;
 
3065
  }
 
3066
 
 
3067
  if (!ds_user.length)
 
3068
    dynstr_set(&ds_user, mysql->user);
 
3069
 
 
3070
  if (!ds_passwd.length)
 
3071
    dynstr_set(&ds_passwd, mysql->passwd);
 
3072
 
 
3073
  if (!ds_db.length)
 
3074
    dynstr_set(&ds_db, mysql->db);
 
3075
 
 
3076
  DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'",
 
3077
                      cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
 
3078
 
 
3079
  if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str))
 
3080
    die("change user failed: %s", mysql_error(mysql));
 
3081
 
 
3082
  dynstr_free(&ds_user);
 
3083
  dynstr_free(&ds_passwd);
 
3084
  dynstr_free(&ds_db);
 
3085
 
 
3086
  DBUG_VOID_RETURN;
2851
3087
}
2852
3088
 
2853
3089
 
2854
3090
/*
2855
3091
  SYNOPSIS
2856
3092
  do_perl
2857
 
  command  command handle
 
3093
  command       command handle
2858
3094
 
2859
3095
  DESCRIPTION
2860
3096
  perl [<delimiter>];
2870
3106
  Default <delimiter> is EOF
2871
3107
*/
2872
3108
 
2873
 
static void do_perl(struct st_command *command)
 
3109
void do_perl(struct st_command *command)
2874
3110
{
2875
3111
  int error;
2876
3112
  File fd;
2877
3113
  FILE *res_file;
2878
3114
  char buf[FN_REFLEN];
2879
3115
  char temp_file_path[FN_REFLEN];
2880
 
  string ds_script;
2881
 
  string ds_delimiter;
 
3116
  static DYNAMIC_STRING ds_script;
 
3117
  static DYNAMIC_STRING ds_delimiter;
2882
3118
  const struct command_arg perl_args[] = {
2883
 
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
 
3119
    { "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until" }
2884
3120
  };
2885
 
 
 
3121
  DBUG_ENTER("do_perl");
2886
3122
 
2887
3123
  check_command_args(command,
2888
3124
                     command->first_argument,
2891
3127
                     ' ');
2892
3128
 
2893
3129
  /* If no delimiter was provided, use EOF */
2894
 
  if (ds_delimiter.length() == 0)
2895
 
    ds_delimiter= "EOF";
 
3130
  if (ds_delimiter.length == 0)
 
3131
    dynstr_set(&ds_delimiter, "EOF");
2896
3132
 
 
3133
  init_dynamic_string(&ds_script, "", 1024, 1024);
2897
3134
  read_until_delimiter(&ds_script, &ds_delimiter);
2898
3135
 
 
3136
  DBUG_PRINT("info", ("Executing perl: %s", ds_script.str));
 
3137
 
2899
3138
  /* Create temporary file name */
2900
3139
  if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
2901
 
                            "tmp", O_CREAT | O_RDWR,
 
3140
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
2902
3141
                            MYF(MY_WME))) < 0)
2903
3142
    die("Failed to create temporary file for perl command");
2904
3143
  my_close(fd, MYF(0));
2905
3144
 
2906
 
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
 
3145
  str_to_file(temp_file_path, ds_script.str, ds_script.length);
2907
3146
 
2908
3147
  /* Format the "perl <filename>" command */
2909
 
  snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
 
3148
  my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
2910
3149
 
2911
3150
  if (!(res_file= popen(buf, "r")) && command->abort_on_error)
2912
3151
    die("popen(\"%s\", \"r\") failed", buf);
2914
3153
  while (fgets(buf, sizeof(buf), res_file))
2915
3154
  {
2916
3155
    if (disable_result_log)
 
3156
    {
2917
3157
      buf[strlen(buf)-1]=0;
 
3158
      DBUG_PRINT("exec_result",("%s", buf));
 
3159
    }
2918
3160
    else
2919
 
      replace_append(&ds_res, buf);
 
3161
    {
 
3162
      replace_dynstr_append(&ds_res, buf);
 
3163
    }
2920
3164
  }
2921
3165
  error= pclose(res_file);
2922
3166
 
2924
3168
  my_delete(temp_file_path, MYF(0));
2925
3169
 
2926
3170
  handle_command_error(command, WEXITSTATUS(error));
2927
 
  return;
 
3171
  dynstr_free(&ds_script);
 
3172
  dynstr_free(&ds_delimiter);
 
3173
  DBUG_VOID_RETURN;
2928
3174
}
2929
3175
 
2930
3176
 
2931
3177
/*
2932
3178
  Print the content between echo and <delimiter> to result file.
2933
3179
  Evaluate all variables in the string before printing, allow
2934
 
  for variable names to be escaped using        \
 
3180
  for variable names to be escaped using \
2935
3181
 
2936
3182
  SYNOPSIS
2937
3183
  do_echo()
2952
3198
  Print "Some text" plus $<var_name> to result file
2953
3199
*/
2954
3200
 
2955
 
static int do_echo(struct st_command *command)
 
3201
int do_echo(struct st_command *command)
2956
3202
{
2957
 
  string ds_echo;
2958
 
 
2959
 
 
2960
 
  do_eval(&ds_echo, command->first_argument, command->end, false);
2961
 
  ds_res.append(ds_echo.c_str(), ds_echo.length());
2962
 
  ds_res.append("\n");
 
3203
  DYNAMIC_STRING ds_echo;
 
3204
  DBUG_ENTER("do_echo");
 
3205
 
 
3206
  init_dynamic_string(&ds_echo, "", command->query_len, 256);
 
3207
  do_eval(&ds_echo, command->first_argument, command->end, FALSE);
 
3208
  dynstr_append_mem(&ds_res, ds_echo.str, ds_echo.length);
 
3209
  dynstr_append_mem(&ds_res, "\n", 1);
 
3210
  dynstr_free(&ds_echo);
2963
3211
  command->last_argument= command->end;
2964
 
  return(0);
 
3212
  DBUG_RETURN(0);
2965
3213
}
2966
3214
 
2967
3215
 
2968
 
static void
2969
 
do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
 
3216
void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
2970
3217
{
2971
3218
  static int SLAVE_POLL_INTERVAL= 300000;
2972
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3219
  MYSQL* mysql = &cur_con->mysql;
2973
3220
  for (;;)
2974
3221
  {
2975
 
    DRIZZLE_RES *res= NULL;
2976
 
    DRIZZLE_ROW row;
 
3222
    MYSQL_RES *res= NULL;
 
3223
    MYSQL_ROW row;
2977
3224
    int done;
2978
3225
 
2979
 
    if (drizzle_query(drizzle,"show status like 'Slave_running'") ||
2980
 
        !(res=drizzle_store_result(drizzle)))
 
3226
    if (mysql_query(mysql,"show status like 'Slave_running'") ||
 
3227
        !(res=mysql_store_result(mysql)))
2981
3228
      die("Query failed while probing slave for stop: %s",
2982
 
          drizzle_error(drizzle));
2983
 
    if (!(row=drizzle_fetch_row(res)) || !row[1])
 
3229
          mysql_error(mysql));
 
3230
    if (!(row=mysql_fetch_row(res)) || !row[1])
2984
3231
    {
2985
 
      drizzle_free_result(res);
 
3232
      mysql_free_result(res);
2986
3233
      die("Strange result from query while probing slave for stop");
2987
3234
    }
2988
3235
    done = !strcmp(row[1],"OFF");
2989
 
    drizzle_free_result(res);
 
3236
    mysql_free_result(res);
2990
3237
    if (done)
2991
3238
      break;
2992
3239
    my_sleep(SLAVE_POLL_INTERVAL);
2995
3242
}
2996
3243
 
2997
3244
 
2998
 
static void do_sync_with_master2(long offset)
 
3245
void do_sync_with_master2(long offset)
2999
3246
{
3000
 
  DRIZZLE_RES *res;
3001
 
  DRIZZLE_ROW row;
3002
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3247
  MYSQL_RES *res;
 
3248
  MYSQL_ROW row;
 
3249
  MYSQL *mysql= &cur_con->mysql;
3003
3250
  char query_buf[FN_REFLEN+128];
3004
3251
  int tries= 0;
3005
3252
 
3007
3254
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3008
3255
 
3009
3256
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3010
 
          master_pos.pos + offset);
 
3257
          master_pos.pos + offset);
3011
3258
 
3012
3259
wait_for_position:
3013
3260
 
3014
 
  if (drizzle_query(drizzle, query_buf))
3015
 
    die("failed in '%s': %d: %s", query_buf, drizzle_errno(drizzle),
3016
 
        drizzle_error(drizzle));
 
3261
  if (mysql_query(mysql, query_buf))
 
3262
    die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
 
3263
        mysql_error(mysql));
3017
3264
 
3018
 
  if (!(res= drizzle_store_result(drizzle)))
3019
 
    die("drizzle_store_result() returned NULL for '%s'", query_buf);
3020
 
  if (!(row= drizzle_fetch_row(res)))
 
3265
  if (!(res= mysql_store_result(mysql)))
 
3266
    die("mysql_store_result() returned NULL for '%s'", query_buf);
 
3267
  if (!(row= mysql_fetch_row(res)))
3021
3268
  {
3022
 
    drizzle_free_result(res);
 
3269
    mysql_free_result(res);
3023
3270
    die("empty result in %s", query_buf);
3024
3271
  }
3025
3272
  if (!row[0])
3028
3275
      It may be that the slave SQL thread has not started yet, though START
3029
3276
      SLAVE has been issued ?
3030
3277
    */
3031
 
    drizzle_free_result(res);
 
3278
    mysql_free_result(res);
3032
3279
    if (tries++ == 30)
3033
3280
    {
3034
 
      show_query(drizzle, "SHOW MASTER STATUS");
3035
 
      show_query(drizzle, "SHOW SLAVE STATUS");
 
3281
      show_query(mysql, "SHOW MASTER STATUS");
 
3282
      show_query(mysql, "SHOW SLAVE STATUS");
3036
3283
      die("could not sync with master ('%s' returned NULL)", query_buf);
3037
3284
    }
3038
3285
    sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
3039
3286
    goto wait_for_position;
3040
3287
  }
3041
 
  drizzle_free_result(res);
 
3288
  mysql_free_result(res);
3042
3289
  return;
3043
3290
}
3044
3291
 
3045
3292
 
3046
 
static void do_sync_with_master(struct st_command *command)
 
3293
void do_sync_with_master(struct st_command *command)
3047
3294
{
3048
3295
  long offset= 0;
3049
3296
  char *p= command->first_argument;
3064
3311
 
3065
3312
/*
3066
3313
  when ndb binlog is on, this call will wait until last updated epoch
3067
 
  (locally in the drizzled) has been received into the binlog
 
3314
  (locally in the mysqld) has been received into the binlog
3068
3315
*/
3069
 
static int do_save_master_pos(void)
 
3316
int do_save_master_pos()
3070
3317
{
3071
 
  DRIZZLE_RES *res;
3072
 
  DRIZZLE_ROW row;
3073
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3318
  MYSQL_RES *res;
 
3319
  MYSQL_ROW row;
 
3320
  MYSQL *mysql = &cur_con->mysql;
3074
3321
  const char *query;
3075
 
 
3076
 
 
3077
 
  if (drizzle_query(drizzle, query= "show master status"))
 
3322
  DBUG_ENTER("do_save_master_pos");
 
3323
 
 
3324
#ifdef HAVE_NDB_BINLOG
 
3325
  /*
 
3326
    Wait for ndb binlog to be up-to-date with all changes
 
3327
    done on the local mysql server
 
3328
  */
 
3329
  {
 
3330
    ulong have_ndbcluster;
 
3331
    if (mysql_query(mysql, query= "show variables like 'have_ndbcluster'"))
 
3332
      die("'%s' failed: %d %s", query,
 
3333
          mysql_errno(mysql), mysql_error(mysql));
 
3334
    if (!(res= mysql_store_result(mysql)))
 
3335
      die("mysql_store_result() returned NULL for '%s'", query);
 
3336
    if (!(row= mysql_fetch_row(res)))
 
3337
      die("Query '%s' returned empty result", query);
 
3338
 
 
3339
    have_ndbcluster= strcmp("YES", row[1]) == 0;
 
3340
    mysql_free_result(res);
 
3341
 
 
3342
    if (have_ndbcluster)
 
3343
    {
 
3344
      ulonglong start_epoch= 0, handled_epoch= 0,
 
3345
        latest_epoch=0, latest_trans_epoch=0,
 
3346
        latest_handled_binlog_epoch= 0, latest_received_binlog_epoch= 0,
 
3347
        latest_applied_binlog_epoch= 0;
 
3348
      int count= 0;
 
3349
      int do_continue= 1;
 
3350
      while (do_continue)
 
3351
      {
 
3352
        const char binlog[]= "binlog";
 
3353
        const char latest_epoch_str[]=
 
3354
          "latest_epoch=";
 
3355
        const char latest_trans_epoch_str[]=
 
3356
          "latest_trans_epoch=";
 
3357
        const char latest_received_binlog_epoch_str[]=
 
3358
          "latest_received_binlog_epoch";
 
3359
        const char latest_handled_binlog_epoch_str[]=
 
3360
          "latest_handled_binlog_epoch=";
 
3361
        const char latest_applied_binlog_epoch_str[]=
 
3362
          "latest_applied_binlog_epoch=";
 
3363
        if (count)
 
3364
          sleep(1);
 
3365
        if (mysql_query(mysql, query= "show engine ndb status"))
 
3366
          die("failed in '%s': %d %s", query,
 
3367
              mysql_errno(mysql), mysql_error(mysql));
 
3368
        if (!(res= mysql_store_result(mysql)))
 
3369
          die("mysql_store_result() returned NULL for '%s'", query);
 
3370
        while ((row= mysql_fetch_row(res)))
 
3371
        {
 
3372
          if (strcmp(row[1], binlog) == 0)
 
3373
          {
 
3374
            const char *status= row[2];
 
3375
 
 
3376
            /* latest_epoch */
 
3377
            while (*status && strncmp(status, latest_epoch_str,
 
3378
                                      sizeof(latest_epoch_str)-1))
 
3379
              status++;
 
3380
            if (*status)
 
3381
            {
 
3382
              status+= sizeof(latest_epoch_str)-1;
 
3383
              latest_epoch= strtoull(status, (char**) 0, 10);
 
3384
            }
 
3385
            else
 
3386
              die("result does not contain '%s' in '%s'",
 
3387
                  latest_epoch_str, query);
 
3388
            /* latest_trans_epoch */
 
3389
            while (*status && strncmp(status, latest_trans_epoch_str,
 
3390
                                      sizeof(latest_trans_epoch_str)-1))
 
3391
              status++;
 
3392
            if (*status)
 
3393
            {
 
3394
              status+= sizeof(latest_trans_epoch_str)-1;
 
3395
              latest_trans_epoch= strtoull(status, (char**) 0, 10);
 
3396
            }
 
3397
            else
 
3398
              die("result does not contain '%s' in '%s'",
 
3399
                  latest_trans_epoch_str, query);
 
3400
            /* latest_received_binlog_epoch */
 
3401
            while (*status &&
 
3402
                   strncmp(status, latest_received_binlog_epoch_str,
 
3403
                           sizeof(latest_received_binlog_epoch_str)-1))
 
3404
              status++;
 
3405
            if (*status)
 
3406
            {
 
3407
              status+= sizeof(latest_received_binlog_epoch_str)-1;
 
3408
              latest_received_binlog_epoch= strtoull(status, (char**) 0, 10);
 
3409
            }
 
3410
            else
 
3411
              die("result does not contain '%s' in '%s'",
 
3412
                  latest_received_binlog_epoch_str, query);
 
3413
            /* latest_handled_binlog */
 
3414
            while (*status &&
 
3415
                   strncmp(status, latest_handled_binlog_epoch_str,
 
3416
                           sizeof(latest_handled_binlog_epoch_str)-1))
 
3417
              status++;
 
3418
            if (*status)
 
3419
            {
 
3420
              status+= sizeof(latest_handled_binlog_epoch_str)-1;
 
3421
              latest_handled_binlog_epoch= strtoull(status, (char**) 0, 10);
 
3422
            }
 
3423
            else
 
3424
              die("result does not contain '%s' in '%s'",
 
3425
                  latest_handled_binlog_epoch_str, query);
 
3426
            /* latest_applied_binlog_epoch */
 
3427
            while (*status &&
 
3428
                   strncmp(status, latest_applied_binlog_epoch_str,
 
3429
                           sizeof(latest_applied_binlog_epoch_str)-1))
 
3430
              status++;
 
3431
            if (*status)
 
3432
            {
 
3433
              status+= sizeof(latest_applied_binlog_epoch_str)-1;
 
3434
              latest_applied_binlog_epoch= strtoull(status, (char**) 0, 10);
 
3435
            }
 
3436
            else
 
3437
              die("result does not contain '%s' in '%s'",
 
3438
                  latest_applied_binlog_epoch_str, query);
 
3439
            if (count == 0)
 
3440
              start_epoch= latest_trans_epoch;
 
3441
            break;
 
3442
          }
 
3443
        }
 
3444
        if (!row)
 
3445
          die("result does not contain '%s' in '%s'",
 
3446
              binlog, query);
 
3447
        if (latest_handled_binlog_epoch > handled_epoch)
 
3448
          count= 0;
 
3449
        handled_epoch= latest_handled_binlog_epoch;
 
3450
        count++;
 
3451
        if (latest_handled_binlog_epoch >= start_epoch)
 
3452
          do_continue= 0;
 
3453
        else if (count > 30)
 
3454
        {
 
3455
          break;
 
3456
        }
 
3457
        mysql_free_result(res);
 
3458
      }
 
3459
    }
 
3460
  }
 
3461
#endif
 
3462
  if (mysql_query(mysql, query= "show master status"))
3078
3463
    die("failed in 'show master status': %d %s",
3079
 
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
3464
        mysql_errno(mysql), mysql_error(mysql));
3080
3465
 
3081
 
  if (!(res = drizzle_store_result(drizzle)))
3082
 
    die("drizzle_store_result() retuned NULL for '%s'", query);
3083
 
  if (!(row = drizzle_fetch_row(res)))
 
3466
  if (!(res = mysql_store_result(mysql)))
 
3467
    die("mysql_store_result() retuned NULL for '%s'", query);
 
3468
  if (!(row = mysql_fetch_row(res)))
3084
3469
    die("empty result in show master status");
3085
 
  my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
 
3470
  strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
3086
3471
  master_pos.pos = strtoul(row[1], (char**) 0, 10);
3087
 
  drizzle_free_result(res);
3088
 
  return(0);
 
3472
  mysql_free_result(res);
 
3473
  DBUG_RETURN(0);
3089
3474
}
3090
3475
 
3091
3476
 
3094
3479
 
3095
3480
  SYNOPSIS
3096
3481
  do_let()
3097
 
  query  called command
 
3482
  query called command
3098
3483
 
3099
3484
  DESCRIPTION
3100
3485
  let $<var_name>=<var_val><delimiter>
3108
3493
  Program will die if error detected
3109
3494
*/
3110
3495
 
3111
 
static void do_let(struct st_command *command)
 
3496
void do_let(struct st_command *command)
3112
3497
{
3113
3498
  char *p= command->first_argument;
3114
3499
  char *var_name, *var_name_end;
3115
 
  string let_rhs_expr;
 
3500
  DYNAMIC_STRING let_rhs_expr;
 
3501
  DBUG_ENTER("do_let");
3116
3502
 
 
3503
  init_dynamic_string(&let_rhs_expr, "", 512, 2048);
3117
3504
 
3118
3505
  /* Find <var_name> */
3119
3506
  if (!*p)
3134
3521
  while (*p && my_isspace(charset_info,*p))
3135
3522
    p++;
3136
3523
 
3137
 
  do_eval(&let_rhs_expr, p, command->end, false);
 
3524
  do_eval(&let_rhs_expr, p, command->end, FALSE);
3138
3525
 
3139
3526
  command->last_argument= command->end;
3140
3527
  /* Assign var_val to var_name */
3141
 
  var_set(var_name, var_name_end, let_rhs_expr.c_str(),
3142
 
          (let_rhs_expr.c_str() + let_rhs_expr.length()));
3143
 
  return;
 
3528
  var_set(var_name, var_name_end, let_rhs_expr.str,
 
3529
          (let_rhs_expr.str + let_rhs_expr.length));
 
3530
  dynstr_free(&let_rhs_expr);
 
3531
  DBUG_VOID_RETURN;
3144
3532
}
3145
3533
 
3146
3534
 
3149
3537
 
3150
3538
  SYNOPSIS
3151
3539
  do_sleep()
3152
 
  q         called command
 
3540
  q            called command
3153
3541
  real_sleep   use the value from opt_sleep as number of seconds to sleep
3154
 
  if real_sleep is false
 
3542
               if real_sleep is false
3155
3543
 
3156
3544
  DESCRIPTION
3157
3545
  sleep <seconds>
3166
3554
  used for cpu-independent delays.
3167
3555
*/
3168
3556
 
3169
 
static int do_sleep(struct st_command *command, bool real_sleep)
 
3557
int do_sleep(struct st_command *command, my_bool real_sleep)
3170
3558
{
3171
3559
  int error= 0;
3172
3560
  char *p= command->first_argument;
3191
3579
  if (opt_sleep >= 0 && !real_sleep)
3192
3580
    sleep_val= opt_sleep;
3193
3581
 
 
3582
  DBUG_PRINT("info", ("sleep_val: %f", sleep_val));
3194
3583
  if (sleep_val)
3195
 
    my_sleep((uint32_t) (sleep_val * 1000000L));
 
3584
    my_sleep((ulong) (sleep_val * 1000000L));
3196
3585
  command->last_argument= sleep_end;
3197
3586
  return 0;
3198
3587
}
3199
3588
 
3200
3589
 
3201
 
static void do_get_file_name(struct st_command *command,
3202
 
                             char* dest, uint dest_max_len)
 
3590
void do_get_file_name(struct st_command *command,
 
3591
                      char* dest, uint dest_max_len)
3203
3592
{
3204
3593
  char *p= command->first_argument, *name;
3205
3594
  if (!*p)
3214
3603
}
3215
3604
 
3216
3605
 
3217
 
static void do_set_charset(struct st_command *command)
 
3606
void do_set_charset(struct st_command *command)
3218
3607
{
3219
3608
  char *charset_name= command->first_argument;
3220
3609
  char *p;
3233
3622
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3234
3623
}
3235
3624
 
3236
 
static uint get_errcode_from_name(char *error_name, char *error_end)
 
3625
 
 
3626
#if MYSQL_VERSION_ID >= 50000
 
3627
/* List of error names to error codes, available from 5.0 */
 
3628
typedef struct
 
3629
{
 
3630
  const char *name;
 
3631
  uint        code;
 
3632
} st_error;
 
3633
 
 
3634
static st_error global_error_names[] =
 
3635
{
 
3636
#include <mysqld_ername.h>
 
3637
  { 0, 0 }
 
3638
};
 
3639
 
 
3640
uint get_errcode_from_name(char *error_name, char *error_end)
3237
3641
{
3238
3642
  /* SQL error as string */
3239
3643
  st_error *e= global_error_names;
3240
3644
 
 
3645
  DBUG_ENTER("get_errcode_from_name");
 
3646
  DBUG_PRINT("enter", ("error_name: %s", error_name));
 
3647
 
3241
3648
  /* Loop through the array of known error names */
3242
3649
  for (; e->name; e++)
3243
3650
  {
3249
3656
    if (!strncmp(error_name, e->name, (int) (error_end - error_name)) &&
3250
3657
        (uint) strlen(e->name) == (uint) (error_end - error_name))
3251
3658
    {
3252
 
      return(e->code);
 
3659
      DBUG_RETURN(e->code);
3253
3660
    }
3254
3661
  }
3255
3662
  if (!e->name)
3256
3663
    die("Unknown SQL error name '%s'", error_name);
3257
 
  return(0);
3258
 
}
3259
 
 
3260
 
static void do_get_errcodes(struct st_command *command)
 
3664
  DBUG_RETURN(0);
 
3665
}
 
3666
#else
 
3667
uint get_errcode_from_name(char *error_name __attribute__((unused)),
 
3668
                           char *error_end __attribute__((unused)))
 
3669
{
 
3670
  abort_not_in_this_version();
 
3671
  return 0; /* Never reached */
 
3672
}
 
3673
#endif
 
3674
 
 
3675
 
 
3676
 
 
3677
void do_get_errcodes(struct st_command *command)
3261
3678
{
3262
3679
  struct st_match_err *to= saved_expected_errors.err;
3263
3680
  char *p= command->first_argument;
3264
3681
  uint count= 0;
3265
3682
 
3266
 
 
 
3683
  DBUG_ENTER("do_get_errcodes");
3267
3684
 
3268
3685
  if (!*p)
3269
3686
    die("Missing argument(s) to 'error'");
3300
3717
        if (my_isdigit(charset_info, *p) || my_isupper(charset_info, *p))
3301
3718
          *to_ptr++= *p++;
3302
3719
        else
3303
 
          die("The sqlstate may only consist of digits[0-9] "   \
 
3720
          die("The sqlstate may only consist of digits[0-9] " \
3304
3721
              "and _uppercase_ letters");
3305
3722
      }
3306
3723
 
3307
3724
      *to_ptr= 0;
3308
3725
      to->type= ERR_SQLSTATE;
 
3726
      DBUG_PRINT("info", ("ERR_SQLSTATE: %s", to->code.sqlstate));
3309
3727
    }
3310
3728
    else if (*p == 's')
3311
3729
    {
3315
3733
    {
3316
3734
      /* Error name string */
3317
3735
 
 
3736
      DBUG_PRINT("info", ("Error name: %s", p));
3318
3737
      to->code.errnum= get_errcode_from_name(p, end);
3319
3738
      to->type= ERR_ERRNO;
 
3739
      DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
3320
3740
    }
3321
3741
    else if (*p == 'e')
3322
3742
    {
3330
3750
      while (*p && p != end)
3331
3751
      {
3332
3752
        if (!my_isdigit(charset_info, *p))
3333
 
          die("Invalid argument to error: '%s' - "              \
 
3753
          die("Invalid argument to error: '%s' - "\
3334
3754
              "the errno may only consist of digits[0-9]",
3335
3755
              command->first_argument);
3336
3756
        p++;
3338
3758
 
3339
3759
      /* Convert the sting to int */
3340
3760
      if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
3341
 
        die("Invalid argument to error: '%s'", command->first_argument);
 
3761
        die("Invalid argument to error: '%s'", command->first_argument);
3342
3762
 
3343
3763
      to->code.errnum= (uint) val;
3344
3764
      to->type= ERR_ERRNO;
 
3765
      DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
3345
3766
    }
3346
3767
    to++;
3347
3768
    count++;
3365
3786
  command->last_argument= p;
3366
3787
  to->type= ERR_EMPTY;                        /* End of data */
3367
3788
 
 
3789
  DBUG_PRINT("info", ("Expected errors: %d", count));
3368
3790
  saved_expected_errors.count= count;
3369
 
  return;
 
3791
  DBUG_VOID_RETURN;
3370
3792
}
3371
3793
 
3372
3794
 
3377
3799
  If string is a '$variable', return the value of the variable.
3378
3800
*/
3379
3801
 
3380
 
static char *get_string(char **to_ptr, char **from_ptr,
3381
 
                        struct st_command *command)
 
3802
char *get_string(char **to_ptr, char **from_ptr,
 
3803
                 struct st_command *command)
3382
3804
{
3383
3805
  char c, sep;
3384
3806
  char *to= *to_ptr, *from= *from_ptr, *start=to;
3385
 
 
 
3807
  DBUG_ENTER("get_string");
3386
3808
 
3387
3809
  /* Find separator */
3388
3810
  if (*from == '"' || *from == '\'')
3389
3811
    sep= *from++;
3390
3812
  else
3391
 
    sep=' ';        /* Separated with space */
 
3813
    sep=' ';                            /* Separated with space */
3392
3814
 
3393
3815
  for ( ; (c=*from) ; from++)
3394
3816
  {
3395
3817
    if (c == '\\' && from[1])
3396
 
    {          /* Escaped character */
 
3818
    {                                   /* Escaped character */
3397
3819
      /* We can't translate \0 -> ASCII 0 as replace can't handle ASCII 0 */
3398
3820
      switch (*++from) {
3399
3821
      case 'n':
3400
 
        *to++= '\n';
3401
 
        break;
 
3822
        *to++= '\n';
 
3823
        break;
3402
3824
      case 't':
3403
 
        *to++= '\t';
3404
 
        break;
 
3825
        *to++= '\t';
 
3826
        break;
3405
3827
      case 'r':
3406
 
        *to++ = '\r';
3407
 
        break;
 
3828
        *to++ = '\r';
 
3829
        break;
3408
3830
      case 'b':
3409
 
        *to++ = '\b';
3410
 
        break;
3411
 
      case 'Z':        /* ^Z must be escaped on Win32 */
3412
 
        *to++='\032';
3413
 
        break;
 
3831
        *to++ = '\b';
 
3832
        break;
 
3833
      case 'Z':                         /* ^Z must be escaped on Win32 */
 
3834
        *to++='\032';
 
3835
        break;
3414
3836
      default:
3415
 
        *to++ = *from;
3416
 
        break;
 
3837
        *to++ = *from;
 
3838
        break;
3417
3839
      }
3418
3840
    }
3419
3841
    else if (c == sep)
3420
3842
    {
3421
3843
      if (c == ' ' || c != *++from)
3422
 
        break;        /* Found end of string */
3423
 
      *to++=c;        /* Copy duplicated separator */
 
3844
        break;                          /* Found end of string */
 
3845
      *to++=c;                          /* Copy duplicated separator */
3424
3846
    }
3425
3847
    else
3426
3848
      *to++=c;
3428
3850
  if (*from != ' ' && *from)
3429
3851
    die("Wrong string argument in %s", command->query);
3430
3852
 
3431
 
  while (my_isspace(charset_info,*from))  /* Point to next string */
 
3853
  while (my_isspace(charset_info,*from))        /* Point to next string */
3432
3854
    from++;
3433
3855
 
3434
 
  *to =0;        /* End of string marker */
3435
 
  *to_ptr= to+1;      /* Store pointer to end */
 
3856
  *to =0;                               /* End of string marker */
 
3857
  *to_ptr= to+1;                        /* Store pointer to end */
3436
3858
  *from_ptr= from;
3437
3859
 
3438
3860
  /* Check if this was a variable */
3441
3863
    const char *end= to;
3442
3864
    VAR *var=var_get(start, &end, 0, 1);
3443
3865
    if (var && to == (char*) end+1)
3444
 
      return(var->str_val);  /* return found variable value */
 
3866
    {
 
3867
      DBUG_PRINT("info",("var: '%s' -> '%s'", start, var->str_val));
 
3868
      DBUG_RETURN(var->str_val);        /* return found variable value */
 
3869
    }
3445
3870
  }
3446
 
  return(start);
3447
 
}
3448
 
 
3449
 
 
3450
 
static void set_reconnect(DRIZZLE *drizzle, int val)
3451
 
{
3452
 
  bool reconnect= val;
3453
 
 
3454
 
  drizzle_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
3455
 
 
3456
 
  return;
3457
 
}
3458
 
 
3459
 
 
3460
 
static int select_connection_name(const char *name)
3461
 
{
 
3871
  DBUG_RETURN(start);
 
3872
}
 
3873
 
 
3874
 
 
3875
void set_reconnect(MYSQL* mysql, int val)
 
3876
{
 
3877
  my_bool reconnect= val;
 
3878
  DBUG_ENTER("set_reconnect");
 
3879
  DBUG_PRINT("info", ("val: %d", val));
 
3880
#if MYSQL_VERSION_ID < 50000
 
3881
  mysql->reconnect= reconnect;
 
3882
#else
 
3883
  mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
 
3884
#endif
 
3885
  DBUG_VOID_RETURN;
 
3886
}
 
3887
 
 
3888
 
 
3889
int select_connection_name(const char *name)
 
3890
{
 
3891
  DBUG_ENTER("select_connection_name");
 
3892
  DBUG_PRINT("enter",("name: '%s'", name));
 
3893
 
3462
3894
  if (!(cur_con= find_connection_by_name(name)))
3463
3895
    die("connection '%s' not found in connection pool", name);
3464
3896
 
3465
 
  /* Update $drizzle_get_server_version to that of current connection */
3466
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
3897
  /* Update $mysql_get_server_version to that of current connection */
 
3898
  var_set_mysql_get_server_version(&cur_con->mysql);
3467
3899
 
3468
 
  return(0);
 
3900
  DBUG_RETURN(0);
3469
3901
}
3470
3902
 
3471
3903
 
3472
 
static int select_connection(struct st_command *command)
 
3904
int select_connection(struct st_command *command)
3473
3905
{
3474
3906
  char *name;
3475
3907
  char *p= command->first_argument;
3476
 
 
 
3908
  DBUG_ENTER("select_connection");
3477
3909
 
3478
3910
  if (!*p)
3479
3911
    die("Missing connection name in connect");
3483
3915
  if (*p)
3484
3916
    *p++= 0;
3485
3917
  command->last_argument= p;
3486
 
  return(select_connection_name(name));
 
3918
  DBUG_RETURN(select_connection_name(name));
3487
3919
}
3488
3920
 
3489
3921
 
3490
 
static void do_close_connection(struct st_command *command)
 
3922
void do_close_connection(struct st_command *command)
3491
3923
{
3492
3924
  char *p= command->first_argument, *name;
3493
3925
  struct st_connection *con;
3494
3926
 
 
3927
  DBUG_ENTER("close_connection");
 
3928
  DBUG_PRINT("enter",("name: '%s'",p));
 
3929
 
3495
3930
  if (!*p)
3496
3931
    die("Missing connection name in disconnect");
3497
3932
  name= p;
3505
3940
  if (!(con= find_connection_by_name(name)))
3506
3941
    die("connection '%s' not found in connection pool", name);
3507
3942
 
 
3943
  DBUG_PRINT("info", ("Closing connection %s", con->name));
 
3944
#ifndef EMBEDDED_LIBRARY
3508
3945
  if (command->type == Q_DIRTY_CLOSE)
3509
3946
  {
3510
 
    if (con->drizzle.net.vio)
 
3947
    if (con->mysql.net.vio)
3511
3948
    {
3512
 
      net_close(&(con->drizzle.net));
 
3949
      vio_delete(con->mysql.net.vio);
 
3950
      con->mysql.net.vio = 0;
3513
3951
    }
3514
3952
  }
3515
 
 
3516
 
  drizzle_close(&con->drizzle);
3517
 
 
3518
 
  if (con->util_drizzle)
3519
 
    drizzle_close(con->util_drizzle);
3520
 
  con->util_drizzle= 0;
3521
 
 
3522
 
  free(con->name);
 
3953
#else
 
3954
  /*
 
3955
    As query could be still executed in a separate theread
 
3956
    we need to check if the query's thread was finished and probably wait
 
3957
    (embedded-server specific)
 
3958
  */
 
3959
  wait_query_thread_end(con);
 
3960
#endif /*EMBEDDED_LIBRARY*/
 
3961
  if (con->stmt)
 
3962
    mysql_stmt_close(con->stmt);
 
3963
  con->stmt= 0;
 
3964
 
 
3965
  mysql_close(&con->mysql);
 
3966
 
 
3967
  if (con->util_mysql)
 
3968
    mysql_close(con->util_mysql);
 
3969
  con->util_mysql= 0;
 
3970
 
 
3971
  my_free(con->name, MYF(0));
3523
3972
 
3524
3973
  /*
3525
3974
    When the connection is closed set name to "-closed_connection-"
3528
3977
  if (!(con->name = my_strdup("-closed_connection-", MYF(MY_WME))))
3529
3978
    die("Out of memory");
3530
3979
 
3531
 
  return;
 
3980
  DBUG_VOID_RETURN;
3532
3981
}
3533
3982
 
3534
3983
 
3557
4006
 
3558
4007
*/
3559
4008
 
3560
 
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
3561
 
                         const char *user, const char *pass, const char *db,
3562
 
                         int port)
 
4009
void safe_connect(MYSQL* mysql, const char *name, const char *host,
 
4010
                  const char *user, const char *pass, const char *db,
 
4011
                  int port)
3563
4012
{
3564
4013
  int failed_attempts= 0;
3565
 
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3566
 
 
3567
 
 
3568
 
  while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3569
 
                         CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
 
4014
  static ulong connection_retry_sleep= 100000; /* Microseconds */
 
4015
 
 
4016
  DBUG_ENTER("safe_connect");
 
4017
  while(!mysql_real_connect(mysql, host, user, pass, db, port, NULL,
 
4018
                            CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3570
4019
  {
3571
4020
    /*
3572
4021
      Connect failed
3576
4025
      on protocol/connection type
3577
4026
    */
3578
4027
 
3579
 
    if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
3580
 
         drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
 
4028
    if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
 
4029
         mysql_errno(mysql) == CR_CONNECTION_ERROR) &&
3581
4030
        failed_attempts < opt_max_connect_retries)
3582
4031
    {
3583
4032
      verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3584
 
                  opt_max_connect_retries, drizzle_errno(drizzle),
3585
 
                  drizzle_error(drizzle));
 
4033
                  opt_max_connect_retries, mysql_errno(mysql),
 
4034
                  mysql_error(mysql));
3586
4035
      my_sleep(connection_retry_sleep);
3587
4036
    }
3588
4037
    else
3589
4038
    {
3590
4039
      if (failed_attempts > 0)
3591
4040
        die("Could not open connection '%s' after %d attempts: %d %s", name,
3592
 
            failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
 
4041
            failed_attempts, mysql_errno(mysql), mysql_error(mysql));
3593
4042
      else
3594
4043
        die("Could not open connection '%s': %d %s", name,
3595
 
            drizzle_errno(drizzle), drizzle_error(drizzle));
 
4044
            mysql_errno(mysql), mysql_error(mysql));
3596
4045
    }
3597
4046
    failed_attempts++;
3598
4047
  }
3599
 
  return;
 
4048
  DBUG_VOID_RETURN;
3600
4049
}
3601
4050
 
3602
4051
 
3623
4072
 
3624
4073
*/
3625
4074
 
3626
 
static int connect_n_handle_errors(struct st_command *command,
3627
 
                                   DRIZZLE *con, const char* host,
3628
 
                                   const char* user, const char* pass,
3629
 
                                   const char* db, int port, const char* sock)
 
4075
int connect_n_handle_errors(struct st_command *command,
 
4076
                            MYSQL* con, const char* host,
 
4077
                            const char* user, const char* pass,
 
4078
                            const char* db, int port, const char* sock)
3630
4079
{
 
4080
  DYNAMIC_STRING *ds;
 
4081
 
 
4082
  ds= &ds_res;
3631
4083
 
3632
4084
  /* Only log if an error is expected */
3633
4085
  if (!command->abort_on_error &&
3636
4088
    /*
3637
4089
      Log the connect to result log
3638
4090
    */
3639
 
    ds_res.append("connect(");
3640
 
    replace_append(&ds_res, host);
3641
 
    ds_res.append(",");
3642
 
    replace_append(&ds_res, user);
3643
 
    ds_res.append(",");
3644
 
    replace_append(&ds_res, pass);
3645
 
    ds_res.append(",");
 
4091
    dynstr_append_mem(ds, "connect(", 8);
 
4092
    replace_dynstr_append(ds, host);
 
4093
    dynstr_append_mem(ds, ",", 1);
 
4094
    replace_dynstr_append(ds, user);
 
4095
    dynstr_append_mem(ds, ",", 1);
 
4096
    replace_dynstr_append(ds, pass);
 
4097
    dynstr_append_mem(ds, ",", 1);
3646
4098
    if (db)
3647
 
      replace_append(&ds_res, db);
3648
 
    ds_res.append(",");
3649
 
    replace_append_uint(&ds_res, port);
3650
 
    ds_res.append(",");
 
4099
      replace_dynstr_append(ds, db);
 
4100
    dynstr_append_mem(ds, ",", 1);
 
4101
    replace_dynstr_append_uint(ds, port);
 
4102
    dynstr_append_mem(ds, ",", 1);
3651
4103
    if (sock)
3652
 
      replace_append(&ds_res, sock);
3653
 
    ds_res.append(")");
3654
 
    ds_res.append(delimiter);
3655
 
    ds_res.append("\n");
 
4104
      replace_dynstr_append(ds, sock);
 
4105
    dynstr_append_mem(ds, ")", 1);
 
4106
    dynstr_append_mem(ds, delimiter, delimiter_length);
 
4107
    dynstr_append_mem(ds, "\n", 1);
3656
4108
  }
3657
 
  if (!drizzle_connect(con, host, user, pass, db, port, 0,
3658
 
                       CLIENT_MULTI_STATEMENTS))
 
4109
  if (!mysql_real_connect(con, host, user, pass, db, port, 0,
 
4110
                          CLIENT_MULTI_STATEMENTS))
3659
4111
  {
3660
 
    var_set_errno(drizzle_errno(con));
3661
 
    handle_error(command, drizzle_errno(con), drizzle_error(con),
3662
 
                 drizzle_sqlstate(con), &ds_res);
 
4112
    var_set_errno(mysql_errno(con));
 
4113
    handle_error(command, mysql_errno(con), mysql_error(con),
 
4114
                 mysql_sqlstate(con), ds);
3663
4115
    return 0; /* Not connected */
3664
4116
  }
3665
4117
 
3670
4122
 
3671
4123
 
3672
4124
/*
3673
 
  Open a new connection to DRIZZLE Server with the parameters
 
4125
  Open a new connection to MySQL Server with the parameters
3674
4126
  specified. Make the new connection the current connection.
3675
4127
 
3676
4128
  SYNOPSIS
3677
4129
  do_connect()
3678
 
  q         called command
 
4130
  q            called command
3679
4131
 
3680
4132
  DESCRIPTION
3681
4133
  connect(<name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]]);
3689
4141
  <port> - server port
3690
4142
  <sock> - server socket
3691
4143
  <opts> - options to use for the connection
3692
 
  * SSL - use SSL if available
3693
 
  * COMPRESS - use compression if available
3694
 
 
3695
 
  */
3696
 
 
3697
 
static void do_connect(struct st_command *command)
 
4144
   * SSL - use SSL if available
 
4145
   * COMPRESS - use compression if available
 
4146
 
 
4147
*/
 
4148
 
 
4149
void do_connect(struct st_command *command)
3698
4150
{
3699
4151
  int con_port= opt_port;
3700
 
  const char *con_options;
3701
 
  bool con_ssl= 0, con_compress= 0;
 
4152
  char *con_options;
 
4153
  my_bool con_ssl= 0, con_compress= 0;
3702
4154
  struct st_connection* con_slot;
3703
4155
 
3704
 
  string ds_connection_name;
3705
 
  string ds_host;
3706
 
  string ds_user;
3707
 
  string ds_password;
3708
 
  string ds_database;
3709
 
  string ds_port;
3710
 
  string ds_sock;
3711
 
  string ds_options;
 
4156
  static DYNAMIC_STRING ds_connection_name;
 
4157
  static DYNAMIC_STRING ds_host;
 
4158
  static DYNAMIC_STRING ds_user;
 
4159
  static DYNAMIC_STRING ds_password;
 
4160
  static DYNAMIC_STRING ds_database;
 
4161
  static DYNAMIC_STRING ds_port;
 
4162
  static DYNAMIC_STRING ds_sock;
 
4163
  static DYNAMIC_STRING ds_options;
3712
4164
  const struct command_arg connect_args[] = {
3713
 
    { "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3714
 
    { "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3715
 
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
3716
 
    { "passsword", ARG_STRING, false, &ds_password, "Password used when connecting" },
3717
 
    { "database", ARG_STRING, false, &ds_database, "Database to select after connect" },
3718
 
    { "port", ARG_STRING, false, &ds_port, "Port to connect to" },
3719
 
    { "socket", ARG_STRING, false, &ds_sock, "Socket to connect with" },
3720
 
    { "options", ARG_STRING, false, &ds_options, "Options to use while connecting" }
 
4165
    { "connection name", ARG_STRING, TRUE, &ds_connection_name, "Name of the connection" },
 
4166
    { "host", ARG_STRING, TRUE, &ds_host, "Host to connect to" },
 
4167
    { "user", ARG_STRING, FALSE, &ds_user, "User to connect as" },
 
4168
    { "passsword", ARG_STRING, FALSE, &ds_password, "Password used when connecting" },
 
4169
    { "database", ARG_STRING, FALSE, &ds_database, "Database to select after connect" },
 
4170
    { "port", ARG_STRING, FALSE, &ds_port, "Port to connect to" },
 
4171
    { "socket", ARG_STRING, FALSE, &ds_sock, "Socket to connect with" },
 
4172
    { "options", ARG_STRING, FALSE, &ds_options, "Options to use while connecting" }
3721
4173
  };
3722
4174
 
 
4175
  DBUG_ENTER("do_connect");
 
4176
  DBUG_PRINT("enter",("connect: %s", command->first_argument));
3723
4177
 
3724
4178
  strip_parentheses(command);
3725
4179
  check_command_args(command, command->first_argument, connect_args,
3727
4181
                     ',');
3728
4182
 
3729
4183
  /* Port */
3730
 
  if (ds_port.length())
 
4184
  if (ds_port.length)
3731
4185
  {
3732
 
    con_port= atoi(ds_port.c_str());
 
4186
    con_port= atoi(ds_port.str);
3733
4187
    if (con_port == 0)
3734
 
      die("Illegal argument for port: '%s'", ds_port.c_str());
 
4188
      die("Illegal argument for port: '%s'", ds_port.str);
3735
4189
  }
3736
4190
 
3737
4191
  /* Sock */
3738
 
  if (!ds_sock.empty())
 
4192
  if (ds_sock.length)
3739
4193
  {
3740
4194
    /*
3741
4195
      If the socket is specified just as a name without path
3742
4196
      append tmpdir in front
3743
4197
    */
3744
 
    if (*ds_sock.c_str() != FN_LIBCHAR)
 
4198
    if (*ds_sock.str != FN_LIBCHAR)
3745
4199
    {
3746
4200
      char buff[FN_REFLEN];
3747
 
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3748
 
      ds_sock= buff;
 
4201
      fn_format(buff, ds_sock.str, TMPDIR, "", 0);
 
4202
      dynstr_set(&ds_sock, buff);
3749
4203
    }
3750
4204
  }
 
4205
  else
 
4206
  {
 
4207
    /* No socket specified, use default */
 
4208
    dynstr_set(&ds_sock, unix_sock);
 
4209
  }
 
4210
  DBUG_PRINT("info", ("socket: %s", ds_sock.str));
 
4211
 
3751
4212
 
3752
4213
  /* Options */
3753
 
  con_options= ds_options.c_str();
 
4214
  con_options= ds_options.str;
3754
4215
  while (*con_options)
3755
4216
  {
3756
 
    const char* end;
 
4217
    char* end;
3757
4218
    /* Step past any spaces in beginning of option*/
3758
4219
    while (*con_options && my_isspace(charset_info, *con_options))
3759
 
      con_options++;
 
4220
     con_options++;
3760
4221
    /* Find end of this option */
3761
4222
    end= con_options;
3762
4223
    while (*end && !my_isspace(charset_info, *end))
3766
4227
    else if (!strncmp(con_options, "COMPRESS", 8))
3767
4228
      con_compress= 1;
3768
4229
    else
3769
 
      die("Illegal option to connect: %.*s",
 
4230
      die("Illegal option to connect: %.*s", 
3770
4231
          (int) (end - con_options), con_options);
3771
4232
    /* Process next option */
3772
4233
    con_options= end;
3773
4234
  }
3774
4235
 
3775
 
  if (find_connection_by_name(ds_connection_name.c_str()))
3776
 
    die("Connection %s already exists", ds_connection_name.c_str());
3777
 
 
 
4236
  if (find_connection_by_name(ds_connection_name.str))
 
4237
    die("Connection %s already exists", ds_connection_name.str);
 
4238
    
3778
4239
  if (next_con != connections_end)
3779
 
  {
3780
4240
    con_slot= next_con;
3781
 
  }
3782
4241
  else
3783
4242
  {
3784
4243
    if (!(con_slot= find_connection_by_name("-closed_connection-")))
3786
4245
          (int) (sizeof(connections)/sizeof(struct st_connection)));
3787
4246
  }
3788
4247
 
3789
 
  if (!drizzle_create(&con_slot->drizzle))
3790
 
    die("Failed on drizzle_create()");
 
4248
#ifdef EMBEDDED_LIBRARY
 
4249
  con_slot->query_done= 1;
 
4250
#endif
 
4251
  if (!mysql_init(&con_slot->mysql))
 
4252
    die("Failed on mysql_init()");
3791
4253
  if (opt_compress || con_compress)
3792
 
    drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NULL);
3793
 
  drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
4254
    mysql_options(&con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
 
4255
  mysql_options(&con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
 
4256
  mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_NAME,
 
4257
                charset_info->csname);
 
4258
  int opt_protocol= MYSQL_PROTOCOL_TCP;
 
4259
  mysql_options(&con_slot->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
4260
  if (opt_charsets_dir)
 
4261
    mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
 
4262
                  opt_charsets_dir);
3794
4263
 
3795
4264
  /* Use default db name */
3796
 
  if (ds_database.length() == 0)
3797
 
    ds_database= opt_db;
 
4265
  if (ds_database.length == 0)
 
4266
    dynstr_set(&ds_database, opt_db);
3798
4267
 
3799
4268
  /* Special database to allow one to connect without a database name */
3800
 
  if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
3801
 
    ds_database= "";
 
4269
  if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
 
4270
    dynstr_set(&ds_database, "");
3802
4271
 
3803
 
  if (connect_n_handle_errors(command, &con_slot->drizzle,
3804
 
                              ds_host.c_str(),ds_user.c_str(),
3805
 
                              ds_password.c_str(), ds_database.c_str(),
3806
 
                              con_port, ds_sock.c_str()))
 
4272
  if (connect_n_handle_errors(command, &con_slot->mysql,
 
4273
                              ds_host.str,ds_user.str,
 
4274
                              ds_password.str, ds_database.str,
 
4275
                              con_port, ds_sock.str))
3807
4276
  {
3808
 
    if (!(con_slot->name= strdup(ds_connection_name.c_str())))
 
4277
    DBUG_PRINT("info", ("Inserting connection %s in connection pool",
 
4278
                        ds_connection_name.str));
 
4279
    if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3809
4280
      die("Out of memory");
3810
4281
    cur_con= con_slot;
3811
 
 
 
4282
    
3812
4283
    if (con_slot == next_con)
3813
4284
      next_con++; /* if we used the next_con slot, advance the pointer */
3814
4285
  }
3815
4286
 
3816
 
  /* Update $drizzle_get_server_version to that of current connection */
3817
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
4287
  /* Update $mysql_get_server_version to that of current connection */
 
4288
  var_set_mysql_get_server_version(&cur_con->mysql);
3818
4289
 
3819
 
  return;
 
4290
  dynstr_free(&ds_connection_name);
 
4291
  dynstr_free(&ds_host);
 
4292
  dynstr_free(&ds_user);
 
4293
  dynstr_free(&ds_password);
 
4294
  dynstr_free(&ds_database);
 
4295
  dynstr_free(&ds_port);
 
4296
  dynstr_free(&ds_sock);
 
4297
  dynstr_free(&ds_options);
 
4298
  DBUG_VOID_RETURN;
3820
4299
}
3821
4300
 
3822
4301
 
3823
 
static int do_done(struct st_command *command)
 
4302
int do_done(struct st_command *command)
3824
4303
{
3825
4304
  /* Check if empty block stack */
3826
4305
  if (cur_block == block_stack)
3853
4332
  SYNOPSIS
3854
4333
  do_block()
3855
4334
  cmd        Type of block
3856
 
  q         called command
 
4335
  q            called command
3857
4336
 
3858
4337
  DESCRIPTION
3859
4338
  if ([!]<expr>)
3873
4352
 
3874
4353
*/
3875
4354
 
3876
 
static void do_block(enum block_cmd cmd, struct st_command* command)
 
4355
void do_block(enum block_cmd cmd, struct st_command* command)
3877
4356
{
3878
4357
  char *p= command->first_argument;
3879
4358
  const char *expr_start, *expr_end;
3880
4359
  VAR v;
3881
4360
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
3882
 
  bool not_expr= false;
 
4361
  my_bool not_expr= FALSE;
 
4362
  DBUG_ENTER("do_block");
 
4363
  DBUG_PRINT("enter", ("%s", cmd_name));
3883
4364
 
3884
4365
  /* Check stack overflow */
3885
4366
  if (cur_block == block_stack_end)
3894
4375
    /* Inner block should be ignored too */
3895
4376
    cur_block++;
3896
4377
    cur_block->cmd= cmd;
3897
 
    cur_block->ok= false;
3898
 
    return;
 
4378
    cur_block->ok= FALSE;
 
4379
    DBUG_VOID_RETURN;
3899
4380
  }
3900
4381
 
3901
4382
  /* Parse and evaluate test expression */
3906
4387
  /* Check for !<expr> */
3907
4388
  if (*expr_start == '!')
3908
4389
  {
3909
 
    not_expr= true;
 
4390
    not_expr= TRUE;
3910
4391
    expr_start++; /* Step past the '!' */
3911
4392
  }
3912
4393
  /* Find ending ')' */
3926
4407
  /* Define inner block */
3927
4408
  cur_block++;
3928
4409
  cur_block->cmd= cmd;
3929
 
  cur_block->ok= (v.int_val ? true : false);
 
4410
  cur_block->ok= (v.int_val ? TRUE : FALSE);
3930
4411
 
3931
4412
  if (not_expr)
3932
4413
    cur_block->ok = !cur_block->ok;
3933
4414
 
 
4415
  DBUG_PRINT("info", ("OK: %d", cur_block->ok));
 
4416
 
3934
4417
  var_free(&v);
3935
 
  return;
 
4418
  DBUG_VOID_RETURN;
3936
4419
}
3937
4420
 
3938
4421
 
3939
 
static void do_delimiter(struct st_command* command)
 
4422
void do_delimiter(struct st_command* command)
3940
4423
{
3941
4424
  char* p= command->first_argument;
 
4425
  DBUG_ENTER("do_delimiter");
 
4426
  DBUG_PRINT("enter", ("first_argument: %s", command->first_argument));
3942
4427
 
3943
4428
  while (*p && my_isspace(charset_info, *p))
3944
4429
    p++;
3949
4434
  strmake(delimiter, p, sizeof(delimiter) - 1);
3950
4435
  delimiter_length= strlen(delimiter);
3951
4436
 
 
4437
  DBUG_PRINT("exit", ("delimiter: %s", delimiter));
3952
4438
  command->last_argument= p + delimiter_length;
3953
 
  return;
 
4439
  DBUG_VOID_RETURN;
3954
4440
}
3955
4441
 
3956
4442
 
3957
 
bool match_delimiter(int c, const char *delim, uint length)
 
4443
my_bool match_delimiter(int c, const char *delim, uint length)
3958
4444
{
3959
4445
  uint i;
3960
4446
  char tmp[MAX_DELIMITER_LENGTH];
3963
4449
    return 0;
3964
4450
 
3965
4451
  for (i= 1; i < length &&
3966
 
         (c= my_getc(cur_file->file)) == *(delim + i);
 
4452
         (c= my_getc(cur_file->file)) == *(delim + i);
3967
4453
       i++)
3968
4454
    tmp[i]= c;
3969
4455
 
3970
4456
  if (i == length)
3971
 
    return 1;          /* Found delimiter */
 
4457
    return 1;                                   /* Found delimiter */
3972
4458
 
3973
4459
  /* didn't find delimiter, push back things that we read */
3974
4460
  my_ungetc(c);
3978
4464
}
3979
4465
 
3980
4466
 
3981
 
static bool end_of_query(int c)
 
4467
my_bool end_of_query(int c)
3982
4468
{
3983
4469
  return match_delimiter(c, delimiter, delimiter_length);
3984
4470
}
4008
4494
 
4009
4495
*/
4010
4496
 
4011
 
static int read_line(char *buf, int size)
 
4497
int read_line(char *buf, int size)
4012
4498
{
4013
4499
  char c, last_quote= 0;
4014
4500
  char *p= buf, *buf_end= buf + size - 1;
4015
4501
  int skip_char= 0;
4016
4502
  enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
4017
4503
        R_COMMENT, R_LINE_START} state= R_LINE_START;
4018
 
 
 
4504
  DBUG_ENTER("read_line");
4019
4505
 
4020
4506
  start_lineno= cur_file->lineno;
 
4507
  DBUG_PRINT("info", ("Starting to read at lineno: %d", start_lineno));
4021
4508
  for (; p < buf_end ;)
4022
4509
  {
4023
4510
    skip_char= 0;
4027
4514
  found_eof:
4028
4515
      if (cur_file->file != stdin)
4029
4516
      {
4030
 
        my_fclose(cur_file->file, MYF(0));
 
4517
        my_fclose(cur_file->file, MYF(0));
4031
4518
        cur_file->file= 0;
4032
4519
      }
4033
 
      free((unsigned char*) cur_file->file_name);
 
4520
      my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
4034
4521
      cur_file->file_name= 0;
4035
4522
      if (cur_file == file_stack)
4036
4523
      {
4041
4528
          die("Missing end of block");
4042
4529
 
4043
4530
        *p= 0;
4044
 
        return(1);
 
4531
        DBUG_PRINT("info", ("end of file at line %d", cur_file->lineno));
 
4532
        DBUG_RETURN(1);
4045
4533
      }
4046
4534
      cur_file--;
4047
4535
      start_lineno= cur_file->lineno;
4062
4550
    case R_NORMAL:
4063
4551
      if (end_of_query(c))
4064
4552
      {
4065
 
        *p= 0;
4066
 
        return(0);
 
4553
        *p= 0;
 
4554
        DBUG_PRINT("exit", ("Found delimiter '%s' at line %d",
 
4555
                            delimiter, cur_file->lineno));
 
4556
        DBUG_RETURN(0);
4067
4557
      }
4068
4558
      else if ((c == '{' &&
4069
 
                (!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
4070
 
                                      (unsigned char*) buf, cmin((long)5, p - buf), 0) ||
4071
 
                 !my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
4072
 
                                      (unsigned char*) buf, cmin((long)2, p - buf), 0))))
 
4559
                (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
 
4560
                                      (uchar*) buf, min(5, p - buf), 0) ||
 
4561
                 !my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
 
4562
                                      (uchar*) buf, min(2, p - buf), 0))))
4073
4563
      {
4074
4564
        /* Only if and while commands can be terminated by { */
4075
4565
        *p++= c;
4076
 
        *p= 0;
4077
 
        return(0);
 
4566
        *p= 0;
 
4567
        DBUG_PRINT("exit", ("Found '{' indicating start of block at line %d",
 
4568
                            cur_file->lineno));
 
4569
        DBUG_RETURN(0);
4078
4570
      }
4079
4571
      else if (c == '\'' || c == '"' || c == '`')
4080
4572
      {
4081
4573
        last_quote= c;
4082
 
        state= R_Q;
 
4574
        state= R_Q;
4083
4575
      }
4084
4576
      break;
4085
4577
 
4087
4579
      if (c == '\n')
4088
4580
      {
4089
4581
        /* Comments are terminated by newline */
4090
 
        *p= 0;
4091
 
        return(0);
 
4582
        *p= 0;
 
4583
        DBUG_PRINT("exit", ("Found newline in comment at line: %d",
 
4584
                            cur_file->lineno));
 
4585
        DBUG_RETURN(0);
4092
4586
      }
4093
4587
      break;
4094
4588
 
4096
4590
      if (c == '#' || c == '-')
4097
4591
      {
4098
4592
        /* A # or - in the first position of the line - this is a comment */
4099
 
        state = R_COMMENT;
 
4593
        state = R_COMMENT;
4100
4594
      }
4101
4595
      else if (my_isspace(charset_info, c))
4102
4596
      {
4103
4597
        /* Skip all space at begining of line */
4104
 
        if (c == '\n')
 
4598
        if (c == '\n')
4105
4599
        {
4106
4600
          /* Query hasn't started yet */
4107
 
          start_lineno= cur_file->lineno;
 
4601
          start_lineno= cur_file->lineno;
 
4602
          DBUG_PRINT("info", ("Query hasn't started yet, start_lineno: %d",
 
4603
                              start_lineno));
4108
4604
        }
4109
 
        skip_char= 1;
 
4605
        skip_char= 1;
4110
4606
      }
4111
4607
      else if (end_of_query(c))
4112
4608
      {
4113
 
        *p= 0;
4114
 
        return(0);
 
4609
        *p= 0;
 
4610
        DBUG_PRINT("exit", ("Found delimiter '%s' at line: %d",
 
4611
                            delimiter, cur_file->lineno));
 
4612
        DBUG_RETURN(0);
4115
4613
      }
4116
4614
      else if (c == '}')
4117
4615
      {
4118
4616
        /* A "}" need to be by itself in the begining of a line to terminate */
4119
4617
        *p++= c;
4120
 
        *p= 0;
4121
 
        return(0);
 
4618
        *p= 0;
 
4619
        DBUG_PRINT("exit", ("Found '}' in begining of a line at line: %d",
 
4620
                            cur_file->lineno));
 
4621
        DBUG_RETURN(0);
4122
4622
      }
4123
4623
      else if (c == '\'' || c == '"' || c == '`')
4124
4624
      {
4125
4625
        last_quote= c;
4126
 
        state= R_Q;
 
4626
        state= R_Q;
4127
4627
      }
4128
4628
      else
4129
 
        state= R_NORMAL;
 
4629
        state= R_NORMAL;
4130
4630
      break;
4131
4631
 
4132
4632
    case R_Q:
4133
4633
      if (c == last_quote)
4134
 
        state= R_NORMAL;
 
4634
        state= R_NORMAL;
4135
4635
      else if (c == '\\')
4136
 
        state= R_SLASH_IN_Q;
 
4636
        state= R_SLASH_IN_Q;
4137
4637
      break;
4138
4638
 
4139
4639
    case R_SLASH_IN_Q:
4152
4652
      /* completed before we pass buf_end */
4153
4653
      if ((charlen > 1) && (p + charlen) <= buf_end)
4154
4654
      {
4155
 
        int i;
4156
 
        char* mb_start = p;
4157
 
 
4158
 
        *p++ = c;
4159
 
 
4160
 
        for (i= 1; i < charlen; i++)
4161
 
        {
4162
 
          if (feof(cur_file->file))
4163
 
            goto found_eof;
4164
 
          c= my_getc(cur_file->file);
4165
 
          *p++ = c;
4166
 
        }
4167
 
        if (! my_ismbchar(charset_info, mb_start, p))
4168
 
        {
4169
 
          /* It was not a multiline char, push back the characters */
4170
 
          /* We leave first 'c', i.e. pretend it was a normal char */
4171
 
          while (p > mb_start)
4172
 
            my_ungetc(*--p);
4173
 
        }
 
4655
        int i;
 
4656
        char* mb_start = p;
 
4657
 
 
4658
        *p++ = c;
 
4659
 
 
4660
        for (i= 1; i < charlen; i++)
 
4661
        {
 
4662
          if (feof(cur_file->file))
 
4663
            goto found_eof;
 
4664
          c= my_getc(cur_file->file);
 
4665
          *p++ = c;
 
4666
        }
 
4667
        if (! my_ismbchar(charset_info, mb_start, p))
 
4668
        {
 
4669
          /* It was not a multiline char, push back the characters */
 
4670
          /* We leave first 'c', i.e. pretend it was a normal char */
 
4671
          while (p > mb_start)
 
4672
            my_ungetc(*--p);
 
4673
        }
4174
4674
      }
4175
4675
      else
4176
4676
#endif
4177
 
        *p++= c;
 
4677
        *p++= c;
4178
4678
    }
4179
4679
  }
4180
 
  die("The input buffer is too small for this query.x\n"        \
 
4680
  die("The input buffer is too small for this query.x\n" \
4181
4681
      "check your query or increase MAX_QUERY and recompile");
4182
 
  return(0);
 
4682
  DBUG_RETURN(0);
4183
4683
}
4184
4684
 
4185
4685
 
4194
4694
 
4195
4695
*/
4196
4696
 
4197
 
static void convert_to_format_v1(char* query)
 
4697
void convert_to_format_v1(char* query)
4198
4698
{
4199
4699
  int last_c_was_quote= 0;
4200
4700
  char *p= query, *to= query;
4201
 
  char *end= strchr(query, '\0');
 
4701
  char *end= strend(query);
4202
4702
  char last_c;
4203
4703
 
4204
4704
  while (p <= end)
4237
4737
 
4238
4738
/*
4239
4739
  Check a command that is about to be sent (or should have been
4240
 
  sent if parsing was enabled) to DRIZZLE server for
 
4740
  sent if parsing was enabled) to mysql server for
4241
4741
  suspicious things and generate warnings.
4242
4742
*/
4243
4743
 
4244
 
static void scan_command_for_warnings(struct st_command *command)
 
4744
void scan_command_for_warnings(struct st_command *command)
4245
4745
{
4246
4746
  const char *ptr= command->query;
 
4747
  DBUG_ENTER("scan_command_for_warnings");
 
4748
  DBUG_PRINT("enter", ("query: %s", command->query));
4247
4749
 
4248
4750
  while(*ptr)
4249
4751
  {
4250
4752
    /*
4251
4753
      Look for query's that lines that start with a -- comment
4252
 
      and has a drizzletest command
 
4754
      and has a mysqltest command
4253
4755
    */
4254
4756
    if (ptr[0] == '\n' &&
4255
4757
        ptr[1] && ptr[1] == '-' &&
4268
4770
        end++;
4269
4771
      save= *end;
4270
4772
      *end= 0;
 
4773
      DBUG_PRINT("info", ("Checking '%s'", start));
4271
4774
      type= find_type(start, &command_typelib, 1+2);
4272
4775
      if (type)
4273
 
        warning_msg("Embedded drizzletest command '--%s' detected in "
 
4776
        warning_msg("Embedded mysqltest command '--%s' detected in "
4274
4777
                    "query '%s' was this intentional? ",
4275
4778
                    start, command->query);
4276
4779
      *end= save;
4278
4781
 
4279
4782
    ptr++;
4280
4783
  }
4281
 
  return;
 
4784
  DBUG_VOID_RETURN;
4282
4785
}
4283
4786
 
4284
4787
/*
4287
4790
  switching between different delimiters
4288
4791
*/
4289
4792
 
4290
 
static void check_eol_junk_line(const char *line)
 
4793
void check_eol_junk_line(const char *line)
4291
4794
{
4292
4795
  const char *p= line;
 
4796
  DBUG_ENTER("check_eol_junk_line");
 
4797
  DBUG_PRINT("enter", ("line: %s", line));
4293
4798
 
4294
4799
  /* Check for extra delimiter */
4295
4800
  if (*p && !strncmp(p, delimiter, delimiter_length))
4302
4807
      die("Missing delimiter");
4303
4808
    die("End of line junk detected: \"%s\"", p);
4304
4809
  }
4305
 
  return;
 
4810
  DBUG_VOID_RETURN;
4306
4811
}
4307
4812
 
4308
 
static void check_eol_junk(const char *eol)
 
4813
void check_eol_junk(const char *eol)
4309
4814
{
4310
4815
  const char *p= eol;
 
4816
  DBUG_ENTER("check_eol_junk");
 
4817
  DBUG_PRINT("enter", ("eol: %s", eol));
4311
4818
 
4312
4819
  /* Skip past all spacing chars and comments */
4313
4820
  while (*p && (my_isspace(charset_info, *p) || *p == '#' || *p == '\n'))
4330
4837
 
4331
4838
  check_eol_junk_line(p);
4332
4839
 
4333
 
  return;
 
4840
  DBUG_VOID_RETURN;
4334
4841
}
4335
4842
 
4336
4843
 
4339
4846
  Create a command from a set of lines
4340
4847
 
4341
4848
  SYNOPSIS
4342
 
  read_command()
4343
 
  command_ptr pointer where to return the new query
 
4849
    read_command()
 
4850
    command_ptr pointer where to return the new query
4344
4851
 
4345
4852
  DESCRIPTION
4346
 
  Converts lines returned by read_line into a command, this involves
4347
 
  parsing the first word in the read line to find the command type.
 
4853
    Converts lines returned by read_line into a command, this involves
 
4854
    parsing the first word in the read line to find the command type.
4348
4855
 
4349
4856
  A -- comment may contain a valid query as the first word after the
4350
4857
  comment start. Thus it's always checked to see if that is the case.
4355
4862
#define MAX_QUERY (256*1024*2) /* 256K -- a test in sp-big is >128K */
4356
4863
static char read_command_buf[MAX_QUERY];
4357
4864
 
4358
 
static int read_command(struct st_command** command_ptr)
 
4865
int read_command(struct st_command** command_ptr)
4359
4866
{
4360
4867
  char *p= read_command_buf;
4361
4868
  struct st_command* command;
4362
 
 
 
4869
  DBUG_ENTER("read_command");
4363
4870
 
4364
4871
  if (parser.current_line < parser.read_lines)
4365
4872
  {
4366
 
    *command_ptr= q_lines[parser.current_line];
4367
 
    return(0);
 
4873
    get_dynamic(&q_lines, (uchar*) command_ptr, parser.current_line) ;
 
4874
    DBUG_RETURN(0);
4368
4875
  }
4369
4876
  if (!(*command_ptr= command=
4370
4877
        (struct st_command*) my_malloc(sizeof(*command),
4371
 
                                       MYF(MY_WME|MY_ZEROFILL))))
4372
 
    die(NULL);
4373
 
  q_lines.push_back(command);
 
4878
                                       MYF(MY_WME|MY_ZEROFILL))) ||
 
4879
      insert_dynamic(&q_lines, (uchar*) &command))
 
4880
    die(NullS);
4374
4881
  command->type= Q_UNKNOWN;
4375
4882
 
4376
4883
  read_command_buf[0]= 0;
4377
4884
  if (read_line(read_command_buf, sizeof(read_command_buf)))
4378
4885
  {
4379
4886
    check_eol_junk(read_command_buf);
4380
 
    return(1);
 
4887
    DBUG_RETURN(1);
4381
4888
  }
4382
4889
 
4383
4890
  convert_to_format_v1(read_command_buf);
4384
4891
 
 
4892
  DBUG_PRINT("info", ("query: %s", read_command_buf));
4385
4893
  if (*p == '#')
4386
4894
  {
4387
4895
    command->type= Q_COMMENT;
4404
4912
  while (*p && !my_isspace(charset_info, *p) && *p != '(')
4405
4913
    p++;
4406
4914
  command->first_word_len= (uint) (p - command->query);
 
4915
  DBUG_PRINT("info", ("first_word: %.*s",
 
4916
                      command->first_word_len, command->query));
4407
4917
 
4408
4918
  /* Skip spaces between command and first argument */
4409
4919
  while (*p && my_isspace(charset_info, *p))
4410
4920
    p++;
4411
4921
  command->first_argument= p;
4412
4922
 
4413
 
  command->end= strchr(command->query, '\0');
 
4923
  command->end= strend(command->query);
4414
4924
  command->query_len= (command->end - command->query);
4415
4925
  parser.read_lines++;
4416
 
  return(0);
 
4926
  DBUG_RETURN(0);
4417
4927
}
4418
4928
 
4419
4929
 
4421
4931
{
4422
4932
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
4423
4933
   0, 0, 0, 0, 0, 0},
4424
 
  {"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
4425
 
   (char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4934
  {"basedir", 'b', "Basedir for tests.", (uchar**) &opt_basedir,
 
4935
   (uchar**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4426
4936
  {"character-sets-dir", OPT_CHARSETS_DIR,
4427
 
   "Directory where character sets are.", (char**) &opt_charsets_dir,
4428
 
   (char**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4937
   "Directory where character sets are.", (uchar**) &opt_charsets_dir,
 
4938
   (uchar**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4429
4939
  {"compress", 'C', "Use the compressed server/client protocol.",
4430
 
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
4940
   (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
4431
4941
   0, 0, 0},
4432
 
  {"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
 
4942
  {"cursor-protocol", OPT_CURSOR_PROTOCOL, "Use cursors for prepared statements.",
 
4943
   (uchar**) &cursor_protocol, (uchar**) &cursor_protocol, 0,
 
4944
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4945
  {"database", 'D', "Database to use.", (uchar**) &opt_db, (uchar**) &opt_db, 0,
4433
4946
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4947
#ifdef DBUG_OFF
 
4948
  {"debug", '#', "This is a non-debug version. Catch this and exit",
 
4949
   0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
4950
#else
 
4951
  {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
 
4952
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
4953
#endif
4434
4954
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
4435
 
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
 
4955
   (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
4436
4956
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4437
4957
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
4438
 
   (char**) &debug_info_flag, (char**) &debug_info_flag,
 
4958
   (uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
4439
4959
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4440
 
  {"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
 
4960
  {"host", 'h', "Connect to host.", (uchar**) &opt_host, (uchar**) &opt_host, 0,
4441
4961
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4442
 
  {"include", 'i', "Include SQL before each test case.", (char**) &opt_include,
4443
 
   (char**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4444
 
  {"logdir", OPT_LOG_DIR, "Directory for log files", (char**) &opt_logdir,
4445
 
   (char**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4962
  {"include", 'i', "Include SQL before each test case.", (uchar**) &opt_include,
 
4963
   (uchar**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4964
  {"logdir", OPT_LOG_DIR, "Directory for log files", (uchar**) &opt_logdir,
 
4965
   (uchar**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4446
4966
  {"mark-progress", OPT_MARK_PROGRESS,
4447
4967
   "Write linenumber and elapsed time to <testname>.progress ",
4448
 
   (char**) &opt_mark_progress, (char**) &opt_mark_progress, 0,
 
4968
   (uchar**) &opt_mark_progress, (uchar**) &opt_mark_progress, 0,
4449
4969
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4450
4970
  {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
4451
4971
   "Max number of connection attempts when connecting to server",
4452
 
   (char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
 
4972
   (uchar**) &opt_max_connect_retries, (uchar**) &opt_max_connect_retries, 0,
4453
4973
   GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
4454
4974
  {"password", 'p', "Password to use when connecting to server.",
4455
4975
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4456
4976
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
4457
 
   "order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
4458
 
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
4459
 
   (char**) &opt_port,
4460
 
   (char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4461
 
  {"quiet", 's', "Suppress all normal output.", (char**) &silent,
4462
 
   (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4977
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
 
4978
#if MYSQL_PORT_DEFAULT == 0
 
4979
   "/etc/services, "
 
4980
#endif
 
4981
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
 
4982
   (uchar**) &opt_port,
 
4983
   (uchar**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4984
  {"protocol", OPT_MYSQL_PROTOCOL,
 
4985
    "The protocol of connection (tcp,socket,pipe,memory).",
 
4986
    0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4987
  {"ps-protocol", OPT_PS_PROTOCOL, "Use prepared statements protocol for communication",
 
4988
   (uchar**) &ps_protocol, (uchar**) &ps_protocol, 0,
 
4989
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4990
  {"quiet", 's', "Suppress all normal output.", (uchar**) &silent,
 
4991
   (uchar**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4463
4992
  {"record", 'r', "Record output of test_file into result file.",
4464
4993
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
4465
4994
  {"result-file", 'R', "Read/Store result from/in this file.",
4466
 
   (char**) &result_file_name, (char**) &result_file_name, 0,
 
4995
   (uchar**) &result_file_name, (uchar**) &result_file_name, 0,
4467
4996
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4468
4997
  {"server-arg", 'A', "Send option value to embedded server as a parameter.",
4469
4998
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4470
4999
  {"server-file", 'F', "Read embedded server arguments from file.",
4471
5000
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4472
5001
  {"silent", 's', "Suppress all normal output. Synonym for --quiet.",
4473
 
   (char**) &silent, (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
5002
   (uchar**) &silent, (uchar**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4474
5003
  {"sleep", 'T', "Sleep always this many seconds on sleep commands.",
4475
 
   (char**) &opt_sleep, (char**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
4476
 
   0, 0, 0},
 
5004
   (uchar**) &opt_sleep, (uchar**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
 
5005
   0, 0, 0},
 
5006
  {"socket", 'S', "Socket file to use for connection.",
 
5007
   (uchar**) &unix_sock, (uchar**) &unix_sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
 
5008
   0, 0, 0},
 
5009
  {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select",
 
5010
   (uchar**) &sp_protocol, (uchar**) &sp_protocol, 0,
 
5011
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4477
5012
  {"tail-lines", OPT_TAIL_LINES,
4478
5013
   "Number of lines of the resul to include in a failure report",
4479
 
   (char**) &opt_tail_lines, (char**) &opt_tail_lines, 0,
 
5014
   (uchar**) &opt_tail_lines, (uchar**) &opt_tail_lines, 0,
4480
5015
   GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
4481
5016
  {"test-file", 'x', "Read test from/in this file (default stdin).",
4482
5017
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4484
5019
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4485
5020
  {"tmpdir", 't', "Temporary directory where sockets are put.",
4486
5021
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4487
 
  {"user", 'u', "User for login.", (char**) &opt_user, (char**) &opt_user, 0,
 
5022
  {"user", 'u', "User for login.", (uchar**) &opt_user, (uchar**) &opt_user, 0,
4488
5023
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4489
 
  {"verbose", 'v', "Write more.", (char**) &verbose, (char**) &verbose, 0,
 
5024
  {"verbose", 'v', "Write more.", (uchar**) &verbose, (uchar**) &verbose, 0,
4490
5025
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4491
5026
  {"version", 'V', "Output version information and exit.",
4492
5027
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
5028
  {"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select",
 
5029
   (uchar**) &view_protocol, (uchar**) &view_protocol, 0,
 
5030
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4493
5031
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
4494
5032
};
4495
5033
 
4496
5034
 
4497
 
static void print_version(void)
 
5035
#include <help_start.h>
 
5036
 
 
5037
void print_version(void)
4498
5038
{
4499
5039
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4500
 
         drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
5040
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
4501
5041
}
4502
5042
 
4503
 
static void usage(void)
 
5043
void usage()
4504
5044
{
4505
5045
  print_version();
4506
5046
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4507
5047
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4508
 
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
 
5048
  printf("Runs a test against the mysql server and compares output with a results file.\n\n");
4509
5049
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4510
5050
  my_print_help(my_long_options);
4511
5051
  printf("  --no-defaults       Don't read default options from any options file.\n");
4512
5052
  my_print_variables(my_long_options);
4513
5053
}
4514
5054
 
 
5055
#include <help_end.h>
 
5056
 
 
5057
 
4515
5058
/*
4516
5059
  Read arguments for embedded server and put them into
4517
5060
  embedded_server_args[]
4518
5061
*/
4519
5062
 
4520
 
static void read_embedded_server_arguments(const char *name)
 
5063
void read_embedded_server_arguments(const char *name)
4521
5064
{
4522
5065
  char argument[1024],buff[FN_REFLEN], *str=0;
4523
5066
  FILE *file;
4524
5067
 
4525
5068
  if (!test_if_hard_path(name))
4526
5069
  {
4527
 
    strxmov(buff, opt_basedir, name, NULL);
 
5070
    strxmov(buff, opt_basedir, name, NullS);
4528
5071
    name=buff;
4529
5072
  }
4530
5073
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
4532
5075
  if (!embedded_server_arg_count)
4533
5076
  {
4534
5077
    embedded_server_arg_count=1;
4535
 
    embedded_server_args[0]= (char*) "";    /* Progname */
 
5078
    embedded_server_args[0]= (char*) "";                /* Progname */
4536
5079
  }
4537
 
  if (!(file=my_fopen(buff, O_RDONLY, MYF(MY_WME))))
 
5080
  if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4538
5081
    die("Failed to open file '%s'", buff);
4539
5082
 
4540
5083
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4541
 
         (str=fgets(argument,sizeof(argument), file)))
 
5084
         (str=fgets(argument,sizeof(argument), file)))
4542
5085
  {
4543
 
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
 
5086
    *(strend(str)-1)=0;                         /* Remove end newline */
4544
5087
    if (!(embedded_server_args[embedded_server_arg_count]=
4545
 
          (char*) my_strdup(str,MYF(MY_WME))))
 
5088
          (char*) my_strdup(str,MYF(MY_WME))))
4546
5089
    {
4547
5090
      my_fclose(file,MYF(0));
4548
5091
      die("Out of memory");
4558
5101
}
4559
5102
 
4560
5103
 
4561
 
static bool
 
5104
static my_bool
4562
5105
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
4563
 
               char *argument)
 
5106
               char *argument)
4564
5107
{
4565
5108
  switch(optid) {
 
5109
  case '#':
 
5110
#ifndef DBUG_OFF
 
5111
    DBUG_PUSH(argument ? argument : "d:t:S:i:O,/tmp/mysqltest.trace");
 
5112
    debug_check_flag= 1;
 
5113
#endif
 
5114
    break;
4566
5115
  case 'r':
4567
5116
    record = 1;
4568
5117
    break;
4571
5120
    char buff[FN_REFLEN];
4572
5121
    if (!test_if_hard_path(argument))
4573
5122
    {
4574
 
      strxmov(buff, opt_basedir, argument, NULL);
 
5123
      strxmov(buff, opt_basedir, argument, NullS);
4575
5124
      argument= buff;
4576
5125
    }
4577
5126
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4578
 
    assert(cur_file == file_stack && cur_file->file == 0);
 
5127
    DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
4579
5128
    if (!(cur_file->file=
4580
 
          my_fopen(buff, O_RDONLY, MYF(0))))
 
5129
          my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
4581
5130
      die("Could not open '%s' for reading: errno = %d", buff, errno);
4582
5131
    cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
4583
5132
    cur_file->lineno= 1;
4588
5137
    static char buff[FN_REFLEN];
4589
5138
    if (!test_if_hard_path(argument))
4590
5139
    {
4591
 
      strxmov(buff, opt_basedir, argument, NULL);
 
5140
      strxmov(buff, opt_basedir, argument, NullS);
4592
5141
      argument= buff;
4593
5142
    }
4594
5143
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4595
5144
    timer_file= buff;
4596
 
    unlink(timer_file);       /* Ignore error, may not exist */
 
5145
    unlink(timer_file);      /* Ignore error, may not exist */
4597
5146
    break;
4598
5147
  }
4599
5148
  case 'p':
4600
5149
    if (argument)
4601
5150
    {
4602
 
      free(opt_pass);
 
5151
      my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
4603
5152
      opt_pass= my_strdup(argument, MYF(MY_FAE));
4604
 
      while (*argument) *argument++= 'x';    /* Destroy argument */
 
5153
      while (*argument) *argument++= 'x';               /* Destroy argument */
4605
5154
      tty_password= 0;
4606
5155
    }
4607
5156
    else
4608
5157
      tty_password= 1;
4609
5158
    break;
4610
5159
  case 't':
4611
 
    my_stpncpy(TMPDIR, argument, sizeof(TMPDIR));
 
5160
    strnmov(TMPDIR, argument, sizeof(TMPDIR));
4612
5161
    break;
4613
5162
  case 'A':
4614
5163
    if (!embedded_server_arg_count)
4637
5186
}
4638
5187
 
4639
5188
 
4640
 
static int parse_args(int argc, char **argv)
 
5189
int parse_args(int argc, char **argv)
4641
5190
{
4642
5191
  load_defaults("my",load_default_groups,&argc,&argv);
4643
5192
  default_argv= argv;
4653
5202
  if (argc == 1)
4654
5203
    opt_db= *argv;
4655
5204
  if (tty_password)
4656
 
    opt_pass= get_tty_password(NULL);          /* purify tested */
 
5205
    opt_pass= get_tty_password(NullS);          /* purify tested */
4657
5206
  if (debug_info_flag)
4658
5207
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
4659
5208
  if (debug_check_flag)
4673
5222
  append - append to file instead of overwriting old file
4674
5223
*/
4675
5224
 
4676
 
void str_to_file2(const char *fname, const char *str, int size, bool append)
 
5225
void str_to_file2(const char *fname, char *str, int size, my_bool append)
4677
5226
{
4678
5227
  int fd;
4679
5228
  char buff[FN_REFLEN];
4680
5229
  int flags= O_WRONLY | O_CREAT;
4681
5230
  if (!test_if_hard_path(fname))
4682
5231
  {
4683
 
    strxmov(buff, opt_basedir, fname, NULL);
 
5232
    strxmov(buff, opt_basedir, fname, NullS);
4684
5233
    fname= buff;
4685
5234
  }
4686
5235
  fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4692
5241
    die("Could not open '%s' for writing: errno = %d", buff, errno);
4693
5242
  if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
4694
5243
    die("Could not find end of file '%s': errno = %d", buff, errno);
4695
 
  if (my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
 
5244
  if (my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP)))
4696
5245
    die("write failed");
4697
5246
  my_close(fd, MYF(0));
4698
5247
}
4707
5256
  size - size of content witten to file
4708
5257
*/
4709
5258
 
4710
 
void str_to_file(const char *fname, const char *str, int size)
 
5259
void str_to_file(const char *fname, char *str, int size)
4711
5260
{
4712
 
  str_to_file2(fname, str, size, false);
 
5261
  str_to_file2(fname, str, size, FALSE);
4713
5262
}
4714
5263
 
4715
5264
 
4716
 
void dump_result_to_log_file(const char *buf, int size)
 
5265
void dump_result_to_log_file(char *buf, int size)
4717
5266
{
4718
5267
  char log_file[FN_REFLEN];
4719
5268
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
4731
5280
                        opt_logdir, ".progress",
4732
5281
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4733
5282
                        MY_REPLACE_EXT),
4734
 
              ds_progress.c_str(), ds_progress.length());
 
5283
              ds_progress.str, ds_progress.length);
4735
5284
}
4736
5285
 
4737
5286
void dump_warning_messages(void)
4741
5290
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
4742
5291
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4743
5292
                        MY_REPLACE_EXT),
4744
 
              ds_warning_messages.c_str(), ds_warning_messages.length());
4745
 
}
4746
 
 
 
5293
              ds_warning_messages.str, ds_warning_messages.length);
 
5294
}
 
5295
 
 
5296
void check_regerr(my_regex_t* r, int err)
 
5297
{
 
5298
  char err_buf[1024];
 
5299
 
 
5300
  if (err)
 
5301
  {
 
5302
    my_regerror(err,r,err_buf,sizeof(err_buf));
 
5303
    die("Regex error: %s\n", err_buf);
 
5304
  }
 
5305
}
4747
5306
 
4748
5307
/*
4749
5308
  Append the result for one field to the dynamic string ds
4750
5309
*/
4751
5310
 
4752
 
static void append_field(string *ds, uint col_idx, const DRIZZLE_FIELD* field,
4753
 
                         const char* val, uint64_t len, bool is_null)
 
5311
void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
 
5312
                  const char* val, ulonglong len, my_bool is_null)
4754
5313
{
4755
5314
  if (col_idx < max_replace_column && replace_column[col_idx])
4756
5315
  {
4766
5325
  if (!display_result_vertically)
4767
5326
  {
4768
5327
    if (col_idx)
4769
 
      ds->append("\t");
4770
 
    replace_append_mem(ds, val, (int)len);
 
5328
      dynstr_append_mem(ds, "\t", 1);
 
5329
    replace_dynstr_append_mem(ds, val, (int)len);
4771
5330
  }
4772
5331
  else
4773
5332
  {
4774
 
    ds->append(field->name);
4775
 
    ds->append("\t");
4776
 
    replace_append_mem(ds, val, (int)len);
4777
 
    ds->append("\n");
 
5333
    dynstr_append(ds, field->name);
 
5334
    dynstr_append_mem(ds, "\t", 1);
 
5335
    replace_dynstr_append_mem(ds, val, (int)len);
 
5336
    dynstr_append_mem(ds, "\n", 1);
4778
5337
  }
4779
5338
}
4780
5339
 
4784
5343
  Values may be converted with 'replace_column'
4785
5344
*/
4786
5345
 
4787
 
static void append_result(string *ds, DRIZZLE_RES *res)
 
5346
void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
4788
5347
{
4789
 
  DRIZZLE_ROW row;
4790
 
  uint32_t num_fields= drizzle_num_fields(res);
4791
 
  const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
4792
 
  uint32_t *lengths;
 
5348
  MYSQL_ROW row;
 
5349
  uint num_fields= mysql_num_fields(res);
 
5350
  MYSQL_FIELD *fields= mysql_fetch_fields(res);
 
5351
  ulong *lengths;
4793
5352
 
4794
 
  while ((row = drizzle_fetch_row(res)))
 
5353
  while ((row = mysql_fetch_row(res)))
4795
5354
  {
4796
 
    uint32_t i;
4797
 
    lengths = drizzle_fetch_lengths(res);
 
5355
    uint i;
 
5356
    lengths = mysql_fetch_lengths(res);
4798
5357
    for (i = 0; i < num_fields; i++)
4799
5358
      append_field(ds, i, &fields[i],
4800
5359
                   (const char*)row[i], lengths[i], !row[i]);
4801
5360
    if (!display_result_vertically)
4802
 
      ds->append("\n");
4803
 
 
4804
 
  }
 
5361
      dynstr_append_mem(ds, "\n", 1);
 
5362
  }
 
5363
}
 
5364
 
 
5365
 
 
5366
/*
 
5367
  Append all results from ps execution to the dynamic string separated
 
5368
  with '\t'. Values may be converted with 'replace_column'
 
5369
*/
 
5370
 
 
5371
void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
 
5372
                        MYSQL_FIELD *fields, uint num_fields)
 
5373
{
 
5374
  MYSQL_BIND *my_bind;
 
5375
  my_bool *is_null;
 
5376
  ulong *length;
 
5377
  uint i;
 
5378
 
 
5379
  /* Allocate array with bind structs, lengths and NULL flags */
 
5380
  my_bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND),
 
5381
                                MYF(MY_WME | MY_FAE | MY_ZEROFILL));
 
5382
  length= (ulong*) my_malloc(num_fields * sizeof(ulong),
 
5383
                             MYF(MY_WME | MY_FAE));
 
5384
  is_null= (my_bool*) my_malloc(num_fields * sizeof(my_bool),
 
5385
                                MYF(MY_WME | MY_FAE));
 
5386
 
 
5387
  /* Allocate data for the result of each field */
 
5388
  for (i= 0; i < num_fields; i++)
 
5389
  {
 
5390
    uint max_length= fields[i].max_length + 1;
 
5391
    my_bind[i].buffer_type= MYSQL_TYPE_STRING;
 
5392
    my_bind[i].buffer= (char *)my_malloc(max_length, MYF(MY_WME | MY_FAE));
 
5393
    my_bind[i].buffer_length= max_length;
 
5394
    my_bind[i].is_null= &is_null[i];
 
5395
    my_bind[i].length= &length[i];
 
5396
 
 
5397
    DBUG_PRINT("bind", ("col[%d]: buffer_type: %d, buffer_length: %lu",
 
5398
                        i, my_bind[i].buffer_type, my_bind[i].buffer_length));
 
5399
  }
 
5400
 
 
5401
  if (mysql_stmt_bind_result(stmt, my_bind))
 
5402
    die("mysql_stmt_bind_result failed: %d: %s",
 
5403
        mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
 
5404
 
 
5405
  while (mysql_stmt_fetch(stmt) == 0)
 
5406
  {
 
5407
    for (i= 0; i < num_fields; i++)
 
5408
      append_field(ds, i, &fields[i], (const char *) my_bind[i].buffer,
 
5409
                   *my_bind[i].length, *my_bind[i].is_null);
 
5410
    if (!display_result_vertically)
 
5411
      dynstr_append_mem(ds, "\n", 1);
 
5412
  }
 
5413
 
 
5414
  if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
 
5415
    die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
 
5416
        mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
 
5417
 
 
5418
  for (i= 0; i < num_fields; i++)
 
5419
  {
 
5420
    /* Free data for output */
 
5421
    my_free(my_bind[i].buffer, MYF(MY_WME | MY_FAE));
 
5422
  }
 
5423
  /* Free array with bind structs, lengths and NULL flags */
 
5424
  my_free(my_bind    , MYF(MY_WME | MY_FAE));
 
5425
  my_free(length  , MYF(MY_WME | MY_FAE));
 
5426
  my_free(is_null , MYF(MY_WME | MY_FAE));
4805
5427
}
4806
5428
 
4807
5429
 
4809
5431
  Append metadata for fields to output
4810
5432
*/
4811
5433
 
4812
 
static void append_metadata(string *ds,
4813
 
                            const DRIZZLE_FIELD *field,
4814
 
                            uint num_fields)
 
5434
void append_metadata(DYNAMIC_STRING *ds,
 
5435
                     MYSQL_FIELD *field,
 
5436
                     uint num_fields)
4815
5437
{
4816
 
  const DRIZZLE_FIELD *field_end;
4817
 
  ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4818
 
             "Column_alias\tType\tLength\tMax length\tIs_null\t"
4819
 
             "Flags\tDecimals\tCharsetnr\n");
 
5438
  MYSQL_FIELD *field_end;
 
5439
  dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
 
5440
                "Column_alias\tType\tLength\tMax length\tIs_null\t"
 
5441
                "Flags\tDecimals\tCharsetnr\n");
4820
5442
 
4821
5443
  for (field_end= field+num_fields ;
4822
5444
       field < field_end ;
4823
5445
       field++)
4824
5446
  {
4825
 
    ds->append(field->catalog,
4826
 
               field->catalog_length);
4827
 
    ds->append("\t", 1);
4828
 
    ds->append(field->db, field->db_length);
4829
 
    ds->append("\t", 1);
4830
 
    ds->append(field->org_table,
4831
 
               field->org_table_length);
4832
 
    ds->append("\t", 1);
4833
 
    ds->append(field->table,
4834
 
               field->table_length);
4835
 
    ds->append("\t", 1);
4836
 
    ds->append(field->org_name,
4837
 
               field->org_name_length);
4838
 
    ds->append("\t", 1);
4839
 
    ds->append(field->name, field->name_length);
4840
 
    ds->append("\t", 1);
4841
 
    replace_append_uint(ds, field->type);
4842
 
    ds->append("\t", 1);
4843
 
    replace_append_uint(ds, field->length);
4844
 
    ds->append("\t", 1);
4845
 
    replace_append_uint(ds, field->max_length);
4846
 
    ds->append("\t", 1);
4847
 
    ds->append((char*) ((field->flags & NOT_NULL_FLAG) ?
4848
 
                        "N" : "Y"), 1);
4849
 
    ds->append("\t", 1);
4850
 
    replace_append_uint(ds, field->flags);
4851
 
    ds->append("\t", 1);
4852
 
    replace_append_uint(ds, field->decimals);
4853
 
    ds->append("\t", 1);
4854
 
    replace_append_uint(ds, field->charsetnr);
4855
 
    ds->append("\n", 1);
 
5447
    dynstr_append_mem(ds, field->catalog,
 
5448
                      field->catalog_length);
 
5449
    dynstr_append_mem(ds, "\t", 1);
 
5450
    dynstr_append_mem(ds, field->db, field->db_length);
 
5451
    dynstr_append_mem(ds, "\t", 1);
 
5452
    dynstr_append_mem(ds, field->org_table,
 
5453
                      field->org_table_length);
 
5454
    dynstr_append_mem(ds, "\t", 1);
 
5455
    dynstr_append_mem(ds, field->table,
 
5456
                      field->table_length);
 
5457
    dynstr_append_mem(ds, "\t", 1);
 
5458
    dynstr_append_mem(ds, field->org_name,
 
5459
                      field->org_name_length);
 
5460
    dynstr_append_mem(ds, "\t", 1);
 
5461
    dynstr_append_mem(ds, field->name, field->name_length);
 
5462
    dynstr_append_mem(ds, "\t", 1);
 
5463
    replace_dynstr_append_uint(ds, field->type);
 
5464
    dynstr_append_mem(ds, "\t", 1);
 
5465
    replace_dynstr_append_uint(ds, field->length);
 
5466
    dynstr_append_mem(ds, "\t", 1);
 
5467
    replace_dynstr_append_uint(ds, field->max_length);
 
5468
    dynstr_append_mem(ds, "\t", 1);
 
5469
    dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
 
5470
                                   "N" : "Y"), 1);
 
5471
    dynstr_append_mem(ds, "\t", 1);
 
5472
    replace_dynstr_append_uint(ds, field->flags);
 
5473
    dynstr_append_mem(ds, "\t", 1);
 
5474
    replace_dynstr_append_uint(ds, field->decimals);
 
5475
    dynstr_append_mem(ds, "\t", 1);
 
5476
    replace_dynstr_append_uint(ds, field->charsetnr);
 
5477
    dynstr_append_mem(ds, "\n", 1);
4856
5478
  }
4857
5479
}
4858
5480
 
4861
5483
  Append affected row count and other info to output
4862
5484
*/
4863
5485
 
4864
 
static void append_info(string *ds, uint64_t affected_rows,
4865
 
                        const char *info)
 
5486
void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows,
 
5487
                 const char *info)
4866
5488
{
4867
5489
  char buf[40], buff2[21];
4868
5490
  sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
4869
 
  ds->append(buf);
 
5491
  dynstr_append(ds, buf);
4870
5492
  if (info)
4871
5493
  {
4872
 
    ds->append("info: ");
4873
 
    ds->append(info);
4874
 
    ds->append("\n", 1);
 
5494
    dynstr_append(ds, "info: ");
 
5495
    dynstr_append(ds, info);
 
5496
    dynstr_append_mem(ds, "\n", 1);
4875
5497
  }
4876
5498
}
4877
5499
 
4880
5502
  Display the table headings with the names tab separated
4881
5503
*/
4882
5504
 
4883
 
static void append_table_headings(string *ds,
4884
 
                                  const DRIZZLE_FIELD *field,
4885
 
                                  uint num_fields)
 
5505
void append_table_headings(DYNAMIC_STRING *ds,
 
5506
                           MYSQL_FIELD *field,
 
5507
                           uint num_fields)
4886
5508
{
4887
5509
  uint col_idx;
4888
5510
  for (col_idx= 0; col_idx < num_fields; col_idx++)
4889
5511
  {
4890
5512
    if (col_idx)
4891
 
      ds->append("\t", 1);
4892
 
    replace_append(ds, field[col_idx].name);
 
5513
      dynstr_append_mem(ds, "\t", 1);
 
5514
    replace_dynstr_append(ds, field[col_idx].name);
4893
5515
  }
4894
 
  ds->append("\n", 1);
 
5516
  dynstr_append_mem(ds, "\n", 1);
4895
5517
}
4896
5518
 
4897
5519
/*
4901
5523
  Number of warnings appended to ds
4902
5524
*/
4903
5525
 
4904
 
static int append_warnings(string *ds, DRIZZLE *drizzle)
 
5526
int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
4905
5527
{
4906
5528
  uint count;
4907
 
  DRIZZLE_RES *warn_res;
4908
 
 
4909
 
 
4910
 
  if (!(count= drizzle_warning_count(drizzle)))
4911
 
    return(0);
 
5529
  MYSQL_RES *warn_res;
 
5530
  DBUG_ENTER("append_warnings");
 
5531
 
 
5532
  if (!(count= mysql_warning_count(mysql)))
 
5533
    DBUG_RETURN(0);
4912
5534
 
4913
5535
  /*
4914
5536
    If one day we will support execution of multi-statements
4915
5537
    through PS API we should not issue SHOW WARNINGS until
4916
5538
    we have not read all results...
4917
5539
  */
4918
 
  assert(!drizzle_more_results(drizzle));
4919
 
 
4920
 
  if (drizzle_real_query(drizzle, "SHOW WARNINGS", 13))
4921
 
    die("Error running query \"SHOW WARNINGS\": %s", drizzle_error(drizzle));
4922
 
 
4923
 
  if (!(warn_res= drizzle_store_result(drizzle)))
 
5540
  DBUG_ASSERT(!mysql_more_results(mysql));
 
5541
 
 
5542
  if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
 
5543
    die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql));
 
5544
 
 
5545
  if (!(warn_res= mysql_store_result(mysql)))
4924
5546
    die("Warning count is %u but didn't get any warnings",
4925
 
        count);
 
5547
        count);
4926
5548
 
4927
5549
  append_result(ds, warn_res);
4928
 
 
4929
 
  return(count);
 
5550
  mysql_free_result(warn_res);
 
5551
 
 
5552
  DBUG_PRINT("warnings", ("%s", ds->str));
 
5553
 
 
5554
  DBUG_RETURN(count);
4930
5555
}
4931
5556
 
4932
5557
 
4933
5558
/*
4934
 
  Run query using DRIZZLE C API
 
5559
  Run query using MySQL C API
4935
5560
 
4936
5561
  SYNOPSIS
4937
 
  run_query_normal()
4938
 
  drizzle  DRIZZLE handle
4939
 
  command  current command pointer
4940
 
  flags  flags indicating if we should SEND and/or REAP
4941
 
  query  query string to execute
4942
 
  query_len  length query string to execute
4943
 
  ds    output buffer where to store result form query
 
5562
    run_query_normal()
 
5563
    mysql       mysql handle
 
5564
    command     current command pointer
 
5565
    flags       flags indicating if we should SEND and/or REAP
 
5566
    query       query string to execute
 
5567
    query_len   length query string to execute
 
5568
    ds          output buffer where to store result form query
4944
5569
*/
4945
5570
 
4946
 
static void run_query_normal(struct st_connection *cn,
4947
 
                             struct st_command *command,
4948
 
                             int flags, char *query, int query_len,
4949
 
                             string *ds, string *ds_warnings)
 
5571
void run_query_normal(struct st_connection *cn, struct st_command *command,
 
5572
                      int flags, char *query, int query_len,
 
5573
                      DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4950
5574
{
4951
 
  DRIZZLE_RES *res= 0;
4952
 
  DRIZZLE *drizzle= &cn->drizzle;
 
5575
  MYSQL_RES *res= 0;
 
5576
  MYSQL *mysql= &cn->mysql;
4953
5577
  int err= 0, counter= 0;
 
5578
  DBUG_ENTER("run_query_normal");
 
5579
  DBUG_PRINT("enter",("flags: %d", flags));
 
5580
  DBUG_PRINT("enter", ("query: '%-.60s'", query));
4954
5581
 
4955
5582
  if (flags & QUERY_SEND_FLAG)
4956
5583
  {
4957
5584
    /*
4958
 
     * Send the query
4959
 
     */
 
5585
      Send the query
 
5586
    */
4960
5587
    if (do_send_query(cn, query, query_len, flags))
4961
5588
    {
4962
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4963
 
                   drizzle_sqlstate(drizzle), ds);
 
5589
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5590
                   mysql_sqlstate(mysql), ds);
4964
5591
      goto end;
4965
5592
    }
4966
5593
  }
 
5594
#ifdef EMBEDDED_LIBRARY
 
5595
  /*
 
5596
    Here we handle 'reap' command, so we need to check if the
 
5597
    query's thread was finished and probably wait
 
5598
  */
 
5599
  else if (flags & QUERY_REAP_FLAG)
 
5600
    wait_query_thread_end(cn);
 
5601
#endif /*EMBEDDED_LIBRARY*/
4967
5602
  if (!(flags & QUERY_REAP_FLAG))
4968
 
    return;
 
5603
    DBUG_VOID_RETURN;
4969
5604
 
4970
5605
  do
4971
5606
  {
4972
5607
    /*
4973
 
      When  on first result set, call drizzle_read_query_result to retrieve
 
5608
      When  on first result set, call mysql_read_query_result to retrieve
4974
5609
      answer to the query sent earlier
4975
5610
    */
4976
 
    if ((counter==0) && drizzle_read_query_result(drizzle))
 
5611
    if ((counter==0) && mysql_read_query_result(mysql))
4977
5612
    {
4978
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4979
 
                   drizzle_sqlstate(drizzle), ds);
 
5613
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5614
                   mysql_sqlstate(mysql), ds);
4980
5615
      goto end;
4981
5616
 
4982
5617
    }
4984
5619
    /*
4985
5620
      Store the result of the query if it will return any fields
4986
5621
    */
4987
 
    if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
 
5622
    if (mysql_field_count(mysql) && ((res= mysql_store_result(mysql)) == 0))
4988
5623
    {
4989
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4990
 
                   drizzle_sqlstate(drizzle), ds);
 
5624
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5625
                   mysql_sqlstate(mysql), ds);
4991
5626
      goto end;
4992
5627
    }
4993
5628
 
4994
5629
    if (!disable_result_log)
4995
5630
    {
4996
 
      uint64_t affected_rows= 0;    /* Ok to be undef if 'disable_info' is set */
 
5631
      ulonglong affected_rows= 0;    /* Ok to be undef if 'disable_info' is set */
4997
5632
 
4998
5633
      if (res)
4999
5634
      {
5000
 
        const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
5001
 
        uint num_fields= drizzle_num_fields(res);
 
5635
        MYSQL_FIELD *fields= mysql_fetch_fields(res);
 
5636
        uint num_fields= mysql_num_fields(res);
5002
5637
 
5003
 
        if (display_metadata)
 
5638
        if (display_metadata)
5004
5639
          append_metadata(ds, fields, num_fields);
5005
5640
 
5006
 
        if (!display_result_vertically)
5007
 
          append_table_headings(ds, fields, num_fields);
 
5641
        if (!display_result_vertically)
 
5642
          append_table_headings(ds, fields, num_fields);
5008
5643
 
5009
 
        append_result(ds, res);
 
5644
        append_result(ds, res);
5010
5645
      }
5011
5646
 
5012
5647
      /*
5013
 
        Need to call drizzle_affected_rows() before the "new"
 
5648
        Need to call mysql_affected_rows() before the "new"
5014
5649
        query to find the warnings
5015
5650
      */
5016
5651
      if (!disable_info)
5017
 
        affected_rows= drizzle_affected_rows(drizzle);
 
5652
        affected_rows= mysql_affected_rows(mysql);
5018
5653
 
5019
5654
      /*
5020
5655
        Add all warnings to the result. We can't do this if we are in
5021
5656
        the middle of processing results from multi-statement, because
5022
5657
        this will break protocol.
5023
5658
      */
5024
 
      if (!disable_warnings && !drizzle_more_results(drizzle))
 
5659
      if (!disable_warnings && !mysql_more_results(mysql))
5025
5660
      {
5026
 
        if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
5027
 
        {
5028
 
          ds->append("Warnings:\n", 10);
5029
 
          ds->append(ds_warnings->c_str(), ds_warnings->length());
5030
 
        }
 
5661
        if (append_warnings(ds_warnings, mysql) || ds_warnings->length)
 
5662
        {
 
5663
          dynstr_append_mem(ds, "Warnings:\n", 10);
 
5664
          dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
 
5665
        }
5031
5666
      }
5032
5667
 
5033
5668
      if (!disable_info)
5034
 
        append_info(ds, affected_rows, drizzle_info(drizzle));
 
5669
        append_info(ds, affected_rows, mysql_info(mysql));
5035
5670
    }
5036
5671
 
5037
5672
    if (res)
5038
5673
    {
5039
 
      drizzle_free_result(res);
 
5674
      mysql_free_result(res);
5040
5675
      res= 0;
5041
5676
    }
5042
5677
    counter++;
5043
 
  } while (!(err= drizzle_next_result(drizzle)));
 
5678
  } while (!(err= mysql_next_result(mysql)));
5044
5679
  if (err > 0)
5045
5680
  {
5046
 
    /* We got an error from drizzle_next_result, maybe expected */
5047
 
    handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5048
 
                 drizzle_sqlstate(drizzle), ds);
 
5681
    /* We got an error from mysql_next_result, maybe expected */
 
5682
    handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5683
                 mysql_sqlstate(mysql), ds);
5049
5684
    goto end;
5050
5685
  }
5051
 
  assert(err == -1); /* Successful and there are no more results */
 
5686
  DBUG_ASSERT(err == -1); /* Successful and there are no more results */
5052
5687
 
5053
5688
  /* If we come here the query is both executed and read successfully */
5054
5689
  handle_no_error(command);
5056
5691
end:
5057
5692
 
5058
5693
  /*
5059
 
    We save the return code (drizzle_errno(drizzle)) from the last call sent
5060
 
    to the server into the drizzletest builtin variable $drizzle_errno. This
 
5694
    We save the return code (mysql_errno(mysql)) from the last call sent
 
5695
    to the server into the mysqltest builtin variable $mysql_errno. This
5061
5696
    variable then can be used from the test case itself.
5062
5697
  */
5063
 
  var_set_errno(drizzle_errno(drizzle));
5064
 
  return;
 
5698
  var_set_errno(mysql_errno(mysql));
 
5699
  DBUG_VOID_RETURN;
5065
5700
}
5066
5701
 
5067
5702
 
5077
5712
  ds    - dynamic string which is used for output buffer
5078
5713
 
5079
5714
  NOTE
5080
 
  If there is an unexpected error this function will abort drizzletest
5081
 
  immediately.
 
5715
    If there is an unexpected error this function will abort mysqltest
 
5716
    immediately.
5082
5717
*/
5083
5718
 
5084
5719
void handle_error(struct st_command *command,
5085
5720
                  unsigned int err_errno, const char *err_error,
5086
 
                  const char *err_sqlstate, string *ds)
 
5721
                  const char *err_sqlstate, DYNAMIC_STRING *ds)
5087
5722
{
5088
5723
  uint i;
5089
5724
 
 
5725
  DBUG_ENTER("handle_error");
5090
5726
 
5091
5727
  if (command->require_file[0])
5092
5728
  {
5108
5744
  if (command->abort_on_error)
5109
5745
    die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
5110
5746
 
 
5747
  DBUG_PRINT("info", ("expected_errors.count: %d",
 
5748
                      command->expected_errors.count));
5111
5749
  for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
5112
5750
  {
5113
5751
    if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
5121
5759
        if (command->expected_errors.count == 1)
5122
5760
        {
5123
5761
          /* Only log error if there is one possible error */
5124
 
          ds->append("ERROR ", 6);
5125
 
          replace_append(ds, err_sqlstate);
5126
 
          ds->append(": ", 2);
5127
 
          replace_append(ds, err_error);
5128
 
          ds->append("\n",1);
 
5762
          dynstr_append_mem(ds, "ERROR ", 6);
 
5763
          replace_dynstr_append(ds, err_sqlstate);
 
5764
          dynstr_append_mem(ds, ": ", 2);
 
5765
          replace_dynstr_append(ds, err_error);
 
5766
          dynstr_append_mem(ds,"\n",1);
5129
5767
        }
5130
5768
        /* Don't log error if we may not get an error */
5131
5769
        else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5132
5770
                 (command->expected_errors.err[0].type == ERR_ERRNO &&
5133
5771
                  command->expected_errors.err[0].code.errnum != 0))
5134
 
          ds->append("Got one of the listed errors\n");
 
5772
          dynstr_append(ds,"Got one of the listed errors\n");
5135
5773
      }
5136
5774
      /* OK */
5137
 
      return;
 
5775
      DBUG_VOID_RETURN;
5138
5776
    }
5139
5777
  }
5140
5778
 
 
5779
  DBUG_PRINT("info",("i: %d  expected_errors: %d", i,
 
5780
                     command->expected_errors.count));
 
5781
 
5141
5782
  if (!disable_result_log)
5142
5783
  {
5143
 
    ds->append("ERROR ",6);
5144
 
    replace_append(ds, err_sqlstate);
5145
 
    ds->append(": ", 2);
5146
 
    replace_append(ds, err_error);
5147
 
    ds->append("\n", 1);
 
5784
    dynstr_append_mem(ds, "ERROR ",6);
 
5785
    replace_dynstr_append(ds, err_sqlstate);
 
5786
    dynstr_append_mem(ds, ": ", 2);
 
5787
    replace_dynstr_append(ds, err_error);
 
5788
    dynstr_append_mem(ds, "\n", 1);
5148
5789
  }
5149
5790
 
5150
5791
  if (i)
5156
5797
    else
5157
5798
      die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
5158
5799
          command->query, err_sqlstate, err_error,
5159
 
          command->expected_errors.err[0].code.sqlstate);
 
5800
          command->expected_errors.err[0].code.sqlstate);
5160
5801
  }
5161
5802
 
5162
 
  return;
 
5803
  DBUG_VOID_RETURN;
5163
5804
}
5164
5805
 
5165
5806
 
5176
5817
 
5177
5818
void handle_no_error(struct st_command *command)
5178
5819
{
5179
 
 
 
5820
  DBUG_ENTER("handle_no_error");
5180
5821
 
5181
5822
  if (command->expected_errors.err[0].type == ERR_ERRNO &&
5182
5823
      command->expected_errors.err[0].code.errnum != 0)
5193
5834
        command->query, command->expected_errors.err[0].code.sqlstate);
5194
5835
  }
5195
5836
 
5196
 
  return;
5197
 
}
 
5837
  DBUG_VOID_RETURN;
 
5838
}
 
5839
 
 
5840
 
 
5841
/*
 
5842
  Run query using prepared statement C API
 
5843
 
 
5844
  SYNPOSIS
 
5845
  run_query_stmt
 
5846
  mysql - mysql handle
 
5847
  command - currrent command pointer
 
5848
  query - query string to execute
 
5849
  query_len - length query string to execute
 
5850
  ds - output buffer where to store result form query
 
5851
 
 
5852
  RETURN VALUE
 
5853
  error - function will not return
 
5854
*/
 
5855
 
 
5856
void run_query_stmt(MYSQL *mysql, struct st_command *command,
 
5857
                    char *query, int query_len, DYNAMIC_STRING *ds,
 
5858
                    DYNAMIC_STRING *ds_warnings)
 
5859
{
 
5860
  MYSQL_RES *res= NULL;     /* Note that here 'res' is meta data result set */
 
5861
  MYSQL_STMT *stmt;
 
5862
  DYNAMIC_STRING ds_prepare_warnings;
 
5863
  DYNAMIC_STRING ds_execute_warnings;
 
5864
  DBUG_ENTER("run_query_stmt");
 
5865
  DBUG_PRINT("query", ("'%-.60s'", query));
 
5866
 
 
5867
  /*
 
5868
    Init a new stmt if it's not already one created for this connection
 
5869
  */
 
5870
  if(!(stmt= cur_con->stmt))
 
5871
  {
 
5872
    if (!(stmt= mysql_stmt_init(mysql)))
 
5873
      die("unable to init stmt structure");
 
5874
    cur_con->stmt= stmt;
 
5875
  }
 
5876
 
 
5877
  /* Init dynamic strings for warnings */
 
5878
  if (!disable_warnings)
 
5879
  {
 
5880
    init_dynamic_string(&ds_prepare_warnings, NULL, 0, 256);
 
5881
    init_dynamic_string(&ds_execute_warnings, NULL, 0, 256);
 
5882
  }
 
5883
 
 
5884
  /*
 
5885
    Prepare the query
 
5886
  */
 
5887
  if (mysql_stmt_prepare(stmt, query, query_len))
 
5888
  {
 
5889
    handle_error(command,  mysql_stmt_errno(stmt),
 
5890
                 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
 
5891
    goto end;
 
5892
  }
 
5893
 
 
5894
  /*
 
5895
    Get the warnings from mysql_stmt_prepare and keep them in a
 
5896
    separate string
 
5897
  */
 
5898
  if (!disable_warnings)
 
5899
    append_warnings(&ds_prepare_warnings, mysql);
 
5900
 
 
5901
  /*
 
5902
    No need to call mysql_stmt_bind_param() because we have no
 
5903
    parameter markers.
 
5904
  */
 
5905
 
 
5906
#if MYSQL_VERSION_ID >= 50000
 
5907
  if (cursor_protocol_enabled)
 
5908
  {
 
5909
    /*
 
5910
      Use cursor when retrieving result
 
5911
    */
 
5912
    ulong type= CURSOR_TYPE_READ_ONLY;
 
5913
    if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type))
 
5914
      die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
 
5915
          mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
 
5916
  }
 
5917
#endif
 
5918
 
 
5919
  /*
 
5920
    Execute the query
 
5921
  */
 
5922
  if (mysql_stmt_execute(stmt))
 
5923
  {
 
5924
    handle_error(command, mysql_stmt_errno(stmt),
 
5925
                 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
 
5926
    goto end;
 
5927
  }
 
5928
 
 
5929
  /*
 
5930
    When running in cursor_protocol get the warnings from execute here
 
5931
    and keep them in a separate string for later.
 
5932
  */
 
5933
  if (cursor_protocol_enabled && !disable_warnings)
 
5934
    append_warnings(&ds_execute_warnings, mysql);
 
5935
 
 
5936
  /*
 
5937
    We instruct that we want to update the "max_length" field in
 
5938
    mysql_stmt_store_result(), this is our only way to know how much
 
5939
    buffer to allocate for result data
 
5940
  */
 
5941
  {
 
5942
    my_bool one= 1;
 
5943
    if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one))
 
5944
      die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s",
 
5945
          mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
 
5946
  }
 
5947
 
 
5948
  /*
 
5949
    If we got here the statement succeeded and was expected to do so,
 
5950
    get data. Note that this can still give errors found during execution!
 
5951
    Store the result of the query if if will return any fields
 
5952
  */
 
5953
  if (mysql_stmt_field_count(stmt) && mysql_stmt_store_result(stmt))
 
5954
  {
 
5955
    handle_error(command, mysql_stmt_errno(stmt),
 
5956
                 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
 
5957
    goto end;
 
5958
  }
 
5959
 
 
5960
  /* If we got here the statement was both executed and read successfully */
 
5961
  handle_no_error(command);
 
5962
  if (!disable_result_log)
 
5963
  {
 
5964
    /*
 
5965
      Not all statements creates a result set. If there is one we can
 
5966
      now create another normal result set that contains the meta
 
5967
      data. This set can be handled almost like any other non prepared
 
5968
      statement result set.
 
5969
    */
 
5970
    if ((res= mysql_stmt_result_metadata(stmt)) != NULL)
 
5971
    {
 
5972
      /* Take the column count from meta info */
 
5973
      MYSQL_FIELD *fields= mysql_fetch_fields(res);
 
5974
      uint num_fields= mysql_num_fields(res);
 
5975
 
 
5976
      if (display_metadata)
 
5977
        append_metadata(ds, fields, num_fields);
 
5978
 
 
5979
      if (!display_result_vertically)
 
5980
        append_table_headings(ds, fields, num_fields);
 
5981
 
 
5982
      append_stmt_result(ds, stmt, fields, num_fields);
 
5983
 
 
5984
      mysql_free_result(res);     /* Free normal result set with meta data */
 
5985
 
 
5986
      /* Clear prepare warnings */
 
5987
      dynstr_set(&ds_prepare_warnings, NULL);
 
5988
    }
 
5989
    else
 
5990
    {
 
5991
      /*
 
5992
        This is a query without resultset
 
5993
      */
 
5994
    }
 
5995
 
 
5996
    if (!disable_warnings)
 
5997
    {
 
5998
      /* Get the warnings from execute */
 
5999
 
 
6000
      /* Append warnings to ds - if there are any */
 
6001
      if (append_warnings(&ds_execute_warnings, mysql) ||
 
6002
          ds_execute_warnings.length ||
 
6003
          ds_prepare_warnings.length ||
 
6004
          ds_warnings->length)
 
6005
      {
 
6006
        dynstr_append_mem(ds, "Warnings:\n", 10);
 
6007
        if (ds_warnings->length)
 
6008
          dynstr_append_mem(ds, ds_warnings->str,
 
6009
                            ds_warnings->length);
 
6010
        if (ds_prepare_warnings.length)
 
6011
          dynstr_append_mem(ds, ds_prepare_warnings.str,
 
6012
                            ds_prepare_warnings.length);
 
6013
        if (ds_execute_warnings.length)
 
6014
          dynstr_append_mem(ds, ds_execute_warnings.str,
 
6015
                            ds_execute_warnings.length);
 
6016
      }
 
6017
    }
 
6018
 
 
6019
    if (!disable_info)
 
6020
      append_info(ds, mysql_affected_rows(mysql), mysql_info(mysql));
 
6021
 
 
6022
  }
 
6023
 
 
6024
end:
 
6025
  if (!disable_warnings)
 
6026
  {
 
6027
    dynstr_free(&ds_prepare_warnings);
 
6028
    dynstr_free(&ds_execute_warnings);
 
6029
  }
 
6030
 
 
6031
 
 
6032
  /* Close the statement if - no reconnect, need new prepare */
 
6033
  if (mysql->reconnect)
 
6034
  {
 
6035
    mysql_stmt_close(stmt);
 
6036
    cur_con->stmt= NULL;
 
6037
  }
 
6038
 
 
6039
  /*
 
6040
    We save the return code (mysql_stmt_errno(stmt)) from the last call sent
 
6041
    to the server into the mysqltest builtin variable $mysql_errno. This
 
6042
    variable then can be used from the test case itself.
 
6043
  */
 
6044
 
 
6045
  var_set_errno(mysql_stmt_errno(stmt));
 
6046
 
 
6047
  DBUG_VOID_RETURN;
 
6048
}
 
6049
 
 
6050
 
 
6051
 
 
6052
/*
 
6053
  Create a util connection if one does not already exists
 
6054
  and use that to run the query
 
6055
  This is done to avoid implict commit when creating/dropping objects such
 
6056
  as view, sp etc.
 
6057
*/
 
6058
 
 
6059
int util_query(MYSQL* org_mysql, const char* query){
 
6060
 
 
6061
  MYSQL* mysql;
 
6062
  DBUG_ENTER("util_query");
 
6063
 
 
6064
  if(!(mysql= cur_con->util_mysql))
 
6065
  {
 
6066
    int opt_protocol= MYSQL_PROTOCOL_TCP;
 
6067
    DBUG_PRINT("info", ("Creating util_mysql"));
 
6068
    if (!(mysql= mysql_init(mysql)))
 
6069
      die("Failed in mysql_init()");
 
6070
    mysql_options(mysql, MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
6071
 
 
6072
    /* enable local infile, in non-binary builds often disabled by default */
 
6073
    mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0);
 
6074
    safe_connect(mysql, "util", org_mysql->host, org_mysql->user,
 
6075
                 org_mysql->passwd, org_mysql->db, org_mysql->port);
 
6076
 
 
6077
    cur_con->util_mysql= mysql;
 
6078
  }
 
6079
 
 
6080
  return mysql_query(mysql, query);
 
6081
}
 
6082
 
5198
6083
 
5199
6084
 
5200
6085
/*
5201
6086
  Run query
5202
6087
 
5203
6088
  SYNPOSIS
5204
 
  run_query()
5205
 
  drizzle  DRIZZLE handle
5206
 
  command  currrent command pointer
 
6089
    run_query()
 
6090
     mysql      mysql handle
 
6091
     command    currrent command pointer
5207
6092
 
5208
6093
  flags control the phased/stages of query execution to be performed
5209
6094
  if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
5210
6095
  is on the result will be read - for regular query, both bits must be on
5211
6096
*/
5212
6097
 
5213
 
static void run_query(struct st_connection *cn,
5214
 
                      struct st_command *command,
5215
 
                      int flags)
 
6098
void run_query(struct st_connection *cn, struct st_command *command, int flags)
5216
6099
{
5217
 
  string *ds= NULL;
5218
 
  string *save_ds= NULL;
5219
 
  string ds_result;
5220
 
  string ds_sorted;
5221
 
  string ds_warnings;
5222
 
  string eval_query;
 
6100
  MYSQL *mysql= &cn->mysql;
 
6101
  DYNAMIC_STRING *ds;
 
6102
  DYNAMIC_STRING *save_ds= NULL;
 
6103
  DYNAMIC_STRING ds_result;
 
6104
  DYNAMIC_STRING ds_sorted;
 
6105
  DYNAMIC_STRING ds_warnings;
 
6106
  DYNAMIC_STRING eval_query;
5223
6107
  char *query;
5224
6108
  int query_len;
 
6109
  my_bool view_created= 0, sp_created= 0;
 
6110
  my_bool complete_query= ((flags & QUERY_SEND_FLAG) &&
 
6111
                           (flags & QUERY_REAP_FLAG));
 
6112
  DBUG_ENTER("run_query");
5225
6113
 
 
6114
  init_dynamic_string(&ds_warnings, NULL, 0, 256);
5226
6115
 
5227
6116
  /* Scan for warning before sending to server */
5228
6117
  scan_command_for_warnings(command);
5232
6121
  */
5233
6122
  if (command->type == Q_EVAL)
5234
6123
  {
5235
 
    do_eval(&eval_query, command->query, command->end, false);
5236
 
    query = strdup(eval_query.c_str());
5237
 
    query_len = eval_query.length();
 
6124
    init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
 
6125
    do_eval(&eval_query, command->query, command->end, FALSE);
 
6126
    query = eval_query.str;
 
6127
    query_len = eval_query.length;
5238
6128
  }
5239
6129
  else
5240
6130
  {
5250
6140
  */
5251
6141
  if (command->require_file[0])
5252
6142
  {
 
6143
    init_dynamic_string(&ds_result, "", 1024, 1024);
5253
6144
    ds= &ds_result;
5254
6145
  }
5255
6146
  else
5256
 
  {
5257
6147
    ds= &ds_res;
5258
 
  }
 
6148
 
5259
6149
  /*
5260
6150
    Log the query into the output buffer
5261
6151
  */
5262
6152
  if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5263
6153
  {
5264
 
    replace_append_mem(ds, query, query_len);
5265
 
    ds->append(delimiter, delimiter_length);
5266
 
    ds->append("\n");
 
6154
    replace_dynstr_append_mem(ds, query, query_len);
 
6155
    dynstr_append_mem(ds, delimiter, delimiter_length);
 
6156
    dynstr_append_mem(ds, "\n", 1);
 
6157
  }
 
6158
 
 
6159
  if (view_protocol_enabled &&
 
6160
      complete_query &&
 
6161
      match_re(&view_re, query))
 
6162
  {
 
6163
    /*
 
6164
      Create the query as a view.
 
6165
      Use replace since view can exist from a failed mysqltest run
 
6166
    */
 
6167
    DYNAMIC_STRING query_str;
 
6168
    init_dynamic_string(&query_str,
 
6169
                        "CREATE OR REPLACE VIEW mysqltest_tmp_v AS ",
 
6170
                        query_len+64, 256);
 
6171
    dynstr_append_mem(&query_str, query, query_len);
 
6172
    if (util_query(mysql, query_str.str))
 
6173
    {
 
6174
      /*
 
6175
        Failed to create the view, this is not fatal
 
6176
        just run the query the normal way
 
6177
      */
 
6178
      DBUG_PRINT("view_create_error",
 
6179
                 ("Failed to create view '%s': %d: %s", query_str.str,
 
6180
                  mysql_errno(mysql), mysql_error(mysql)));
 
6181
 
 
6182
      /* Log error to create view */
 
6183
      verbose_msg("Failed to create view '%s' %d: %s", query_str.str,
 
6184
                  mysql_errno(mysql), mysql_error(mysql));
 
6185
    }
 
6186
    else
 
6187
    {
 
6188
      /*
 
6189
        Yes, it was possible to create this query as a view
 
6190
      */
 
6191
      view_created= 1;
 
6192
      query= (char*)"SELECT * FROM mysqltest_tmp_v";
 
6193
      query_len = strlen(query);
 
6194
 
 
6195
      /*
 
6196
        Collect warnings from create of the view that should otherwise
 
6197
        have been produced when the SELECT was executed
 
6198
      */
 
6199
      append_warnings(&ds_warnings, cur_con->util_mysql);
 
6200
    }
 
6201
 
 
6202
    dynstr_free(&query_str);
 
6203
 
 
6204
  }
 
6205
 
 
6206
  if (sp_protocol_enabled &&
 
6207
      complete_query &&
 
6208
      match_re(&sp_re, query))
 
6209
  {
 
6210
    /*
 
6211
      Create the query as a stored procedure
 
6212
      Drop first since sp can exist from a failed mysqltest run
 
6213
    */
 
6214
    DYNAMIC_STRING query_str;
 
6215
    init_dynamic_string(&query_str,
 
6216
                        "DROP PROCEDURE IF EXISTS mysqltest_tmp_sp;",
 
6217
                        query_len+64, 256);
 
6218
    util_query(mysql, query_str.str);
 
6219
    dynstr_set(&query_str, "CREATE PROCEDURE mysqltest_tmp_sp()\n");
 
6220
    dynstr_append_mem(&query_str, query, query_len);
 
6221
    if (util_query(mysql, query_str.str))
 
6222
    {
 
6223
      /*
 
6224
        Failed to create the stored procedure for this query,
 
6225
        this is not fatal just run the query the normal way
 
6226
      */
 
6227
      DBUG_PRINT("sp_create_error",
 
6228
                 ("Failed to create sp '%s': %d: %s", query_str.str,
 
6229
                  mysql_errno(mysql), mysql_error(mysql)));
 
6230
 
 
6231
      /* Log error to create sp */
 
6232
      verbose_msg("Failed to create sp '%s' %d: %s", query_str.str,
 
6233
                  mysql_errno(mysql), mysql_error(mysql));
 
6234
 
 
6235
    }
 
6236
    else
 
6237
    {
 
6238
      sp_created= 1;
 
6239
 
 
6240
      query= (char*)"CALL mysqltest_tmp_sp()";
 
6241
      query_len = strlen(query);
 
6242
    }
 
6243
    dynstr_free(&query_str);
5267
6244
  }
5268
6245
 
5269
6246
  if (display_result_sorted)
5270
6247
  {
5271
6248
    /*
5272
 
      Collect the query output in a separate string
5273
 
      that can be sorted before it's added to the
5274
 
      global result string
 
6249
       Collect the query output in a separate string
 
6250
       that can be sorted before it's added to the
 
6251
       global result string
5275
6252
    */
 
6253
    init_dynamic_string(&ds_sorted, "", 1024, 1024);
5276
6254
    save_ds= ds; /* Remember original ds */
5277
6255
    ds= &ds_sorted;
5278
6256
  }
5279
6257
 
5280
6258
  /*
 
6259
    Find out how to run this query
 
6260
 
5281
6261
    Always run with normal C API if it's not a complete
5282
6262
    SEND + REAP
 
6263
 
 
6264
    If it is a '?' in the query it may be a SQL level prepared
 
6265
    statement already and we can't do it twice
5283
6266
  */
5284
 
  run_query_normal(cn, command, flags, query, query_len,
5285
 
                   ds, &ds_warnings);
 
6267
  if (ps_protocol_enabled &&
 
6268
      complete_query &&
 
6269
      match_re(&ps_re, query))
 
6270
    run_query_stmt(mysql, command, query, query_len, ds, &ds_warnings);
 
6271
  else
 
6272
    run_query_normal(cn, command, flags, query, query_len,
 
6273
                     ds, &ds_warnings);
5286
6274
 
5287
6275
  if (display_result_sorted)
5288
6276
  {
5289
6277
    /* Sort the result set and append it to result */
5290
 
    append_sorted(save_ds, &ds_sorted);
 
6278
    dynstr_append_sorted(save_ds, &ds_sorted);
5291
6279
    ds= save_ds;
 
6280
    dynstr_free(&ds_sorted);
 
6281
  }
 
6282
 
 
6283
  if (sp_created)
 
6284
  {
 
6285
    if (util_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp "))
 
6286
      die("Failed to drop sp: %d: %s", mysql_errno(mysql), mysql_error(mysql));
 
6287
  }
 
6288
 
 
6289
  if (view_created)
 
6290
  {
 
6291
    if (util_query(mysql, "DROP VIEW mysqltest_tmp_v "))
 
6292
      die("Failed to drop view: %d: %s",
 
6293
          mysql_errno(mysql), mysql_error(mysql));
5292
6294
  }
5293
6295
 
5294
6296
  if (command->require_file[0])
5300
6302
    check_require(ds, command->require_file);
5301
6303
  }
5302
6304
 
5303
 
  return;
5304
 
}
5305
 
 
5306
 
 
5307
 
/****************************************************************************/
5308
 
 
5309
 
static void get_command_type(struct st_command* command)
 
6305
  dynstr_free(&ds_warnings);
 
6306
  if (ds == &ds_result)
 
6307
    dynstr_free(&ds_result);
 
6308
  if (command->type == Q_EVAL)
 
6309
    dynstr_free(&eval_query);
 
6310
  DBUG_VOID_RETURN;
 
6311
}
 
6312
 
 
6313
/****************************************************************************/
 
6314
/*
 
6315
  Functions to detect different SQL statements
 
6316
*/
 
6317
 
 
6318
char *re_eprint(int err)
 
6319
{
 
6320
  static char epbuf[100];
 
6321
  size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL,
 
6322
                          epbuf, sizeof(epbuf));
 
6323
  assert(len <= sizeof(epbuf));
 
6324
  return(epbuf);
 
6325
}
 
6326
 
 
6327
void init_re_comp(my_regex_t *re, const char* str)
 
6328
{
 
6329
  int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB),
 
6330
                      &my_charset_latin1);
 
6331
  if (err)
 
6332
  {
 
6333
    char erbuf[100];
 
6334
    int len= my_regerror(err, re, erbuf, sizeof(erbuf));
 
6335
    die("error %s, %d/%d `%s'\n",
 
6336
        re_eprint(err), len, (int)sizeof(erbuf), erbuf);
 
6337
  }
 
6338
}
 
6339
 
 
6340
void init_re(void)
 
6341
{
 
6342
  /*
 
6343
    Filter for queries that can be run using the
 
6344
    MySQL Prepared Statements C API
 
6345
  */
 
6346
  const char *ps_re_str =
 
6347
    "^("
 
6348
    "[[:space:]]*REPLACE[[:space:]]|"
 
6349
    "[[:space:]]*INSERT[[:space:]]|"
 
6350
    "[[:space:]]*UPDATE[[:space:]]|"
 
6351
    "[[:space:]]*DELETE[[:space:]]|"
 
6352
    "[[:space:]]*SELECT[[:space:]]|"
 
6353
    "[[:space:]]*CREATE[[:space:]]+TABLE[[:space:]]|"
 
6354
    "[[:space:]]*DO[[:space:]]|"
 
6355
    "[[:space:]]*SET[[:space:]]+OPTION[[:space:]]|"
 
6356
    "[[:space:]]*DELETE[[:space:]]+MULTI[[:space:]]|"
 
6357
    "[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|"
 
6358
    "[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
 
6359
 
 
6360
  /*
 
6361
    Filter for queries that can be run using the
 
6362
    Stored procedures
 
6363
  */
 
6364
  const char *sp_re_str =ps_re_str;
 
6365
 
 
6366
  /*
 
6367
    Filter for queries that can be run as views
 
6368
  */
 
6369
  const char *view_re_str =
 
6370
    "^("
 
6371
    "[[:space:]]*SELECT[[:space:]])";
 
6372
 
 
6373
  init_re_comp(&ps_re, ps_re_str);
 
6374
  init_re_comp(&sp_re, sp_re_str);
 
6375
  init_re_comp(&view_re, view_re_str);
 
6376
}
 
6377
 
 
6378
 
 
6379
int match_re(my_regex_t *re, char *str)
 
6380
{
 
6381
  int err= my_regexec(re, str, (size_t)0, NULL, 0);
 
6382
 
 
6383
  if (err == 0)
 
6384
    return 1;
 
6385
  else if (err == REG_NOMATCH)
 
6386
    return 0;
 
6387
 
 
6388
  {
 
6389
    char erbuf[100];
 
6390
    int len= my_regerror(err, re, erbuf, sizeof(erbuf));
 
6391
    die("error %s, %d/%d `%s'\n",
 
6392
        re_eprint(err), len, (int)sizeof(erbuf), erbuf);
 
6393
  }
 
6394
  return 0;
 
6395
}
 
6396
 
 
6397
void free_re(void)
 
6398
{
 
6399
  my_regfree(&ps_re);
 
6400
  my_regfree(&sp_re);
 
6401
  my_regfree(&view_re);
 
6402
  my_regex_end();
 
6403
}
 
6404
 
 
6405
/****************************************************************************/
 
6406
 
 
6407
void get_command_type(struct st_command* command)
5310
6408
{
5311
6409
  char save;
5312
6410
  uint type;
5313
 
 
 
6411
  DBUG_ENTER("get_command_type");
5314
6412
 
5315
6413
  if (*command->query == '}')
5316
6414
  {
5317
6415
    command->type = Q_END_BLOCK;
5318
 
    return;
 
6416
    DBUG_VOID_RETURN;
5319
6417
  }
5320
6418
 
5321
6419
  save= command->query[command->first_word_len];
5324
6422
  command->query[command->first_word_len]= save;
5325
6423
  if (type > 0)
5326
6424
  {
5327
 
    command->type=(enum enum_commands) type;    /* Found command */
 
6425
    command->type=(enum enum_commands) type;            /* Found command */
5328
6426
 
5329
6427
    /*
5330
6428
      Look for case where "query" was explicitly specified to
5338
6436
  }
5339
6437
  else
5340
6438
  {
5341
 
    /* No drizzletest command matched */
 
6439
    /* No mysqltest command matched */
5342
6440
 
5343
6441
    if (command->type != Q_COMMENT_WITH_COMMAND)
5344
6442
    {
5345
 
      /* A query that will sent to drizzled */
 
6443
      /* A query that will sent to mysqld */
5346
6444
      command->type= Q_QUERY;
5347
6445
    }
5348
6446
    else
5349
6447
    {
5350
 
      /* -- comment that didn't contain a drizzletest command */
 
6448
      /* -- comment that didn't contain a mysqltest command */
5351
6449
      command->type= Q_COMMENT;
5352
 
      warning_msg("Suspicious command '--%s' detected, was this intentional? " \
 
6450
      warning_msg("Suspicious command '--%s' detected, was this intentional? "\
5353
6451
                  "Use # instead of -- to avoid this warning",
5354
6452
                  command->query);
5355
6453
 
5375
6473
  /* Set expected error on command */
5376
6474
  memcpy(&command->expected_errors, &saved_expected_errors,
5377
6475
         sizeof(saved_expected_errors));
 
6476
  DBUG_PRINT("info", ("There are %d expected errors",
 
6477
                      command->expected_errors.count));
5378
6478
  command->abort_on_error= (command->expected_errors.count == 0 &&
5379
6479
                            abort_on_error);
5380
6480
 
5381
 
  return;
 
6481
  DBUG_VOID_RETURN;
5382
6482
}
5383
6483
 
5384
6484
 
5392
6492
 
5393
6493
*/
5394
6494
 
5395
 
static void mark_progress(struct st_command* command __attribute__((unused)),
5396
 
                          int line)
 
6495
void mark_progress(struct st_command* command __attribute__((unused)),
 
6496
                   int line)
5397
6497
{
5398
6498
  char buf[32], *end;
5399
 
  uint64_t timer= timer_now();
 
6499
  ulonglong timer= timer_now();
5400
6500
  if (!progress_start)
5401
6501
    progress_start= timer;
5402
6502
  timer-= progress_start;
5403
6503
 
5404
6504
  /* Milliseconds since start */
5405
 
  end= int64_t2str(timer, buf, 10);
5406
 
  ds_progress.append(buf, (int)(end-buf));
5407
 
  ds_progress.append("\t", 1);
 
6505
  end= longlong2str(timer, buf, 10);
 
6506
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
6507
  dynstr_append_mem(&ds_progress, "\t", 1);
5408
6508
 
5409
6509
  /* Parser line number */
5410
6510
  end= int10_to_str(line, buf, 10);
5411
 
  ds_progress.append(buf, (int)(end-buf));
5412
 
  ds_progress.append("\t", 1);
 
6511
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
6512
  dynstr_append_mem(&ds_progress, "\t", 1);
5413
6513
 
5414
6514
  /* Filename */
5415
 
  ds_progress.append(cur_file->file_name);
5416
 
  ds_progress.append(":", 1);
 
6515
  dynstr_append(&ds_progress, cur_file->file_name);
 
6516
  dynstr_append_mem(&ds_progress, ":", 1);
5417
6517
 
5418
6518
  /* Line in file */
5419
6519
  end= int10_to_str(cur_file->lineno, buf, 10);
5420
 
  ds_progress.append(buf, (int)(end-buf));
5421
 
 
5422
 
 
5423
 
  ds_progress.append("\n", 1);
 
6520
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
6521
 
 
6522
 
 
6523
  dynstr_append_mem(&ds_progress, "\n", 1);
5424
6524
 
5425
6525
}
5426
6526
 
5428
6528
int main(int argc, char **argv)
5429
6529
{
5430
6530
  struct st_command *command;
5431
 
  bool q_send_flag= 0, abort_flag= 0;
 
6531
  my_bool q_send_flag= 0, abort_flag= 0;
5432
6532
  uint command_executed= 0, last_command_executed= 0;
5433
6533
  char save_file[FN_REFLEN];
5434
6534
  struct stat res_info;
5446
6546
    (sizeof(connections)/sizeof(struct st_connection)) - 1;
5447
6547
  next_con= connections + 1;
5448
6548
 
 
6549
#ifdef EMBEDDED_LIBRARY
 
6550
  /* set appropriate stack for the 'query' threads */
 
6551
  (void) pthread_attr_init(&cn_thd_attrib);
 
6552
  pthread_attr_setstacksize(&cn_thd_attrib, DEFAULT_THREAD_STACK);
 
6553
#endif /*EMBEDDED_LIBRARY*/
 
6554
 
5449
6555
  /* Init file stack */
5450
6556
  memset(file_stack, 0, sizeof(file_stack));
5451
6557
  file_stack_end=
5457
6563
  block_stack_end=
5458
6564
    block_stack + (sizeof(block_stack)/sizeof(struct st_block)) - 1;
5459
6565
  cur_block= block_stack;
5460
 
  cur_block->ok= true; /* Outer block should always be executed */
 
6566
  cur_block->ok= TRUE; /* Outer block should always be executed */
5461
6567
  cur_block->cmd= cmd_none;
5462
6568
 
 
6569
  my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
 
6570
 
5463
6571
  if (hash_init(&var_hash, charset_info,
5464
6572
                1024, 0, 0, get_var_key, var_free, MYF(0)))
5465
6573
    die("Variable hash initialization failed");
5466
6574
 
5467
 
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
 
6575
  var_set_string("$MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
5468
6576
 
5469
6577
  memset(&master_pos, 0, sizeof(master_pos));
5470
6578
 
5473
6581
 
5474
6582
  init_builtin_echo();
5475
6583
 
5476
 
  ds_res.reserve(65536);
5477
 
  ds_progress.reserve(2048);
5478
 
  ds_warning_messages.reserve(2048);
5479
 
 
 
6584
  init_dynamic_string(&ds_res, "", 65536, 65536);
 
6585
  init_dynamic_string(&ds_progress, "", 0, 2048);
 
6586
  init_dynamic_string(&ds_warning_messages, "", 0, 2048);
5480
6587
  parse_args(argc, argv);
5481
6588
 
 
6589
  var_set_int("$PS_PROTOCOL", ps_protocol);
 
6590
  var_set_int("$SP_PROTOCOL", sp_protocol);
 
6591
  var_set_int("$VIEW_PROTOCOL", view_protocol);
 
6592
  var_set_int("$CURSOR_PROTOCOL", cursor_protocol);
 
6593
 
 
6594
  DBUG_PRINT("info",("result_file: '%s'",
 
6595
                     result_file_name ? result_file_name : ""));
 
6596
  if (mysql_server_init(embedded_server_arg_count,
 
6597
                        embedded_server_args,
 
6598
                        (char**) embedded_server_groups))
 
6599
    die("Can't initialize MySQL server");
5482
6600
  server_initialized= 1;
5483
6601
  if (cur_file == file_stack && cur_file->file == 0)
5484
6602
  {
5486
6604
    cur_file->file_name= my_strdup("<stdin>", MYF(MY_WME));
5487
6605
    cur_file->lineno= 1;
5488
6606
  }
 
6607
  init_re();
 
6608
  ps_protocol_enabled= ps_protocol;
 
6609
  sp_protocol_enabled= sp_protocol;
 
6610
  view_protocol_enabled= view_protocol;
 
6611
  cursor_protocol_enabled= cursor_protocol;
 
6612
  /* Cursor protcol implies ps protocol */
 
6613
  if (cursor_protocol_enabled)
 
6614
    ps_protocol_enabled= 1;
 
6615
 
5489
6616
  cur_con= connections;
5490
 
  if (!( drizzle_create(&cur_con->drizzle)))
5491
 
    die("Failed in drizzle_create()");
 
6617
  if (!( mysql_init(&cur_con->mysql)))
 
6618
    die("Failed in mysql_init()");
5492
6619
  if (opt_compress)
5493
 
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
5494
 
  drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
6620
    mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS);
 
6621
  mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
 
6622
  mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME,
 
6623
                charset_info->csname);
 
6624
  int opt_protocol= MYSQL_PROTOCOL_TCP;
 
6625
  mysql_options(&cur_con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
6626
  if (opt_charsets_dir)
 
6627
    mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR,
 
6628
                  opt_charsets_dir);
 
6629
 
 
6630
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
6631
 
 
6632
  if (opt_use_ssl)
 
6633
  {
 
6634
    mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
 
6635
                  opt_ssl_capath, opt_ssl_cipher);
 
6636
#if MYSQL_VERSION_ID >= 50000
 
6637
    /* Turn on ssl_verify_server_cert only if host is "localhost" */
 
6638
    opt_ssl_verify_server_cert= opt_host && !strcmp(opt_host, "localhost");
 
6639
    mysql_options(&cur_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
 
6640
                  &opt_ssl_verify_server_cert);
 
6641
#endif
 
6642
  }
 
6643
#endif
5495
6644
 
5496
6645
  if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5497
6646
    die("Out of memory");
5498
6647
 
5499
 
  safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
 
6648
  safe_connect(&cur_con->mysql, cur_con->name, opt_host, opt_user, opt_pass,
5500
6649
               opt_db, opt_port);
5501
6650
 
5502
6651
  /* Use all time until exit if no explicit 'start_timer' */
5503
6652
  timer_start= timer_now();
5504
6653
 
5505
6654
  /*
5506
 
    Initialize $drizzle_errno with -1, so we can
 
6655
    Initialize $mysql_errno with -1, so we can
5507
6656
    - distinguish it from valid values ( >= 0 ) and
5508
6657
    - detect if there was never a command sent to the server
5509
6658
  */
5510
6659
  var_set_errno(-1);
5511
6660
 
5512
 
  /* Update $drizzle_get_server_version to that of current connection */
5513
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
6661
  /* Update $mysql_get_server_version to that of current connection */
 
6662
  var_set_mysql_get_server_version(&cur_con->mysql);
5514
6663
 
5515
6664
  if (opt_include)
5516
6665
  {
5539
6688
      case Q_CONNECT:
5540
6689
        do_connect(command);
5541
6690
        break;
5542
 
      case Q_CONNECTION:
5543
 
        select_connection(command);
5544
 
        break;
 
6691
      case Q_CONNECTION: select_connection(command); break;
5545
6692
      case Q_DISCONNECT:
5546
6693
      case Q_DIRTY_CLOSE:
5547
 
        do_close_connection(command); break;
 
6694
        do_close_connection(command); break;
5548
6695
      case Q_ENABLE_QUERY_LOG:   disable_query_log=0; break;
5549
6696
      case Q_DISABLE_QUERY_LOG:  disable_query_log=1; break;
5550
6697
      case Q_ENABLE_ABORT_ON_ERROR:  abort_on_error=1; break;
5580
6727
      case Q_PERL: do_perl(command); break;
5581
6728
      case Q_DELIMITER:
5582
6729
        do_delimiter(command);
5583
 
        break;
 
6730
        break;
5584
6731
      case Q_DISPLAY_VERTICAL_RESULTS:
5585
 
        display_result_vertically= true;
 
6732
        display_result_vertically= TRUE;
5586
6733
        break;
5587
6734
      case Q_DISPLAY_HORIZONTAL_RESULTS:
5588
 
        display_result_vertically= false;
 
6735
        display_result_vertically= FALSE;
5589
6736
        break;
5590
6737
      case Q_SORTED_RESULT:
5591
6738
        /*
5592
6739
          Turn on sorting of result set, will be reset after next
5593
6740
          command
5594
6741
        */
5595
 
        display_result_sorted= true;
 
6742
        display_result_sorted= TRUE;
5596
6743
        break;
5597
6744
      case Q_LET: do_let(command); break;
5598
6745
      case Q_EVAL_RESULT:
5600
6747
      case Q_EVAL:
5601
6748
      case Q_QUERY_VERTICAL:
5602
6749
      case Q_QUERY_HORIZONTAL:
5603
 
        if (command->query == command->query_buf)
 
6750
        if (command->query == command->query_buf)
5604
6751
        {
5605
6752
          /* Skip the first part of command, i.e query_xxx */
5606
 
          command->query= command->first_argument;
 
6753
          command->query= command->first_argument;
5607
6754
          command->first_word_len= 0;
5608
6755
        }
5609
 
        /* fall through */
 
6756
        /* fall through */
5610
6757
      case Q_QUERY:
5611
6758
      case Q_REAP:
5612
6759
      {
5613
 
        bool old_display_result_vertically= display_result_vertically;
 
6760
        my_bool old_display_result_vertically= display_result_vertically;
5614
6761
        /* Default is full query, both reap and send  */
5615
6762
        int flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
5616
6763
 
5628
6775
        /* Check for special property for this query */
5629
6776
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5630
6777
 
5631
 
        if (save_file[0])
5632
 
        {
5633
 
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
5634
 
          save_file[0]= 0;
5635
 
        }
5636
 
        run_query(cur_con, command, flags);
5637
 
        command_executed++;
 
6778
        if (save_file[0])
 
6779
        {
 
6780
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
 
6781
          save_file[0]= 0;
 
6782
        }
 
6783
        run_query(cur_con, command, flags);
 
6784
        command_executed++;
5638
6785
        command->last_argument= command->end;
5639
6786
 
5640
6787
        /* Restore settings */
5641
 
        display_result_vertically= old_display_result_vertically;
 
6788
        display_result_vertically= old_display_result_vertically;
5642
6789
 
5643
 
        break;
 
6790
        break;
5644
6791
      }
5645
6792
      case Q_SEND:
5646
6793
        if (!*command->first_argument)
5654
6801
        }
5655
6802
 
5656
6803
        /* Remove "send" if this is first iteration */
5657
 
        if (command->query == command->query_buf)
5658
 
          command->query= command->first_argument;
 
6804
        if (command->query == command->query_buf)
 
6805
          command->query= command->first_argument;
5659
6806
 
5660
 
        /*
5661
 
          run_query() can execute a query partially, depending on the flags.
5662
 
          QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
 
6807
        /*
 
6808
          run_query() can execute a query partially, depending on the flags.
 
6809
          QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5663
6810
          the query and read the result some time later when reap instruction
5664
 
          is given on this connection.
 
6811
          is given on this connection.
5665
6812
        */
5666
 
        run_query(cur_con, command, QUERY_SEND_FLAG);
5667
 
        command_executed++;
 
6813
        run_query(cur_con, command, QUERY_SEND_FLAG);
 
6814
        command_executed++;
5668
6815
        command->last_argument= command->end;
5669
 
        break;
 
6816
        break;
5670
6817
      case Q_REQUIRE:
5671
 
        do_get_file_name(command, save_file, sizeof(save_file));
5672
 
        break;
 
6818
        do_get_file_name(command, save_file, sizeof(save_file));
 
6819
        break;
5673
6820
      case Q_ERROR:
5674
6821
        do_get_errcodes(command);
5675
 
        break;
 
6822
        break;
5676
6823
      case Q_REPLACE:
5677
 
        do_get_replace(command);
5678
 
        break;
 
6824
        do_get_replace(command);
 
6825
        break;
5679
6826
      case Q_REPLACE_REGEX:
5680
6827
        do_get_replace_regex(command);
5681
6828
        break;
5682
6829
      case Q_REPLACE_COLUMN:
5683
 
        do_get_replace_column(command);
5684
 
        break;
 
6830
        do_get_replace_column(command);
 
6831
        break;
5685
6832
      case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5686
6833
      case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5687
6834
      case Q_SYNC_SLAVE_WITH_MASTER:
5688
6835
      {
5689
 
        do_save_master_pos();
5690
 
        if (*command->first_argument)
5691
 
          select_connection(command);
5692
 
        else
5693
 
          select_connection_name("slave");
5694
 
        do_sync_with_master2(0);
5695
 
        break;
 
6836
        do_save_master_pos();
 
6837
        if (*command->first_argument)
 
6838
          select_connection(command);
 
6839
        else
 
6840
          select_connection_name("slave");
 
6841
        do_sync_with_master2(0);
 
6842
        break;
5696
6843
      }
5697
 
      case Q_COMMENT:        /* Ignore row */
 
6844
      case Q_COMMENT:                           /* Ignore row */
5698
6845
        command->last_argument= command->end;
5699
 
        break;
 
6846
        break;
5700
6847
      case Q_PING:
5701
 
        (void) drizzle_ping(&cur_con->drizzle);
5702
 
        break;
 
6848
        (void) mysql_ping(&cur_con->mysql);
 
6849
        break;
5703
6850
      case Q_EXEC:
5704
 
        do_exec(command);
5705
 
        command_executed++;
5706
 
        break;
 
6851
        do_exec(command);
 
6852
        command_executed++;
 
6853
        break;
5707
6854
      case Q_START_TIMER:
5708
 
        /* Overwrite possible earlier start of timer */
5709
 
        timer_start= timer_now();
5710
 
        break;
 
6855
        /* Overwrite possible earlier start of timer */
 
6856
        timer_start= timer_now();
 
6857
        break;
5711
6858
      case Q_END_TIMER:
5712
 
        /* End timer before ending drizzletest */
5713
 
        timer_output();
5714
 
        break;
 
6859
        /* End timer before ending mysqltest */
 
6860
        timer_output();
 
6861
        break;
5715
6862
      case Q_CHARACTER_SET:
5716
 
        do_set_charset(command);
 
6863
        do_set_charset(command);
 
6864
        break;
 
6865
      case Q_DISABLE_PS_PROTOCOL:
 
6866
        ps_protocol_enabled= 0;
 
6867
        /* Close any open statements */
 
6868
        close_statements();
 
6869
        break;
 
6870
      case Q_ENABLE_PS_PROTOCOL:
 
6871
        ps_protocol_enabled= ps_protocol;
5717
6872
        break;
5718
6873
      case Q_DISABLE_RECONNECT:
5719
 
        set_reconnect(&cur_con->drizzle, 0);
 
6874
        set_reconnect(&cur_con->mysql, 0);
5720
6875
        break;
5721
6876
      case Q_ENABLE_RECONNECT:
5722
 
        set_reconnect(&cur_con->drizzle, 1);
 
6877
        set_reconnect(&cur_con->mysql, 1);
 
6878
        /* Close any open statements - no reconnect, need new prepare */
 
6879
        close_statements();
5723
6880
        break;
5724
6881
      case Q_DISABLE_PARSING:
5725
6882
        if (parsing_disabled == 0)
5791
6948
      free_all_replace();
5792
6949
 
5793
6950
      /* Also reset "sorted_result" */
5794
 
      display_result_sorted= false;
 
6951
      display_result_sorted= FALSE;
5795
6952
    }
5796
6953
    last_command_executed= command_executed;
5797
6954
 
5810
6967
    Time to compare result or save it to record file.
5811
6968
    The entire output from test is now kept in ds_res.
5812
6969
  */
5813
 
  if (ds_res.length())
 
6970
  if (ds_res.length)
5814
6971
  {
5815
6972
    if (result_file_name)
5816
6973
    {
5818
6975
 
5819
6976
      if (record)
5820
6977
      {
5821
 
        /* Recording - dump the output from test to result file */
5822
 
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
 
6978
        /* Recording - dump the output from test to result file */
 
6979
        str_to_file(result_file_name, ds_res.str, ds_res.length);
5823
6980
      }
5824
6981
      else
5825
6982
      {
5826
 
        /* Check that the output from test is equal to result file
5827
 
           - detect missing result file
5828
 
           - detect zero size result file
 
6983
        /* Check that the output from test is equal to result file
 
6984
           - detect missing result file
 
6985
           - detect zero size result file
5829
6986
        */
5830
 
        check_result(&ds_res);
 
6987
        check_result(&ds_res);
5831
6988
      }
5832
6989
    }
5833
6990
    else
5834
6991
    {
5835
6992
      /* No result_file_name specified to compare with, print to stdout */
5836
 
      printf("%s", ds_res.c_str());
 
6993
      printf("%s", ds_res.str);
5837
6994
    }
5838
6995
  }
5839
6996
  else
5858
7015
    dump_progress();
5859
7016
 
5860
7017
  /* Dump warning messages */
5861
 
  if (result_file_name && ds_warning_messages.length())
 
7018
  if (result_file_name && ds_warning_messages.length)
5862
7019
    dump_warning_messages();
5863
7020
 
5864
7021
  timer_output();
5876
7033
  before executing any commands. The time we measure is
5877
7034
 
5878
7035
  - If no explicit 'start_timer' or 'end_timer' is given in the
5879
 
  test case, the timer measure how long we execute in drizzletest.
 
7036
  test case, the timer measure how long we execute in mysqltest.
5880
7037
 
5881
7038
  - If only 'start_timer' is given we measure how long we execute
5882
 
  from that point until we terminate drizzletest.
 
7039
  from that point until we terminate mysqltest.
5883
7040
 
5884
7041
  - If only 'end_timer' is given we measure how long we execute
5885
 
  from that we enter drizzletest to the 'end_timer' is command is
 
7042
  from that we enter mysqltest to the 'end_timer' is command is
5886
7043
  executed.
5887
7044
 
5888
7045
  - If both 'start_timer' and 'end_timer' are given we measure
5894
7051
  if (timer_file)
5895
7052
  {
5896
7053
    char buf[32], *end;
5897
 
    uint64_t timer= timer_now() - timer_start;
5898
 
    end= int64_t2str(timer, buf, 10);
 
7054
    ulonglong timer= timer_now() - timer_start;
 
7055
    end= longlong2str(timer, buf, 10);
5899
7056
    str_to_file(timer_file,buf, (int) (end-buf));
5900
7057
    /* Timer has been written to the file, don't use it anymore */
5901
7058
    timer_file= 0;
5903
7060
}
5904
7061
 
5905
7062
 
5906
 
uint64_t timer_now(void)
 
7063
ulonglong timer_now(void)
5907
7064
{
5908
7065
  return my_micro_time() / 1000;
5909
7066
}
5921
7078
{
5922
7079
  char *from= command->first_argument;
5923
7080
  char *buff, *start;
5924
 
 
 
7081
  DBUG_ENTER("get_replace_columns");
5925
7082
 
5926
7083
  free_replace_column();
5927
7084
  if (!*from)
5928
7085
    die("Missing argument in %s", command->query);
5929
7086
 
5930
7087
  /* Allocate a buffer for results */
5931
 
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
 
7088
  start= buff= my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
5932
7089
  while (*from)
5933
7090
  {
5934
7091
    char *to;
5940
7097
    if (!*from)
5941
7098
      die("Wrong number of arguments to replace_column in '%s'", command->query);
5942
7099
    to= get_string(&buff, &from, command);
5943
 
    free(replace_column[column_number-1]);
 
7100
    my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
5944
7101
    replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
5945
7102
    set_if_bigger(max_replace_column, column_number);
5946
7103
  }
5947
 
  free(start);
 
7104
  my_free(start, MYF(0));
5948
7105
  command->last_argument= command->end;
5949
7106
}
5950
7107
 
5956
7113
  {
5957
7114
    if (replace_column[i])
5958
7115
    {
5959
 
      free(replace_column[i]);
 
7116
      my_free(replace_column[i], 0);
5960
7117
      replace_column[i]= 0;
5961
7118
    }
5962
7119
  }
5971
7128
 
5972
7129
/* Definitions for replace result */
5973
7130
 
5974
 
typedef struct st_pointer_array {    /* when using array-strings */
5975
 
  TYPELIB typelib;        /* Pointer to strings */
5976
 
  unsigned char  *str;          /* Strings is here */
5977
 
  uint8_t *flag;          /* Flag about each var. */
5978
 
  uint  array_allocs,max_count,length,max_length;
 
7131
typedef struct st_pointer_array {               /* when using array-strings */
 
7132
  TYPELIB typelib;                              /* Pointer to strings */
 
7133
  uchar *str;                                   /* Strings is here */
 
7134
  int7  *flag;                                  /* Flag about each var. */
 
7135
  uint  array_allocs,max_count,length,max_length;
5979
7136
} POINTER_ARRAY;
5980
7137
 
5981
7138
struct st_replace;
5982
7139
struct st_replace *init_replace(char * *from, char * *to, uint count,
5983
 
                                char * word_end_chars);
 
7140
                                char * word_end_chars);
5984
7141
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5985
 
void replace_strings_append(struct st_replace *rep, string* ds,
 
7142
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5986
7143
                            const char *from, int len);
5987
7144
void free_pointer_array(POINTER_ARRAY *pa);
5988
7145
 
6003
7160
  char *buff, *start;
6004
7161
  char word_end_chars[256], *pos;
6005
7162
  POINTER_ARRAY to_array, from_array;
6006
 
 
 
7163
  DBUG_ENTER("get_replace");
6007
7164
 
6008
7165
  free_replace();
6009
7166
 
6010
 
  memset(&to_array, 0, sizeof(to_array));
6011
 
  memset(&from_array, 0, sizeof(from_array));
 
7167
  bzero((char*) &to_array,sizeof(to_array));
 
7168
  bzero((char*) &from_array,sizeof(from_array));
6012
7169
  if (!*from)
6013
7170
    die("Missing argument in %s", command->query);
6014
 
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
 
7171
  start= buff= my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6015
7172
  while (*from)
6016
7173
  {
6017
7174
    char *to= buff;
6026
7183
  for (i= 1,pos= word_end_chars ; i < 256 ; i++)
6027
7184
    if (my_isspace(charset_info,i))
6028
7185
      *pos++= i;
6029
 
  *pos=0;          /* End pointer */
 
7186
  *pos=0;                                       /* End pointer */
6030
7187
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
6031
 
                                   (char**) to_array.typelib.type_names,
6032
 
                                   (uint) from_array.typelib.count,
6033
 
                                   word_end_chars)))
 
7188
                                  (char**) to_array.typelib.type_names,
 
7189
                                  (uint) from_array.typelib.count,
 
7190
                                  word_end_chars)))
6034
7191
    die("Can't initialize replace from '%s'", command->query);
6035
7192
  free_pointer_array(&from_array);
6036
7193
  free_pointer_array(&to_array);
6037
 
  free(start);
 
7194
  my_free(start, MYF(0));
6038
7195
  command->last_argument= command->end;
6039
 
  return;
 
7196
  DBUG_VOID_RETURN;
6040
7197
}
6041
7198
 
6042
7199
 
6043
7200
void free_replace()
6044
7201
{
6045
 
 
 
7202
  DBUG_ENTER("free_replace");
6046
7203
  if (glob_replace)
6047
7204
  {
6048
 
    free(glob_replace);
 
7205
    my_free(glob_replace,MYF(0));
6049
7206
    glob_replace=0;
6050
7207
  }
6051
 
  return;
 
7208
  DBUG_VOID_RETURN;
6052
7209
}
6053
7210
 
6054
7211
 
6055
7212
typedef struct st_replace {
6056
 
  bool found;
 
7213
  my_bool found;
6057
7214
  struct st_replace *next[256];
6058
7215
} REPLACE;
6059
7216
 
6060
7217
typedef struct st_replace_found {
6061
 
  bool found;
 
7218
  my_bool found;
6062
7219
  char *replace_string;
6063
7220
  uint to_offset;
6064
7221
  int from_offset;
6065
7222
} REPLACE_STRING;
6066
7223
 
6067
7224
 
6068
 
void replace_strings_append(REPLACE *rep, string* ds,
6069
 
                            const char *str, int len)
 
7225
void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
 
7226
                            const char *str,
 
7227
                            int len __attribute__((unused)))
6070
7228
{
6071
7229
  register REPLACE *rep_pos;
6072
7230
  register REPLACE_STRING *rep_str;
6073
7231
  const char *start, *from;
6074
 
 
 
7232
  DBUG_ENTER("replace_strings_append");
6075
7233
 
6076
7234
  start= from= str;
6077
7235
  rep_pos=rep+1;
6078
7236
  for (;;)
6079
7237
  {
6080
7238
    /* Loop through states */
 
7239
    DBUG_PRINT("info", ("Looping through states"));
6081
7240
    while (!rep_pos->found)
6082
 
      rep_pos= rep_pos->next[(unsigned char) *from++];
 
7241
      rep_pos= rep_pos->next[(uchar) *from++];
6083
7242
 
6084
7243
    /* Does this state contain a string to be replaced */
6085
7244
    if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6086
7245
    {
6087
7246
      /* No match found */
6088
 
      ds->append(start, from - start - 1);
6089
 
      return;
 
7247
      dynstr_append_mem(ds, start, from - start - 1);
 
7248
      DBUG_PRINT("exit", ("Found no more string to replace, appended: %s", start));
 
7249
      DBUG_VOID_RETURN;
6090
7250
    }
6091
7251
 
 
7252
    /* Found a string that needs to be replaced */
 
7253
    DBUG_PRINT("info", ("found: %d, to_offset: %d, from_offset: %d, string: %s",
 
7254
                        rep_str->found, rep_str->to_offset,
 
7255
                        rep_str->from_offset, rep_str->replace_string));
 
7256
 
6092
7257
    /* Append part of original string before replace string */
6093
 
    ds->append(start, (from - rep_str->to_offset) - start);
 
7258
    dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6094
7259
 
6095
7260
    /* Append replace string */
6096
 
    ds->append(rep_str->replace_string,
6097
 
               strlen(rep_str->replace_string));
 
7261
    dynstr_append_mem(ds, rep_str->replace_string,
 
7262
                      strlen(rep_str->replace_string));
6098
7263
 
6099
7264
    if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6100
 
      return;
6101
 
 
6102
 
    assert(from <= str+len);
 
7265
    {
 
7266
      /* End of from string */
 
7267
      DBUG_PRINT("exit", ("Found end of from string"));
 
7268
      DBUG_VOID_RETURN;
 
7269
    }
 
7270
    DBUG_ASSERT(from <= str+len);
6103
7271
    start= from;
6104
7272
    rep_pos=rep;
6105
7273
  }
6180
7348
  Returns: st_replace_regex struct with pairs of substitutions
6181
7349
*/
6182
7350
 
6183
 
static struct st_replace_regex* init_replace_regex(char* expr)
 
7351
struct st_replace_regex* init_replace_regex(char* expr)
6184
7352
{
6185
7353
  struct st_replace_regex* res;
6186
7354
  char* buf,*expr_end;
6203
7371
  /* for each regexp substitution statement */
6204
7372
  while (p < expr_end)
6205
7373
  {
6206
 
    memset(&reg, 0, sizeof(reg));
 
7374
    bzero(&reg,sizeof(reg));
6207
7375
    /* find the start of the statement */
6208
7376
    while (p < expr_end)
6209
7377
    {
6245
7413
      reg.icase= 1;
6246
7414
 
6247
7415
    /* done parsing the statement, now place it in regex_arr */
6248
 
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
7416
    if (insert_dynamic(&res->regex_arr,(uchar*) &reg))
6249
7417
      die("Out of memory");
6250
7418
  }
6251
7419
  res->odd_buf_len= res->even_buf_len= 8192;
6256
7424
  return res;
6257
7425
 
6258
7426
err:
6259
 
  free(res);
 
7427
  my_free(res,0);
6260
7428
  die("Error parsing replace_regex \"%s\"", expr);
6261
7429
  return 0;
6262
7430
}
6280
7448
  in one pass
6281
7449
*/
6282
7450
 
6283
 
static int multi_reg_replace(struct st_replace_regex* r,char* val)
 
7451
int multi_reg_replace(struct st_replace_regex* r,char* val)
6284
7452
{
6285
7453
  uint i;
6286
7454
  char* in_buf, *out_buf;
6297
7465
    struct st_regex re;
6298
7466
    char* save_out_buf= out_buf;
6299
7467
 
6300
 
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
7468
    get_dynamic(&r->regex_arr,(uchar*)&re,i);
6301
7469
 
6302
7470
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6303
7471
                     in_buf, re.icase))
6315
7483
      if (in_buf == val)
6316
7484
        in_buf= r->odd_buf;
6317
7485
 
6318
 
      std::swap(in_buf,out_buf);
 
7486
      swap_variables(char*,in_buf,out_buf);
6319
7487
 
6320
7488
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
6321
7489
        &r->odd_buf_len;
6348
7516
  if (glob_replace_regex)
6349
7517
  {
6350
7518
    delete_dynamic(&glob_replace_regex->regex_arr);
6351
 
    free(glob_replace_regex->even_buf);
6352
 
    free(glob_replace_regex->odd_buf);
6353
 
    free(glob_replace_regex);
 
7519
    my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
 
7520
    my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
 
7521
    my_free(glob_replace_regex,MYF(0));
6354
7522
    glob_replace_regex=0;
6355
7523
  }
6356
7524
}
6382
7550
  icase - flag, if set to 1 the match is case insensitive
6383
7551
*/
6384
7552
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
6385
 
                char *replace, char *in_string, int icase)
 
7553
                char *replace, char *string, int icase)
6386
7554
{
6387
 
  string string_to_match(in_string);
6388
 
  pcrecpp::RE_Options opt;
 
7555
  my_regex_t r;
 
7556
  my_regmatch_t *subs;
 
7557
  char *replace_end;
 
7558
  char *buf= *buf_p;
 
7559
  int len;
 
7560
  int buf_len, need_buf_len;
 
7561
  int cflags= REG_EXTENDED;
 
7562
  int err_code;
 
7563
  char *res_p,*str_p,*str_end;
 
7564
 
 
7565
  buf_len= *buf_len_p;
 
7566
  len= strlen(string);
 
7567
  str_end= string + len;
 
7568
 
 
7569
  /* start with a buffer of a reasonable size that hopefully will not
 
7570
     need to be reallocated
 
7571
  */
 
7572
  need_buf_len= len * 2 + 1;
 
7573
  res_p= buf;
 
7574
 
 
7575
  SECURE_REG_BUF
6389
7576
 
6390
7577
  if (icase)
6391
 
    opt.set_caseless(true);
6392
 
 
6393
 
  if (!pcrecpp::RE(pattern, opt).Replace(replace,&string_to_match)){
6394
 
    return 1;
6395
 
  }
6396
 
 
6397
 
  const char * new_str= string_to_match.c_str();
6398
 
  *buf_len_p= strlen(new_str);
6399
 
  char * new_buf = (char *)malloc(*buf_len_p+1);
6400
 
  if (new_buf == NULL)
6401
 
  {
6402
 
    return 1;
6403
 
  }
6404
 
  strcpy(new_buf, new_str);
6405
 
  *buf_p= new_buf;
6406
 
 
 
7578
    cflags|= REG_ICASE;
 
7579
 
 
7580
  if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1)))
 
7581
  {
 
7582
    check_regerr(&r,err_code);
 
7583
    return 1;
 
7584
  }
 
7585
 
 
7586
  subs= (my_regmatch_t*)my_malloc(sizeof(my_regmatch_t) * (r.re_nsub+1),
 
7587
                                  MYF(MY_WME+MY_FAE));
 
7588
 
 
7589
  *res_p= 0;
 
7590
  str_p= string;
 
7591
  replace_end= replace + strlen(replace);
 
7592
 
 
7593
  /* for each pattern match instance perform a replacement */
 
7594
  while (!err_code)
 
7595
  {
 
7596
    /* find the match */
 
7597
    err_code= my_regexec(&r,str_p, r.re_nsub+1, subs,
 
7598
                         (str_p == string) ? REG_NOTBOL : 0);
 
7599
 
 
7600
    /* if regular expression error (eg. bad syntax, or out of memory) */
 
7601
    if (err_code && err_code != REG_NOMATCH)
 
7602
    {
 
7603
      check_regerr(&r,err_code);
 
7604
      my_regfree(&r);
 
7605
      return 1;
 
7606
    }
 
7607
 
 
7608
    /* if match found */
 
7609
    if (!err_code)
 
7610
    {
 
7611
      char* expr_p= replace;
 
7612
      int c;
 
7613
 
 
7614
      /*
 
7615
        we need at least what we have so far in the buffer + the part
 
7616
        before this match
 
7617
      */
 
7618
      need_buf_len= (res_p - buf) + (int) subs[0].rm_so;
 
7619
 
 
7620
      /* on this pass, calculate the memory for the result buffer */
 
7621
      while (expr_p < replace_end)
 
7622
      {
 
7623
        int back_ref_num= -1;
 
7624
        c= *expr_p;
 
7625
 
 
7626
        if (c == '\\' && expr_p + 1 < replace_end)
 
7627
        {
 
7628
          back_ref_num= (int) (expr_p[1] - '0');
 
7629
        }
 
7630
 
 
7631
        /* found a valid back_ref (eg. \1)*/
 
7632
        if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
 
7633
        {
 
7634
          regoff_t start_off, end_off;
 
7635
          if ((start_off=subs[back_ref_num].rm_so) > -1 &&
 
7636
              (end_off=subs[back_ref_num].rm_eo) > -1)
 
7637
          {
 
7638
            need_buf_len += (int) (end_off - start_off);
 
7639
          }
 
7640
          expr_p += 2;
 
7641
        }
 
7642
        else
 
7643
        {
 
7644
          expr_p++;
 
7645
          need_buf_len++;
 
7646
        }
 
7647
      }
 
7648
      need_buf_len++;
 
7649
      /*
 
7650
        now that we know the size of the buffer,
 
7651
        make sure it is big enough
 
7652
      */
 
7653
      SECURE_REG_BUF
 
7654
 
 
7655
        /* copy the pre-match part */
 
7656
        if (subs[0].rm_so)
 
7657
        {
 
7658
          memcpy(res_p, str_p, (size_t) subs[0].rm_so);
 
7659
          res_p+= subs[0].rm_so;
 
7660
        }
 
7661
 
 
7662
      expr_p= replace;
 
7663
 
 
7664
      /* copy the match and expand back_refs */
 
7665
      while (expr_p < replace_end)
 
7666
      {
 
7667
        int back_ref_num= -1;
 
7668
        c= *expr_p;
 
7669
 
 
7670
        if (c == '\\' && expr_p + 1 < replace_end)
 
7671
        {
 
7672
          back_ref_num= expr_p[1] - '0';
 
7673
        }
 
7674
 
 
7675
        if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
 
7676
        {
 
7677
          regoff_t start_off, end_off;
 
7678
          if ((start_off=subs[back_ref_num].rm_so) > -1 &&
 
7679
              (end_off=subs[back_ref_num].rm_eo) > -1)
 
7680
          {
 
7681
            int block_len= (int) (end_off - start_off);
 
7682
            memcpy(res_p,str_p + start_off, block_len);
 
7683
            res_p += block_len;
 
7684
          }
 
7685
          expr_p += 2;
 
7686
        }
 
7687
        else
 
7688
        {
 
7689
          *res_p++ = *expr_p++;
 
7690
        }
 
7691
      }
 
7692
 
 
7693
      /* handle the post-match part */
 
7694
      if (subs[0].rm_so == subs[0].rm_eo)
 
7695
      {
 
7696
        if (str_p + subs[0].rm_so >= str_end)
 
7697
          break;
 
7698
        str_p += subs[0].rm_eo ;
 
7699
        *res_p++ = *str_p++;
 
7700
      }
 
7701
      else
 
7702
      {
 
7703
        str_p += subs[0].rm_eo;
 
7704
      }
 
7705
    }
 
7706
    else /* no match this time, just copy the string as is */
 
7707
    {
 
7708
      int left_in_str= str_end-str_p;
 
7709
      need_buf_len= (res_p-buf) + left_in_str;
 
7710
      SECURE_REG_BUF
 
7711
        memcpy(res_p,str_p,left_in_str);
 
7712
      res_p += left_in_str;
 
7713
      str_p= str_end;
 
7714
    }
 
7715
  }
 
7716
  my_free(subs, MYF(0));
 
7717
  my_regfree(&r);
 
7718
  *res_p= 0;
 
7719
  *buf_p= buf;
 
7720
  *buf_len_p= buf_len;
6407
7721
  return 0;
6408
7722
}
6409
7723
 
6416
7730
#define LAST_CHAR_CODE 259
6417
7731
 
6418
7732
typedef struct st_rep_set {
6419
 
  uint  *bits;        /* Pointer to used sets */
6420
 
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6421
 
  uint  found_len;      /* Best match to date */
6422
 
  int  found_offset;
6423
 
  uint  table_offset;
6424
 
  uint  size_of_bits;      /* For convinience */
 
7733
  uint  *bits;                          /* Pointer to used sets */
 
7734
  short next[LAST_CHAR_CODE];           /* Pointer to next sets */
 
7735
  uint  found_len;                      /* Best match to date */
 
7736
  int   found_offset;
 
7737
  uint  table_offset;
 
7738
  uint  size_of_bits;                   /* For convinience */
6425
7739
} REP_SET;
6426
7740
 
6427
7741
typedef struct st_rep_sets {
6428
 
  uint    count;      /* Number of sets */
6429
 
  uint    extra;      /* Extra sets in buffer */
6430
 
  uint    invisible;    /* Sets not chown */
6431
 
  uint    size_of_bits;
6432
 
  REP_SET  *set,*set_buffer;
6433
 
  uint    *bit_buffer;
 
7742
  uint          count;                  /* Number of sets */
 
7743
  uint          extra;                  /* Extra sets in buffer */
 
7744
  uint          invisible;              /* Sets not chown */
 
7745
  uint          size_of_bits;
 
7746
  REP_SET       *set,*set_buffer;
 
7747
  uint          *bit_buffer;
6434
7748
} REP_SETS;
6435
7749
 
6436
7750
typedef struct st_found_set {
6465
7779
static uint found_sets=0;
6466
7780
 
6467
7781
 
6468
 
static uint replace_len(char * str)
 
7782
uint replace_len(char * str)
6469
7783
{
6470
7784
  uint len=0;
6471
7785
  while (*str)
6481
7795
/* Init a replace structure for further calls */
6482
7796
 
6483
7797
REPLACE *init_replace(char * *from, char * *to,uint count,
6484
 
                      char * word_end_chars)
 
7798
                      char * word_end_chars)
6485
7799
{
6486
7800
  static const int SPACE_CHAR= 256;
6487
7801
  static const int START_OF_LINE= 257;
6497
7811
  REPLACE *replace;
6498
7812
  FOUND_SET *found_set;
6499
7813
  REPLACE_STRING *rep_str;
6500
 
 
 
7814
  DBUG_ENTER("init_replace");
6501
7815
 
6502
7816
  /* Count number of states */
6503
7817
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6506
7820
    if (!len)
6507
7821
    {
6508
7822
      errno=EINVAL;
6509
 
      return(0);
 
7823
      DBUG_RETURN(0);
6510
7824
    }
6511
7825
    states+=len+1;
6512
7826
    result_len+=(uint) strlen(to[i])+1;
6513
7827
    if (len > max_length)
6514
7828
      max_length=len;
6515
7829
  }
6516
 
  memset(is_word_end, 0, sizeof(is_word_end));
 
7830
  bzero((char*) is_word_end,sizeof(is_word_end));
6517
7831
  for (i=0 ; word_end_chars[i] ; i++)
6518
 
    is_word_end[(unsigned char) word_end_chars[i]]=1;
 
7832
    is_word_end[(uchar) word_end_chars[i]]=1;
6519
7833
 
6520
7834
  if (init_sets(&sets,states))
6521
 
    return(0);
 
7835
    DBUG_RETURN(0);
6522
7836
  found_sets=0;
6523
7837
  if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
6524
 
                                          MYF(MY_WME))))
 
7838
                                          MYF(MY_WME))))
6525
7839
  {
6526
7840
    free_sets(&sets);
6527
 
    return(0);
 
7841
    DBUG_RETURN(0);
6528
7842
  }
6529
 
  make_new_set(&sets);      /* Set starting set */
6530
 
  make_sets_invisible(&sets);      /* Hide previus sets */
 
7843
  VOID(make_new_set(&sets));                    /* Set starting set */
 
7844
  make_sets_invisible(&sets);                   /* Hide previus sets */
6531
7845
  used_sets=-1;
6532
 
  word_states=make_new_set(&sets);    /* Start of new word */
6533
 
  start_states=make_new_set(&sets);    /* This is first state */
 
7846
  word_states=make_new_set(&sets);              /* Start of new word */
 
7847
  start_states=make_new_set(&sets);             /* This is first state */
6534
7848
  if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6535
7849
  {
6536
7850
    free_sets(&sets);
6537
 
    free(found_set);
6538
 
    return(0);
 
7851
    my_free(found_set,MYF(0));
 
7852
    DBUG_RETURN(0);
6539
7853
  }
6540
7854
 
6541
7855
  /* Init follow_ptr[] */
6546
7860
      internal_set_bit(start_states,states+1);
6547
7861
      if (!from[i][2])
6548
7862
      {
6549
 
        start_states->table_offset=i;
6550
 
        start_states->found_offset=1;
 
7863
        start_states->table_offset=i;
 
7864
        start_states->found_offset=1;
6551
7865
      }
6552
7866
    }
6553
7867
    else if (from[i][0] == '\\' && from[i][1] == '$')
6554
7868
    {
6555
7869
      internal_set_bit(start_states,states);
6556
7870
      internal_set_bit(word_states,states);
6557
 
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
 
7871
      if (!from[i][2] && start_states->table_offset == (uint) ~0)
6558
7872
      {
6559
 
        start_states->table_offset=i;
6560
 
        start_states->found_offset=0;
 
7873
        start_states->table_offset=i;
 
7874
        start_states->found_offset=0;
6561
7875
      }
6562
7876
    }
6563
7877
    else
6564
7878
    {
6565
7879
      internal_set_bit(word_states,states);
6566
7880
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6567
 
        internal_set_bit(start_states,states+1);
 
7881
        internal_set_bit(start_states,states+1);
6568
7882
      else
6569
 
        internal_set_bit(start_states,states);
 
7883
        internal_set_bit(start_states,states);
6570
7884
    }
6571
7885
    for (pos=from[i], len=0; *pos ; pos++)
6572
7886
    {
6573
7887
      if (*pos == '\\' && *(pos+1))
6574
7888
      {
6575
 
        pos++;
6576
 
        switch (*pos) {
6577
 
        case 'b':
6578
 
          follow_ptr->chr = SPACE_CHAR;
6579
 
          break;
6580
 
        case '^':
6581
 
          follow_ptr->chr = START_OF_LINE;
6582
 
          break;
6583
 
        case '$':
6584
 
          follow_ptr->chr = END_OF_LINE;
6585
 
          break;
6586
 
        case 'r':
6587
 
          follow_ptr->chr = '\r';
6588
 
          break;
6589
 
        case 't':
6590
 
          follow_ptr->chr = '\t';
6591
 
          break;
6592
 
        case 'v':
6593
 
          follow_ptr->chr = '\v';
6594
 
          break;
6595
 
        default:
6596
 
          follow_ptr->chr = (unsigned char) *pos;
6597
 
          break;
6598
 
        }
 
7889
        pos++;
 
7890
        switch (*pos) {
 
7891
        case 'b':
 
7892
          follow_ptr->chr = SPACE_CHAR;
 
7893
          break;
 
7894
        case '^':
 
7895
          follow_ptr->chr = START_OF_LINE;
 
7896
          break;
 
7897
        case '$':
 
7898
          follow_ptr->chr = END_OF_LINE;
 
7899
          break;
 
7900
        case 'r':
 
7901
          follow_ptr->chr = '\r';
 
7902
          break;
 
7903
        case 't':
 
7904
          follow_ptr->chr = '\t';
 
7905
          break;
 
7906
        case 'v':
 
7907
          follow_ptr->chr = '\v';
 
7908
          break;
 
7909
        default:
 
7910
          follow_ptr->chr = (uchar) *pos;
 
7911
          break;
 
7912
        }
6599
7913
      }
6600
7914
      else
6601
 
        follow_ptr->chr= (unsigned char) *pos;
 
7915
        follow_ptr->chr= (uchar) *pos;
6602
7916
      follow_ptr->table_offset=i;
6603
7917
      follow_ptr->len= ++len;
6604
7918
      follow_ptr++;
6614
7928
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6615
7929
  {
6616
7930
    set=sets.set+set_nr;
6617
 
    default_state= 0;        /* Start from beginning */
 
7931
    default_state= 0;                           /* Start from beginning */
6618
7932
 
6619
7933
    /* If end of found-string not found or start-set with current set */
6620
7934
 
6621
 
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
 
7935
    for (i= (uint) ~0; (i=get_next_bit(set,i)) ;)
6622
7936
    {
6623
7937
      if (!follow[i].chr)
6624
7938
      {
6625
 
        if (! default_state)
6626
 
          default_state= find_found(found_set,set->table_offset,
6627
 
                                    set->found_offset+1);
 
7939
        if (! default_state)
 
7940
          default_state= find_found(found_set,set->table_offset,
 
7941
                                    set->found_offset+1);
6628
7942
      }
6629
7943
    }
6630
 
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
 
7944
    copy_bits(sets.set+used_sets,set);          /* Save set for changes */
6631
7945
    if (!default_state)
6632
 
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
 
7946
      or_bits(sets.set+used_sets,sets.set);     /* Can restart from start */
6633
7947
 
6634
7948
    /* Find all chars that follows current sets */
6635
 
    memset(used_chars, 0, sizeof(used_chars));
6636
 
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
 
7949
    bzero((char*) used_chars,sizeof(used_chars));
 
7950
    for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6637
7951
    {
6638
7952
      used_chars[follow[i].chr]=1;
6639
7953
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6640
 
           follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6641
 
        used_chars[0]=1;
 
7954
           follow[i].len > 1) || follow[i].chr == END_OF_LINE)
 
7955
        used_chars[0]=1;
6642
7956
    }
6643
7957
 
6644
7958
    /* Mark word_chars used if \b is in state */
6645
7959
    if (used_chars[SPACE_CHAR])
6646
7960
      for (pos= word_end_chars ; *pos ; pos++)
6647
 
        used_chars[(int) (unsigned char) *pos] = 1;
 
7961
        used_chars[(int) (uchar) *pos] = 1;
6648
7962
 
6649
7963
    /* Handle other used characters */
6650
7964
    for (chr= 0 ; chr < 256 ; chr++)
6651
7965
    {
6652
7966
      if (! used_chars[chr])
6653
 
        set->next[chr]= chr ? default_state : -1;
 
7967
        set->next[chr]= chr ? default_state : -1;
6654
7968
      else
6655
7969
      {
6656
 
        new_set=make_new_set(&sets);
6657
 
        set=sets.set+set_nr;      /* if realloc */
6658
 
        new_set->table_offset=set->table_offset;
6659
 
        new_set->found_len=set->found_len;
6660
 
        new_set->found_offset=set->found_offset+1;
6661
 
        found_end=0;
 
7970
        new_set=make_new_set(&sets);
 
7971
        set=sets.set+set_nr;                    /* if realloc */
 
7972
        new_set->table_offset=set->table_offset;
 
7973
        new_set->found_len=set->found_len;
 
7974
        new_set->found_offset=set->found_offset+1;
 
7975
        found_end=0;
6662
7976
 
6663
 
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6664
 
        {
6665
 
          if (!follow[i].chr || follow[i].chr == chr ||
6666
 
              (follow[i].chr == SPACE_CHAR &&
6667
 
               (is_word_end[chr] ||
6668
 
                (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6669
 
              (follow[i].chr == END_OF_LINE && ! chr))
6670
 
          {
6671
 
            if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6672
 
                follow[i].len > found_end)
6673
 
              found_end=follow[i].len;
6674
 
            if (chr && follow[i].chr)
6675
 
              internal_set_bit(new_set,i+1);    /* To next set */
6676
 
            else
6677
 
              internal_set_bit(new_set,i);
6678
 
          }
6679
 
        }
6680
 
        if (found_end)
6681
 
        {
6682
 
          new_set->found_len=0;      /* Set for testing if first */
6683
 
          bits_set=0;
6684
 
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6685
 
          {
6686
 
            if ((follow[i].chr == SPACE_CHAR ||
6687
 
                 follow[i].chr == END_OF_LINE) && ! chr)
6688
 
              bit_nr=i+1;
6689
 
            else
6690
 
              bit_nr=i;
6691
 
            if (follow[bit_nr-1].len < found_end ||
6692
 
                (new_set->found_len &&
6693
 
                 (chr == 0 || !follow[bit_nr].chr)))
6694
 
              internal_clear_bit(new_set,i);
6695
 
            else
6696
 
            {
6697
 
              if (chr == 0 || !follow[bit_nr].chr)
6698
 
              {          /* best match  */
6699
 
                new_set->table_offset=follow[bit_nr].table_offset;
6700
 
                if (chr || (follow[i].chr == SPACE_CHAR ||
6701
 
                            follow[i].chr == END_OF_LINE))
6702
 
                  new_set->found_offset=found_end;  /* New match */
6703
 
                new_set->found_len=found_end;
6704
 
              }
6705
 
              bits_set++;
6706
 
            }
6707
 
          }
6708
 
          if (bits_set == 1)
6709
 
          {
6710
 
            set->next[chr] = find_found(found_set,
6711
 
                                        new_set->table_offset,
6712
 
                                        new_set->found_offset);
6713
 
            free_last_set(&sets);
6714
 
          }
6715
 
          else
6716
 
            set->next[chr] = find_set(&sets,new_set);
6717
 
        }
6718
 
        else
6719
 
          set->next[chr] = find_set(&sets,new_set);
 
7977
        for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
 
7978
        {
 
7979
          if (!follow[i].chr || follow[i].chr == chr ||
 
7980
              (follow[i].chr == SPACE_CHAR &&
 
7981
               (is_word_end[chr] ||
 
7982
                (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
 
7983
              (follow[i].chr == END_OF_LINE && ! chr))
 
7984
          {
 
7985
            if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
 
7986
                follow[i].len > found_end)
 
7987
              found_end=follow[i].len;
 
7988
            if (chr && follow[i].chr)
 
7989
              internal_set_bit(new_set,i+1);            /* To next set */
 
7990
            else
 
7991
              internal_set_bit(new_set,i);
 
7992
          }
 
7993
        }
 
7994
        if (found_end)
 
7995
        {
 
7996
          new_set->found_len=0;                 /* Set for testing if first */
 
7997
          bits_set=0;
 
7998
          for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
 
7999
          {
 
8000
            if ((follow[i].chr == SPACE_CHAR ||
 
8001
                 follow[i].chr == END_OF_LINE) && ! chr)
 
8002
              bit_nr=i+1;
 
8003
            else
 
8004
              bit_nr=i;
 
8005
            if (follow[bit_nr-1].len < found_end ||
 
8006
                (new_set->found_len &&
 
8007
                 (chr == 0 || !follow[bit_nr].chr)))
 
8008
              internal_clear_bit(new_set,i);
 
8009
            else
 
8010
            {
 
8011
              if (chr == 0 || !follow[bit_nr].chr)
 
8012
              {                                 /* best match  */
 
8013
                new_set->table_offset=follow[bit_nr].table_offset;
 
8014
                if (chr || (follow[i].chr == SPACE_CHAR ||
 
8015
                            follow[i].chr == END_OF_LINE))
 
8016
                  new_set->found_offset=found_end;      /* New match */
 
8017
                new_set->found_len=found_end;
 
8018
              }
 
8019
              bits_set++;
 
8020
            }
 
8021
          }
 
8022
          if (bits_set == 1)
 
8023
          {
 
8024
            set->next[chr] = find_found(found_set,
 
8025
                                        new_set->table_offset,
 
8026
                                        new_set->found_offset);
 
8027
            free_last_set(&sets);
 
8028
          }
 
8029
          else
 
8030
            set->next[chr] = find_set(&sets,new_set);
 
8031
        }
 
8032
        else
 
8033
          set->next[chr] = find_set(&sets,new_set);
6720
8034
      }
6721
8035
    }
6722
8036
  }
6724
8038
  /* Alloc replace structure for the replace-state-machine */
6725
8039
 
6726
8040
  if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+
6727
 
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
6728
 
                                    sizeof(char *)*count+result_len,
6729
 
                                    MYF(MY_WME | MY_ZEROFILL))))
 
8041
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
 
8042
                                    sizeof(char *)*count+result_len,
 
8043
                                    MYF(MY_WME | MY_ZEROFILL))))
6730
8044
  {
6731
8045
    rep_str=(REPLACE_STRING*) (replace+sets.count);
6732
8046
    to_array= (char **) (rep_str+found_sets+1);
6734
8048
    for (i=0 ; i < count ; i++)
6735
8049
    {
6736
8050
      to_array[i]=to_pos;
6737
 
      to_pos=my_stpcpy(to_pos,to[i])+1;
 
8051
      to_pos=strmov(to_pos,to[i])+1;
6738
8052
    }
6739
8053
    rep_str[0].found=1;
6740
8054
    rep_str[0].replace_string=0;
6741
8055
    for (i=1 ; i <= found_sets ; i++)
6742
8056
    {
6743
8057
      pos=from[found_set[i-1].table_offset];
6744
 
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
 
8058
      rep_str[i].found= !bcmp((const uchar*) pos,
 
8059
                              (const uchar*) "\\^", 3) ? 2 : 1;
6745
8060
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
6746
8061
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
6747
8062
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6748
 
        end_of_word(pos);
 
8063
        end_of_word(pos);
6749
8064
    }
6750
8065
    for (i=0 ; i < sets.count ; i++)
6751
8066
    {
6752
8067
      for (j=0 ; j < 256 ; j++)
6753
 
        if (sets.set[i].next[j] >= 0)
6754
 
          replace[i].next[j]=replace+sets.set[i].next[j];
6755
 
        else
6756
 
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
 
8068
        if (sets.set[i].next[j] >= 0)
 
8069
          replace[i].next[j]=replace+sets.set[i].next[j];
 
8070
        else
 
8071
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6757
8072
    }
6758
8073
  }
6759
 
  free(follow);
 
8074
  my_free(follow,MYF(0));
6760
8075
  free_sets(&sets);
6761
 
  free(found_set);
6762
 
  return(replace);
 
8076
  my_free(found_set,MYF(0));
 
8077
  DBUG_PRINT("exit",("Replace table has %d states",sets.count));
 
8078
  DBUG_RETURN(replace);
6763
8079
}
6764
8080
 
6765
8081
 
6766
8082
int init_sets(REP_SETS *sets,uint states)
6767
8083
{
6768
 
  memset(sets, 0, sizeof(*sets));
 
8084
  bzero((char*) sets,sizeof(*sets));
6769
8085
  sets->size_of_bits=((states+7)/8);
6770
8086
  if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
6771
 
                                              MYF(MY_WME))))
 
8087
                                              MYF(MY_WME))))
6772
8088
    return 1;
6773
8089
  if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
6774
 
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
 
8090
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
6775
8091
  {
6776
 
    free(sets->set);
 
8092
    my_free(sets->set,MYF(0));
6777
8093
    return 1;
6778
8094
  }
6779
8095
  return 0;
6796
8112
  {
6797
8113
    sets->extra--;
6798
8114
    set=sets->set+ sets->count++;
6799
 
    memset(set->bits, 0, sizeof(uint)*sets->size_of_bits);
6800
 
    memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
 
8115
    bzero((char*) set->bits,sizeof(uint)*sets->size_of_bits);
 
8116
    bzero((char*) &set->next[0],sizeof(set->next[0])*LAST_CHAR_CODE);
6801
8117
    set->found_offset=0;
6802
8118
    set->found_len=0;
6803
 
    set->table_offset= UINT32_MAX;
 
8119
    set->table_offset= (uint) ~0;
6804
8120
    set->size_of_bits=sets->size_of_bits;
6805
8121
    return set;
6806
8122
  }
6807
8123
  count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6808
 
  if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
 
8124
  if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6809
8125
                                  sizeof(REP_SET)*count,
6810
 
                                  MYF(MY_WME))))
 
8126
                                  MYF(MY_WME))))
6811
8127
    return 0;
6812
8128
  sets->set_buffer=set;
6813
8129
  sets->set=set+sets->invisible;
6814
 
  if (!(bit_buffer=(uint*) my_realloc((unsigned char*) sets->bit_buffer,
6815
 
                                      (sizeof(uint)*sets->size_of_bits)*count,
6816
 
                                      MYF(MY_WME))))
 
8130
  if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
 
8131
                                      (sizeof(uint)*sets->size_of_bits)*count,
 
8132
                                      MYF(MY_WME))))
6817
8133
    return 0;
6818
8134
  sets->bit_buffer=bit_buffer;
6819
8135
  for (i=0 ; i < count ; i++)
6834
8150
 
6835
8151
void free_sets(REP_SETS *sets)
6836
8152
{
6837
 
  free(sets->set_buffer);
6838
 
  free(sets->bit_buffer);
 
8153
  my_free(sets->set_buffer,MYF(0));
 
8154
  my_free(sets->bit_buffer,MYF(0));
6839
8155
  return;
6840
8156
}
6841
8157
 
6862
8178
 
6863
8179
void copy_bits(REP_SET *to,REP_SET *from)
6864
8180
{
6865
 
  memcpy(to->bits,from->bits,
6866
 
         (size_t) (sizeof(uint) * to->size_of_bits));
 
8181
  memcpy((uchar*) to->bits,(uchar*) from->bits,
 
8182
         (size_t) (sizeof(uint) * to->size_of_bits));
6867
8183
}
6868
8184
 
6869
8185
int cmp_bits(REP_SET *set1,REP_SET *set2)
6870
8186
{
6871
 
  return memcmp(set1->bits,set2->bits, sizeof(uint) * set1->size_of_bits);
 
8187
  return bcmp((uchar*) set1->bits,(uchar*) set2->bits,
 
8188
              sizeof(uint) * set1->size_of_bits);
6872
8189
}
6873
8190
 
6874
8191
 
6910
8227
      return i;
6911
8228
    }
6912
8229
  }
6913
 
  return i;        /* return new postion */
 
8230
  return i;                             /* return new postion */
6914
8231
}
6915
8232
 
6916
8233
/* find if there is a found_set with same table_offset & found_offset
6925
8242
  int i;
6926
8243
  for (i=0 ; (uint) i < found_sets ; i++)
6927
8244
    if (found_set[i].table_offset == table_offset &&
6928
 
        found_set[i].found_offset == found_offset)
 
8245
        found_set[i].found_offset == found_offset)
6929
8246
      return -i-2;
6930
8247
  found_set[i].table_offset=table_offset;
6931
8248
  found_set[i].found_offset=found_offset;
6932
8249
  found_sets++;
6933
 
  return -i-2;        /* return new postion */
 
8250
  return -i-2;                          /* return new postion */
6934
8251
}
6935
8252
 
6936
8253
/* Return 1 if regexp starts with \b or ends with \b*/
6937
8254
 
6938
8255
uint start_at_word(char * pos)
6939
8256
{
6940
 
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
6941
 
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
 
8257
  return (((!bcmp((const uchar*) pos, (const uchar*) "\\b",2) && pos[2]) ||
 
8258
           !bcmp((const uchar*) pos, (const uchar*) "\\^", 2)) ? 1 : 0);
6942
8259
}
6943
8260
 
6944
8261
uint end_of_word(char * pos)
6945
8262
{
6946
 
  char * end= strchr(pos, '\0');
6947
 
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
6948
 
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
 
8263
  char * end=strend(pos);
 
8264
  return ((end > pos+2 && !bcmp((const uchar*) end-2,
 
8265
                                (const uchar*) "\\b", 2)) ||
 
8266
          (end >= pos+2 && !bcmp((const uchar*) end-2,
 
8267
                                (const uchar*) "\\$",2))) ? 1 : 0;
6949
8268
}
6950
8269
 
6951
8270
/****************************************************************************
6952
8271
 * Handle replacement of strings
6953
8272
 ****************************************************************************/
6954
8273
 
6955
 
#define PC_MALLOC    256  /* Bytes for pointers */
6956
 
#define PS_MALLOC    512  /* Bytes for data */
 
8274
#define PC_MALLOC               256     /* Bytes for pointers */
 
8275
#define PS_MALLOC               512     /* Bytes for data */
6957
8276
 
6958
8277
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6959
8278
{
6960
8279
  uint i,length,old_count;
6961
 
  unsigned char *new_pos;
 
8280
  uchar *new_pos;
6962
8281
  const char **new_array;
6963
 
 
 
8282
  DBUG_ENTER("insert_pointer_name");
6964
8283
 
6965
8284
  if (! pa->typelib.count)
6966
8285
  {
6967
8286
    if (!(pa->typelib.type_names=(const char **)
6968
 
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
6969
 
                     (sizeof(char *)+sizeof(*pa->flag))*
6970
 
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6971
 
      return(-1);
6972
 
    if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
6973
 
                                      MYF(MY_WME))))
 
8287
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
 
8288
                     (sizeof(char *)+sizeof(*pa->flag))*
 
8289
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
 
8290
      DBUG_RETURN(-1);
 
8291
    if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
 
8292
                                     MYF(MY_WME))))
6974
8293
    {
6975
 
      free((char*) pa->typelib.type_names);
6976
 
      return (-1);
 
8294
      my_free((char*) pa->typelib.type_names,MYF(0));
 
8295
      DBUG_RETURN (-1);
6977
8296
    }
6978
 
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(unsigned char*)+
6979
 
                                               sizeof(*pa->flag));
6980
 
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
 
8297
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
 
8298
                                               sizeof(*pa->flag));
 
8299
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6981
8300
    pa->length=0;
6982
8301
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6983
8302
    pa->array_allocs=1;
6985
8304
  length=(uint) strlen(name)+1;
6986
8305
  if (pa->length+length >= pa->max_length)
6987
8306
  {
6988
 
    if (!(new_pos= (unsigned char*) my_realloc((unsigned char*) pa->str,
6989
 
                                       (uint) (pa->max_length+PS_MALLOC),
6990
 
                                       MYF(MY_WME))))
6991
 
      return(1);
 
8307
    if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
 
8308
                                      (uint) (pa->max_length+PS_MALLOC),
 
8309
                                      MYF(MY_WME))))
 
8310
      DBUG_RETURN(1);
6992
8311
    if (new_pos != pa->str)
6993
8312
    {
6994
8313
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
6995
8314
      for (i=0 ; i < pa->typelib.count ; i++)
6996
 
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
6997
 
                                              char*);
 
8315
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
 
8316
                                              char*);
6998
8317
      pa->str=new_pos;
6999
8318
    }
7000
8319
    pa->max_length+=PS_MALLOC;
7004
8323
    int len;
7005
8324
    pa->array_allocs++;
7006
8325
    len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7007
 
    if (!(new_array=(const char **) my_realloc((unsigned char*) pa->typelib.type_names,
7008
 
                                               (uint) len/
7009
 
                                               (sizeof(unsigned char*)+sizeof(*pa->flag))*
7010
 
                                               (sizeof(unsigned char*)+sizeof(*pa->flag)),
 
8326
    if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
 
8327
                                               (uint) len/
 
8328
                                               (sizeof(uchar*)+sizeof(*pa->flag))*
 
8329
                                               (sizeof(uchar*)+sizeof(*pa->flag)),
7011
8330
                                               MYF(MY_WME))))
7012
 
      return(1);
 
8331
      DBUG_RETURN(1);
7013
8332
    pa->typelib.type_names=new_array;
7014
8333
    old_count=pa->max_count;
7015
 
    pa->max_count=len/(sizeof(unsigned char*) + sizeof(*pa->flag));
7016
 
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
7017
 
    memcpy(pa->flag, pa->typelib.type_names+old_count,
7018
 
           old_count*sizeof(*pa->flag));
 
8334
    pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
 
8335
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
 
8336
    memcpy((uchar*) pa->flag,(char *) (pa->typelib.type_names+old_count),
 
8337
           old_count*sizeof(*pa->flag));
7019
8338
  }
7020
 
  pa->flag[pa->typelib.count]=0;      /* Reset flag */
 
8339
  pa->flag[pa->typelib.count]=0;                        /* Reset flag */
7021
8340
  pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
7022
 
  pa->typelib.type_names[pa->typelib.count]= NULL;  /* Put end-mark */
7023
 
  my_stpcpy((char*) pa->str+pa->length,name);
 
8341
  pa->typelib.type_names[pa->typelib.count]= NullS;     /* Put end-mark */
 
8342
  VOID(strmov((char*) pa->str+pa->length,name));
7024
8343
  pa->length+=length;
7025
 
  return(0);
 
8344
  DBUG_RETURN(0);
7026
8345
} /* insert_pointer_name */
7027
8346
 
7028
8347
 
7033
8352
  if (pa->typelib.count)
7034
8353
  {
7035
8354
    pa->typelib.count=0;
7036
 
    free((char*) pa->typelib.type_names);
 
8355
    my_free((char*) pa->typelib.type_names,MYF(0));
7037
8356
    pa->typelib.type_names=0;
7038
 
    free(pa->str);
 
8357
    my_free(pa->str,MYF(0));
7039
8358
  }
7040
8359
} /* free_pointer_array */
7041
8360
 
7043
8362
/* Functions that uses replace and replace_regex */
7044
8363
 
7045
8364
/* Append the string to ds, with optional replace */
7046
 
void replace_append_mem(string *ds,
7047
 
                        const char *val, int len)
 
8365
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
 
8366
                               const char *val, int len)
7048
8367
{
7049
 
  char *v= strdup(val);
7050
 
 
7051
8368
  if (glob_replace_regex)
7052
8369
  {
7053
8370
    /* Regex replace */
7054
 
    if (!multi_reg_replace(glob_replace_regex, v))
 
8371
    if (!multi_reg_replace(glob_replace_regex, (char*)val))
7055
8372
    {
7056
 
      v= glob_replace_regex->buf;
7057
 
      len= strlen(v);
 
8373
      val= glob_replace_regex->buf;
 
8374
      len= strlen(val);
7058
8375
    }
7059
8376
  }
7060
8377
 
7061
8378
  if (glob_replace)
7062
8379
  {
7063
8380
    /* Normal replace */
7064
 
    replace_strings_append(glob_replace, ds, v, len);
 
8381
    replace_strings_append(glob_replace, ds, val, len);
7065
8382
  }
7066
8383
  else
7067
 
  {
7068
 
    ds->append(v, len);
7069
 
  }
 
8384
    dynstr_append_mem(ds, val, len);
7070
8385
}
7071
8386
 
7072
8387
 
7073
8388
/* Append zero-terminated string to ds, with optional replace */
7074
 
void replace_append(string *ds, const char *val)
 
8389
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7075
8390
{
7076
 
  replace_append_mem(ds, val, strlen(val));
 
8391
  replace_dynstr_append_mem(ds, val, strlen(val));
7077
8392
}
7078
8393
 
7079
8394
/* Append uint to ds, with optional replace */
7080
 
void replace_append_uint(string *ds, uint val)
 
8395
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7081
8396
{
7082
8397
  char buff[22]; /* This should be enough for any int */
7083
 
  char *end= int64_t10_to_str(val, buff, 10);
7084
 
  replace_append_mem(ds, buff, end - buff);
7085
 
 
 
8398
  char *end= longlong10_to_str(val, buff, 10);
 
8399
  replace_dynstr_append_mem(ds, buff, end - buff);
7086
8400
}
7087
8401
 
7088
8402
 
7099
8413
 
7100
8414
*/
7101
8415
 
7102
 
 
7103
 
void append_sorted(string* ds, string *ds_input)
7104
 
{
7105
 
  priority_queue<string, vector<string>, greater<string> > lines;
7106
 
 
7107
 
  if (ds_input->empty())
7108
 
    return;  /* No input */
7109
 
 
7110
 
  unsigned long eol_pos= 0;
7111
 
 
7112
 
  eol_pos= ds_input->find_first_of('\n', 0);
7113
 
  if (eol_pos == string::npos)
7114
 
    return; // We should have at least one header here
7115
 
 
7116
 
  ds->append(ds_input->substr(0, eol_pos+1));
7117
 
 
7118
 
  unsigned long start_pos= eol_pos+1;
 
8416
static int comp_lines(const char **a, const char **b)
 
8417
{
 
8418
  return (strcmp(*a,*b));
 
8419
}
 
8420
 
 
8421
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
 
8422
{
 
8423
  unsigned i;
 
8424
  char *start= ds_input->str;
 
8425
  DYNAMIC_ARRAY lines;
 
8426
  DBUG_ENTER("dynstr_append_sorted");
 
8427
 
 
8428
  if (!*start)
 
8429
    DBUG_VOID_RETURN;  /* No input */
 
8430
 
 
8431
  my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
 
8432
 
 
8433
  /* First line is result header, skip past it */
 
8434
  while (*start && *start != '\n')
 
8435
    start++;
 
8436
  start++; /* Skip past \n */
 
8437
  dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
7119
8438
 
7120
8439
  /* Insert line(s) in array */
7121
 
  do {
 
8440
  while (*start)
 
8441
  {
 
8442
    char* line_end= (char*)start;
7122
8443
 
7123
 
    eol_pos= ds_input->find_first_of('\n', start_pos);
7124
8444
    /* Find end of line */
7125
 
    lines.push(ds_input->substr(start_pos, eol_pos-start_pos+1));
7126
 
    start_pos= eol_pos+1;
7127
 
 
7128
 
  } while ( eol_pos != string::npos);
 
8445
    while (*line_end && *line_end != '\n')
 
8446
      line_end++;
 
8447
    *line_end= 0;
 
8448
 
 
8449
    /* Insert pointer to the line in array */
 
8450
    if (insert_dynamic(&lines, (uchar*) &start))
 
8451
      die("Out of memory inserting lines to sort");
 
8452
 
 
8453
    start= line_end+1;
 
8454
  }
 
8455
 
 
8456
  /* Sort array */
 
8457
  qsort(lines.buffer, lines.elements,
 
8458
        sizeof(char**), (qsort_cmp)comp_lines);
7129
8459
 
7130
8460
  /* Create new result */
7131
 
  while (!lines.empty()) {
7132
 
    ds->append(lines.top());
7133
 
    lines.pop();
 
8461
  for (i= 0; i < lines.elements ; i++)
 
8462
  {
 
8463
    const char **line= dynamic_element(&lines, i, const char**);
 
8464
    dynstr_append(ds, *line);
 
8465
    dynstr_append(ds, "\n");
7134
8466
  }
7135
8467
 
7136
 
  return;
 
8468
  delete_dynamic(&lines);
 
8469
  DBUG_VOID_RETURN;
7137
8470
}