~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqltest.cc

Removed/replaced DBUG symbols and standardized TRUE/FALSE

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
 
37
32
*/
38
33
 
39
34
#define MTEST_VERSION "3.3"
 
35
#include <pcrecpp.h>
40
36
 
41
 
#include "config.h"
42
37
#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>
 
38
#include <drizzle_version.h>
 
39
#include <mysqld_error.h>
 
40
#include <m_ctype.h>
 
41
#include <my_dir.h>
 
42
#include <hash.h>
52
43
#include <stdarg.h>
53
 
 
54
 
#include "errname.h"
55
 
 
56
 
using namespace std;
 
44
#include <violite.h>
 
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 parsing_disabled= 0;
 
78
static my_bool display_result_vertically= FALSE,
 
79
  display_metadata= FALSE, display_result_sorted= FALSE;
 
80
static my_bool disable_query_log= 0, disable_result_log= 0;
 
81
static my_bool disable_warnings= 0;
 
82
static my_bool disable_info= 1;
 
83
static my_bool abort_on_error= 1;
 
84
static my_bool server_initialized= 0;
 
85
static my_bool is_windows= 0;
92
86
static char **default_argv;
93
 
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
 
87
static const char *load_default_groups[]= { "mysqltest", "client", 0 };
94
88
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
95
89
 
96
90
static uint start_lineno= 0; /* Start line of current command */
114
108
struct st_block
115
109
{
116
110
  int             line; /* Start line of block */
117
 
  bool         ok;   /* Should block be executed */
 
111
  my_bool         ok;   /* Should block be executed */
118
112
  enum block_cmd  cmd;  /* Command owning the block */
119
113
};
120
114
 
134
128
static struct st_test_file* file_stack_end;
135
129
 
136
130
 
137
 
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
 
131
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
 
132
 
 
133
static const char *embedded_server_groups[]=
 
134
{
 
135
  "server",
 
136
  "embedded",
 
137
  "mysqltest_SERVER",
 
138
  NullS
 
139
};
138
140
 
139
141
static int embedded_server_arg_count=0;
140
142
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
144
146
  See the timer_output() definition for details
145
147
*/
146
148
static char *timer_file = NULL;
147
 
static uint64_t timer_start;
 
149
static ulonglong timer_start;
148
150
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;
 
151
static ulonglong timer_now(void);
 
152
 
 
153
static ulonglong progress_start= 0;
 
154
 
 
155
DYNAMIC_ARRAY q_lines;
154
156
 
155
157
typedef struct {
156
158
  int read_lines,current_line;
160
162
typedef struct
161
163
{
162
164
  char file[FN_REFLEN];
163
 
  uint32_t pos;
 
165
  ulong pos;
164
166
} master_pos_st;
165
167
 
166
168
master_pos_st master_pos;
188
190
 
189
191
struct st_connection
190
192
{
191
 
  DRIZZLE drizzle;
 
193
  MYSQL mysql;
192
194
  /* Used when creating views and sp, to avoid implicit commit */
193
 
  DRIZZLE *util_drizzle;
 
195
  MYSQL* util_mysql;
194
196
  char *name;
195
197
};
196
198
struct st_connection connections[128];
197
199
struct st_connection* cur_con= NULL, *next_con, *connections_end;
198
200
 
199
201
/*
200
 
  List of commands in drizzletest
 
202
  List of commands in mysqltest
201
203
  Must match the "command_names" array
202
204
  Add new commands before Q_UNKNOWN!
203
205
*/
204
206
enum enum_commands {
205
207
  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,
 
208
  Q_CONNECT,        Q_SLEEP, Q_REAL_SLEEP,
 
209
  Q_INC,                    Q_DEC,
 
210
  Q_SOURCE,         Q_DISCONNECT,
 
211
  Q_LET,                    Q_ECHO,
 
212
  Q_WHILE,          Q_END_BLOCK,
 
213
  Q_SYSTEM,         Q_RESULT,
 
214
  Q_REQUIRE,        Q_SAVE_MASTER_POS,
213
215
  Q_SYNC_WITH_MASTER,
214
216
  Q_SYNC_SLAVE_WITH_MASTER,
215
217
  Q_ERROR,
216
 
  Q_SEND,        Q_REAP,
217
 
  Q_DIRTY_CLOSE,      Q_REPLACE, Q_REPLACE_COLUMN,
218
 
  Q_PING,        Q_EVAL,
 
218
  Q_SEND,                   Q_REAP,
 
219
  Q_DIRTY_CLOSE,            Q_REPLACE, Q_REPLACE_COLUMN,
 
220
  Q_PING,                   Q_EVAL,
219
221
  Q_EVAL_RESULT,
220
222
  Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
221
223
  Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
228
230
  Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
229
231
  Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
230
232
  Q_START_TIMER, Q_END_TIMER,
231
 
  Q_CHARACTER_SET,
 
233
  Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
232
234
  Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
233
235
  Q_IF,
234
236
  Q_DISABLE_PARSING, Q_ENABLE_PARSING,
237
239
  Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
238
240
  Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
239
241
 
240
 
  Q_UNKNOWN,             /* Unknown command.   */
241
 
  Q_COMMENT,             /* Comments, ignored. */
 
242
  Q_UNKNOWN,                           /* Unknown command.   */
 
243
  Q_COMMENT,                           /* Comments, ignored. */
242
244
  Q_COMMENT_WITH_COMMAND
243
245
};
244
246
 
310
312
  "copy_file",
311
313
  "perl",
312
314
  "die",
313
 
 
 
315
               
314
316
  /* Don't execute any more commands, compare result */
315
317
  "exit",
316
318
  "skip",
362
364
{
363
365
  char *query, *query_buf,*first_argument,*last_argument,*end;
364
366
  int first_word_len, query_len;
365
 
  bool abort_on_error;
 
367
  my_bool abort_on_error;
366
368
  struct st_expected_errors expected_errors;
367
369
  char require_file[FN_REFLEN];
368
370
  enum enum_commands type;
369
371
};
370
372
 
371
373
TYPELIB command_typelib= {array_elements(command_names),"",
372
 
                          command_names, 0};
 
374
                          command_names, 0};
373
375
 
374
 
string ds_res, ds_progress, ds_warning_messages;
 
376
DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
375
377
 
376
378
char builtin_echo[FN_REFLEN];
377
379
 
378
380
void die(const char *fmt, ...)
379
 
  __attribute__((format(printf, 1, 2)));
 
381
  ATTRIBUTE_FORMAT(printf, 1, 2);
380
382
void abort_not_supported_test(const char *fmt, ...)
381
 
  __attribute__((format(printf, 1, 2)));
 
383
  ATTRIBUTE_FORMAT(printf, 1, 2);
382
384
void verbose_msg(const char *fmt, ...)
383
 
  __attribute__((format(printf, 1, 2)));
 
385
  ATTRIBUTE_FORMAT(printf, 1, 2);
384
386
void warning_msg(const char *fmt, ...)
385
 
  __attribute__((format(printf, 1, 2)));
 
387
  ATTRIBUTE_FORMAT(printf, 1, 2);
386
388
void log_msg(const char *fmt, ...)
387
 
  __attribute__((format(printf, 1, 2)));
 
389
  ATTRIBUTE_FORMAT(printf, 1, 2);
388
390
 
389
391
VAR* var_from_env(const char *, const char *);
390
392
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
391
393
              int val_len);
392
394
void var_free(void* v);
393
395
VAR* var_get(const char *var_name, const char** var_name_end,
394
 
             bool raw, bool ignore_not_existing);
 
396
             my_bool raw, my_bool ignore_not_existing);
395
397
void eval_expr(VAR* v, const char *p, const char** p_end);
396
 
bool match_delimiter(int c, const char *delim, uint length);
 
398
my_bool match_delimiter(int c, const char *delim, uint length);
397
399
void dump_result_to_reject_file(char *buf, int size);
398
 
void dump_result_to_log_file(const char *buf, int size);
 
400
void dump_result_to_log_file(char *buf, int size);
399
401
void dump_warning_messages(void);
400
402
void dump_progress(void);
401
403
 
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);
 
404
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
 
405
             const char *query_end, my_bool pass_through_escape_chars);
 
406
void str_to_file(const char *fname, char *str, int size);
 
407
void str_to_file2(const char *fname, char *str, int size, my_bool append);
406
408
 
407
409
/* For replace_column */
408
410
static char *replace_column[MAX_COLUMNS];
428
430
  free_replace_column();
429
431
}
430
432
 
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);
 
433
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
 
434
                               int len);
 
435
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
 
436
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
 
437
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input);
436
438
 
437
439
void handle_error(struct st_command*,
438
440
                  unsigned int err_errno, const char *err_error,
439
 
                  const char *err_sqlstate, string *ds);
 
441
                  const char *err_sqlstate, DYNAMIC_STRING *ds);
440
442
void handle_no_error(struct st_command*);
441
443
 
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)
 
444
#ifdef EMBEDDED_LIBRARY
 
445
 
 
446
/* attributes of the query thread */
 
447
pthread_attr_t cn_thd_attrib;
 
448
 
 
449
/*
 
450
  send_one_query executes query in separate thread, which is
 
451
  necessary in embedded library to run 'send' in proper way.
 
452
  This implementation doesn't handle errors returned
 
453
  by mysql_send_query. It's technically possible, though
 
454
  I don't see where it is needed.
 
455
*/
 
456
pthread_handler_t send_one_query(void *arg)
 
457
{
 
458
  struct st_connection *cn= (struct st_connection*)arg;
 
459
 
 
460
  mysql_thread_init();
 
461
  VOID(mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len));
 
462
 
 
463
  mysql_thread_end();
 
464
  pthread_mutex_lock(&cn->mutex);
 
465
  cn->query_done= 1;
 
466
  VOID(pthread_cond_signal(&cn->cond));
 
467
  pthread_mutex_unlock(&cn->mutex);
 
468
  pthread_exit(0);
 
469
  return 0;
 
470
}
 
471
 
 
472
static int do_send_query(struct st_connection *cn, const char *q, int q_len,
 
473
                         int flags)
 
474
{
 
475
  pthread_t tid;
 
476
 
 
477
  if (flags & QUERY_REAP_FLAG)
 
478
    return mysql_send_query(&cn->mysql, q, q_len);
 
479
 
 
480
  if (pthread_mutex_init(&cn->mutex, NULL) ||
 
481
      pthread_cond_init(&cn->cond, NULL))
 
482
    die("Error in the thread library");
 
483
 
 
484
  cn->cur_query= q;
 
485
  cn->cur_query_len= q_len;
 
486
  cn->query_done= 0;
 
487
  if (pthread_create(&tid, &cn_thd_attrib, send_one_query, (void*)cn))
 
488
    die("Cannot start new thread for query");
 
489
 
 
490
  return 0;
 
491
}
 
492
 
 
493
static void wait_query_thread_end(struct st_connection *con)
 
494
{
 
495
  if (!con->query_done)
 
496
  {
 
497
    pthread_mutex_lock(&con->mutex);
 
498
    while (!con->query_done)
 
499
      pthread_cond_wait(&con->cond, &con->mutex);
 
500
    pthread_mutex_unlock(&con->mutex);
 
501
  }
 
502
}
 
503
 
 
504
#else /*EMBEDDED_LIBRARY*/
 
505
 
 
506
#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q, q_len)
 
507
 
 
508
#endif /*EMBEDDED_LIBRARY*/
 
509
 
 
510
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
 
511
             const char *query_end, my_bool pass_through_escape_chars)
447
512
{
448
513
  const char *p;
449
514
  register char c, next_c;
450
515
  register int escaped = 0;
451
516
  VAR *v;
452
 
 
 
517
  DBUG_ENTER("do_eval");
453
518
 
454
519
  for (p= query; (c= *p) && p < query_end; ++p)
455
520
  {
457
522
    case '$':
458
523
      if (escaped)
459
524
      {
460
 
        escaped= 0;
461
 
        query_eval->append(p, 1);
 
525
        escaped= 0;
 
526
        dynstr_append_mem(query_eval, p, 1);
462
527
      }
463
528
      else
464
529
      {
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);
 
530
        if (!(v= var_get(p, &p, 0, 0)))
 
531
          die("Bad variable in eval");
 
532
        dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
468
533
      }
469
534
      break;
470
535
    case '\\':
471
536
      next_c= *(p+1);
472
537
      if (escaped)
473
538
      {
474
 
        escaped= 0;
475
 
        query_eval->append(p, 1);
 
539
        escaped= 0;
 
540
        dynstr_append_mem(query_eval, p, 1);
476
541
      }
477
542
      else if (next_c == '\\' || next_c == '$' || next_c == '"')
478
543
      {
479
544
        /* Set escaped only if next char is \, " or $ */
480
 
        escaped= 1;
 
545
        escaped= 1;
481
546
 
482
547
        if (pass_through_escape_chars)
483
548
        {
484
549
          /* The escape char should be added to the output string. */
485
 
          query_eval->append(p, 1);
 
550
          dynstr_append_mem(query_eval, p, 1);
486
551
        }
487
552
      }
488
553
      else
489
 
        query_eval->append(p, 1);
 
554
        dynstr_append_mem(query_eval, p, 1);
490
555
      break;
491
556
    default:
492
557
      escaped= 0;
493
 
      query_eval->append(p, 1);
 
558
      dynstr_append_mem(query_eval, p, 1);
494
559
      break;
495
560
    }
496
561
  }
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 */
 
562
  DBUG_VOID_RETURN;
542
563
}
543
564
 
544
565
 
550
571
 
551
572
  SYNOPSIS
552
573
  show_query
553
 
  drizzle - connection to use
 
574
  mysql - connection to use
554
575
  query - query to run
555
576
 
556
577
*/
557
578
 
558
 
static void show_query(DRIZZLE *drizzle, const char* query)
 
579
static void show_query(MYSQL* mysql, const char* query)
559
580
{
560
 
  DRIZZLE_RES* res;
561
 
 
562
 
 
563
 
  if (!drizzle)
564
 
    return;
565
 
 
566
 
  if (drizzle_query(drizzle, query))
 
581
  MYSQL_RES* res;
 
582
  DBUG_ENTER("show_query");
 
583
 
 
584
  if (!mysql)
 
585
    DBUG_VOID_RETURN;
 
586
 
 
587
  if (mysql_query(mysql, query))
567
588
  {
568
589
    log_msg("Error running query '%s': %d %s",
569
 
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
570
 
    return;
 
590
            query, mysql_errno(mysql), mysql_error(mysql));
 
591
    DBUG_VOID_RETURN;
571
592
  }
572
593
 
573
 
  if ((res= drizzle_store_result(drizzle)) == NULL)
 
594
  if ((res= mysql_store_result(mysql)) == NULL)
574
595
  {
575
596
    /* No result set returned */
576
 
    return;
 
597
    DBUG_VOID_RETURN;
577
598
  }
578
599
 
579
600
  {
580
 
    DRIZZLE_ROW row;
 
601
    MYSQL_ROW row;
581
602
    unsigned int i;
582
603
    unsigned int row_num= 0;
583
 
    unsigned int num_fields= drizzle_num_fields(res);
584
 
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
604
    unsigned int num_fields= mysql_num_fields(res);
 
605
    MYSQL_FIELD *fields= mysql_fetch_fields(res);
585
606
 
586
607
    fprintf(stderr, "=== %s ===\n", query);
587
 
    while ((row= drizzle_fetch_row(res)))
 
608
    while ((row= mysql_fetch_row(res)))
588
609
    {
589
 
      uint32_t *lengths= drizzle_fetch_lengths(res);
 
610
      unsigned long *lengths= mysql_fetch_lengths(res);
590
611
      row_num++;
591
612
 
592
613
      fprintf(stderr, "---- %d. ----\n", row_num);
601
622
      fprintf(stderr, "=");
602
623
    fprintf(stderr, "\n\n");
603
624
  }
604
 
  drizzle_free_result(res);
 
625
  mysql_free_result(res);
605
626
 
606
 
  return;
 
627
  DBUG_VOID_RETURN;
607
628
}
608
629
 
609
630
 
616
637
 
617
638
  SYNOPSIS
618
639
  show_warnings_before_error
619
 
  drizzle - connection to use
 
640
  mysql - connection to use
620
641
 
621
642
*/
622
643
 
623
 
static void show_warnings_before_error(DRIZZLE *drizzle)
 
644
static void show_warnings_before_error(MYSQL* mysql)
624
645
{
625
 
  DRIZZLE_RES* res;
 
646
  MYSQL_RES* res;
626
647
  const char* query= "SHOW WARNINGS";
627
 
 
628
 
 
629
 
  if (!drizzle)
630
 
    return;
631
 
 
632
 
  if (drizzle_query(drizzle, query))
 
648
  DBUG_ENTER("show_warnings_before_error");
 
649
 
 
650
  if (!mysql)
 
651
    DBUG_VOID_RETURN;
 
652
 
 
653
  if (mysql_query(mysql, query))
633
654
  {
634
655
    log_msg("Error running query '%s': %d %s",
635
 
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
636
 
    return;
 
656
            query, mysql_errno(mysql), mysql_error(mysql));
 
657
    DBUG_VOID_RETURN;
637
658
  }
638
659
 
639
 
  if ((res= drizzle_store_result(drizzle)) == NULL)
 
660
  if ((res= mysql_store_result(mysql)) == NULL)
640
661
  {
641
662
    /* No result set returned */
642
 
    return;
 
663
    DBUG_VOID_RETURN;
643
664
  }
644
665
 
645
 
  if (drizzle_num_rows(res) <= 1)
 
666
  if (mysql_num_rows(res) <= 1)
646
667
  {
647
668
    /* Don't display the last row, it's "last error" */
648
669
  }
649
670
  else
650
671
  {
651
 
    DRIZZLE_ROW row;
 
672
    MYSQL_ROW row;
652
673
    unsigned int row_num= 0;
653
 
    unsigned int num_fields= drizzle_num_fields(res);
 
674
    unsigned int num_fields= mysql_num_fields(res);
654
675
 
655
676
    fprintf(stderr, "\nWarnings from just before the error:\n");
656
 
    while ((row= drizzle_fetch_row(res)))
 
677
    while ((row= mysql_fetch_row(res)))
657
678
    {
658
 
      uint32_t i;
659
 
      uint32_t *lengths= drizzle_fetch_lengths(res);
 
679
      unsigned int i;
 
680
      unsigned long *lengths= mysql_fetch_lengths(res);
660
681
 
661
 
      if (++row_num >= drizzle_num_rows(res))
 
682
      if (++row_num >= mysql_num_rows(res))
662
683
      {
663
684
        /* Don't display the last row, it's "last error" */
664
685
        break;
672
693
      fprintf(stderr, "\n");
673
694
    }
674
695
  }
675
 
  drizzle_free_result(res);
 
696
  mysql_free_result(res);
676
697
 
677
 
  return;
 
698
  DBUG_VOID_RETURN;
678
699
}
679
700
 
680
701
 
687
708
struct command_arg {
688
709
  const char *argname;       /* Name of argument   */
689
710
  enum arg_type type;        /* Type of argument   */
690
 
  bool required;          /* Argument required  */
691
 
  string *ds;        /* Storage for argument */
 
711
  my_bool required;          /* Argument required  */
 
712
  DYNAMIC_STRING *ds;        /* Storage for argument */
692
713
  const char *description;   /* Description of the argument */
693
714
};
694
715
 
701
722
  int i;
702
723
  const char *ptr= arguments;
703
724
  const char *start;
 
725
  DBUG_ENTER("check_command_args");
 
726
  DBUG_PRINT("enter", ("num_args: %d", num_args));
704
727
 
705
728
  for (i= 0; i < num_args; i++)
706
729
  {
718
741
        ptr++;
719
742
      if (ptr > start)
720
743
      {
721
 
        do_eval(arg->ds, start, ptr, false);
 
744
        init_dynamic_string(arg->ds, 0, ptr-start, 32);
 
745
        do_eval(arg->ds, start, ptr, FALSE);
722
746
      }
723
747
      else
724
748
      {
725
749
        /* Empty string */
726
 
        arg->ds->erase();
 
750
        init_dynamic_string(arg->ds, "", 0, 0);
727
751
      }
728
752
      command->last_argument= (char*)ptr;
729
753
 
730
754
      /* Step past the delimiter */
731
755
      if (*ptr && *ptr == delimiter_arg)
732
756
        ptr++;
 
757
      DBUG_PRINT("info", ("val: %s", arg->ds->str));
733
758
      break;
734
759
 
735
760
      /* Rest of line */
736
761
    case ARG_REST:
737
762
      start= ptr;
738
 
      do_eval(arg->ds, start, command->end, false);
 
763
      init_dynamic_string(arg->ds, 0, command->query_len, 256);
 
764
      do_eval(arg->ds, start, command->end, FALSE);
739
765
      command->last_argument= command->end;
 
766
      DBUG_PRINT("info", ("val: %s", arg->ds->str));
740
767
      break;
741
768
 
742
769
    default:
743
 
      assert("Unknown argument type");
 
770
      DBUG_ASSERT("Unknown argument type");
744
771
      break;
745
772
    }
746
773
 
747
774
    /* Check required arg */
748
 
    if (arg->ds->length() == 0 && arg->required)
 
775
    if (arg->ds->length == 0 && arg->required)
749
776
      die("Missing required argument '%s' to command '%.*s'", arg->argname,
750
777
          command->first_word_len, command->query);
751
778
 
759
786
          ptr, command->first_word_len, command->query);
760
787
    ptr++;
761
788
  }
762
 
  return;
 
789
  DBUG_VOID_RETURN;
763
790
}
764
791
 
765
792
 
766
793
static void handle_command_error(struct st_command *command, uint error)
767
794
{
768
 
 
 
795
  DBUG_ENTER("handle_command_error");
 
796
  DBUG_PRINT("enter", ("error: %d", error));
769
797
  if (error != 0)
770
798
  {
771
799
    uint i;
775
803
          command->first_word_len, command->query, error);
776
804
    for (i= 0; i < command->expected_errors.count; i++)
777
805
    {
 
806
      DBUG_PRINT("info", ("expected error: %d",
 
807
                          command->expected_errors.err[i].code.errnum));
778
808
      if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
779
809
          (command->expected_errors.err[i].code.errnum == error))
780
810
      {
781
 
        return;
 
811
        DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d",
 
812
                            command->first_word_len, command->query, error));
 
813
        DBUG_VOID_RETURN;
782
814
      }
783
815
    }
784
816
    die("command \"%.*s\" failed with wrong error: %d",
792
824
        command->first_word_len, command->query,
793
825
        command->expected_errors.err[0].code.errnum);
794
826
  }
795
 
  return;
 
827
  DBUG_VOID_RETURN;
796
828
}
797
829
 
798
830
 
799
831
static void close_connections(void)
800
832
{
801
 
 
 
833
  DBUG_ENTER("close_connections");
802
834
  for (--next_con; next_con >= connections; --next_con)
803
835
  {
804
 
    drizzle_close(&next_con->drizzle);
805
 
    if (next_con->util_drizzle)
806
 
      drizzle_close(next_con->util_drizzle);
807
 
    free(next_con->name);
 
836
    mysql_close(&next_con->mysql);
 
837
    if (next_con->util_mysql)
 
838
      mysql_close(next_con->util_mysql);
 
839
    my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
808
840
  }
809
 
  return;
 
841
  DBUG_VOID_RETURN;
810
842
}
811
843
 
812
844
 
813
845
static void close_files(void)
814
846
{
815
 
 
 
847
  DBUG_ENTER("close_files");
816
848
  for (; cur_file >= file_stack; cur_file--)
817
849
  {
818
850
    if (cur_file->file && cur_file->file != stdin)
819
851
    {
 
852
      DBUG_PRINT("info", ("closing file: %s", cur_file->file_name));
820
853
      my_fclose(cur_file->file, MYF(0));
821
854
    }
822
 
    free((unsigned char*) cur_file->file_name);
 
855
    my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
823
856
    cur_file->file_name= 0;
824
857
  }
825
 
  return;
 
858
  DBUG_VOID_RETURN;
826
859
}
827
860
 
828
861
 
829
862
static void free_used_memory(void)
830
863
{
831
864
  uint i;
832
 
 
 
865
  DBUG_ENTER("free_used_memory");
833
866
 
834
867
  close_connections();
835
868
  close_files();
836
869
  hash_free(&var_hash);
837
870
 
838
 
  vector<struct st_command *>::iterator iter;
839
 
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
 
871
  for (i= 0 ; i < q_lines.elements ; i++)
840
872
  {
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);
 
873
    struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
 
874
    my_free((*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
 
875
    my_free((*q),MYF(0));
847
876
  }
848
 
 
849
877
  for (i= 0; i < 10; i++)
850
878
  {
851
879
    if (var_reg[i].alloced_len)
852
 
      free(var_reg[i].str_val);
 
880
      my_free(var_reg[i].str_val, MYF(MY_WME));
853
881
  }
854
882
  while (embedded_server_arg_count > 1)
855
 
    free(embedded_server_args[--embedded_server_arg_count]);
856
 
 
 
883
    my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
 
884
  delete_dynamic(&q_lines);
 
885
  dynstr_free(&ds_res);
 
886
  dynstr_free(&ds_progress);
 
887
  dynstr_free(&ds_warning_messages);
857
888
  free_all_replace();
858
 
  free(opt_pass);
 
889
  my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
859
890
  free_defaults(default_argv);
860
891
 
 
892
  /* Only call mysql_server_end if mysql_server_init has been called */
 
893
  if (server_initialized)
 
894
    mysql_server_end();
 
895
 
 
896
  /* Don't use DBUG after mysql_server_end() */
861
897
  return;
862
898
}
863
899
 
877
913
      break;
878
914
    case 62:
879
915
      printf("skipped\n");
880
 
      break;
 
916
    break;
881
917
    default:
882
918
      printf("unknown exit code: %d\n", exit_code);
883
 
      assert(0);
 
919
      DBUG_ASSERT(0);
884
920
    }
885
921
  }
886
922
 
891
927
{
892
928
  static int dying= 0;
893
929
  va_list args;
 
930
  DBUG_ENTER("die");
 
931
  DBUG_PRINT("enter", ("start_lineno: %d", start_lineno));
894
932
 
895
933
  /*
896
934
    Protect against dying twice
902
940
  dying= 1;
903
941
 
904
942
  /* Print the error message */
905
 
  fprintf(stderr, "drizzletest: ");
 
943
  fprintf(stderr, "mysqltest: ");
906
944
  if (cur_file && cur_file != file_stack)
907
945
    fprintf(stderr, "In included file \"%s\": ",
908
946
            cur_file->file_name);
920
958
  fflush(stderr);
921
959
 
922
960
  /* Show results from queries just before failure */
923
 
  if (ds_res.length() && opt_tail_lines)
 
961
  if (ds_res.length && opt_tail_lines)
924
962
  {
925
963
    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 )
 
964
    char* show_from= ds_res.str + ds_res.length - 1;
 
965
    while(show_from > ds_res.str && tail_lines > 0 )
928
966
    {
929
967
      show_from--;
930
968
      if (*show_from == '\n')
931
969
        tail_lines--;
932
970
    }
933
971
    fprintf(stderr, "\nThe result from queries just before the failure was:\n");
934
 
    if (show_from > ds_res.c_str())
 
972
    if (show_from > ds_res.str)
935
973
      fprintf(stderr, "< snip >");
936
974
    fprintf(stderr, "%s", show_from);
937
975
    fflush(stderr);
938
976
  }
939
977
 
940
978
  /* 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());
 
979
  if (result_file_name && ds_res.length)
 
980
    dump_result_to_log_file(ds_res.str, ds_res.length);
943
981
 
944
982
  /* Dump warning messages */
945
 
  if (result_file_name && ds_warning_messages.length())
 
983
  if (result_file_name && ds_warning_messages.length)
946
984
    dump_warning_messages();
947
985
 
948
986
  /*
950
988
    been produced prior to the error
951
989
  */
952
990
  if (cur_con)
953
 
    show_warnings_before_error(&cur_con->drizzle);
 
991
    show_warnings_before_error(&cur_con->mysql);
954
992
 
955
993
  cleanup_and_exit(1);
956
994
}
960
998
{
961
999
  va_list args;
962
1000
  struct st_test_file* err_file= cur_file;
963
 
 
 
1001
  DBUG_ENTER("abort_not_supported_test");
964
1002
 
965
1003
  /* Print include filestack */
966
1004
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
992
1030
void verbose_msg(const char *fmt, ...)
993
1031
{
994
1032
  va_list args;
995
 
 
 
1033
  DBUG_ENTER("verbose_msg");
996
1034
  if (!verbose)
997
 
    return;
 
1035
    DBUG_VOID_RETURN;
998
1036
 
999
1037
  va_start(args, fmt);
1000
 
  fprintf(stderr, "drizzletest: ");
 
1038
  fprintf(stderr, "mysqltest: ");
1001
1039
  if (cur_file && cur_file != file_stack)
1002
1040
    fprintf(stderr, "In included file \"%s\": ",
1003
1041
            cur_file->file_name);
1007
1045
  fprintf(stderr, "\n");
1008
1046
  va_end(args);
1009
1047
 
1010
 
  return;
 
1048
  DBUG_VOID_RETURN;
1011
1049
}
1012
1050
 
1013
1051
 
1016
1054
  va_list args;
1017
1055
  char buff[512];
1018
1056
  size_t len;
1019
 
 
 
1057
  DBUG_ENTER("warning_msg");
1020
1058
 
1021
1059
  va_start(args, fmt);
1022
 
  ds_warning_messages.append("drizzletest: ");
 
1060
  dynstr_append(&ds_warning_messages, "mysqltest: ");
1023
1061
  if (start_lineno != 0)
1024
1062
  {
1025
 
    ds_warning_messages.append("Warning detected ");
 
1063
    dynstr_append(&ds_warning_messages, "Warning detected ");
1026
1064
    if (cur_file && cur_file != file_stack)
1027
1065
    {
1028
1066
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1029
 
                    cur_file->file_name);
1030
 
      ds_warning_messages.append(buff, len);
 
1067
                       cur_file->file_name);
 
1068
      dynstr_append_mem(&ds_warning_messages,
 
1069
                        buff, len);
1031
1070
    }
1032
1071
    len= snprintf(buff, sizeof(buff), "at line %d: ",
1033
 
                  start_lineno);
1034
 
    ds_warning_messages.append(buff, len);
 
1072
                     start_lineno);
 
1073
    dynstr_append_mem(&ds_warning_messages,
 
1074
                      buff, len);
1035
1075
  }
1036
1076
 
1037
1077
  len= vsnprintf(buff, sizeof(buff), fmt, args);
1038
 
  ds_warning_messages.append(buff, len);
 
1078
  dynstr_append_mem(&ds_warning_messages, buff, len);
1039
1079
 
1040
 
  ds_warning_messages.append("\n");
 
1080
  dynstr_append(&ds_warning_messages, "\n");
1041
1081
  va_end(args);
1042
1082
 
1043
 
  return;
 
1083
  DBUG_VOID_RETURN;
1044
1084
}
1045
1085
 
1046
1086
 
1049
1089
  va_list args;
1050
1090
  char buff[1024];
1051
1091
  size_t len;
1052
 
 
 
1092
  DBUG_ENTER("log_msg");
1053
1093
 
1054
1094
  va_start(args, fmt);
1055
1095
  len= vsnprintf(buff, sizeof(buff)-1, fmt, args);
1056
1096
  va_end(args);
1057
1097
 
1058
 
  ds_res.append(buff, len);
1059
 
  ds_res.append("\n");
 
1098
  dynstr_append_mem(&ds_res, buff, len);
 
1099
  dynstr_append(&ds_res, "\n");
1060
1100
 
1061
 
  return;
 
1101
  DBUG_VOID_RETURN;
1062
1102
}
1063
1103
 
1064
1104
 
1072
1112
 
1073
1113
*/
1074
1114
 
1075
 
static void cat_file(string* ds, const char* filename)
 
1115
static void cat_file(DYNAMIC_STRING* ds, const char* filename)
1076
1116
{
1077
1117
  int fd;
1078
1118
  uint len;
1080
1120
 
1081
1121
  if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
1082
1122
    die("Failed to open file '%s'", filename);
1083
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1123
  while((len= my_read(fd, (uchar*)&buff,
1084
1124
                      sizeof(buff), MYF(0))) > 0)
1085
1125
  {
1086
1126
    char *p= buff, *start= buff;
1092
1132
        /* Add fake newline instead of cr and output the line */
1093
1133
        *p= '\n';
1094
1134
        p++; /* Step past the "fake" newline */
1095
 
        ds->append(start, p-start);
 
1135
        dynstr_append_mem(ds, start, p-start);
1096
1136
        p++; /* Step past the "fake" newline */
1097
1137
        start= p;
1098
1138
      }
1099
1139
      else
1100
1140
        p++;
1101
1141
    }
1102
 
    /* Output any chars that might be left */
1103
 
    ds->append(start, p-start);
 
1142
    /* Output any chars that migh be left */
 
1143
    dynstr_append_mem(ds, start, p-start);
1104
1144
  }
1105
1145
  my_close(fd, MYF(0));
1106
1146
}
1112
1152
  SYNOPSIS
1113
1153
  run_command
1114
1154
  cmd - command to execute(should be properly quoted
1115
 
  result - pointer to string where to store the result
 
1155
  ds_res- pointer to dynamic string where to store the result
1116
1156
 
1117
1157
*/
1118
1158
 
1119
 
static int run_command(const char * cmd, string * result)
 
1159
static int run_command(char* cmd,
 
1160
                       DYNAMIC_STRING *ds_res)
1120
1161
{
1121
 
  assert(result!=NULL);
1122
1162
  char buf[512]= {0};
1123
1163
  FILE *res_file;
1124
1164
  int error;
1128
1168
 
1129
1169
  while (fgets(buf, sizeof(buf), res_file))
1130
1170
  {
1131
 
    /* Save the output of this command in the supplied string */
1132
 
    result->append(buf);
 
1171
    DBUG_PRINT("info", ("buf: %s", buf));
 
1172
    if(ds_res)
 
1173
    {
 
1174
      /* Save the output of this command in the supplied string */
 
1175
      dynstr_append(ds_res, buf);
 
1176
    }
 
1177
    else
 
1178
    {
 
1179
      /* Print it directly on screen */
 
1180
      fprintf(stdout, "%s", buf);
 
1181
    }
1133
1182
  }
1134
1183
 
1135
1184
  error= pclose(res_file);
1143
1192
  SYNOPSIS
1144
1193
  run_tool
1145
1194
  tool_path - the name of the tool to run
1146
 
  result - pointer to dynamic string where to store the result
 
1195
  ds_res - pointer to dynamic string where to store the result
1147
1196
  ... - variable number of arguments that will be properly
1148
 
  quoted and appended after the tool's name
 
1197
        quoted and appended after the tool's name
1149
1198
 
1150
1199
*/
1151
1200
 
1152
 
static int run_tool(const char *tool_path, string * result, ...)
 
1201
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1153
1202
{
1154
1203
  int ret;
1155
1204
  const char* arg;
1156
1205
  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);
 
1206
  DYNAMIC_STRING ds_cmdline;
 
1207
 
 
1208
  DBUG_ENTER("run_tool");
 
1209
  DBUG_PRINT("enter", ("tool_path: %s", tool_path));
 
1210
 
 
1211
  if (init_dynamic_string(&ds_cmdline, "", FN_REFLEN, FN_REFLEN))
 
1212
    die("Out of memory");
 
1213
 
 
1214
  dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
 
1215
  dynstr_append(&ds_cmdline, " ");
 
1216
 
 
1217
  va_start(args, ds_res);
1164
1218
 
1165
1219
  while ((arg= va_arg(args, char *)))
1166
1220
  {
1167
1221
    /* Options should be os quoted */
1168
1222
    if (strncmp(arg, "--", 2) == 0)
1169
 
      append_os_quoted(&ds_cmdline, arg, NULL);
 
1223
      dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1170
1224
    else
1171
 
      ds_cmdline.append(arg);
1172
 
    ds_cmdline.append(" ");
 
1225
      dynstr_append(&ds_cmdline, arg);
 
1226
    dynstr_append(&ds_cmdline, " ");
1173
1227
  }
1174
1228
 
1175
1229
  va_end(args);
1176
1230
 
1177
 
  ret= run_command(ds_cmdline.c_str(), result);
1178
 
  return(ret);
 
1231
  DBUG_PRINT("info", ("Running: %s", ds_cmdline.str));
 
1232
  ret= run_command(ds_cmdline.str, ds_res);
 
1233
  DBUG_PRINT("exit", ("ret: %d", ret));
 
1234
  dynstr_free(&ds_cmdline);
 
1235
  DBUG_RETURN(ret);
1179
1236
}
1180
1237
 
1181
1238
 
1192
1249
 
1193
1250
*/
1194
1251
 
1195
 
static void show_diff(string* ds,
 
1252
static void show_diff(DYNAMIC_STRING* ds,
1196
1253
                      const char* filename1, const char* filename2)
1197
1254
{
1198
1255
 
1199
 
  string ds_tmp;
 
1256
  DYNAMIC_STRING ds_tmp;
 
1257
 
 
1258
  if (init_dynamic_string(&ds_tmp, "", 256, 256))
 
1259
    die("Out of memory");
1200
1260
 
1201
1261
  /* First try with unified diff */
1202
1262
  if (run_tool("diff",
1207
1267
               "2>&1",
1208
1268
               NULL) > 1) /* Most "diff" tools return >1 if error */
1209
1269
  {
1210
 
    ds_tmp= "";
 
1270
    dynstr_set(&ds_tmp, "");
1211
1271
 
1212
1272
    /* Fallback to context diff with "diff -c" */
1213
1273
    if (run_tool("diff",
1222
1282
        Fallback to dump both files to result file and inform
1223
1283
        about installing "diff"
1224
1284
      */
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");
 
1285
      dynstr_set(&ds_tmp, "");
 
1286
 
 
1287
      dynstr_append(&ds_tmp,
 
1288
"\n"
 
1289
"The two files differ but it was not possible to execute 'diff' in\n"
 
1290
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
 
1291
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
 
1292
"To get a better report you should install 'diff' on your system, which you\n"
 
1293
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
 
1294
"\n");
 
1295
 
 
1296
      dynstr_append(&ds_tmp, " --- ");
 
1297
      dynstr_append(&ds_tmp, filename1);
 
1298
      dynstr_append(&ds_tmp, " >>>\n");
1239
1299
      cat_file(&ds_tmp, filename1);
1240
 
      ds_tmp.append("<<<\n --- ");
1241
 
      ds_tmp.append(filename1);
1242
 
      ds_tmp.append(" >>>\n");
 
1300
      dynstr_append(&ds_tmp, "<<<\n --- ");
 
1301
      dynstr_append(&ds_tmp, filename1);
 
1302
      dynstr_append(&ds_tmp, " >>>\n");
1243
1303
      cat_file(&ds_tmp, filename2);
1244
 
      ds_tmp.append("<<<<\n");
 
1304
      dynstr_append(&ds_tmp, "<<<<\n");
1245
1305
    }
1246
1306
  }
1247
1307
 
1248
1308
  if (ds)
1249
1309
  {
1250
1310
    /* Add the diff to output */
1251
 
    ds->append(ds_tmp.c_str(), ds_tmp.length());
 
1311
    dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1252
1312
  }
1253
1313
  else
1254
1314
  {
1255
1315
    /* Print diff directly to stdout */
1256
 
    fprintf(stderr, "%s\n", ds_tmp.c_str());
 
1316
    fprintf(stderr, "%s\n", ds_tmp.str);
1257
1317
  }
 
1318
 
 
1319
  dynstr_free(&ds_tmp);
1258
1320
 
1259
1321
}
1260
1322
 
1261
1323
 
1262
1324
enum compare_files_result_enum {
1263
 
  RESULT_OK= 0,
1264
 
  RESULT_CONTENT_MISMATCH= 1,
1265
 
  RESULT_LENGTH_MISMATCH= 2
 
1325
   RESULT_OK= 0,
 
1326
   RESULT_CONTENT_MISMATCH= 1,
 
1327
   RESULT_LENGTH_MISMATCH= 2
1266
1328
};
1267
1329
 
1268
1330
/*
1291
1353
    my_close(fd, MYF(0));
1292
1354
    die("Failed to open second file: '%s'", filename2);
1293
1355
  }
1294
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1356
  while((len= my_read(fd, (uchar*)&buff,
1295
1357
                      sizeof(buff), MYF(0))) > 0)
1296
1358
  {
1297
 
    if ((len2= my_read(fd2, (unsigned char*)&buff2,
 
1359
    if ((len2= my_read(fd2, (uchar*)&buff2,
1298
1360
                       sizeof(buff2), MYF(0))) < len)
1299
1361
    {
1300
1362
      /* File 2 was smaller */
1314
1376
      break;
1315
1377
    }
1316
1378
  }
1317
 
  if (!error && my_read(fd2, (unsigned char*)&buff2,
 
1379
  if (!error && my_read(fd2, (uchar*)&buff2,
1318
1380
                        sizeof(buff2), MYF(0)) > 0)
1319
1381
  {
1320
1382
    /* File 1 was smaller */
1360
1422
  Compare content of the string in ds to content of file fname
1361
1423
 
1362
1424
  SYNOPSIS
1363
 
  string_cmp
 
1425
  dyn_string_cmp
1364
1426
  ds - Dynamic string containing the string o be compared
1365
1427
  fname - Name of file to compare with
1366
1428
 
1368
1430
  See 'compare_files2'
1369
1431
*/
1370
1432
 
1371
 
static int string_cmp(string* ds, const char *fname)
 
1433
static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
1372
1434
{
1373
1435
  int error;
1374
1436
  File fd;
1375
1437
  char temp_file_path[FN_REFLEN];
1376
1438
 
 
1439
  DBUG_ENTER("dyn_string_cmp");
 
1440
  DBUG_PRINT("enter", ("fname: %s", fname));
 
1441
 
1377
1442
  if ((fd= create_temp_file(temp_file_path, NULL,
1378
 
                            "tmp", O_CREAT | O_RDWR,
 
1443
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
1379
1444
                            MYF(MY_WME))) < 0)
1380
1445
    die("Failed to create temporary file for ds");
1381
1446
 
1382
1447
  /* Write ds to temporary file and set file pos to beginning*/
1383
 
  if (my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
 
1448
  if (my_write(fd, (uchar *) ds->str, ds->length,
1384
1449
               MYF(MY_FNABP | MY_WME)) ||
1385
1450
      my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1386
1451
  {
1396
1461
  /* Remove the temporary file */
1397
1462
  my_delete(temp_file_path, MYF(0));
1398
1463
 
1399
 
  return(error);
 
1464
  DBUG_RETURN(error);
1400
1465
}
1401
1466
 
1402
1467
 
1412
1477
 
1413
1478
*/
1414
1479
 
1415
 
static void check_result(string* ds)
 
1480
static void check_result(DYNAMIC_STRING* ds)
1416
1481
{
1417
1482
  const char* mess= "Result content mismatch\n";
1418
1483
 
1419
 
 
1420
 
  assert(result_file_name);
 
1484
  DBUG_ENTER("check_result");
 
1485
  DBUG_ASSERT(result_file_name);
 
1486
  DBUG_PRINT("enter", ("result_file_name: %s", result_file_name));
1421
1487
 
1422
1488
  if (access(result_file_name, F_OK) != 0)
1423
1489
    die("The specified result file does not exist: '%s'", result_file_name);
1424
1490
 
1425
 
  switch (string_cmp(ds, result_file_name)) {
 
1491
  switch (dyn_string_cmp(ds, result_file_name)) {
1426
1492
  case RESULT_OK:
1427
1493
    break; /* ok */
1428
1494
  case RESULT_LENGTH_MISMATCH:
1450
1516
      fn_format(reject_file, result_file_name, opt_logdir,
1451
1517
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1452
1518
    }
1453
 
    str_to_file(reject_file, ds->c_str(), ds->length());
 
1519
    str_to_file(reject_file, ds->str, ds->length);
1454
1520
 
1455
 
    ds->erase(); /* Don't create a .log file */
 
1521
    dynstr_set(ds, NULL); /* Don't create a .log file */
1456
1522
 
1457
1523
    show_diff(NULL, result_file_name, reject_file);
1458
1524
    die(mess);
1462
1528
    die("Unknown error code from dyn_string_cmp()");
1463
1529
  }
1464
1530
 
1465
 
  return;
 
1531
  DBUG_VOID_RETURN;
1466
1532
}
1467
1533
 
1468
1534
 
1481
1547
 
1482
1548
*/
1483
1549
 
1484
 
static void check_require(string* ds, const char *fname)
 
1550
static void check_require(DYNAMIC_STRING* ds, const char *fname)
1485
1551
{
1486
 
 
1487
 
 
1488
 
  if (string_cmp(ds, fname))
 
1552
  DBUG_ENTER("check_require");
 
1553
 
 
1554
  if (dyn_string_cmp(ds, fname))
1489
1555
  {
1490
1556
    char reason[FN_REFLEN];
1491
1557
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1492
1558
    abort_not_supported_test("Test requires: '%s'", reason);
1493
1559
  }
1494
 
  return;
 
1560
  DBUG_VOID_RETURN;
1495
1561
}
1496
1562
 
1497
1563
 
1498
1564
/*
1499
 
  Remove surrounding chars from string
 
1565
   Remove surrounding chars from string
1500
1566
 
1501
 
  Return 1 if first character is found but not last
 
1567
   Return 1 if first character is found but not last
1502
1568
*/
1503
1569
static int strip_surrounding(char* str, char c1, char c2)
1504
1570
{
1513
1579
    *ptr= ' ';
1514
1580
 
1515
1581
    /* Last non space charecter should be c2 */
1516
 
    ptr= strchr(str, '\0')-1;
 
1582
    ptr= strend(str)-1;
1517
1583
    while(*ptr && my_isspace(charset_info, *ptr))
1518
1584
      ptr--;
1519
1585
    if (*ptr == c2)
1534
1600
static void strip_parentheses(struct st_command *command)
1535
1601
{
1536
1602
  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, '(', ')');
 
1603
      die("%.*s - argument list started with '%c' must be ended with '%c'",
 
1604
          command->first_word_len, command->query, '(', ')');
1539
1605
}
1540
1606
 
1541
1607
 
1542
 
static unsigned char *get_var_key(const unsigned char* var, size_t *len,
1543
 
                          bool __attribute__((unused)) t)
 
1608
static uchar *get_var_key(const uchar* var, size_t *len,
 
1609
                          my_bool __attribute__((unused)) t)
1544
1610
{
1545
1611
  register char* key;
1546
1612
  key = ((VAR*)var)->name;
1547
1613
  *len = ((VAR*)var)->name_len;
1548
 
  return (unsigned char*)key;
 
1614
  return (uchar*)key;
1549
1615
}
1550
1616
 
1551
1617
 
1587
1653
 
1588
1654
void var_free(void *v)
1589
1655
{
1590
 
  free(((VAR*) v)->str_val);
1591
 
  free(((VAR*) v)->env_s);
 
1656
  my_free(((VAR*) v)->str_val, MYF(MY_WME));
 
1657
  my_free(((VAR*) v)->env_s, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
1592
1658
  if (((VAR*)v)->alloced)
1593
 
    free(v);
 
1659
    my_free(v, MYF(MY_WME));
1594
1660
}
1595
1661
 
1596
1662
 
1602
1668
    tmp = def_val;
1603
1669
 
1604
1670
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1605
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1671
  my_hash_insert(&var_hash, (uchar*)v);
1606
1672
  return v;
1607
1673
}
1608
1674
 
1609
1675
 
1610
 
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1611
 
             bool ignore_not_existing)
 
1676
VAR* var_get(const char *var_name, const char **var_name_end, my_bool raw,
 
1677
             my_bool ignore_not_existing)
1612
1678
{
1613
1679
  int digit;
1614
1680
  VAR *v;
 
1681
  DBUG_ENTER("var_get");
 
1682
  DBUG_PRINT("enter", ("var_name: %s",var_name));
1615
1683
 
1616
1684
  if (*var_name != '$')
1617
1685
    goto err;
1626
1694
    if (var_name == save_var_name)
1627
1695
    {
1628
1696
      if (ignore_not_existing)
1629
 
        return(0);
 
1697
        DBUG_RETURN(0);
1630
1698
      die("Empty variable");
1631
1699
    }
1632
1700
    length= (uint) (var_name - save_var_name);
1633
1701
    if (length >= MAX_VAR_NAME_LENGTH)
1634
1702
      die("Too long variable name: %s", save_var_name);
1635
1703
 
1636
 
    if (!(v = (VAR*) hash_search(&var_hash, (const unsigned char*) save_var_name,
1637
 
                                 length)))
 
1704
    if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
 
1705
                                            length)))
1638
1706
    {
1639
1707
      char buff[MAX_VAR_NAME_LENGTH+1];
1640
1708
      strmake(buff, save_var_name, length);
1641
1709
      v= var_from_env(buff, "");
1642
1710
    }
1643
 
    var_name--;  /* Point at last character */
 
1711
    var_name--; /* Point at last character */
1644
1712
  }
1645
1713
  else
1646
1714
    v = var_reg + digit;
1653
1721
  }
1654
1722
  if (var_name_end)
1655
1723
    *var_name_end = var_name  ;
1656
 
  return(v);
 
1724
  DBUG_RETURN(v);
1657
1725
err:
1658
1726
  if (var_name_end)
1659
1727
    *var_name_end = 0;
1660
1728
  die("Unsupported variable name: %s", var_name);
1661
 
  return(0);
 
1729
  DBUG_RETURN(0);
1662
1730
}
1663
1731
 
1664
1732
 
1665
1733
static VAR *var_obtain(const char *name, int len)
1666
1734
{
1667
1735
  VAR* v;
1668
 
  if ((v = (VAR*)hash_search(&var_hash, (const unsigned char *) name, len)))
 
1736
  if ((v = (VAR*)hash_search(&var_hash, (const uchar *) name, len)))
1669
1737
    return v;
1670
1738
  v = var_init(0, name, len, "", 0);
1671
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1739
  my_hash_insert(&var_hash, (uchar*)v);
1672
1740
  return v;
1673
1741
}
1674
1742
 
1684
1752
{
1685
1753
  int digit, env_var= 0;
1686
1754
  VAR *v;
 
1755
  DBUG_ENTER("var_set");
 
1756
  DBUG_PRINT("enter", ("var_name: '%.*s' = '%.*s' (length: %d)",
 
1757
                       (int) (var_name_end - var_name), var_name,
 
1758
                       (int) (var_val_end - var_val), var_val,
 
1759
                       (int) (var_val_end - var_val)));
1687
1760
 
1688
1761
  if (*var_name != '$')
1689
1762
    env_var= 1;
1710
1783
      v->str_val_len= strlen(v->str_val);
1711
1784
    }
1712
1785
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
1713
 
             v->name_len, v->name,
1714
 
             v->str_val_len, v->str_val);
 
1786
                v->name_len, v->name,
 
1787
                v->str_val_len, v->str_val);
1715
1788
    if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
1716
1789
      die("Out of memory");
1717
1790
    putenv(v->env_s);
1718
 
    free(old_env_s);
 
1791
    my_free(old_env_s, MYF(MY_ALLOW_ZERO_PTR));
1719
1792
  }
1720
 
  return;
 
1793
  DBUG_VOID_RETURN;
1721
1794
}
1722
1795
 
1723
1796
 
1737
1810
 
1738
1811
/*
1739
1812
  Store an integer (typically the returncode of the last SQL)
1740
 
  statement in the drizzletest builtin variable $drizzle_errno
 
1813
  statement in the mysqltest builtin variable $mysql_errno
1741
1814
*/
1742
1815
 
1743
1816
static void var_set_errno(int sql_errno)
1744
1817
{
1745
 
  var_set_int("$drizzle_errno", sql_errno);
 
1818
  var_set_int("$mysql_errno", sql_errno);
1746
1819
}
1747
1820
 
1748
1821
 
1749
1822
/*
1750
 
  Update $drizzle_get_server_version variable with version
 
1823
  Update $mysql_get_server_version variable with version
1751
1824
  of the currently connected server
1752
1825
*/
1753
1826
 
1754
 
static void var_set_drizzle_get_server_version(DRIZZLE *drizzle)
 
1827
static void var_set_mysql_get_server_version(MYSQL* mysql)
1755
1828
{
1756
 
  var_set_int("$drizzle_get_server_version", drizzle_get_server_version(drizzle));
 
1829
  var_set_int("$mysql_get_server_version", mysql_get_server_version(mysql));
1757
1830
}
1758
1831
 
1759
1832
 
1762
1835
 
1763
1836
  SYNOPSIS
1764
1837
  var_query_set()
1765
 
  var          variable to set from query
 
1838
  var           variable to set from query
1766
1839
  query       start of query string to execute
1767
1840
  query_end   end of the query string to execute
1768
1841
 
1782
1855
 
1783
1856
static void var_query_set(VAR *var, const char *query, const char** query_end)
1784
1857
{
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
 
 
 
1858
  char *end = (char*)((query_end && *query_end) ?
 
1859
                      *query_end : query + strlen(query));
 
1860
  MYSQL_RES *res;
 
1861
  MYSQL_ROW row;
 
1862
  MYSQL* mysql = &cur_con->mysql;
 
1863
  DYNAMIC_STRING ds_query;
 
1864
  DBUG_ENTER("var_query_set");
1792
1865
 
1793
1866
  while (end > query && *end != '`')
1794
1867
    --end;
1797
1870
  ++query;
1798
1871
 
1799
1872
  /* 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])
 
1873
  init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
 
1874
  do_eval(&ds_query, query, end, FALSE);
 
1875
 
 
1876
  if (mysql_real_query(mysql, ds_query.str, ds_query.length))
 
1877
    die("Error running query '%s': %d %s", ds_query.str,
 
1878
        mysql_errno(mysql), mysql_error(mysql));
 
1879
  if (!(res= mysql_store_result(mysql)))
 
1880
    die("Query '%s' didn't return a result set", ds_query.str);
 
1881
  dynstr_free(&ds_query);
 
1882
 
 
1883
  if ((row= mysql_fetch_row(res)) && row[0])
1809
1884
  {
1810
1885
    /*
1811
1886
      Concatenate all fields in the first row with tab in between
1812
1887
      and assign that string to the $variable
1813
1888
    */
1814
 
    string result;
1815
 
    uint32_t i;
1816
 
    uint32_t *lengths;
 
1889
    DYNAMIC_STRING result;
 
1890
    uint i;
 
1891
    ulong *lengths;
1817
1892
 
1818
 
    lengths= drizzle_fetch_lengths(res);
1819
 
    for (i= 0; i < drizzle_num_fields(res); i++)
 
1893
    init_dynamic_string(&result, "", 512, 512);
 
1894
    lengths= mysql_fetch_lengths(res);
 
1895
    for (i= 0; i < mysql_num_fields(res); i++)
1820
1896
    {
1821
1897
      if (row[i])
1822
1898
      {
1823
1899
        /* Add column to tab separated string */
1824
 
        result.append(row[i], lengths[i]);
 
1900
        dynstr_append_mem(&result, row[i], lengths[i]);
1825
1901
      }
1826
 
      result.append("\t", 1);
 
1902
      dynstr_append_mem(&result, "\t", 1);
1827
1903
    }
1828
 
    end= result.c_str() + result.length()-1;
1829
 
    eval_expr(var, result.c_str(), (const char**) &end);
 
1904
    end= result.str + result.length-1;
 
1905
    eval_expr(var, result.str, (const char**) &end);
 
1906
    dynstr_free(&result);
1830
1907
  }
1831
1908
  else
1832
1909
    eval_expr(var, "", 0);
1833
1910
 
1834
 
  drizzle_free_result(res);
1835
 
  return;
 
1911
  mysql_free_result(res);
 
1912
  DBUG_VOID_RETURN;
1836
1913
}
1837
1914
 
1838
1915
 
1852
1929
 
1853
1930
  <query to run> -    The query that should be sent to the server
1854
1931
  <column name> -     Name of the column that holds the field be compared
1855
 
  against the expected value
 
1932
                      against the expected value
1856
1933
  <row no> -          Number of the row that holds the field to be
1857
 
  compared against the expected value
 
1934
                      compared against the expected value
1858
1935
 
1859
1936
*/
1860
1937
 
1862
1939
{
1863
1940
  long row_no;
1864
1941
  int col_no= -1;
1865
 
  DRIZZLE_RES* res;
1866
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
1942
  MYSQL_RES* res;
 
1943
  MYSQL* mysql= &cur_con->mysql;
1867
1944
 
1868
 
  string ds_query;
1869
 
  string ds_col;
1870
 
  string ds_row;
 
1945
  static DYNAMIC_STRING ds_query;
 
1946
  static DYNAMIC_STRING ds_col;
 
1947
  static DYNAMIC_STRING ds_row;
1871
1948
  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"}
 
1949
    {"query", ARG_STRING, TRUE, &ds_query, "Query to run"},
 
1950
    {"column name", ARG_STRING, TRUE, &ds_col, "Name of column"},
 
1951
    {"row number", ARG_STRING, TRUE, &ds_row, "Number for row"}
1875
1952
  };
1876
1953
 
1877
 
 
 
1954
  DBUG_ENTER("var_set_query_get_value");
1878
1955
 
1879
1956
  strip_parentheses(command);
 
1957
  DBUG_PRINT("info", ("query: %s", command->query));
1880
1958
  check_command_args(command, command->first_argument, query_get_value_args,
1881
1959
                     sizeof(query_get_value_args)/sizeof(struct command_arg),
1882
1960
                     ',');
1883
1961
 
 
1962
  DBUG_PRINT("info", ("query: %s", ds_query.str));
 
1963
  DBUG_PRINT("info", ("col: %s", ds_col.str));
 
1964
 
1884
1965
  /* 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());
 
1966
  if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
 
1967
    die("Invalid row number: '%s'", ds_row.str);
 
1968
  DBUG_PRINT("info", ("row: %s, row_no: %ld", ds_row.str, row_no));
 
1969
  dynstr_free(&ds_row);
1887
1970
 
1888
1971
  /* 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;
 
1972
  if (strip_surrounding(ds_query.str, '"', '"'))
 
1973
    die("Mismatched \"'s around query '%s'", ds_query.str);
1894
1974
 
1895
1975
  /* 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());
 
1976
  if (mysql_real_query(mysql, ds_query.str, ds_query.length))
 
1977
    die("Error running query '%s': %d %s", ds_query.str,
 
1978
        mysql_errno(mysql), mysql_error(mysql));
 
1979
  if (!(res= mysql_store_result(mysql)))
 
1980
    die("Query '%s' didn't return a result set", ds_query.str);
1901
1981
 
1902
1982
  {
1903
1983
    /* Find column number from the given column name */
1904
1984
    uint i;
1905
 
    uint num_fields= drizzle_num_fields(res);
1906
 
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
1985
    uint num_fields= mysql_num_fields(res);
 
1986
    MYSQL_FIELD *fields= mysql_fetch_fields(res);
1907
1987
 
1908
1988
    for (i= 0; i < num_fields; i++)
1909
1989
    {
1910
 
      if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
1911
 
          strlen(fields[i].name) == ds_col.length())
 
1990
      if (strcmp(fields[i].name, ds_col.str) == 0 &&
 
1991
          strlen(fields[i].name) == ds_col.length)
1912
1992
      {
1913
1993
        col_no= i;
1914
1994
        break;
1916
1996
    }
1917
1997
    if (col_no == -1)
1918
1998
    {
1919
 
      drizzle_free_result(res);
 
1999
      mysql_free_result(res);
1920
2000
      die("Could not find column '%s' in the result of '%s'",
1921
 
          ds_col.c_str(), ds_query.c_str());
 
2001
          ds_col.str, ds_query.str);
1922
2002
    }
 
2003
    DBUG_PRINT("info", ("Found column %d with name '%s'",
 
2004
                        i, fields[i].name));
1923
2005
  }
 
2006
  dynstr_free(&ds_col);
1924
2007
 
1925
2008
  {
1926
2009
    /* Get the value */
1927
 
    DRIZZLE_ROW row;
 
2010
    MYSQL_ROW row;
1928
2011
    long rows= 0;
1929
2012
    const char* value= "No such row";
1930
2013
 
1931
 
    while ((row= drizzle_fetch_row(res)))
 
2014
    while ((row= mysql_fetch_row(res)))
1932
2015
    {
1933
2016
      if (++rows == row_no)
1934
2017
      {
1935
2018
 
 
2019
        DBUG_PRINT("info", ("At row %ld, column %d is '%s'",
 
2020
                            row_no, col_no, row[col_no]));
1936
2021
        /* Found the row to get */
1937
2022
        if (row[col_no])
1938
2023
          value= row[col_no];
1944
2029
    }
1945
2030
    eval_expr(var, value, 0);
1946
2031
  }
1947
 
  drizzle_free_result(res);
 
2032
  dynstr_free(&ds_query);
 
2033
  mysql_free_result(res);
1948
2034
 
1949
 
  return;
 
2035
  DBUG_VOID_RETURN;
1950
2036
}
1951
2037
 
1952
2038
 
1973
2059
 
1974
2060
void eval_expr(VAR *v, const char *p, const char **p_end)
1975
2061
{
 
2062
 
 
2063
  DBUG_ENTER("eval_expr");
 
2064
  DBUG_PRINT("enter", ("p: '%s'", p));
 
2065
 
1976
2066
  if (*p == '$')
1977
2067
  {
1978
2068
    VAR *vp;
1979
2069
    if ((vp= var_get(p, p_end, 0, 0)))
1980
2070
      var_copy(v, vp);
1981
 
    return;
 
2071
    DBUG_VOID_RETURN;
1982
2072
  }
1983
2073
 
1984
2074
  if (*p == '`')
1985
2075
  {
1986
2076
    var_query_set(v, p, p_end);
1987
 
    return;
 
2077
    DBUG_VOID_RETURN;
1988
2078
  }
1989
2079
 
1990
2080
  {
2000
2090
      command.first_argument= command.query + len;
2001
2091
      command.end= (char*)*p_end;
2002
2092
      var_set_query_get_value(&command, v);
2003
 
      return;
 
2093
      DBUG_VOID_RETURN;
2004
2094
    }
2005
2095
  }
2006
2096
 
2014
2104
        MIN_VAR_ALLOC : new_val_len + 1;
2015
2105
      if (!(v->str_val =
2016
2106
            v->str_val ? (char *)my_realloc(v->str_val, v->alloced_len+1,
2017
 
                                            MYF(MY_WME)) :
 
2107
                                    MYF(MY_WME)) :
2018
2108
            (char *)my_malloc(v->alloced_len+1, MYF(MY_WME))))
2019
2109
        die("Out of memory");
2020
2110
    }
2022
2112
    memcpy(v->str_val, p, new_val_len);
2023
2113
    v->str_val[new_val_len] = 0;
2024
2114
    v->int_val=atoi(p);
 
2115
    DBUG_PRINT("info", ("atoi on '%s', returns: %d", p, v->int_val));
2025
2116
    v->int_dirty=0;
2026
2117
  }
2027
 
  return;
 
2118
  DBUG_VOID_RETURN;
2028
2119
}
2029
2120
 
2030
2121
 
2031
2122
static int open_file(const char *name)
2032
2123
{
2033
2124
  char buff[FN_REFLEN];
2034
 
 
 
2125
  DBUG_ENTER("open_file");
 
2126
  DBUG_PRINT("enter", ("name: %s", name));
2035
2127
  if (!test_if_hard_path(name))
2036
2128
  {
2037
 
    strxmov(buff, opt_basedir, name, NULL);
 
2129
    strxmov(buff, opt_basedir, name, NullS);
2038
2130
    name=buff;
2039
2131
  }
2040
2132
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2042
2134
  if (cur_file == file_stack_end)
2043
2135
    die("Source directives are nesting too deep");
2044
2136
  cur_file++;
2045
 
  if (!(cur_file->file = my_fopen(buff, O_RDONLY, MYF(0))))
 
2137
  if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
2046
2138
  {
2047
2139
    cur_file--;
2048
2140
    die("Could not open '%s' for reading", buff);
2049
2141
  }
2050
2142
  cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
2051
2143
  cur_file->lineno=1;
2052
 
  return(0);
 
2144
  DBUG_RETURN(0);
2053
2145
}
2054
2146
 
2055
2147
 
2058
2150
 
2059
2151
  SYNOPSIS
2060
2152
  do_source()
2061
 
  query  called command
 
2153
  query called command
2062
2154
 
2063
2155
  DESCRIPTION
2064
2156
  source <file_name>
2069
2161
 
2070
2162
static void do_source(struct st_command *command)
2071
2163
{
2072
 
  string ds_filename;
 
2164
  static DYNAMIC_STRING ds_filename;
2073
2165
  const struct command_arg source_args[] = {
2074
 
    { "filename", ARG_STRING, true, &ds_filename, "File to source" }
 
2166
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to source" }
2075
2167
  };
2076
 
 
 
2168
  DBUG_ENTER("do_source");
2077
2169
 
2078
2170
  check_command_args(command, command->first_argument, source_args,
2079
2171
                     sizeof(source_args)/sizeof(struct command_arg),
2087
2179
    ; /* Do nothing */
2088
2180
  else
2089
2181
  {
2090
 
    open_file(ds_filename.c_str());
 
2182
    DBUG_PRINT("info", ("sourcing file: %s", ds_filename.str));
 
2183
    open_file(ds_filename.str);
2091
2184
  }
2092
2185
 
 
2186
  dynstr_free(&ds_filename);
2093
2187
  return;
2094
2188
}
2095
2189
 
2096
2190
 
 
2191
static FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
 
2192
{
 
2193
  return popen(ds_cmd->str, mode);
 
2194
}
 
2195
 
 
2196
 
2097
2197
static void init_builtin_echo(void)
2098
2198
{
2099
2199
  builtin_echo[0]= 0;
2105
2205
  Replace a substring
2106
2206
 
2107
2207
  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
 
2208
    replace
 
2209
    ds_str      The string to search and perform the replace in
 
2210
    search_str  The string to search for
 
2211
    search_len  Length of the string to search for
 
2212
    replace_str The string to replace with
 
2213
    replace_len Length of the string to replace with
2114
2214
 
2115
2215
  RETURN
2116
 
  0 String replaced
2117
 
  1 Could not find search_str in str
 
2216
    0 String replaced
 
2217
    1 Could not find search_str in str
2118
2218
*/
2119
2219
 
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)
 
2220
static int replace(DYNAMIC_STRING *ds_str,
 
2221
                   const char *search_str, ulong search_len,
 
2222
                   const char *replace_str, ulong replace_len)
2123
2223
{
2124
 
  string ds_tmp;
2125
 
  const char *start= strstr(ds_str->c_str(), search_str);
 
2224
  DYNAMIC_STRING ds_tmp;
 
2225
  const char *start= strstr(ds_str->str, search_str);
2126
2226
  if (!start)
2127
2227
    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;
 
2228
  init_dynamic_string(&ds_tmp, "",
 
2229
                      ds_str->length + replace_len, 256);
 
2230
  dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
 
2231
  dynstr_append_mem(&ds_tmp, replace_str, replace_len);
 
2232
  dynstr_append(&ds_tmp, start + search_len);
 
2233
  dynstr_set(ds_str, ds_tmp.str);
 
2234
  dynstr_free(&ds_tmp);
2132
2235
  return 0;
2133
2236
}
2134
2237
 
2138
2241
 
2139
2242
  SYNOPSIS
2140
2243
  do_exec()
2141
 
  query  called command
 
2244
  query called command
2142
2245
 
2143
2246
  DESCRIPTION
2144
2247
  exec <command>
2149
2252
  It can thus be used to execute a command that shall fail.
2150
2253
 
2151
2254
  NOTE
2152
 
  Although drizzletest is executed from cygwin shell, the command will be
 
2255
  Although mysqltest is executed from cygwin shell, the command will be
2153
2256
  executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
2154
 
  drizzletest commmand(s) like "remove_file" for that
 
2257
  mysqltest commmand(s) like "remove_file" for that
2155
2258
*/
2156
2259
 
2157
2260
static void do_exec(struct st_command *command)
2160
2263
  char buf[512];
2161
2264
  FILE *res_file;
2162
2265
  char *cmd= command->first_argument;
2163
 
  string ds_cmd;
 
2266
  DYNAMIC_STRING ds_cmd;
 
2267
  DBUG_ENTER("do_exec");
 
2268
  DBUG_PRINT("enter", ("cmd: '%s'", cmd));
2164
2269
 
2165
2270
  /* Skip leading space */
2166
2271
  while (*cmd && my_isspace(charset_info, *cmd))
2169
2274
    die("Missing argument in exec");
2170
2275
  command->last_argument= command->end;
2171
2276
 
 
2277
  init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
2172
2278
  /* Eval the command, thus replacing all environment variables */
2173
2279
  do_eval(&ds_cmd, cmd, command->end, !is_windows);
2174
2280
 
2179
2285
    replace(&ds_cmd, "echo", 4, builtin_echo, strlen(builtin_echo));
2180
2286
  }
2181
2287
 
2182
 
  if (!(res_file= popen(ds_cmd.c_str(), "r")) && command->abort_on_error)
 
2288
  DBUG_PRINT("info", ("Executing '%s' as '%s'",
 
2289
                      command->first_argument, ds_cmd.str));
 
2290
 
 
2291
  if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
2183
2292
  {
 
2293
    dynstr_free(&ds_cmd);
2184
2294
    die("popen(\"%s\", \"r\") failed", command->first_argument);
2185
2295
  }
2186
2296
 
2189
2299
    if (disable_result_log)
2190
2300
    {
2191
2301
      buf[strlen(buf)-1]=0;
 
2302
      DBUG_PRINT("exec_result",("%s", buf));
2192
2303
    }
2193
2304
    else
2194
2305
    {
2195
 
      replace_append(&ds_res, buf);
 
2306
      replace_dynstr_append(&ds_res, buf);
2196
2307
    }
2197
2308
  }
2198
2309
  error= pclose(res_file);
2199
2310
  if (error > 0)
2200
2311
  {
2201
2312
    uint status= WEXITSTATUS(error), i;
2202
 
    bool ok= 0;
 
2313
    my_bool ok= 0;
2203
2314
 
2204
2315
    if (command->abort_on_error)
2205
2316
    {
2206
2317
      log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
2207
 
              ds_cmd.c_str(), error, status, errno);
 
2318
              ds_cmd.str, error, status, errno);
 
2319
      dynstr_free(&ds_cmd);
2208
2320
      die("command \"%s\" failed", command->first_argument);
2209
2321
    }
2210
2322
 
 
2323
    DBUG_PRINT("info",
 
2324
               ("error: %d, status: %d", error, status));
2211
2325
    for (i= 0; i < command->expected_errors.count; i++)
2212
2326
    {
 
2327
      DBUG_PRINT("info", ("expected error: %d",
 
2328
                          command->expected_errors.err[i].code.errnum));
2213
2329
      if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
2214
2330
          (command->expected_errors.err[i].code.errnum == status))
2215
2331
      {
2216
2332
        ok= 1;
 
2333
        DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d",
 
2334
                            command->first_argument, status));
2217
2335
      }
2218
2336
    }
2219
2337
    if (!ok)
2220
2338
    {
 
2339
      dynstr_free(&ds_cmd);
2221
2340
      die("command \"%s\" failed with wrong error: %d",
2222
2341
          command->first_argument, status);
2223
2342
    }
2227
2346
  {
2228
2347
    /* Error code we wanted was != 0, i.e. not an expected success */
2229
2348
    log_msg("exec of '%s failed, error: %d, errno: %d",
2230
 
            ds_cmd.c_str(), error, errno);
 
2349
            ds_cmd.str, error, errno);
 
2350
    dynstr_free(&ds_cmd);
2231
2351
    die("command \"%s\" succeeded - should have failed with errno %d...",
2232
2352
        command->first_argument, command->expected_errors.err[0].code.errnum);
2233
2353
  }
2234
2354
 
2235
 
  return;
 
2355
  dynstr_free(&ds_cmd);
 
2356
  DBUG_VOID_RETURN;
2236
2357
}
2237
2358
 
2238
2359
enum enum_operator
2247
2368
 
2248
2369
  SYNOPSIS
2249
2370
  do_modify_var()
2250
 
  query  called command
 
2371
  query called command
2251
2372
  operator    operation to perform on the var
2252
2373
 
2253
2374
  DESCRIPTION
2285
2406
 
2286
2407
 
2287
2408
/*
 
2409
  Wrapper for 'system' function
 
2410
 
 
2411
  NOTE
 
2412
  If mysqltest is executed from cygwin shell, the command will be
 
2413
  executed in the "windows command interpreter" cmd.exe and we prepend "sh"
 
2414
  to make it be executed by cygwins "bash". Thus commands like "rm",
 
2415
  "mkdir" as well as shellscripts can executed by "system" in Windows.
 
2416
 
 
2417
*/
 
2418
 
 
2419
static int my_system(DYNAMIC_STRING* ds_cmd)
 
2420
{
 
2421
  return system(ds_cmd->str);
 
2422
}
 
2423
 
 
2424
 
 
2425
/*
2288
2426
  SYNOPSIS
2289
2427
  do_system
2290
 
  command  called command
 
2428
  command       called command
2291
2429
 
2292
2430
  DESCRIPTION
2293
2431
  system <command>
2299
2437
 
2300
2438
static void do_system(struct st_command *command)
2301
2439
{
2302
 
  string ds_cmd;
2303
 
 
 
2440
  DYNAMIC_STRING ds_cmd;
 
2441
  DBUG_ENTER("do_system");
2304
2442
 
2305
2443
  if (strlen(command->first_argument) == 0)
2306
2444
    die("Missing arguments to system, nothing to do!");
2307
2445
 
 
2446
  init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
 
2447
 
2308
2448
  /* Eval the system command, thus replacing all environment variables */
2309
2449
  do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2310
2450
 
2311
 
  if (system(ds_cmd.c_str()))
 
2451
  DBUG_PRINT("info", ("running system command '%s' as '%s'",
 
2452
                      command->first_argument, ds_cmd.str));
 
2453
  if (my_system(&ds_cmd))
2312
2454
  {
2313
2455
    if (command->abort_on_error)
2314
2456
      die("system command '%s' failed", command->first_argument);
2315
2457
 
2316
2458
    /* 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");
 
2459
    dynstr_append(&ds_res, "system command '");
 
2460
    replace_dynstr_append(&ds_res, command->first_argument);
 
2461
    dynstr_append(&ds_res, "' failed\n");
2320
2462
  }
2321
2463
 
2322
2464
  command->last_argument= command->end;
2323
 
  return;
 
2465
  dynstr_free(&ds_cmd);
 
2466
  DBUG_VOID_RETURN;
2324
2467
}
2325
2468
 
2326
2469
 
2327
2470
/*
2328
2471
  SYNOPSIS
2329
2472
  do_remove_file
2330
 
  command  called command
 
2473
  command       called command
2331
2474
 
2332
2475
  DESCRIPTION
2333
2476
  remove_file <file_name>
2337
2480
static void do_remove_file(struct st_command *command)
2338
2481
{
2339
2482
  int error;
2340
 
  string ds_filename;
 
2483
  static DYNAMIC_STRING ds_filename;
2341
2484
  const struct command_arg rm_args[] = {
2342
 
    { "filename", ARG_STRING, true, &ds_filename, "File to delete" }
 
2485
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to delete" }
2343
2486
  };
2344
 
 
 
2487
  DBUG_ENTER("do_remove_file");
2345
2488
 
2346
2489
  check_command_args(command, command->first_argument,
2347
2490
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2348
2491
                     ' ');
2349
2492
 
2350
 
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2493
  DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
 
2494
  error= my_delete(ds_filename.str, MYF(0)) != 0;
2351
2495
  handle_command_error(command, error);
2352
 
  return;
 
2496
  dynstr_free(&ds_filename);
 
2497
  DBUG_VOID_RETURN;
2353
2498
}
2354
2499
 
2355
2500
 
2356
2501
/*
2357
2502
  SYNOPSIS
2358
2503
  do_copy_file
2359
 
  command  command handle
 
2504
  command       command handle
2360
2505
 
2361
2506
  DESCRIPTION
2362
2507
  copy_file <from_file> <to_file>
2368
2513
static void do_copy_file(struct st_command *command)
2369
2514
{
2370
2515
  int error;
2371
 
  string ds_from_file;
2372
 
  string ds_to_file;
 
2516
  static DYNAMIC_STRING ds_from_file;
 
2517
  static DYNAMIC_STRING ds_to_file;
2373
2518
  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" }
 
2519
    { "from_file", ARG_STRING, TRUE, &ds_from_file, "Filename to copy from" },
 
2520
    { "to_file", ARG_STRING, TRUE, &ds_to_file, "Filename to copy to" }
2376
2521
  };
2377
 
 
 
2522
  DBUG_ENTER("do_copy_file");
2378
2523
 
2379
2524
  check_command_args(command, command->first_argument,
2380
2525
                     copy_file_args,
2381
2526
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2382
2527
                     ' ');
2383
2528
 
2384
 
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2529
  DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
 
2530
  error= (my_copy(ds_from_file.str, ds_to_file.str,
2385
2531
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2386
2532
  handle_command_error(command, error);
2387
 
  return;
 
2533
  dynstr_free(&ds_from_file);
 
2534
  dynstr_free(&ds_to_file);
 
2535
  DBUG_VOID_RETURN;
2388
2536
}
2389
2537
 
2390
2538
 
2391
2539
/*
2392
2540
  SYNOPSIS
2393
2541
  do_chmod_file
2394
 
  command  command handle
 
2542
  command       command handle
2395
2543
 
2396
2544
  DESCRIPTION
2397
2545
  chmod <octal> <file_name>
2402
2550
static void do_chmod_file(struct st_command *command)
2403
2551
{
2404
2552
  long mode= 0;
2405
 
  string ds_mode;
2406
 
  string ds_file;
 
2553
  static DYNAMIC_STRING ds_mode;
 
2554
  static DYNAMIC_STRING ds_file;
2407
2555
  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" }
 
2556
    { "mode", ARG_STRING, TRUE, &ds_mode, "Mode of file(octal) ex. 0660"}, 
 
2557
    { "filename", ARG_STRING, TRUE, &ds_file, "Filename of file to modify" }
2410
2558
  };
2411
 
 
 
2559
  DBUG_ENTER("do_chmod_file");
2412
2560
 
2413
2561
  check_command_args(command, command->first_argument,
2414
2562
                     chmod_file_args,
2416
2564
                     ' ');
2417
2565
 
2418
2566
  /* Parse what mode to set */
2419
 
  if (ds_mode.length() != 4 ||
2420
 
      str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NULL)
 
2567
  if (ds_mode.length != 4 ||
 
2568
      str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
2421
2569
    die("You must write a 4 digit octal number for mode");
2422
2570
 
2423
 
  handle_command_error(command, chmod(ds_file.c_str(), mode));
2424
 
  return;
 
2571
  DBUG_PRINT("info", ("chmod %o %s", (uint)mode, ds_file.str));
 
2572
  handle_command_error(command, chmod(ds_file.str, mode));
 
2573
  dynstr_free(&ds_mode);
 
2574
  dynstr_free(&ds_file);
 
2575
  DBUG_VOID_RETURN;
2425
2576
}
2426
2577
 
2427
2578
 
2428
2579
/*
2429
2580
  SYNOPSIS
2430
2581
  do_file_exists
2431
 
  command  called command
 
2582
  command       called command
2432
2583
 
2433
2584
  DESCRIPTION
2434
2585
  fiile_exist <file_name>
2438
2589
static void do_file_exist(struct st_command *command)
2439
2590
{
2440
2591
  int error;
2441
 
  string ds_filename;
 
2592
  static DYNAMIC_STRING ds_filename;
2442
2593
  const struct command_arg file_exist_args[] = {
2443
 
    { "filename", ARG_STRING, true, &ds_filename, "File to check if it exist" }
 
2594
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to check if it exist" }
2444
2595
  };
2445
 
 
 
2596
  DBUG_ENTER("do_file_exist");
2446
2597
 
2447
2598
  check_command_args(command, command->first_argument,
2448
2599
                     file_exist_args,
2449
2600
                     sizeof(file_exist_args)/sizeof(struct command_arg),
2450
2601
                     ' ');
2451
2602
 
2452
 
  error= (access(ds_filename.c_str(), F_OK) != 0);
 
2603
  DBUG_PRINT("info", ("Checking for existence of file: %s", ds_filename.str));
 
2604
  error= (access(ds_filename.str, F_OK) != 0);
2453
2605
  handle_command_error(command, error);
2454
 
  return;
 
2606
  dynstr_free(&ds_filename);
 
2607
  DBUG_VOID_RETURN;
2455
2608
}
2456
2609
 
2457
2610
 
2458
2611
/*
2459
2612
  SYNOPSIS
2460
2613
  do_mkdir
2461
 
  command  called command
 
2614
  command       called command
2462
2615
 
2463
2616
  DESCRIPTION
2464
2617
  mkdir <dir_name>
2468
2621
static void do_mkdir(struct st_command *command)
2469
2622
{
2470
2623
  int error;
2471
 
  string ds_dirname;
 
2624
  static DYNAMIC_STRING ds_dirname;
2472
2625
  const struct command_arg mkdir_args[] = {
2473
 
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
 
2626
    {"dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to create"}
2474
2627
  };
2475
 
 
 
2628
  DBUG_ENTER("do_mkdir");
2476
2629
 
2477
2630
  check_command_args(command, command->first_argument,
2478
2631
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2479
2632
                     ' ');
2480
2633
 
2481
 
  error= my_mkdir(ds_dirname.c_str(), 0777, MYF(0)) != 0;
 
2634
  DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
 
2635
  error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
2482
2636
  handle_command_error(command, error);
2483
 
  return;
 
2637
  dynstr_free(&ds_dirname);
 
2638
  DBUG_VOID_RETURN;
2484
2639
}
2485
2640
 
2486
2641
/*
2487
2642
  SYNOPSIS
2488
2643
  do_rmdir
2489
 
  command  called command
 
2644
  command       called command
2490
2645
 
2491
2646
  DESCRIPTION
2492
2647
  rmdir <dir_name>
2496
2651
static void do_rmdir(struct st_command *command)
2497
2652
{
2498
2653
  int error;
2499
 
  string ds_dirname;
 
2654
  static DYNAMIC_STRING ds_dirname;
2500
2655
  const struct command_arg rmdir_args[] = {
2501
 
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to remove"}
 
2656
    {"dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove"}
2502
2657
  };
2503
 
 
 
2658
  DBUG_ENTER("do_rmdir");
2504
2659
 
2505
2660
  check_command_args(command, command->first_argument,
2506
2661
                     rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
2507
2662
                     ' ');
2508
2663
 
2509
 
  error= rmdir(ds_dirname.c_str()) != 0;
 
2664
  DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
 
2665
  error= rmdir(ds_dirname.str) != 0;
2510
2666
  handle_command_error(command, error);
2511
 
  return;
 
2667
  dynstr_free(&ds_dirname);
 
2668
  DBUG_VOID_RETURN;
2512
2669
}
2513
2670
 
2514
2671
 
2536
2693
}
2537
2694
 
2538
2695
 
2539
 
static void read_until_delimiter(string *ds,
2540
 
                                 string *ds_delimiter)
 
2696
static void read_until_delimiter(DYNAMIC_STRING *ds,
 
2697
                                 DYNAMIC_STRING *ds_delimiter)
2541
2698
{
2542
2699
  char c;
 
2700
  DBUG_ENTER("read_until_delimiter");
 
2701
  DBUG_PRINT("enter", ("delimiter: %s, length: %u",
 
2702
                       ds_delimiter->str, (uint) ds_delimiter->length));
2543
2703
 
2544
 
  if (ds_delimiter->length() > MAX_DELIMITER_LENGTH)
 
2704
  if (ds_delimiter->length > MAX_DELIMITER_LENGTH)
2545
2705
    die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
2546
2706
 
2547
2707
  /* Read from file until delimiter is found */
2568
2728
 
2569
2729
    if (feof(cur_file->file))
2570
2730
      die("End of file encountered before '%s' delimiter was found",
2571
 
          ds_delimiter->c_str());
 
2731
          ds_delimiter->str);
2572
2732
 
2573
 
    if (match_delimiter(c, ds_delimiter->c_str(), ds_delimiter->length()))
 
2733
    if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
 
2734
    {
 
2735
      DBUG_PRINT("exit", ("Found delimiter '%s'", ds_delimiter->str));
2574
2736
      break;
2575
 
 
2576
 
    ds->push_back(c);
 
2737
    }
 
2738
    dynstr_append_mem(ds, (const char*)&c, 1);
2577
2739
  }
2578
 
  return;
 
2740
  DBUG_PRINT("exit", ("ds: %s", ds->str));
 
2741
  DBUG_VOID_RETURN;
2579
2742
}
2580
2743
 
2581
2744
 
2582
 
static void do_write_file_command(struct st_command *command, bool append)
 
2745
static void do_write_file_command(struct st_command *command, my_bool append)
2583
2746
{
2584
 
  string ds_content;
2585
 
  string ds_filename;
2586
 
  string ds_delimiter;
 
2747
  static DYNAMIC_STRING ds_content;
 
2748
  static DYNAMIC_STRING ds_filename;
 
2749
  static DYNAMIC_STRING ds_delimiter;
2587
2750
  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" }
 
2751
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to write to" },
 
2752
    { "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until" }
2590
2753
  };
2591
 
 
 
2754
  DBUG_ENTER("do_write_file");
2592
2755
 
2593
2756
  check_command_args(command,
2594
2757
                     command->first_argument,
2597
2760
                     ' ');
2598
2761
 
2599
2762
  /* If no delimiter was provided, use EOF */
2600
 
  if (ds_delimiter.length() == 0)
2601
 
    ds_delimiter= "EOF";
 
2763
  if (ds_delimiter.length == 0)
 
2764
    dynstr_set(&ds_delimiter, "EOF");
2602
2765
 
2603
 
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
 
2766
  if (!append && access(ds_filename.str, F_OK) == 0)
2604
2767
  {
2605
2768
    /* The file should not be overwritten */
2606
 
    die("File already exist: '%s'", ds_filename.c_str());
 
2769
    die("File already exist: '%s'", ds_filename.str);
2607
2770
  }
2608
2771
 
 
2772
  init_dynamic_string(&ds_content, "", 1024, 1024);
2609
2773
  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;
 
2774
  DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str));
 
2775
  str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
 
2776
  dynstr_free(&ds_content);
 
2777
  dynstr_free(&ds_filename);
 
2778
  dynstr_free(&ds_delimiter);
 
2779
  DBUG_VOID_RETURN;
2613
2780
}
2614
2781
 
2615
2782
 
2616
2783
/*
2617
2784
  SYNOPSIS
2618
2785
  do_write_file
2619
 
  command  called command
 
2786
  command       called command
2620
2787
 
2621
2788
  DESCRIPTION
2622
2789
  write_file <file_name> [<delimiter>];
2642
2809
 
2643
2810
static void do_write_file(struct st_command *command)
2644
2811
{
2645
 
  do_write_file_command(command, false);
 
2812
  do_write_file_command(command, FALSE);
2646
2813
}
2647
2814
 
2648
2815
 
2649
2816
/*
2650
2817
  SYNOPSIS
2651
2818
  do_append_file
2652
 
  command  called command
 
2819
  command       called command
2653
2820
 
2654
2821
  DESCRIPTION
2655
2822
  append_file <file_name> [<delimiter>];
2673
2840
 
2674
2841
static void do_append_file(struct st_command *command)
2675
2842
{
2676
 
  do_write_file_command(command, true);
 
2843
  do_write_file_command(command, TRUE);
2677
2844
}
2678
2845
 
2679
2846
 
2680
2847
/*
2681
2848
  SYNOPSIS
2682
2849
  do_cat_file
2683
 
  command  called command
 
2850
  command       called command
2684
2851
 
2685
2852
  DESCRIPTION
2686
2853
  cat_file <file_name>;
2691
2858
 
2692
2859
static void do_cat_file(struct st_command *command)
2693
2860
{
2694
 
  static string ds_filename;
 
2861
  static DYNAMIC_STRING ds_filename;
2695
2862
  const struct command_arg cat_file_args[] = {
2696
 
    { "filename", ARG_STRING, true, &ds_filename, "File to read from" }
 
2863
    { "filename", ARG_STRING, TRUE, &ds_filename, "File to read from" }
2697
2864
  };
2698
 
 
 
2865
  DBUG_ENTER("do_cat_file");
2699
2866
 
2700
2867
  check_command_args(command,
2701
2868
                     command->first_argument,
2703
2870
                     sizeof(cat_file_args)/sizeof(struct command_arg),
2704
2871
                     ' ');
2705
2872
 
2706
 
  cat_file(&ds_res, ds_filename.c_str());
2707
 
 
2708
 
  return;
 
2873
  DBUG_PRINT("info", ("Reading from, file: %s", ds_filename.str));
 
2874
 
 
2875
  cat_file(&ds_res, ds_filename.str);
 
2876
 
 
2877
  dynstr_free(&ds_filename);
 
2878
  DBUG_VOID_RETURN;
2709
2879
}
2710
2880
 
2711
2881
 
2712
2882
/*
2713
2883
  SYNOPSIS
2714
2884
  do_diff_files
2715
 
  command  called command
 
2885
  command       called command
2716
2886
 
2717
2887
  DESCRIPTION
2718
2888
  diff_files <file1> <file2>;
2724
2894
static void do_diff_files(struct st_command *command)
2725
2895
{
2726
2896
  int error= 0;
2727
 
  string ds_filename;
2728
 
  string ds_filename2;
 
2897
  static DYNAMIC_STRING ds_filename;
 
2898
  static DYNAMIC_STRING ds_filename2;
2729
2899
  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" }
 
2900
    { "file1", ARG_STRING, TRUE, &ds_filename, "First file to diff" },
 
2901
    { "file2", ARG_STRING, TRUE, &ds_filename2, "Second file to diff" }
2732
2902
  };
2733
 
 
 
2903
  DBUG_ENTER("do_diff_files");
2734
2904
 
2735
2905
  check_command_args(command,
2736
2906
                     command->first_argument,
2738
2908
                     sizeof(diff_file_args)/sizeof(struct command_arg),
2739
2909
                     ' ');
2740
2910
 
2741
 
  if ((error= compare_files(ds_filename.c_str(), ds_filename2.c_str())))
 
2911
  if ((error= compare_files(ds_filename.str, ds_filename2.str)))
2742
2912
  {
2743
2913
    /* Compare of the two files failed, append them to output
2744
2914
       so the failure can be analyzed
2745
2915
    */
2746
 
    show_diff(&ds_res, ds_filename.c_str(), ds_filename2.c_str());
 
2916
    show_diff(&ds_res, ds_filename.str, ds_filename2.str);
2747
2917
  }
2748
2918
 
 
2919
  dynstr_free(&ds_filename);
 
2920
  dynstr_free(&ds_filename2);
2749
2921
  handle_command_error(command, error);
2750
 
  return;
 
2922
  DBUG_VOID_RETURN;
2751
2923
}
2752
2924
 
2753
2925
 
2768
2940
/*
2769
2941
  SYNOPSIS
2770
2942
  do_send_quit
2771
 
  command  called command
 
2943
  command       called command
2772
2944
 
2773
2945
  DESCRIPTION
2774
2946
  Sends a simple quit command to the server for the named connection.
2780
2952
  char *p= command->first_argument, *name;
2781
2953
  struct st_connection *con;
2782
2954
 
 
2955
  DBUG_ENTER("do_send_quit");
 
2956
  DBUG_PRINT("enter",("name: '%s'",p));
 
2957
 
2783
2958
  if (!*p)
2784
2959
    die("Missing connection name in send_quit");
2785
2960
  name= p;
2793
2968
  if (!(con= find_connection_by_name(name)))
2794
2969
    die("connection '%s' not found in connection pool", name);
2795
2970
 
2796
 
  simple_command(&con->drizzle,COM_QUIT,0,0,1);
 
2971
  simple_command(&con->mysql,COM_QUIT,0,0,1);
2797
2972
 
2798
 
  return;
 
2973
  DBUG_VOID_RETURN;
2799
2974
}
2800
2975
 
2801
2976
 
2817
2992
 
2818
2993
static void do_change_user(struct st_command *command)
2819
2994
{
2820
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
2995
  MYSQL *mysql = &cur_con->mysql;
2821
2996
  /* static keyword to make the NetWare compiler happy. */
2822
 
  string ds_user, ds_passwd, ds_db;
 
2997
  static DYNAMIC_STRING ds_user, ds_passwd, ds_db;
2823
2998
  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" },
 
2999
    { "user", ARG_STRING, FALSE, &ds_user, "User to connect as" },
 
3000
    { "password", ARG_STRING, FALSE, &ds_passwd, "Password used when connecting" },
 
3001
    { "database", ARG_STRING, FALSE, &ds_db, "Database to select after connect" },
2827
3002
  };
2828
3003
 
2829
 
 
 
3004
  DBUG_ENTER("do_change_user");
2830
3005
 
2831
3006
  check_command_args(command, command->first_argument,
2832
3007
                     change_user_args,
2833
3008
                     sizeof(change_user_args)/sizeof(struct command_arg),
2834
3009
                     ',');
2835
3010
 
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;
 
3011
  if (!ds_user.length)
 
3012
    dynstr_set(&ds_user, mysql->user);
 
3013
 
 
3014
  if (!ds_passwd.length)
 
3015
    dynstr_set(&ds_passwd, mysql->passwd);
 
3016
 
 
3017
  if (!ds_db.length)
 
3018
    dynstr_set(&ds_db, mysql->db);
 
3019
 
 
3020
  DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'",
 
3021
                      cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
 
3022
 
 
3023
  if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str))
 
3024
    die("change user failed: %s", mysql_error(mysql));
 
3025
 
 
3026
  dynstr_free(&ds_user);
 
3027
  dynstr_free(&ds_passwd);
 
3028
  dynstr_free(&ds_db);
 
3029
 
 
3030
  DBUG_VOID_RETURN;
2851
3031
}
2852
3032
 
2853
3033
 
2854
3034
/*
2855
3035
  SYNOPSIS
2856
3036
  do_perl
2857
 
  command  command handle
 
3037
  command       command handle
2858
3038
 
2859
3039
  DESCRIPTION
2860
3040
  perl [<delimiter>];
2877
3057
  FILE *res_file;
2878
3058
  char buf[FN_REFLEN];
2879
3059
  char temp_file_path[FN_REFLEN];
2880
 
  string ds_script;
2881
 
  string ds_delimiter;
 
3060
  static DYNAMIC_STRING ds_script;
 
3061
  static DYNAMIC_STRING ds_delimiter;
2882
3062
  const struct command_arg perl_args[] = {
2883
 
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
 
3063
    { "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until" }
2884
3064
  };
2885
 
 
 
3065
  DBUG_ENTER("do_perl");
2886
3066
 
2887
3067
  check_command_args(command,
2888
3068
                     command->first_argument,
2891
3071
                     ' ');
2892
3072
 
2893
3073
  /* If no delimiter was provided, use EOF */
2894
 
  if (ds_delimiter.length() == 0)
2895
 
    ds_delimiter= "EOF";
 
3074
  if (ds_delimiter.length == 0)
 
3075
    dynstr_set(&ds_delimiter, "EOF");
2896
3076
 
 
3077
  init_dynamic_string(&ds_script, "", 1024, 1024);
2897
3078
  read_until_delimiter(&ds_script, &ds_delimiter);
2898
3079
 
 
3080
  DBUG_PRINT("info", ("Executing perl: %s", ds_script.str));
 
3081
 
2899
3082
  /* Create temporary file name */
2900
3083
  if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
2901
 
                            "tmp", O_CREAT | O_RDWR,
 
3084
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
2902
3085
                            MYF(MY_WME))) < 0)
2903
3086
    die("Failed to create temporary file for perl command");
2904
3087
  my_close(fd, MYF(0));
2905
3088
 
2906
 
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
 
3089
  str_to_file(temp_file_path, ds_script.str, ds_script.length);
2907
3090
 
2908
3091
  /* Format the "perl <filename>" command */
2909
3092
  snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
2914
3097
  while (fgets(buf, sizeof(buf), res_file))
2915
3098
  {
2916
3099
    if (disable_result_log)
 
3100
    {
2917
3101
      buf[strlen(buf)-1]=0;
 
3102
      DBUG_PRINT("exec_result",("%s", buf));
 
3103
    }
2918
3104
    else
2919
 
      replace_append(&ds_res, buf);
 
3105
    {
 
3106
      replace_dynstr_append(&ds_res, buf);
 
3107
    }
2920
3108
  }
2921
3109
  error= pclose(res_file);
2922
3110
 
2924
3112
  my_delete(temp_file_path, MYF(0));
2925
3113
 
2926
3114
  handle_command_error(command, WEXITSTATUS(error));
2927
 
  return;
 
3115
  dynstr_free(&ds_script);
 
3116
  dynstr_free(&ds_delimiter);
 
3117
  DBUG_VOID_RETURN;
2928
3118
}
2929
3119
 
2930
3120
 
2931
3121
/*
2932
3122
  Print the content between echo and <delimiter> to result file.
2933
3123
  Evaluate all variables in the string before printing, allow
2934
 
  for variable names to be escaped using        \
 
3124
  for variable names to be escaped using \
2935
3125
 
2936
3126
  SYNOPSIS
2937
3127
  do_echo()
2954
3144
 
2955
3145
static int do_echo(struct st_command *command)
2956
3146
{
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");
 
3147
  DYNAMIC_STRING ds_echo;
 
3148
  DBUG_ENTER("do_echo");
 
3149
 
 
3150
  init_dynamic_string(&ds_echo, "", command->query_len, 256);
 
3151
  do_eval(&ds_echo, command->first_argument, command->end, FALSE);
 
3152
  dynstr_append_mem(&ds_res, ds_echo.str, ds_echo.length);
 
3153
  dynstr_append_mem(&ds_res, "\n", 1);
 
3154
  dynstr_free(&ds_echo);
2963
3155
  command->last_argument= command->end;
2964
 
  return(0);
 
3156
  DBUG_RETURN(0);
2965
3157
}
2966
3158
 
2967
3159
 
2969
3161
do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
2970
3162
{
2971
3163
  static int SLAVE_POLL_INTERVAL= 300000;
2972
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3164
  MYSQL* mysql = &cur_con->mysql;
2973
3165
  for (;;)
2974
3166
  {
2975
 
    DRIZZLE_RES *res= NULL;
2976
 
    DRIZZLE_ROW row;
 
3167
    MYSQL_RES *res= NULL;
 
3168
    MYSQL_ROW row;
2977
3169
    int done;
2978
3170
 
2979
 
    if (drizzle_query(drizzle,"show status like 'Slave_running'") ||
2980
 
        !(res=drizzle_store_result(drizzle)))
 
3171
    if (mysql_query(mysql,"show status like 'Slave_running'") ||
 
3172
        !(res=mysql_store_result(mysql)))
2981
3173
      die("Query failed while probing slave for stop: %s",
2982
 
          drizzle_error(drizzle));
2983
 
    if (!(row=drizzle_fetch_row(res)) || !row[1])
 
3174
          mysql_error(mysql));
 
3175
    if (!(row=mysql_fetch_row(res)) || !row[1])
2984
3176
    {
2985
 
      drizzle_free_result(res);
 
3177
      mysql_free_result(res);
2986
3178
      die("Strange result from query while probing slave for stop");
2987
3179
    }
2988
3180
    done = !strcmp(row[1],"OFF");
2989
 
    drizzle_free_result(res);
 
3181
    mysql_free_result(res);
2990
3182
    if (done)
2991
3183
      break;
2992
3184
    my_sleep(SLAVE_POLL_INTERVAL);
2997
3189
 
2998
3190
static void do_sync_with_master2(long offset)
2999
3191
{
3000
 
  DRIZZLE_RES *res;
3001
 
  DRIZZLE_ROW row;
3002
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3192
  MYSQL_RES *res;
 
3193
  MYSQL_ROW row;
 
3194
  MYSQL *mysql= &cur_con->mysql;
3003
3195
  char query_buf[FN_REFLEN+128];
3004
3196
  int tries= 0;
3005
3197
 
3007
3199
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3008
3200
 
3009
3201
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3010
 
          master_pos.pos + offset);
 
3202
          master_pos.pos + offset);
3011
3203
 
3012
3204
wait_for_position:
3013
3205
 
3014
 
  if (drizzle_query(drizzle, query_buf))
3015
 
    die("failed in '%s': %d: %s", query_buf, drizzle_errno(drizzle),
3016
 
        drizzle_error(drizzle));
 
3206
  if (mysql_query(mysql, query_buf))
 
3207
    die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
 
3208
        mysql_error(mysql));
3017
3209
 
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)))
 
3210
  if (!(res= mysql_store_result(mysql)))
 
3211
    die("mysql_store_result() returned NULL for '%s'", query_buf);
 
3212
  if (!(row= mysql_fetch_row(res)))
3021
3213
  {
3022
 
    drizzle_free_result(res);
 
3214
    mysql_free_result(res);
3023
3215
    die("empty result in %s", query_buf);
3024
3216
  }
3025
3217
  if (!row[0])
3028
3220
      It may be that the slave SQL thread has not started yet, though START
3029
3221
      SLAVE has been issued ?
3030
3222
    */
3031
 
    drizzle_free_result(res);
 
3223
    mysql_free_result(res);
3032
3224
    if (tries++ == 30)
3033
3225
    {
3034
 
      show_query(drizzle, "SHOW MASTER STATUS");
3035
 
      show_query(drizzle, "SHOW SLAVE STATUS");
 
3226
      show_query(mysql, "SHOW MASTER STATUS");
 
3227
      show_query(mysql, "SHOW SLAVE STATUS");
3036
3228
      die("could not sync with master ('%s' returned NULL)", query_buf);
3037
3229
    }
3038
3230
    sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
3039
3231
    goto wait_for_position;
3040
3232
  }
3041
 
  drizzle_free_result(res);
 
3233
  mysql_free_result(res);
3042
3234
  return;
3043
3235
}
3044
3236
 
3064
3256
 
3065
3257
/*
3066
3258
  when ndb binlog is on, this call will wait until last updated epoch
3067
 
  (locally in the drizzled) has been received into the binlog
 
3259
  (locally in the mysqld) has been received into the binlog
3068
3260
*/
3069
3261
static int do_save_master_pos(void)
3070
3262
{
3071
 
  DRIZZLE_RES *res;
3072
 
  DRIZZLE_ROW row;
3073
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3263
  MYSQL_RES *res;
 
3264
  MYSQL_ROW row;
 
3265
  MYSQL *mysql = &cur_con->mysql;
3074
3266
  const char *query;
3075
 
 
3076
 
 
3077
 
  if (drizzle_query(drizzle, query= "show master status"))
 
3267
  DBUG_ENTER("do_save_master_pos");
 
3268
 
 
3269
#ifdef HAVE_NDB_BINLOG
 
3270
  /*
 
3271
    Wait for ndb binlog to be up-to-date with all changes
 
3272
    done on the local mysql server
 
3273
  */
 
3274
  {
 
3275
    ulong have_ndbcluster;
 
3276
    if (mysql_query(mysql, query= "show variables like 'have_ndbcluster'"))
 
3277
      die("'%s' failed: %d %s", query,
 
3278
          mysql_errno(mysql), mysql_error(mysql));
 
3279
    if (!(res= mysql_store_result(mysql)))
 
3280
      die("mysql_store_result() returned NULL for '%s'", query);
 
3281
    if (!(row= mysql_fetch_row(res)))
 
3282
      die("Query '%s' returned empty result", query);
 
3283
 
 
3284
    have_ndbcluster= strcmp("YES", row[1]) == 0;
 
3285
    mysql_free_result(res);
 
3286
 
 
3287
    if (have_ndbcluster)
 
3288
    {
 
3289
      ulonglong start_epoch= 0, handled_epoch= 0,
 
3290
        latest_epoch=0, latest_trans_epoch=0,
 
3291
        latest_handled_binlog_epoch= 0, latest_received_binlog_epoch= 0,
 
3292
        latest_applied_binlog_epoch= 0;
 
3293
      int count= 0;
 
3294
      int do_continue= 1;
 
3295
      while (do_continue)
 
3296
      {
 
3297
        const char binlog[]= "binlog";
 
3298
        const char latest_epoch_str[]=
 
3299
          "latest_epoch=";
 
3300
        const char latest_trans_epoch_str[]=
 
3301
          "latest_trans_epoch=";
 
3302
        const char latest_received_binlog_epoch_str[]=
 
3303
          "latest_received_binlog_epoch";
 
3304
        const char latest_handled_binlog_epoch_str[]=
 
3305
          "latest_handled_binlog_epoch=";
 
3306
        const char latest_applied_binlog_epoch_str[]=
 
3307
          "latest_applied_binlog_epoch=";
 
3308
        if (count)
 
3309
          sleep(1);
 
3310
        if (mysql_query(mysql, query= "show engine ndb status"))
 
3311
          die("failed in '%s': %d %s", query,
 
3312
              mysql_errno(mysql), mysql_error(mysql));
 
3313
        if (!(res= mysql_store_result(mysql)))
 
3314
          die("mysql_store_result() returned NULL for '%s'", query);
 
3315
        while ((row= mysql_fetch_row(res)))
 
3316
        {
 
3317
          if (strcmp(row[1], binlog) == 0)
 
3318
          {
 
3319
            const char *status= row[2];
 
3320
 
 
3321
            /* latest_epoch */
 
3322
            while (*status && strncmp(status, latest_epoch_str,
 
3323
                                      sizeof(latest_epoch_str)-1))
 
3324
              status++;
 
3325
            if (*status)
 
3326
            {
 
3327
              status+= sizeof(latest_epoch_str)-1;
 
3328
              latest_epoch= strtoull(status, (char**) 0, 10);
 
3329
            }
 
3330
            else
 
3331
              die("result does not contain '%s' in '%s'",
 
3332
                  latest_epoch_str, query);
 
3333
            /* latest_trans_epoch */
 
3334
            while (*status && strncmp(status, latest_trans_epoch_str,
 
3335
                                      sizeof(latest_trans_epoch_str)-1))
 
3336
              status++;
 
3337
            if (*status)
 
3338
            {
 
3339
              status+= sizeof(latest_trans_epoch_str)-1;
 
3340
              latest_trans_epoch= strtoull(status, (char**) 0, 10);
 
3341
            }
 
3342
            else
 
3343
              die("result does not contain '%s' in '%s'",
 
3344
                  latest_trans_epoch_str, query);
 
3345
            /* latest_received_binlog_epoch */
 
3346
            while (*status &&
 
3347
                   strncmp(status, latest_received_binlog_epoch_str,
 
3348
                           sizeof(latest_received_binlog_epoch_str)-1))
 
3349
              status++;
 
3350
            if (*status)
 
3351
            {
 
3352
              status+= sizeof(latest_received_binlog_epoch_str)-1;
 
3353
              latest_received_binlog_epoch= strtoull(status, (char**) 0, 10);
 
3354
            }
 
3355
            else
 
3356
              die("result does not contain '%s' in '%s'",
 
3357
                  latest_received_binlog_epoch_str, query);
 
3358
            /* latest_handled_binlog */
 
3359
            while (*status &&
 
3360
                   strncmp(status, latest_handled_binlog_epoch_str,
 
3361
                           sizeof(latest_handled_binlog_epoch_str)-1))
 
3362
              status++;
 
3363
            if (*status)
 
3364
            {
 
3365
              status+= sizeof(latest_handled_binlog_epoch_str)-1;
 
3366
              latest_handled_binlog_epoch= strtoull(status, (char**) 0, 10);
 
3367
            }
 
3368
            else
 
3369
              die("result does not contain '%s' in '%s'",
 
3370
                  latest_handled_binlog_epoch_str, query);
 
3371
            /* latest_applied_binlog_epoch */
 
3372
            while (*status &&
 
3373
                   strncmp(status, latest_applied_binlog_epoch_str,
 
3374
                           sizeof(latest_applied_binlog_epoch_str)-1))
 
3375
              status++;
 
3376
            if (*status)
 
3377
            {
 
3378
              status+= sizeof(latest_applied_binlog_epoch_str)-1;
 
3379
              latest_applied_binlog_epoch= strtoull(status, (char**) 0, 10);
 
3380
            }
 
3381
            else
 
3382
              die("result does not contain '%s' in '%s'",
 
3383
                  latest_applied_binlog_epoch_str, query);
 
3384
            if (count == 0)
 
3385
              start_epoch= latest_trans_epoch;
 
3386
            break;
 
3387
          }
 
3388
        }
 
3389
        if (!row)
 
3390
          die("result does not contain '%s' in '%s'",
 
3391
              binlog, query);
 
3392
        if (latest_handled_binlog_epoch > handled_epoch)
 
3393
          count= 0;
 
3394
        handled_epoch= latest_handled_binlog_epoch;
 
3395
        count++;
 
3396
        if (latest_handled_binlog_epoch >= start_epoch)
 
3397
          do_continue= 0;
 
3398
        else if (count > 30)
 
3399
        {
 
3400
          break;
 
3401
        }
 
3402
        mysql_free_result(res);
 
3403
      }
 
3404
    }
 
3405
  }
 
3406
#endif
 
3407
  if (mysql_query(mysql, query= "show master status"))
3078
3408
    die("failed in 'show master status': %d %s",
3079
 
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
3409
        mysql_errno(mysql), mysql_error(mysql));
3080
3410
 
3081
 
  if (!(res = drizzle_store_result(drizzle)))
3082
 
    die("drizzle_store_result() retuned NULL for '%s'", query);
3083
 
  if (!(row = drizzle_fetch_row(res)))
 
3411
  if (!(res = mysql_store_result(mysql)))
 
3412
    die("mysql_store_result() retuned NULL for '%s'", query);
 
3413
  if (!(row = mysql_fetch_row(res)))
3084
3414
    die("empty result in show master status");
3085
 
  my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
 
3415
  strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
3086
3416
  master_pos.pos = strtoul(row[1], (char**) 0, 10);
3087
 
  drizzle_free_result(res);
3088
 
  return(0);
 
3417
  mysql_free_result(res);
 
3418
  DBUG_RETURN(0);
3089
3419
}
3090
3420
 
3091
3421
 
3094
3424
 
3095
3425
  SYNOPSIS
3096
3426
  do_let()
3097
 
  query  called command
 
3427
  query called command
3098
3428
 
3099
3429
  DESCRIPTION
3100
3430
  let $<var_name>=<var_val><delimiter>
3112
3442
{
3113
3443
  char *p= command->first_argument;
3114
3444
  char *var_name, *var_name_end;
3115
 
  string let_rhs_expr;
 
3445
  DYNAMIC_STRING let_rhs_expr;
 
3446
  DBUG_ENTER("do_let");
3116
3447
 
 
3448
  init_dynamic_string(&let_rhs_expr, "", 512, 2048);
3117
3449
 
3118
3450
  /* Find <var_name> */
3119
3451
  if (!*p)
3134
3466
  while (*p && my_isspace(charset_info,*p))
3135
3467
    p++;
3136
3468
 
3137
 
  do_eval(&let_rhs_expr, p, command->end, false);
 
3469
  do_eval(&let_rhs_expr, p, command->end, FALSE);
3138
3470
 
3139
3471
  command->last_argument= command->end;
3140
3472
  /* 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;
 
3473
  var_set(var_name, var_name_end, let_rhs_expr.str,
 
3474
          (let_rhs_expr.str + let_rhs_expr.length));
 
3475
  dynstr_free(&let_rhs_expr);
 
3476
  DBUG_VOID_RETURN;
3144
3477
}
3145
3478
 
3146
3479
 
3149
3482
 
3150
3483
  SYNOPSIS
3151
3484
  do_sleep()
3152
 
  q         called command
 
3485
  q            called command
3153
3486
  real_sleep   use the value from opt_sleep as number of seconds to sleep
3154
 
  if real_sleep is false
 
3487
               if real_sleep is false
3155
3488
 
3156
3489
  DESCRIPTION
3157
3490
  sleep <seconds>
3166
3499
  used for cpu-independent delays.
3167
3500
*/
3168
3501
 
3169
 
static int do_sleep(struct st_command *command, bool real_sleep)
 
3502
static int do_sleep(struct st_command *command, my_bool real_sleep)
3170
3503
{
3171
3504
  int error= 0;
3172
3505
  char *p= command->first_argument;
3191
3524
  if (opt_sleep >= 0 && !real_sleep)
3192
3525
    sleep_val= opt_sleep;
3193
3526
 
 
3527
  DBUG_PRINT("info", ("sleep_val: %f", sleep_val));
3194
3528
  if (sleep_val)
3195
 
    my_sleep((uint32_t) (sleep_val * 1000000L));
 
3529
    my_sleep((ulong) (sleep_val * 1000000L));
3196
3530
  command->last_argument= sleep_end;
3197
3531
  return 0;
3198
3532
}
3199
3533
 
3200
3534
 
3201
3535
static void do_get_file_name(struct st_command *command,
3202
 
                             char* dest, uint dest_max_len)
 
3536
                      char* dest, uint dest_max_len)
3203
3537
{
3204
3538
  char *p= command->first_argument, *name;
3205
3539
  if (!*p)
3233
3567
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3234
3568
}
3235
3569
 
 
3570
 
 
3571
#if MYSQL_VERSION_ID >= 50000
 
3572
/* List of error names to error codes, available from 5.0 */
 
3573
typedef struct
 
3574
{
 
3575
  const char *name;
 
3576
  uint        code;
 
3577
} st_error;
 
3578
 
 
3579
static st_error global_error_names[] =
 
3580
{
 
3581
#include <mysqld_ername.h>
 
3582
  { 0, 0 }
 
3583
};
 
3584
 
3236
3585
static uint get_errcode_from_name(char *error_name, char *error_end)
3237
3586
{
3238
3587
  /* SQL error as string */
3239
3588
  st_error *e= global_error_names;
3240
3589
 
 
3590
  DBUG_ENTER("get_errcode_from_name");
 
3591
  DBUG_PRINT("enter", ("error_name: %s", error_name));
 
3592
 
3241
3593
  /* Loop through the array of known error names */
3242
3594
  for (; e->name; e++)
3243
3595
  {
3249
3601
    if (!strncmp(error_name, e->name, (int) (error_end - error_name)) &&
3250
3602
        (uint) strlen(e->name) == (uint) (error_end - error_name))
3251
3603
    {
3252
 
      return(e->code);
 
3604
      DBUG_RETURN(e->code);
3253
3605
    }
3254
3606
  }
3255
3607
  if (!e->name)
3256
3608
    die("Unknown SQL error name '%s'", error_name);
3257
 
  return(0);
3258
 
}
 
3609
  DBUG_RETURN(0);
 
3610
}
 
3611
#else
 
3612
uint get_errcode_from_name(char *error_name __attribute__((unused)),
 
3613
                           char *error_end __attribute__((unused)))
 
3614
{
 
3615
  abort_not_in_this_version();
 
3616
  return 0; /* Never reached */
 
3617
}
 
3618
#endif
 
3619
 
 
3620
 
3259
3621
 
3260
3622
static void do_get_errcodes(struct st_command *command)
3261
3623
{
3263
3625
  char *p= command->first_argument;
3264
3626
  uint count= 0;
3265
3627
 
3266
 
 
 
3628
  DBUG_ENTER("do_get_errcodes");
3267
3629
 
3268
3630
  if (!*p)
3269
3631
    die("Missing argument(s) to 'error'");
3300
3662
        if (my_isdigit(charset_info, *p) || my_isupper(charset_info, *p))
3301
3663
          *to_ptr++= *p++;
3302
3664
        else
3303
 
          die("The sqlstate may only consist of digits[0-9] "   \
 
3665
          die("The sqlstate may only consist of digits[0-9] " \
3304
3666
              "and _uppercase_ letters");
3305
3667
      }
3306
3668
 
3307
3669
      *to_ptr= 0;
3308
3670
      to->type= ERR_SQLSTATE;
 
3671
      DBUG_PRINT("info", ("ERR_SQLSTATE: %s", to->code.sqlstate));
3309
3672
    }
3310
3673
    else if (*p == 's')
3311
3674
    {
3315
3678
    {
3316
3679
      /* Error name string */
3317
3680
 
 
3681
      DBUG_PRINT("info", ("Error name: %s", p));
3318
3682
      to->code.errnum= get_errcode_from_name(p, end);
3319
3683
      to->type= ERR_ERRNO;
 
3684
      DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
3320
3685
    }
3321
3686
    else if (*p == 'e')
3322
3687
    {
3330
3695
      while (*p && p != end)
3331
3696
      {
3332
3697
        if (!my_isdigit(charset_info, *p))
3333
 
          die("Invalid argument to error: '%s' - "              \
 
3698
          die("Invalid argument to error: '%s' - "\
3334
3699
              "the errno may only consist of digits[0-9]",
3335
3700
              command->first_argument);
3336
3701
        p++;
3338
3703
 
3339
3704
      /* Convert the sting to int */
3340
3705
      if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
3341
 
        die("Invalid argument to error: '%s'", command->first_argument);
 
3706
        die("Invalid argument to error: '%s'", command->first_argument);
3342
3707
 
3343
3708
      to->code.errnum= (uint) val;
3344
3709
      to->type= ERR_ERRNO;
 
3710
      DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
3345
3711
    }
3346
3712
    to++;
3347
3713
    count++;
3365
3731
  command->last_argument= p;
3366
3732
  to->type= ERR_EMPTY;                        /* End of data */
3367
3733
 
 
3734
  DBUG_PRINT("info", ("Expected errors: %d", count));
3368
3735
  saved_expected_errors.count= count;
3369
 
  return;
 
3736
  DBUG_VOID_RETURN;
3370
3737
}
3371
3738
 
3372
3739
 
3382
3749
{
3383
3750
  char c, sep;
3384
3751
  char *to= *to_ptr, *from= *from_ptr, *start=to;
3385
 
 
 
3752
  DBUG_ENTER("get_string");
3386
3753
 
3387
3754
  /* Find separator */
3388
3755
  if (*from == '"' || *from == '\'')
3389
3756
    sep= *from++;
3390
3757
  else
3391
 
    sep=' ';        /* Separated with space */
 
3758
    sep=' ';                            /* Separated with space */
3392
3759
 
3393
3760
  for ( ; (c=*from) ; from++)
3394
3761
  {
3395
3762
    if (c == '\\' && from[1])
3396
 
    {          /* Escaped character */
 
3763
    {                                   /* Escaped character */
3397
3764
      /* We can't translate \0 -> ASCII 0 as replace can't handle ASCII 0 */
3398
3765
      switch (*++from) {
3399
3766
      case 'n':
3400
 
        *to++= '\n';
3401
 
        break;
 
3767
        *to++= '\n';
 
3768
        break;
3402
3769
      case 't':
3403
 
        *to++= '\t';
3404
 
        break;
 
3770
        *to++= '\t';
 
3771
        break;
3405
3772
      case 'r':
3406
 
        *to++ = '\r';
3407
 
        break;
 
3773
        *to++ = '\r';
 
3774
        break;
3408
3775
      case 'b':
3409
 
        *to++ = '\b';
3410
 
        break;
3411
 
      case 'Z':        /* ^Z must be escaped on Win32 */
3412
 
        *to++='\032';
3413
 
        break;
 
3776
        *to++ = '\b';
 
3777
        break;
 
3778
      case 'Z':                         /* ^Z must be escaped on Win32 */
 
3779
        *to++='\032';
 
3780
        break;
3414
3781
      default:
3415
 
        *to++ = *from;
3416
 
        break;
 
3782
        *to++ = *from;
 
3783
        break;
3417
3784
      }
3418
3785
    }
3419
3786
    else if (c == sep)
3420
3787
    {
3421
3788
      if (c == ' ' || c != *++from)
3422
 
        break;        /* Found end of string */
3423
 
      *to++=c;        /* Copy duplicated separator */
 
3789
        break;                          /* Found end of string */
 
3790
      *to++=c;                          /* Copy duplicated separator */
3424
3791
    }
3425
3792
    else
3426
3793
      *to++=c;
3428
3795
  if (*from != ' ' && *from)
3429
3796
    die("Wrong string argument in %s", command->query);
3430
3797
 
3431
 
  while (my_isspace(charset_info,*from))  /* Point to next string */
 
3798
  while (my_isspace(charset_info,*from))        /* Point to next string */
3432
3799
    from++;
3433
3800
 
3434
 
  *to =0;        /* End of string marker */
3435
 
  *to_ptr= to+1;      /* Store pointer to end */
 
3801
  *to =0;                               /* End of string marker */
 
3802
  *to_ptr= to+1;                        /* Store pointer to end */
3436
3803
  *from_ptr= from;
3437
3804
 
3438
3805
  /* Check if this was a variable */
3441
3808
    const char *end= to;
3442
3809
    VAR *var=var_get(start, &end, 0, 1);
3443
3810
    if (var && to == (char*) end+1)
3444
 
      return(var->str_val);  /* return found variable value */
 
3811
    {
 
3812
      DBUG_PRINT("info",("var: '%s' -> '%s'", start, var->str_val));
 
3813
      DBUG_RETURN(var->str_val);        /* return found variable value */
 
3814
    }
3445
3815
  }
3446
 
  return(start);
 
3816
  DBUG_RETURN(start);
3447
3817
}
3448
3818
 
3449
3819
 
3450
 
static void set_reconnect(DRIZZLE *drizzle, int val)
 
3820
static void set_reconnect(MYSQL* mysql, int val)
3451
3821
{
3452
 
  bool reconnect= val;
3453
 
 
3454
 
  drizzle_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
3455
 
 
3456
 
  return;
 
3822
  my_bool reconnect= val;
 
3823
  DBUG_ENTER("set_reconnect");
 
3824
  DBUG_PRINT("info", ("val: %d", val));
 
3825
#if MYSQL_VERSION_ID < 50000
 
3826
  mysql->reconnect= reconnect;
 
3827
#else
 
3828
  mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
 
3829
#endif
 
3830
  DBUG_VOID_RETURN;
3457
3831
}
3458
3832
 
3459
3833
 
3460
3834
static int select_connection_name(const char *name)
3461
3835
{
 
3836
  DBUG_ENTER("select_connection_name");
 
3837
  DBUG_PRINT("enter",("name: '%s'", name));
 
3838
 
3462
3839
  if (!(cur_con= find_connection_by_name(name)))
3463
3840
    die("connection '%s' not found in connection pool", name);
3464
3841
 
3465
 
  /* Update $drizzle_get_server_version to that of current connection */
3466
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
3842
  /* Update $mysql_get_server_version to that of current connection */
 
3843
  var_set_mysql_get_server_version(&cur_con->mysql);
3467
3844
 
3468
 
  return(0);
 
3845
  DBUG_RETURN(0);
3469
3846
}
3470
3847
 
3471
3848
 
3473
3850
{
3474
3851
  char *name;
3475
3852
  char *p= command->first_argument;
3476
 
 
 
3853
  DBUG_ENTER("select_connection");
3477
3854
 
3478
3855
  if (!*p)
3479
3856
    die("Missing connection name in connect");
3483
3860
  if (*p)
3484
3861
    *p++= 0;
3485
3862
  command->last_argument= p;
3486
 
  return(select_connection_name(name));
 
3863
  DBUG_RETURN(select_connection_name(name));
3487
3864
}
3488
3865
 
3489
3866
 
3492
3869
  char *p= command->first_argument, *name;
3493
3870
  struct st_connection *con;
3494
3871
 
 
3872
  DBUG_ENTER("close_connection");
 
3873
  DBUG_PRINT("enter",("name: '%s'",p));
 
3874
 
3495
3875
  if (!*p)
3496
3876
    die("Missing connection name in disconnect");
3497
3877
  name= p;
3505
3885
  if (!(con= find_connection_by_name(name)))
3506
3886
    die("connection '%s' not found in connection pool", name);
3507
3887
 
 
3888
  DBUG_PRINT("info", ("Closing connection %s", con->name));
3508
3889
  if (command->type == Q_DIRTY_CLOSE)
3509
3890
  {
3510
 
    if (con->drizzle.net.vio)
 
3891
    if (con->mysql.net.vio)
3511
3892
    {
3512
 
      net_close(&(con->drizzle.net));
 
3893
      vio_delete(con->mysql.net.vio);
 
3894
      con->mysql.net.vio = 0;
3513
3895
    }
3514
3896
  }
3515
3897
 
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);
 
3898
  mysql_close(&con->mysql);
 
3899
 
 
3900
  if (con->util_mysql)
 
3901
    mysql_close(con->util_mysql);
 
3902
  con->util_mysql= 0;
 
3903
 
 
3904
  my_free(con->name, MYF(0));
3523
3905
 
3524
3906
  /*
3525
3907
    When the connection is closed set name to "-closed_connection-"
3528
3910
  if (!(con->name = my_strdup("-closed_connection-", MYF(MY_WME))))
3529
3911
    die("Out of memory");
3530
3912
 
3531
 
  return;
 
3913
  DBUG_VOID_RETURN;
3532
3914
}
3533
3915
 
3534
3916
 
3557
3939
 
3558
3940
*/
3559
3941
 
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)
 
3942
static void safe_connect(MYSQL* mysql, const char *name, const char *host,
 
3943
                  const char *user, const char *pass, const char *db,
 
3944
                  int port)
3563
3945
{
3564
3946
  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))
 
3947
  static ulong connection_retry_sleep= 100000; /* Microseconds */
 
3948
 
 
3949
  DBUG_ENTER("safe_connect");
 
3950
  while(!mysql_real_connect(mysql, host, user, pass, db, port, NULL,
 
3951
                            CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3570
3952
  {
3571
3953
    /*
3572
3954
      Connect failed
3576
3958
      on protocol/connection type
3577
3959
    */
3578
3960
 
3579
 
    if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
3580
 
         drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
 
3961
    if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
 
3962
         mysql_errno(mysql) == CR_CONNECTION_ERROR) &&
3581
3963
        failed_attempts < opt_max_connect_retries)
3582
3964
    {
3583
3965
      verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3584
 
                  opt_max_connect_retries, drizzle_errno(drizzle),
3585
 
                  drizzle_error(drizzle));
 
3966
                  opt_max_connect_retries, mysql_errno(mysql),
 
3967
                  mysql_error(mysql));
3586
3968
      my_sleep(connection_retry_sleep);
3587
3969
    }
3588
3970
    else
3589
3971
    {
3590
3972
      if (failed_attempts > 0)
3591
3973
        die("Could not open connection '%s' after %d attempts: %d %s", name,
3592
 
            failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
 
3974
            failed_attempts, mysql_errno(mysql), mysql_error(mysql));
3593
3975
      else
3594
3976
        die("Could not open connection '%s': %d %s", name,
3595
 
            drizzle_errno(drizzle), drizzle_error(drizzle));
 
3977
            mysql_errno(mysql), mysql_error(mysql));
3596
3978
    }
3597
3979
    failed_attempts++;
3598
3980
  }
3599
 
  return;
 
3981
  DBUG_VOID_RETURN;
3600
3982
}
3601
3983
 
3602
3984
 
3624
4006
*/
3625
4007
 
3626
4008
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)
 
4009
                            MYSQL* con, const char* host,
 
4010
                            const char* user, const char* pass,
 
4011
                            const char* db, int port, const char* sock)
3630
4012
{
 
4013
  DYNAMIC_STRING *ds;
 
4014
 
 
4015
  ds= &ds_res;
3631
4016
 
3632
4017
  /* Only log if an error is expected */
3633
4018
  if (!command->abort_on_error &&
3636
4021
    /*
3637
4022
      Log the connect to result log
3638
4023
    */
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(",");
 
4024
    dynstr_append_mem(ds, "connect(", 8);
 
4025
    replace_dynstr_append(ds, host);
 
4026
    dynstr_append_mem(ds, ",", 1);
 
4027
    replace_dynstr_append(ds, user);
 
4028
    dynstr_append_mem(ds, ",", 1);
 
4029
    replace_dynstr_append(ds, pass);
 
4030
    dynstr_append_mem(ds, ",", 1);
3646
4031
    if (db)
3647
 
      replace_append(&ds_res, db);
3648
 
    ds_res.append(",");
3649
 
    replace_append_uint(&ds_res, port);
3650
 
    ds_res.append(",");
 
4032
      replace_dynstr_append(ds, db);
 
4033
    dynstr_append_mem(ds, ",", 1);
 
4034
    replace_dynstr_append_uint(ds, port);
 
4035
    dynstr_append_mem(ds, ",", 1);
3651
4036
    if (sock)
3652
 
      replace_append(&ds_res, sock);
3653
 
    ds_res.append(")");
3654
 
    ds_res.append(delimiter);
3655
 
    ds_res.append("\n");
 
4037
      replace_dynstr_append(ds, sock);
 
4038
    dynstr_append_mem(ds, ")", 1);
 
4039
    dynstr_append_mem(ds, delimiter, delimiter_length);
 
4040
    dynstr_append_mem(ds, "\n", 1);
3656
4041
  }
3657
 
  if (!drizzle_connect(con, host, user, pass, db, port, 0,
3658
 
                       CLIENT_MULTI_STATEMENTS))
 
4042
  if (!mysql_real_connect(con, host, user, pass, db, port, 0,
 
4043
                          CLIENT_MULTI_STATEMENTS))
3659
4044
  {
3660
 
    var_set_errno(drizzle_errno(con));
3661
 
    handle_error(command, drizzle_errno(con), drizzle_error(con),
3662
 
                 drizzle_sqlstate(con), &ds_res);
 
4045
    var_set_errno(mysql_errno(con));
 
4046
    handle_error(command, mysql_errno(con), mysql_error(con),
 
4047
                 mysql_sqlstate(con), ds);
3663
4048
    return 0; /* Not connected */
3664
4049
  }
3665
4050
 
3670
4055
 
3671
4056
 
3672
4057
/*
3673
 
  Open a new connection to DRIZZLE Server with the parameters
 
4058
  Open a new connection to MySQL Server with the parameters
3674
4059
  specified. Make the new connection the current connection.
3675
4060
 
3676
4061
  SYNOPSIS
3677
4062
  do_connect()
3678
 
  q         called command
 
4063
  q            called command
3679
4064
 
3680
4065
  DESCRIPTION
3681
4066
  connect(<name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]]);
3689
4074
  <port> - server port
3690
4075
  <sock> - server socket
3691
4076
  <opts> - options to use for the connection
3692
 
  * SSL - use SSL if available
3693
 
  * COMPRESS - use compression if available
 
4077
   * SSL - use SSL if available
 
4078
   * COMPRESS - use compression if available
3694
4079
 
3695
 
  */
 
4080
*/
3696
4081
 
3697
4082
static void do_connect(struct st_command *command)
3698
4083
{
3699
4084
  int con_port= opt_port;
3700
 
  const char *con_options;
3701
 
  bool con_ssl= 0, con_compress= 0;
 
4085
  char *con_options;
 
4086
  my_bool con_ssl= 0, con_compress= 0;
3702
4087
  struct st_connection* con_slot;
3703
4088
 
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;
 
4089
  static DYNAMIC_STRING ds_connection_name;
 
4090
  static DYNAMIC_STRING ds_host;
 
4091
  static DYNAMIC_STRING ds_user;
 
4092
  static DYNAMIC_STRING ds_password;
 
4093
  static DYNAMIC_STRING ds_database;
 
4094
  static DYNAMIC_STRING ds_port;
 
4095
  static DYNAMIC_STRING ds_sock;
 
4096
  static DYNAMIC_STRING ds_options;
3712
4097
  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" }
 
4098
    { "connection name", ARG_STRING, TRUE, &ds_connection_name, "Name of the connection" },
 
4099
    { "host", ARG_STRING, TRUE, &ds_host, "Host to connect to" },
 
4100
    { "user", ARG_STRING, FALSE, &ds_user, "User to connect as" },
 
4101
    { "passsword", ARG_STRING, FALSE, &ds_password, "Password used when connecting" },
 
4102
    { "database", ARG_STRING, FALSE, &ds_database, "Database to select after connect" },
 
4103
    { "port", ARG_STRING, FALSE, &ds_port, "Port to connect to" },
 
4104
    { "socket", ARG_STRING, FALSE, &ds_sock, "Socket to connect with" },
 
4105
    { "options", ARG_STRING, FALSE, &ds_options, "Options to use while connecting" }
3721
4106
  };
3722
4107
 
 
4108
  DBUG_ENTER("do_connect");
 
4109
  DBUG_PRINT("enter",("connect: %s", command->first_argument));
3723
4110
 
3724
4111
  strip_parentheses(command);
3725
4112
  check_command_args(command, command->first_argument, connect_args,
3727
4114
                     ',');
3728
4115
 
3729
4116
  /* Port */
3730
 
  if (ds_port.length())
 
4117
  if (ds_port.length)
3731
4118
  {
3732
 
    con_port= atoi(ds_port.c_str());
 
4119
    con_port= atoi(ds_port.str);
3733
4120
    if (con_port == 0)
3734
 
      die("Illegal argument for port: '%s'", ds_port.c_str());
 
4121
      die("Illegal argument for port: '%s'", ds_port.str);
3735
4122
  }
3736
4123
 
3737
4124
  /* Sock */
3738
 
  if (!ds_sock.empty())
 
4125
  if (ds_sock.length)
3739
4126
  {
3740
4127
    /*
3741
4128
      If the socket is specified just as a name without path
3742
4129
      append tmpdir in front
3743
4130
    */
3744
 
    if (*ds_sock.c_str() != FN_LIBCHAR)
 
4131
    if (*ds_sock.str != FN_LIBCHAR)
3745
4132
    {
3746
4133
      char buff[FN_REFLEN];
3747
 
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3748
 
      ds_sock= buff;
 
4134
      fn_format(buff, ds_sock.str, TMPDIR, "", 0);
 
4135
      dynstr_set(&ds_sock, buff);
3749
4136
    }
3750
4137
  }
 
4138
  else
 
4139
  {
 
4140
    /* No socket specified, use default */
 
4141
    dynstr_set(&ds_sock, unix_sock);
 
4142
  }
 
4143
  DBUG_PRINT("info", ("socket: %s", ds_sock.str));
 
4144
 
3751
4145
 
3752
4146
  /* Options */
3753
 
  con_options= ds_options.c_str();
 
4147
  con_options= ds_options.str;
3754
4148
  while (*con_options)
3755
4149
  {
3756
 
    const char* end;
 
4150
    char* end;
3757
4151
    /* Step past any spaces in beginning of option*/
3758
4152
    while (*con_options && my_isspace(charset_info, *con_options))
3759
 
      con_options++;
 
4153
     con_options++;
3760
4154
    /* Find end of this option */
3761
4155
    end= con_options;
3762
4156
    while (*end && !my_isspace(charset_info, *end))
3766
4160
    else if (!strncmp(con_options, "COMPRESS", 8))
3767
4161
      con_compress= 1;
3768
4162
    else
3769
 
      die("Illegal option to connect: %.*s",
 
4163
      die("Illegal option to connect: %.*s", 
3770
4164
          (int) (end - con_options), con_options);
3771
4165
    /* Process next option */
3772
4166
    con_options= end;
3773
4167
  }
3774
4168
 
3775
 
  if (find_connection_by_name(ds_connection_name.c_str()))
3776
 
    die("Connection %s already exists", ds_connection_name.c_str());
3777
 
 
 
4169
  if (find_connection_by_name(ds_connection_name.str))
 
4170
    die("Connection %s already exists", ds_connection_name.str);
 
4171
    
3778
4172
  if (next_con != connections_end)
3779
 
  {
3780
4173
    con_slot= next_con;
3781
 
  }
3782
4174
  else
3783
4175
  {
3784
4176
    if (!(con_slot= find_connection_by_name("-closed_connection-")))
3786
4178
          (int) (sizeof(connections)/sizeof(struct st_connection)));
3787
4179
  }
3788
4180
 
3789
 
  if (!drizzle_create(&con_slot->drizzle))
3790
 
    die("Failed on drizzle_create()");
 
4181
#ifdef EMBEDDED_LIBRARY
 
4182
  con_slot->query_done= 1;
 
4183
#endif
 
4184
  if (!mysql_init(&con_slot->mysql))
 
4185
    die("Failed on mysql_init()");
3791
4186
  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);
 
4187
    mysql_options(&con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
 
4188
  mysql_options(&con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
 
4189
  mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_NAME,
 
4190
                charset_info->csname);
 
4191
  int opt_protocol= MYSQL_PROTOCOL_TCP;
 
4192
  mysql_options(&con_slot->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
4193
  if (opt_charsets_dir)
 
4194
    mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
 
4195
                  opt_charsets_dir);
3794
4196
 
3795
4197
  /* Use default db name */
3796
 
  if (ds_database.length() == 0)
3797
 
    ds_database= opt_db;
 
4198
  if (ds_database.length == 0)
 
4199
    dynstr_set(&ds_database, opt_db);
3798
4200
 
3799
4201
  /* 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= "";
 
4202
  if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
 
4203
    dynstr_set(&ds_database, "");
3802
4204
 
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()))
 
4205
  if (connect_n_handle_errors(command, &con_slot->mysql,
 
4206
                              ds_host.str,ds_user.str,
 
4207
                              ds_password.str, ds_database.str,
 
4208
                              con_port, ds_sock.str))
3807
4209
  {
3808
 
    if (!(con_slot->name= strdup(ds_connection_name.c_str())))
 
4210
    DBUG_PRINT("info", ("Inserting connection %s in connection pool",
 
4211
                        ds_connection_name.str));
 
4212
    if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3809
4213
      die("Out of memory");
3810
4214
    cur_con= con_slot;
3811
 
 
 
4215
    
3812
4216
    if (con_slot == next_con)
3813
4217
      next_con++; /* if we used the next_con slot, advance the pointer */
3814
4218
  }
3815
4219
 
3816
 
  /* Update $drizzle_get_server_version to that of current connection */
3817
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
4220
  /* Update $mysql_get_server_version to that of current connection */
 
4221
  var_set_mysql_get_server_version(&cur_con->mysql);
3818
4222
 
3819
 
  return;
 
4223
  dynstr_free(&ds_connection_name);
 
4224
  dynstr_free(&ds_host);
 
4225
  dynstr_free(&ds_user);
 
4226
  dynstr_free(&ds_password);
 
4227
  dynstr_free(&ds_database);
 
4228
  dynstr_free(&ds_port);
 
4229
  dynstr_free(&ds_sock);
 
4230
  dynstr_free(&ds_options);
 
4231
  DBUG_VOID_RETURN;
3820
4232
}
3821
4233
 
3822
4234
 
3853
4265
  SYNOPSIS
3854
4266
  do_block()
3855
4267
  cmd        Type of block
3856
 
  q         called command
 
4268
  q            called command
3857
4269
 
3858
4270
  DESCRIPTION
3859
4271
  if ([!]<expr>)
3879
4291
  const char *expr_start, *expr_end;
3880
4292
  VAR v;
3881
4293
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
3882
 
  bool not_expr= false;
 
4294
  my_bool not_expr= FALSE;
 
4295
  DBUG_ENTER("do_block");
 
4296
  DBUG_PRINT("enter", ("%s", cmd_name));
3883
4297
 
3884
4298
  /* Check stack overflow */
3885
4299
  if (cur_block == block_stack_end)
3894
4308
    /* Inner block should be ignored too */
3895
4309
    cur_block++;
3896
4310
    cur_block->cmd= cmd;
3897
 
    cur_block->ok= false;
3898
 
    return;
 
4311
    cur_block->ok= FALSE;
 
4312
    DBUG_VOID_RETURN;
3899
4313
  }
3900
4314
 
3901
4315
  /* Parse and evaluate test expression */
3906
4320
  /* Check for !<expr> */
3907
4321
  if (*expr_start == '!')
3908
4322
  {
3909
 
    not_expr= true;
 
4323
    not_expr= TRUE;
3910
4324
    expr_start++; /* Step past the '!' */
3911
4325
  }
3912
4326
  /* Find ending ')' */
3926
4340
  /* Define inner block */
3927
4341
  cur_block++;
3928
4342
  cur_block->cmd= cmd;
3929
 
  cur_block->ok= (v.int_val ? true : false);
 
4343
  cur_block->ok= (v.int_val ? TRUE : FALSE);
3930
4344
 
3931
4345
  if (not_expr)
3932
4346
    cur_block->ok = !cur_block->ok;
3933
4347
 
 
4348
  DBUG_PRINT("info", ("OK: %d", cur_block->ok));
 
4349
 
3934
4350
  var_free(&v);
3935
 
  return;
 
4351
  DBUG_VOID_RETURN;
3936
4352
}
3937
4353
 
3938
4354
 
3939
4355
static void do_delimiter(struct st_command* command)
3940
4356
{
3941
4357
  char* p= command->first_argument;
 
4358
  DBUG_ENTER("do_delimiter");
 
4359
  DBUG_PRINT("enter", ("first_argument: %s", command->first_argument));
3942
4360
 
3943
4361
  while (*p && my_isspace(charset_info, *p))
3944
4362
    p++;
3949
4367
  strmake(delimiter, p, sizeof(delimiter) - 1);
3950
4368
  delimiter_length= strlen(delimiter);
3951
4369
 
 
4370
  DBUG_PRINT("exit", ("delimiter: %s", delimiter));
3952
4371
  command->last_argument= p + delimiter_length;
3953
 
  return;
 
4372
  DBUG_VOID_RETURN;
3954
4373
}
3955
4374
 
3956
4375
 
3957
 
bool match_delimiter(int c, const char *delim, uint length)
 
4376
my_bool match_delimiter(int c, const char *delim, uint length)
3958
4377
{
3959
4378
  uint i;
3960
4379
  char tmp[MAX_DELIMITER_LENGTH];
3963
4382
    return 0;
3964
4383
 
3965
4384
  for (i= 1; i < length &&
3966
 
         (c= my_getc(cur_file->file)) == *(delim + i);
 
4385
         (c= my_getc(cur_file->file)) == *(delim + i);
3967
4386
       i++)
3968
4387
    tmp[i]= c;
3969
4388
 
3970
4389
  if (i == length)
3971
 
    return 1;          /* Found delimiter */
 
4390
    return 1;                                   /* Found delimiter */
3972
4391
 
3973
4392
  /* didn't find delimiter, push back things that we read */
3974
4393
  my_ungetc(c);
3978
4397
}
3979
4398
 
3980
4399
 
3981
 
static bool end_of_query(int c)
 
4400
static my_bool end_of_query(int c)
3982
4401
{
3983
4402
  return match_delimiter(c, delimiter, delimiter_length);
3984
4403
}
4015
4434
  int skip_char= 0;
4016
4435
  enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
4017
4436
        R_COMMENT, R_LINE_START} state= R_LINE_START;
4018
 
 
 
4437
  DBUG_ENTER("read_line");
4019
4438
 
4020
4439
  start_lineno= cur_file->lineno;
 
4440
  DBUG_PRINT("info", ("Starting to read at lineno: %d", start_lineno));
4021
4441
  for (; p < buf_end ;)
4022
4442
  {
4023
4443
    skip_char= 0;
4027
4447
  found_eof:
4028
4448
      if (cur_file->file != stdin)
4029
4449
      {
4030
 
        my_fclose(cur_file->file, MYF(0));
 
4450
        my_fclose(cur_file->file, MYF(0));
4031
4451
        cur_file->file= 0;
4032
4452
      }
4033
 
      free((unsigned char*) cur_file->file_name);
 
4453
      my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
4034
4454
      cur_file->file_name= 0;
4035
4455
      if (cur_file == file_stack)
4036
4456
      {
4041
4461
          die("Missing end of block");
4042
4462
 
4043
4463
        *p= 0;
4044
 
        return(1);
 
4464
        DBUG_PRINT("info", ("end of file at line %d", cur_file->lineno));
 
4465
        DBUG_RETURN(1);
4045
4466
      }
4046
4467
      cur_file--;
4047
4468
      start_lineno= cur_file->lineno;
4062
4483
    case R_NORMAL:
4063
4484
      if (end_of_query(c))
4064
4485
      {
4065
 
        *p= 0;
4066
 
        return(0);
 
4486
        *p= 0;
 
4487
        DBUG_PRINT("exit", ("Found delimiter '%s' at line %d",
 
4488
                            delimiter, cur_file->lineno));
 
4489
        DBUG_RETURN(0);
4067
4490
      }
4068
4491
      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))))
 
4492
                (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
 
4493
                                      (uchar*) buf, min(5, p - buf), 0) ||
 
4494
                 !my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
 
4495
                                      (uchar*) buf, min(2, p - buf), 0))))
4073
4496
      {
4074
4497
        /* Only if and while commands can be terminated by { */
4075
4498
        *p++= c;
4076
 
        *p= 0;
4077
 
        return(0);
 
4499
        *p= 0;
 
4500
        DBUG_PRINT("exit", ("Found '{' indicating start of block at line %d",
 
4501
                            cur_file->lineno));
 
4502
        DBUG_RETURN(0);
4078
4503
      }
4079
4504
      else if (c == '\'' || c == '"' || c == '`')
4080
4505
      {
4081
4506
        last_quote= c;
4082
 
        state= R_Q;
 
4507
        state= R_Q;
4083
4508
      }
4084
4509
      break;
4085
4510
 
4087
4512
      if (c == '\n')
4088
4513
      {
4089
4514
        /* Comments are terminated by newline */
4090
 
        *p= 0;
4091
 
        return(0);
 
4515
        *p= 0;
 
4516
        DBUG_PRINT("exit", ("Found newline in comment at line: %d",
 
4517
                            cur_file->lineno));
 
4518
        DBUG_RETURN(0);
4092
4519
      }
4093
4520
      break;
4094
4521
 
4096
4523
      if (c == '#' || c == '-')
4097
4524
      {
4098
4525
        /* A # or - in the first position of the line - this is a comment */
4099
 
        state = R_COMMENT;
 
4526
        state = R_COMMENT;
4100
4527
      }
4101
4528
      else if (my_isspace(charset_info, c))
4102
4529
      {
4103
4530
        /* Skip all space at begining of line */
4104
 
        if (c == '\n')
 
4531
        if (c == '\n')
4105
4532
        {
4106
4533
          /* Query hasn't started yet */
4107
 
          start_lineno= cur_file->lineno;
 
4534
          start_lineno= cur_file->lineno;
 
4535
          DBUG_PRINT("info", ("Query hasn't started yet, start_lineno: %d",
 
4536
                              start_lineno));
4108
4537
        }
4109
 
        skip_char= 1;
 
4538
        skip_char= 1;
4110
4539
      }
4111
4540
      else if (end_of_query(c))
4112
4541
      {
4113
 
        *p= 0;
4114
 
        return(0);
 
4542
        *p= 0;
 
4543
        DBUG_PRINT("exit", ("Found delimiter '%s' at line: %d",
 
4544
                            delimiter, cur_file->lineno));
 
4545
        DBUG_RETURN(0);
4115
4546
      }
4116
4547
      else if (c == '}')
4117
4548
      {
4118
4549
        /* A "}" need to be by itself in the begining of a line to terminate */
4119
4550
        *p++= c;
4120
 
        *p= 0;
4121
 
        return(0);
 
4551
        *p= 0;
 
4552
        DBUG_PRINT("exit", ("Found '}' in begining of a line at line: %d",
 
4553
                            cur_file->lineno));
 
4554
        DBUG_RETURN(0);
4122
4555
      }
4123
4556
      else if (c == '\'' || c == '"' || c == '`')
4124
4557
      {
4125
4558
        last_quote= c;
4126
 
        state= R_Q;
 
4559
        state= R_Q;
4127
4560
      }
4128
4561
      else
4129
 
        state= R_NORMAL;
 
4562
        state= R_NORMAL;
4130
4563
      break;
4131
4564
 
4132
4565
    case R_Q:
4133
4566
      if (c == last_quote)
4134
 
        state= R_NORMAL;
 
4567
        state= R_NORMAL;
4135
4568
      else if (c == '\\')
4136
 
        state= R_SLASH_IN_Q;
 
4569
        state= R_SLASH_IN_Q;
4137
4570
      break;
4138
4571
 
4139
4572
    case R_SLASH_IN_Q:
4152
4585
      /* completed before we pass buf_end */
4153
4586
      if ((charlen > 1) && (p + charlen) <= buf_end)
4154
4587
      {
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
 
        }
 
4588
        int i;
 
4589
        char* mb_start = p;
 
4590
 
 
4591
        *p++ = c;
 
4592
 
 
4593
        for (i= 1; i < charlen; i++)
 
4594
        {
 
4595
          if (feof(cur_file->file))
 
4596
            goto found_eof;
 
4597
          c= my_getc(cur_file->file);
 
4598
          *p++ = c;
 
4599
        }
 
4600
        if (! my_ismbchar(charset_info, mb_start, p))
 
4601
        {
 
4602
          /* It was not a multiline char, push back the characters */
 
4603
          /* We leave first 'c', i.e. pretend it was a normal char */
 
4604
          while (p > mb_start)
 
4605
            my_ungetc(*--p);
 
4606
        }
4174
4607
      }
4175
4608
      else
4176
4609
#endif
4177
 
        *p++= c;
 
4610
        *p++= c;
4178
4611
    }
4179
4612
  }
4180
 
  die("The input buffer is too small for this query.x\n"        \
 
4613
  die("The input buffer is too small for this query.x\n" \
4181
4614
      "check your query or increase MAX_QUERY and recompile");
4182
 
  return(0);
 
4615
  DBUG_RETURN(0);
4183
4616
}
4184
4617
 
4185
4618
 
4198
4631
{
4199
4632
  int last_c_was_quote= 0;
4200
4633
  char *p= query, *to= query;
4201
 
  char *end= strchr(query, '\0');
 
4634
  char *end= strend(query);
4202
4635
  char last_c;
4203
4636
 
4204
4637
  while (p <= end)
4237
4670
 
4238
4671
/*
4239
4672
  Check a command that is about to be sent (or should have been
4240
 
  sent if parsing was enabled) to DRIZZLE server for
 
4673
  sent if parsing was enabled) to mysql server for
4241
4674
  suspicious things and generate warnings.
4242
4675
*/
4243
4676
 
4244
4677
static void scan_command_for_warnings(struct st_command *command)
4245
4678
{
4246
4679
  const char *ptr= command->query;
 
4680
  DBUG_ENTER("scan_command_for_warnings");
 
4681
  DBUG_PRINT("enter", ("query: %s", command->query));
4247
4682
 
4248
4683
  while(*ptr)
4249
4684
  {
4250
4685
    /*
4251
4686
      Look for query's that lines that start with a -- comment
4252
 
      and has a drizzletest command
 
4687
      and has a mysqltest command
4253
4688
    */
4254
4689
    if (ptr[0] == '\n' &&
4255
4690
        ptr[1] && ptr[1] == '-' &&
4268
4703
        end++;
4269
4704
      save= *end;
4270
4705
      *end= 0;
 
4706
      DBUG_PRINT("info", ("Checking '%s'", start));
4271
4707
      type= find_type(start, &command_typelib, 1+2);
4272
4708
      if (type)
4273
 
        warning_msg("Embedded drizzletest command '--%s' detected in "
 
4709
        warning_msg("Embedded mysqltest command '--%s' detected in "
4274
4710
                    "query '%s' was this intentional? ",
4275
4711
                    start, command->query);
4276
4712
      *end= save;
4278
4714
 
4279
4715
    ptr++;
4280
4716
  }
4281
 
  return;
 
4717
  DBUG_VOID_RETURN;
4282
4718
}
4283
4719
 
4284
4720
/*
4290
4726
static void check_eol_junk_line(const char *line)
4291
4727
{
4292
4728
  const char *p= line;
 
4729
  DBUG_ENTER("check_eol_junk_line");
 
4730
  DBUG_PRINT("enter", ("line: %s", line));
4293
4731
 
4294
4732
  /* Check for extra delimiter */
4295
4733
  if (*p && !strncmp(p, delimiter, delimiter_length))
4302
4740
      die("Missing delimiter");
4303
4741
    die("End of line junk detected: \"%s\"", p);
4304
4742
  }
4305
 
  return;
 
4743
  DBUG_VOID_RETURN;
4306
4744
}
4307
4745
 
4308
4746
static void check_eol_junk(const char *eol)
4309
4747
{
4310
4748
  const char *p= eol;
 
4749
  DBUG_ENTER("check_eol_junk");
 
4750
  DBUG_PRINT("enter", ("eol: %s", eol));
4311
4751
 
4312
4752
  /* Skip past all spacing chars and comments */
4313
4753
  while (*p && (my_isspace(charset_info, *p) || *p == '#' || *p == '\n'))
4330
4770
 
4331
4771
  check_eol_junk_line(p);
4332
4772
 
4333
 
  return;
 
4773
  DBUG_VOID_RETURN;
4334
4774
}
4335
4775
 
4336
4776
 
4339
4779
  Create a command from a set of lines
4340
4780
 
4341
4781
  SYNOPSIS
4342
 
  read_command()
4343
 
  command_ptr pointer where to return the new query
 
4782
    read_command()
 
4783
    command_ptr pointer where to return the new query
4344
4784
 
4345
4785
  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.
 
4786
    Converts lines returned by read_line into a command, this involves
 
4787
    parsing the first word in the read line to find the command type.
4348
4788
 
4349
4789
  A -- comment may contain a valid query as the first word after the
4350
4790
  comment start. Thus it's always checked to see if that is the case.
4359
4799
{
4360
4800
  char *p= read_command_buf;
4361
4801
  struct st_command* command;
4362
 
 
 
4802
  DBUG_ENTER("read_command");
4363
4803
 
4364
4804
  if (parser.current_line < parser.read_lines)
4365
4805
  {
4366
 
    *command_ptr= q_lines[parser.current_line];
4367
 
    return(0);
 
4806
    get_dynamic(&q_lines, (uchar*) command_ptr, parser.current_line) ;
 
4807
    DBUG_RETURN(0);
4368
4808
  }
4369
4809
  if (!(*command_ptr= command=
4370
4810
        (struct st_command*) my_malloc(sizeof(*command),
4371
 
                                       MYF(MY_WME|MY_ZEROFILL))))
4372
 
    die(NULL);
4373
 
  q_lines.push_back(command);
 
4811
                                       MYF(MY_WME|MY_ZEROFILL))) ||
 
4812
      insert_dynamic(&q_lines, (uchar*) &command))
 
4813
    die(NullS);
4374
4814
  command->type= Q_UNKNOWN;
4375
4815
 
4376
4816
  read_command_buf[0]= 0;
4377
4817
  if (read_line(read_command_buf, sizeof(read_command_buf)))
4378
4818
  {
4379
4819
    check_eol_junk(read_command_buf);
4380
 
    return(1);
 
4820
    DBUG_RETURN(1);
4381
4821
  }
4382
4822
 
4383
4823
  convert_to_format_v1(read_command_buf);
4384
4824
 
 
4825
  DBUG_PRINT("info", ("query: %s", read_command_buf));
4385
4826
  if (*p == '#')
4386
4827
  {
4387
4828
    command->type= Q_COMMENT;
4404
4845
  while (*p && !my_isspace(charset_info, *p) && *p != '(')
4405
4846
    p++;
4406
4847
  command->first_word_len= (uint) (p - command->query);
 
4848
  DBUG_PRINT("info", ("first_word: %.*s",
 
4849
                      command->first_word_len, command->query));
4407
4850
 
4408
4851
  /* Skip spaces between command and first argument */
4409
4852
  while (*p && my_isspace(charset_info, *p))
4410
4853
    p++;
4411
4854
  command->first_argument= p;
4412
4855
 
4413
 
  command->end= strchr(command->query, '\0');
 
4856
  command->end= strend(command->query);
4414
4857
  command->query_len= (command->end - command->query);
4415
4858
  parser.read_lines++;
4416
 
  return(0);
 
4859
  DBUG_RETURN(0);
4417
4860
}
4418
4861
 
4419
4862
 
4421
4864
{
4422
4865
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
4423
4866
   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},
 
4867
  {"basedir", 'b', "Basedir for tests.", (uchar**) &opt_basedir,
 
4868
   (uchar**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4426
4869
  {"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},
 
4870
   "Directory where character sets are.", (uchar**) &opt_charsets_dir,
 
4871
   (uchar**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4429
4872
  {"compress", 'C', "Use the compressed server/client protocol.",
4430
 
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
4873
   (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
4431
4874
   0, 0, 0},
4432
 
  {"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
 
4875
  {"database", 'D', "Database to use.", (uchar**) &opt_db, (uchar**) &opt_db, 0,
4433
4876
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4877
#ifdef DBUG_OFF
 
4878
  {"debug", '#', "This is a non-debug version. Catch this and exit",
 
4879
   0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
4880
#else
 
4881
  {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
 
4882
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
4883
#endif
4434
4884
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
4435
 
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
 
4885
   (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
4436
4886
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4437
4887
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
4438
 
   (char**) &debug_info_flag, (char**) &debug_info_flag,
 
4888
   (uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
4439
4889
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4440
 
  {"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
 
4890
  {"host", 'h', "Connect to host.", (uchar**) &opt_host, (uchar**) &opt_host, 0,
4441
4891
   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},
 
4892
  {"include", 'i', "Include SQL before each test case.", (uchar**) &opt_include,
 
4893
   (uchar**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4894
  {"logdir", OPT_LOG_DIR, "Directory for log files", (uchar**) &opt_logdir,
 
4895
   (uchar**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4446
4896
  {"mark-progress", OPT_MARK_PROGRESS,
4447
4897
   "Write linenumber and elapsed time to <testname>.progress ",
4448
 
   (char**) &opt_mark_progress, (char**) &opt_mark_progress, 0,
 
4898
   (uchar**) &opt_mark_progress, (uchar**) &opt_mark_progress, 0,
4449
4899
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4450
4900
  {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
4451
4901
   "Max number of connection attempts when connecting to server",
4452
 
   (char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
 
4902
   (uchar**) &opt_max_connect_retries, (uchar**) &opt_max_connect_retries, 0,
4453
4903
   GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
4454
4904
  {"password", 'p', "Password to use when connecting to server.",
4455
4905
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4456
4906
  {"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},
 
4907
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
 
4908
#if MYSQL_PORT_DEFAULT == 0
 
4909
   "/etc/services, "
 
4910
#endif
 
4911
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
 
4912
   (uchar**) &opt_port,
 
4913
   (uchar**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4914
  {"quiet", 's', "Suppress all normal output.", (uchar**) &silent,
 
4915
   (uchar**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4463
4916
  {"record", 'r', "Record output of test_file into result file.",
4464
4917
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
4465
4918
  {"result-file", 'R', "Read/Store result from/in this file.",
4466
 
   (char**) &result_file_name, (char**) &result_file_name, 0,
 
4919
   (uchar**) &result_file_name, (uchar**) &result_file_name, 0,
4467
4920
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4468
4921
  {"server-arg", 'A', "Send option value to embedded server as a parameter.",
4469
4922
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4470
4923
  {"server-file", 'F', "Read embedded server arguments from file.",
4471
4924
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4472
4925
  {"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},
 
4926
   (uchar**) &silent, (uchar**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4474
4927
  {"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,
 
4928
   (uchar**) &opt_sleep, (uchar**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
4476
4929
   0, 0, 0},
4477
4930
  {"tail-lines", OPT_TAIL_LINES,
4478
4931
   "Number of lines of the resul to include in a failure report",
4479
 
   (char**) &opt_tail_lines, (char**) &opt_tail_lines, 0,
 
4932
   (uchar**) &opt_tail_lines, (uchar**) &opt_tail_lines, 0,
4480
4933
   GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
4481
4934
  {"test-file", 'x', "Read test from/in this file (default stdin).",
4482
4935
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4484
4937
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4485
4938
  {"tmpdir", 't', "Temporary directory where sockets are put.",
4486
4939
   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,
 
4940
  {"user", 'u', "User for login.", (uchar**) &opt_user, (uchar**) &opt_user, 0,
4488
4941
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4489
 
  {"verbose", 'v', "Write more.", (char**) &verbose, (char**) &verbose, 0,
 
4942
  {"verbose", 'v', "Write more.", (uchar**) &verbose, (uchar**) &verbose, 0,
4490
4943
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4491
4944
  {"version", 'V', "Output version information and exit.",
4492
4945
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
4494
4947
};
4495
4948
 
4496
4949
 
 
4950
#include <help_start.h>
 
4951
 
4497
4952
static void print_version(void)
4498
4953
{
4499
4954
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4500
 
         drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
4955
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
4501
4956
}
4502
4957
 
4503
4958
static void usage(void)
4505
4960
  print_version();
4506
4961
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4507
4962
  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");
 
4963
  printf("Runs a test against the mysql server and compares output with a results file.\n\n");
4509
4964
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4510
4965
  my_print_help(my_long_options);
4511
4966
  printf("  --no-defaults       Don't read default options from any options file.\n");
4512
4967
  my_print_variables(my_long_options);
4513
4968
}
4514
4969
 
 
4970
#include <help_end.h>
 
4971
 
 
4972
 
4515
4973
/*
4516
4974
  Read arguments for embedded server and put them into
4517
4975
  embedded_server_args[]
4524
4982
 
4525
4983
  if (!test_if_hard_path(name))
4526
4984
  {
4527
 
    strxmov(buff, opt_basedir, name, NULL);
 
4985
    strxmov(buff, opt_basedir, name, NullS);
4528
4986
    name=buff;
4529
4987
  }
4530
4988
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
4532
4990
  if (!embedded_server_arg_count)
4533
4991
  {
4534
4992
    embedded_server_arg_count=1;
4535
 
    embedded_server_args[0]= (char*) "";    /* Progname */
 
4993
    embedded_server_args[0]= (char*) "";                /* Progname */
4536
4994
  }
4537
 
  if (!(file=my_fopen(buff, O_RDONLY, MYF(MY_WME))))
 
4995
  if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4538
4996
    die("Failed to open file '%s'", buff);
4539
4997
 
4540
4998
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4541
 
         (str=fgets(argument,sizeof(argument), file)))
 
4999
         (str=fgets(argument,sizeof(argument), file)))
4542
5000
  {
4543
 
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
 
5001
    *(strend(str)-1)=0;                         /* Remove end newline */
4544
5002
    if (!(embedded_server_args[embedded_server_arg_count]=
4545
 
          (char*) my_strdup(str,MYF(MY_WME))))
 
5003
          (char*) my_strdup(str,MYF(MY_WME))))
4546
5004
    {
4547
5005
      my_fclose(file,MYF(0));
4548
5006
      die("Out of memory");
4558
5016
}
4559
5017
 
4560
5018
 
4561
 
static bool
 
5019
static my_bool
4562
5020
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
4563
 
               char *argument)
 
5021
               char *argument)
4564
5022
{
4565
5023
  switch(optid) {
 
5024
  case '#':
 
5025
#ifndef DBUG_OFF
 
5026
    DBUG_PUSH(argument ? argument : "d:t:S:i:O,/tmp/mysqltest.trace");
 
5027
    debug_check_flag= 1;
 
5028
#endif
 
5029
    break;
4566
5030
  case 'r':
4567
5031
    record = 1;
4568
5032
    break;
4571
5035
    char buff[FN_REFLEN];
4572
5036
    if (!test_if_hard_path(argument))
4573
5037
    {
4574
 
      strxmov(buff, opt_basedir, argument, NULL);
 
5038
      strxmov(buff, opt_basedir, argument, NullS);
4575
5039
      argument= buff;
4576
5040
    }
4577
5041
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4578
 
    assert(cur_file == file_stack && cur_file->file == 0);
 
5042
    DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
4579
5043
    if (!(cur_file->file=
4580
 
          my_fopen(buff, O_RDONLY, MYF(0))))
 
5044
          my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
4581
5045
      die("Could not open '%s' for reading: errno = %d", buff, errno);
4582
5046
    cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
4583
5047
    cur_file->lineno= 1;
4588
5052
    static char buff[FN_REFLEN];
4589
5053
    if (!test_if_hard_path(argument))
4590
5054
    {
4591
 
      strxmov(buff, opt_basedir, argument, NULL);
 
5055
      strxmov(buff, opt_basedir, argument, NullS);
4592
5056
      argument= buff;
4593
5057
    }
4594
5058
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4595
5059
    timer_file= buff;
4596
 
    unlink(timer_file);       /* Ignore error, may not exist */
 
5060
    unlink(timer_file);      /* Ignore error, may not exist */
4597
5061
    break;
4598
5062
  }
4599
5063
  case 'p':
4600
5064
    if (argument)
4601
5065
    {
4602
 
      free(opt_pass);
 
5066
      my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
4603
5067
      opt_pass= my_strdup(argument, MYF(MY_FAE));
4604
 
      while (*argument) *argument++= 'x';    /* Destroy argument */
 
5068
      while (*argument) *argument++= 'x';               /* Destroy argument */
4605
5069
      tty_password= 0;
4606
5070
    }
4607
5071
    else
4608
5072
      tty_password= 1;
4609
5073
    break;
4610
5074
  case 't':
4611
 
    my_stpncpy(TMPDIR, argument, sizeof(TMPDIR));
 
5075
    strnmov(TMPDIR, argument, sizeof(TMPDIR));
4612
5076
    break;
4613
5077
  case 'A':
4614
5078
    if (!embedded_server_arg_count)
4653
5117
  if (argc == 1)
4654
5118
    opt_db= *argv;
4655
5119
  if (tty_password)
4656
 
    opt_pass= get_tty_password(NULL);          /* purify tested */
 
5120
    opt_pass= get_tty_password(NullS);          /* purify tested */
4657
5121
  if (debug_info_flag)
4658
5122
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
4659
5123
  if (debug_check_flag)
4673
5137
  append - append to file instead of overwriting old file
4674
5138
*/
4675
5139
 
4676
 
void str_to_file2(const char *fname, const char *str, int size, bool append)
 
5140
void str_to_file2(const char *fname, char *str, int size, my_bool append)
4677
5141
{
4678
5142
  int fd;
4679
5143
  char buff[FN_REFLEN];
4680
5144
  int flags= O_WRONLY | O_CREAT;
4681
5145
  if (!test_if_hard_path(fname))
4682
5146
  {
4683
 
    strxmov(buff, opt_basedir, fname, NULL);
 
5147
    strxmov(buff, opt_basedir, fname, NullS);
4684
5148
    fname= buff;
4685
5149
  }
4686
5150
  fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4692
5156
    die("Could not open '%s' for writing: errno = %d", buff, errno);
4693
5157
  if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
4694
5158
    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)))
 
5159
  if (my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP)))
4696
5160
    die("write failed");
4697
5161
  my_close(fd, MYF(0));
4698
5162
}
4707
5171
  size - size of content witten to file
4708
5172
*/
4709
5173
 
4710
 
void str_to_file(const char *fname, const char *str, int size)
 
5174
void str_to_file(const char *fname, char *str, int size)
4711
5175
{
4712
 
  str_to_file2(fname, str, size, false);
 
5176
  str_to_file2(fname, str, size, FALSE);
4713
5177
}
4714
5178
 
4715
5179
 
4716
 
void dump_result_to_log_file(const char *buf, int size)
 
5180
void dump_result_to_log_file(char *buf, int size)
4717
5181
{
4718
5182
  char log_file[FN_REFLEN];
4719
5183
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
4731
5195
                        opt_logdir, ".progress",
4732
5196
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4733
5197
                        MY_REPLACE_EXT),
4734
 
              ds_progress.c_str(), ds_progress.length());
 
5198
              ds_progress.str, ds_progress.length);
4735
5199
}
4736
5200
 
4737
5201
void dump_warning_messages(void)
4741
5205
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
4742
5206
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4743
5207
                        MY_REPLACE_EXT),
4744
 
              ds_warning_messages.c_str(), ds_warning_messages.length());
 
5208
              ds_warning_messages.str, ds_warning_messages.length);
4745
5209
}
4746
5210
 
4747
5211
 
4749
5213
  Append the result for one field to the dynamic string ds
4750
5214
*/
4751
5215
 
4752
 
static void append_field(string *ds, uint col_idx, const DRIZZLE_FIELD* field,
4753
 
                         const char* val, uint64_t len, bool is_null)
 
5216
static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
 
5217
                         const char* val, ulonglong len, my_bool is_null)
4754
5218
{
4755
5219
  if (col_idx < max_replace_column && replace_column[col_idx])
4756
5220
  {
4766
5230
  if (!display_result_vertically)
4767
5231
  {
4768
5232
    if (col_idx)
4769
 
      ds->append("\t");
4770
 
    replace_append_mem(ds, val, (int)len);
 
5233
      dynstr_append_mem(ds, "\t", 1);
 
5234
    replace_dynstr_append_mem(ds, val, (int)len);
4771
5235
  }
4772
5236
  else
4773
5237
  {
4774
 
    ds->append(field->name);
4775
 
    ds->append("\t");
4776
 
    replace_append_mem(ds, val, (int)len);
4777
 
    ds->append("\n");
 
5238
    dynstr_append(ds, field->name);
 
5239
    dynstr_append_mem(ds, "\t", 1);
 
5240
    replace_dynstr_append_mem(ds, val, (int)len);
 
5241
    dynstr_append_mem(ds, "\n", 1);
4778
5242
  }
4779
5243
}
4780
5244
 
4784
5248
  Values may be converted with 'replace_column'
4785
5249
*/
4786
5250
 
4787
 
static void append_result(string *ds, DRIZZLE_RES *res)
 
5251
static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
4788
5252
{
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;
 
5253
  MYSQL_ROW row;
 
5254
  uint num_fields= mysql_num_fields(res);
 
5255
  MYSQL_FIELD *fields= mysql_fetch_fields(res);
 
5256
  ulong *lengths;
4793
5257
 
4794
 
  while ((row = drizzle_fetch_row(res)))
 
5258
  while ((row = mysql_fetch_row(res)))
4795
5259
  {
4796
 
    uint32_t i;
4797
 
    lengths = drizzle_fetch_lengths(res);
 
5260
    uint i;
 
5261
    lengths = mysql_fetch_lengths(res);
4798
5262
    for (i = 0; i < num_fields; i++)
4799
5263
      append_field(ds, i, &fields[i],
4800
5264
                   (const char*)row[i], lengths[i], !row[i]);
4801
5265
    if (!display_result_vertically)
4802
 
      ds->append("\n");
4803
 
 
 
5266
      dynstr_append_mem(ds, "\n", 1);
4804
5267
  }
4805
5268
}
4806
5269
 
4809
5272
  Append metadata for fields to output
4810
5273
*/
4811
5274
 
4812
 
static void append_metadata(string *ds,
4813
 
                            const DRIZZLE_FIELD *field,
 
5275
static void append_metadata(DYNAMIC_STRING *ds,
 
5276
                            MYSQL_FIELD *field,
4814
5277
                            uint num_fields)
4815
5278
{
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");
 
5279
  MYSQL_FIELD *field_end;
 
5280
  dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
 
5281
                "Column_alias\tType\tLength\tMax length\tIs_null\t"
 
5282
                "Flags\tDecimals\tCharsetnr\n");
4820
5283
 
4821
5284
  for (field_end= field+num_fields ;
4822
5285
       field < field_end ;
4823
5286
       field++)
4824
5287
  {
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);
 
5288
    dynstr_append_mem(ds, field->catalog,
 
5289
                      field->catalog_length);
 
5290
    dynstr_append_mem(ds, "\t", 1);
 
5291
    dynstr_append_mem(ds, field->db, field->db_length);
 
5292
    dynstr_append_mem(ds, "\t", 1);
 
5293
    dynstr_append_mem(ds, field->org_table,
 
5294
                      field->org_table_length);
 
5295
    dynstr_append_mem(ds, "\t", 1);
 
5296
    dynstr_append_mem(ds, field->table,
 
5297
                      field->table_length);
 
5298
    dynstr_append_mem(ds, "\t", 1);
 
5299
    dynstr_append_mem(ds, field->org_name,
 
5300
                      field->org_name_length);
 
5301
    dynstr_append_mem(ds, "\t", 1);
 
5302
    dynstr_append_mem(ds, field->name, field->name_length);
 
5303
    dynstr_append_mem(ds, "\t", 1);
 
5304
    replace_dynstr_append_uint(ds, field->type);
 
5305
    dynstr_append_mem(ds, "\t", 1);
 
5306
    replace_dynstr_append_uint(ds, field->length);
 
5307
    dynstr_append_mem(ds, "\t", 1);
 
5308
    replace_dynstr_append_uint(ds, field->max_length);
 
5309
    dynstr_append_mem(ds, "\t", 1);
 
5310
    dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
 
5311
                                   "N" : "Y"), 1);
 
5312
    dynstr_append_mem(ds, "\t", 1);
 
5313
    replace_dynstr_append_uint(ds, field->flags);
 
5314
    dynstr_append_mem(ds, "\t", 1);
 
5315
    replace_dynstr_append_uint(ds, field->decimals);
 
5316
    dynstr_append_mem(ds, "\t", 1);
 
5317
    replace_dynstr_append_uint(ds, field->charsetnr);
 
5318
    dynstr_append_mem(ds, "\n", 1);
4856
5319
  }
4857
5320
}
4858
5321
 
4861
5324
  Append affected row count and other info to output
4862
5325
*/
4863
5326
 
4864
 
static void append_info(string *ds, uint64_t affected_rows,
 
5327
static void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows,
4865
5328
                        const char *info)
4866
5329
{
4867
5330
  char buf[40], buff2[21];
4868
5331
  sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
4869
 
  ds->append(buf);
 
5332
  dynstr_append(ds, buf);
4870
5333
  if (info)
4871
5334
  {
4872
 
    ds->append("info: ");
4873
 
    ds->append(info);
4874
 
    ds->append("\n", 1);
 
5335
    dynstr_append(ds, "info: ");
 
5336
    dynstr_append(ds, info);
 
5337
    dynstr_append_mem(ds, "\n", 1);
4875
5338
  }
4876
5339
}
4877
5340
 
4880
5343
  Display the table headings with the names tab separated
4881
5344
*/
4882
5345
 
4883
 
static void append_table_headings(string *ds,
4884
 
                                  const DRIZZLE_FIELD *field,
 
5346
static void append_table_headings(DYNAMIC_STRING *ds,
 
5347
                                  MYSQL_FIELD *field,
4885
5348
                                  uint num_fields)
4886
5349
{
4887
5350
  uint col_idx;
4888
5351
  for (col_idx= 0; col_idx < num_fields; col_idx++)
4889
5352
  {
4890
5353
    if (col_idx)
4891
 
      ds->append("\t", 1);
4892
 
    replace_append(ds, field[col_idx].name);
 
5354
      dynstr_append_mem(ds, "\t", 1);
 
5355
    replace_dynstr_append(ds, field[col_idx].name);
4893
5356
  }
4894
 
  ds->append("\n", 1);
 
5357
  dynstr_append_mem(ds, "\n", 1);
4895
5358
}
4896
5359
 
4897
5360
/*
4901
5364
  Number of warnings appended to ds
4902
5365
*/
4903
5366
 
4904
 
static int append_warnings(string *ds, DRIZZLE *drizzle)
 
5367
static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
4905
5368
{
4906
5369
  uint count;
4907
 
  DRIZZLE_RES *warn_res;
4908
 
 
4909
 
 
4910
 
  if (!(count= drizzle_warning_count(drizzle)))
4911
 
    return(0);
 
5370
  MYSQL_RES *warn_res;
 
5371
  DBUG_ENTER("append_warnings");
 
5372
 
 
5373
  if (!(count= mysql_warning_count(mysql)))
 
5374
    DBUG_RETURN(0);
4912
5375
 
4913
5376
  /*
4914
5377
    If one day we will support execution of multi-statements
4915
5378
    through PS API we should not issue SHOW WARNINGS until
4916
5379
    we have not read all results...
4917
5380
  */
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)))
 
5381
  DBUG_ASSERT(!mysql_more_results(mysql));
 
5382
 
 
5383
  if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
 
5384
    die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql));
 
5385
 
 
5386
  if (!(warn_res= mysql_store_result(mysql)))
4924
5387
    die("Warning count is %u but didn't get any warnings",
4925
 
        count);
 
5388
        count);
4926
5389
 
4927
5390
  append_result(ds, warn_res);
4928
 
 
4929
 
  return(count);
 
5391
  mysql_free_result(warn_res);
 
5392
 
 
5393
  DBUG_PRINT("warnings", ("%s", ds->str));
 
5394
 
 
5395
  DBUG_RETURN(count);
4930
5396
}
4931
5397
 
4932
5398
 
4933
5399
/*
4934
 
  Run query using DRIZZLE C API
 
5400
  Run query using MySQL C API
4935
5401
 
4936
5402
  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
 
5403
    run_query_normal()
 
5404
    mysql       mysql handle
 
5405
    command     current command pointer
 
5406
    flags       flags indicating if we should SEND and/or REAP
 
5407
    query       query string to execute
 
5408
    query_len   length query string to execute
 
5409
    ds          output buffer where to store result form query
4944
5410
*/
4945
5411
 
4946
5412
static void run_query_normal(struct st_connection *cn,
4947
5413
                             struct st_command *command,
4948
5414
                             int flags, char *query, int query_len,
4949
 
                             string *ds, string *ds_warnings)
 
5415
                             DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4950
5416
{
4951
 
  DRIZZLE_RES *res= 0;
4952
 
  DRIZZLE *drizzle= &cn->drizzle;
 
5417
  MYSQL_RES *res= 0;
 
5418
  MYSQL *mysql= &cn->mysql;
4953
5419
  int err= 0, counter= 0;
 
5420
  DBUG_ENTER("run_query_normal");
 
5421
  DBUG_PRINT("enter",("flags: %d", flags));
 
5422
  DBUG_PRINT("enter", ("query: '%-.60s'", query));
4954
5423
 
4955
5424
  if (flags & QUERY_SEND_FLAG)
4956
5425
  {
4957
5426
    /*
4958
 
     * Send the query
4959
 
     */
 
5427
      Send the query
 
5428
    */
4960
5429
    if (do_send_query(cn, query, query_len, flags))
4961
5430
    {
4962
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4963
 
                   drizzle_sqlstate(drizzle), ds);
 
5431
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5432
                   mysql_sqlstate(mysql), ds);
4964
5433
      goto end;
4965
5434
    }
4966
5435
  }
 
5436
#ifdef EMBEDDED_LIBRARY
 
5437
  /*
 
5438
    Here we handle 'reap' command, so we need to check if the
 
5439
    query's thread was finished and probably wait
 
5440
  */
 
5441
  else if (flags & QUERY_REAP_FLAG)
 
5442
    wait_query_thread_end(cn);
 
5443
#endif /*EMBEDDED_LIBRARY*/
4967
5444
  if (!(flags & QUERY_REAP_FLAG))
4968
 
    return;
 
5445
    DBUG_VOID_RETURN;
4969
5446
 
4970
5447
  do
4971
5448
  {
4972
5449
    /*
4973
 
      When  on first result set, call drizzle_read_query_result to retrieve
 
5450
      When  on first result set, call mysql_read_query_result to retrieve
4974
5451
      answer to the query sent earlier
4975
5452
    */
4976
 
    if ((counter==0) && drizzle_read_query_result(drizzle))
 
5453
    if ((counter==0) && mysql_read_query_result(mysql))
4977
5454
    {
4978
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4979
 
                   drizzle_sqlstate(drizzle), ds);
 
5455
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5456
                   mysql_sqlstate(mysql), ds);
4980
5457
      goto end;
4981
5458
 
4982
5459
    }
4984
5461
    /*
4985
5462
      Store the result of the query if it will return any fields
4986
5463
    */
4987
 
    if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
 
5464
    if (mysql_field_count(mysql) && ((res= mysql_store_result(mysql)) == 0))
4988
5465
    {
4989
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4990
 
                   drizzle_sqlstate(drizzle), ds);
 
5466
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5467
                   mysql_sqlstate(mysql), ds);
4991
5468
      goto end;
4992
5469
    }
4993
5470
 
4994
5471
    if (!disable_result_log)
4995
5472
    {
4996
 
      uint64_t affected_rows= 0;    /* Ok to be undef if 'disable_info' is set */
 
5473
      ulonglong affected_rows= 0;    /* Ok to be undef if 'disable_info' is set */
4997
5474
 
4998
5475
      if (res)
4999
5476
      {
5000
 
        const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
5001
 
        uint num_fields= drizzle_num_fields(res);
 
5477
        MYSQL_FIELD *fields= mysql_fetch_fields(res);
 
5478
        uint num_fields= mysql_num_fields(res);
5002
5479
 
5003
 
        if (display_metadata)
 
5480
        if (display_metadata)
5004
5481
          append_metadata(ds, fields, num_fields);
5005
5482
 
5006
 
        if (!display_result_vertically)
5007
 
          append_table_headings(ds, fields, num_fields);
 
5483
        if (!display_result_vertically)
 
5484
          append_table_headings(ds, fields, num_fields);
5008
5485
 
5009
 
        append_result(ds, res);
 
5486
        append_result(ds, res);
5010
5487
      }
5011
5488
 
5012
5489
      /*
5013
 
        Need to call drizzle_affected_rows() before the "new"
 
5490
        Need to call mysql_affected_rows() before the "new"
5014
5491
        query to find the warnings
5015
5492
      */
5016
5493
      if (!disable_info)
5017
 
        affected_rows= drizzle_affected_rows(drizzle);
 
5494
        affected_rows= mysql_affected_rows(mysql);
5018
5495
 
5019
5496
      /*
5020
5497
        Add all warnings to the result. We can't do this if we are in
5021
5498
        the middle of processing results from multi-statement, because
5022
5499
        this will break protocol.
5023
5500
      */
5024
 
      if (!disable_warnings && !drizzle_more_results(drizzle))
 
5501
      if (!disable_warnings && !mysql_more_results(mysql))
5025
5502
      {
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
 
        }
 
5503
        if (append_warnings(ds_warnings, mysql) || ds_warnings->length)
 
5504
        {
 
5505
          dynstr_append_mem(ds, "Warnings:\n", 10);
 
5506
          dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
 
5507
        }
5031
5508
      }
5032
5509
 
5033
5510
      if (!disable_info)
5034
 
        append_info(ds, affected_rows, drizzle_info(drizzle));
 
5511
        append_info(ds, affected_rows, mysql_info(mysql));
5035
5512
    }
5036
5513
 
5037
5514
    if (res)
5038
5515
    {
5039
 
      drizzle_free_result(res);
 
5516
      mysql_free_result(res);
5040
5517
      res= 0;
5041
5518
    }
5042
5519
    counter++;
5043
 
  } while (!(err= drizzle_next_result(drizzle)));
 
5520
  } while (!(err= mysql_next_result(mysql)));
5044
5521
  if (err > 0)
5045
5522
  {
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);
 
5523
    /* We got an error from mysql_next_result, maybe expected */
 
5524
    handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5525
                 mysql_sqlstate(mysql), ds);
5049
5526
    goto end;
5050
5527
  }
5051
 
  assert(err == -1); /* Successful and there are no more results */
 
5528
  DBUG_ASSERT(err == -1); /* Successful and there are no more results */
5052
5529
 
5053
5530
  /* If we come here the query is both executed and read successfully */
5054
5531
  handle_no_error(command);
5056
5533
end:
5057
5534
 
5058
5535
  /*
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
 
5536
    We save the return code (mysql_errno(mysql)) from the last call sent
 
5537
    to the server into the mysqltest builtin variable $mysql_errno. This
5061
5538
    variable then can be used from the test case itself.
5062
5539
  */
5063
 
  var_set_errno(drizzle_errno(drizzle));
5064
 
  return;
 
5540
  var_set_errno(mysql_errno(mysql));
 
5541
  DBUG_VOID_RETURN;
5065
5542
}
5066
5543
 
5067
5544
 
5077
5554
  ds    - dynamic string which is used for output buffer
5078
5555
 
5079
5556
  NOTE
5080
 
  If there is an unexpected error this function will abort drizzletest
5081
 
  immediately.
 
5557
    If there is an unexpected error this function will abort mysqltest
 
5558
    immediately.
5082
5559
*/
5083
5560
 
5084
5561
void handle_error(struct st_command *command,
5085
5562
                  unsigned int err_errno, const char *err_error,
5086
 
                  const char *err_sqlstate, string *ds)
 
5563
                  const char *err_sqlstate, DYNAMIC_STRING *ds)
5087
5564
{
5088
5565
  uint i;
5089
5566
 
 
5567
  DBUG_ENTER("handle_error");
5090
5568
 
5091
5569
  if (command->require_file[0])
5092
5570
  {
5108
5586
  if (command->abort_on_error)
5109
5587
    die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
5110
5588
 
 
5589
  DBUG_PRINT("info", ("expected_errors.count: %d",
 
5590
                      command->expected_errors.count));
5111
5591
  for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
5112
5592
  {
5113
5593
    if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
5121
5601
        if (command->expected_errors.count == 1)
5122
5602
        {
5123
5603
          /* 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);
 
5604
          dynstr_append_mem(ds, "ERROR ", 6);
 
5605
          replace_dynstr_append(ds, err_sqlstate);
 
5606
          dynstr_append_mem(ds, ": ", 2);
 
5607
          replace_dynstr_append(ds, err_error);
 
5608
          dynstr_append_mem(ds,"\n",1);
5129
5609
        }
5130
5610
        /* Don't log error if we may not get an error */
5131
5611
        else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5132
5612
                 (command->expected_errors.err[0].type == ERR_ERRNO &&
5133
5613
                  command->expected_errors.err[0].code.errnum != 0))
5134
 
          ds->append("Got one of the listed errors\n");
 
5614
          dynstr_append(ds,"Got one of the listed errors\n");
5135
5615
      }
5136
5616
      /* OK */
5137
 
      return;
 
5617
      DBUG_VOID_RETURN;
5138
5618
    }
5139
5619
  }
5140
5620
 
 
5621
  DBUG_PRINT("info",("i: %d  expected_errors: %d", i,
 
5622
                     command->expected_errors.count));
 
5623
 
5141
5624
  if (!disable_result_log)
5142
5625
  {
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);
 
5626
    dynstr_append_mem(ds, "ERROR ",6);
 
5627
    replace_dynstr_append(ds, err_sqlstate);
 
5628
    dynstr_append_mem(ds, ": ", 2);
 
5629
    replace_dynstr_append(ds, err_error);
 
5630
    dynstr_append_mem(ds, "\n", 1);
5148
5631
  }
5149
5632
 
5150
5633
  if (i)
5156
5639
    else
5157
5640
      die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
5158
5641
          command->query, err_sqlstate, err_error,
5159
 
          command->expected_errors.err[0].code.sqlstate);
 
5642
          command->expected_errors.err[0].code.sqlstate);
5160
5643
  }
5161
5644
 
5162
 
  return;
 
5645
  DBUG_VOID_RETURN;
5163
5646
}
5164
5647
 
5165
5648
 
5176
5659
 
5177
5660
void handle_no_error(struct st_command *command)
5178
5661
{
5179
 
 
 
5662
  DBUG_ENTER("handle_no_error");
5180
5663
 
5181
5664
  if (command->expected_errors.err[0].type == ERR_ERRNO &&
5182
5665
      command->expected_errors.err[0].code.errnum != 0)
5193
5676
        command->query, command->expected_errors.err[0].code.sqlstate);
5194
5677
  }
5195
5678
 
5196
 
  return;
 
5679
  DBUG_VOID_RETURN;
5197
5680
}
5198
5681
 
5199
5682
 
5201
5684
  Run query
5202
5685
 
5203
5686
  SYNPOSIS
5204
 
  run_query()
5205
 
  drizzle  DRIZZLE handle
5206
 
  command  currrent command pointer
 
5687
    run_query()
 
5688
     mysql      mysql handle
 
5689
     command    currrent command pointer
5207
5690
 
5208
5691
  flags control the phased/stages of query execution to be performed
5209
5692
  if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
5210
5693
  is on the result will be read - for regular query, both bits must be on
5211
5694
*/
5212
5695
 
5213
 
static void run_query(struct st_connection *cn,
 
5696
static void run_query(struct st_connection *cn, 
5214
5697
                      struct st_command *command,
5215
5698
                      int flags)
5216
5699
{
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;
 
5700
  DYNAMIC_STRING *ds;
 
5701
  DYNAMIC_STRING *save_ds= NULL;
 
5702
  DYNAMIC_STRING ds_result;
 
5703
  DYNAMIC_STRING ds_sorted;
 
5704
  DYNAMIC_STRING ds_warnings;
 
5705
  DYNAMIC_STRING eval_query;
5223
5706
  char *query;
5224
5707
  int query_len;
 
5708
  DBUG_ENTER("run_query");
5225
5709
 
 
5710
  init_dynamic_string(&ds_warnings, NULL, 0, 256);
5226
5711
 
5227
5712
  /* Scan for warning before sending to server */
5228
5713
  scan_command_for_warnings(command);
5232
5717
  */
5233
5718
  if (command->type == Q_EVAL)
5234
5719
  {
5235
 
    do_eval(&eval_query, command->query, command->end, false);
5236
 
    query = strdup(eval_query.c_str());
5237
 
    query_len = eval_query.length();
 
5720
    init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
 
5721
    do_eval(&eval_query, command->query, command->end, FALSE);
 
5722
    query = eval_query.str;
 
5723
    query_len = eval_query.length;
5238
5724
  }
5239
5725
  else
5240
5726
  {
5250
5736
  */
5251
5737
  if (command->require_file[0])
5252
5738
  {
 
5739
    init_dynamic_string(&ds_result, "", 1024, 1024);
5253
5740
    ds= &ds_result;
5254
5741
  }
5255
5742
  else
5256
 
  {
5257
5743
    ds= &ds_res;
5258
 
  }
 
5744
 
5259
5745
  /*
5260
5746
    Log the query into the output buffer
5261
5747
  */
5262
5748
  if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5263
5749
  {
5264
 
    replace_append_mem(ds, query, query_len);
5265
 
    ds->append(delimiter, delimiter_length);
5266
 
    ds->append("\n");
 
5750
    replace_dynstr_append_mem(ds, query, query_len);
 
5751
    dynstr_append_mem(ds, delimiter, delimiter_length);
 
5752
    dynstr_append_mem(ds, "\n", 1);
5267
5753
  }
5268
5754
 
5269
5755
  if (display_result_sorted)
5270
5756
  {
5271
5757
    /*
5272
 
      Collect the query output in a separate string
5273
 
      that can be sorted before it's added to the
5274
 
      global result string
 
5758
       Collect the query output in a separate string
 
5759
       that can be sorted before it's added to the
 
5760
       global result string
5275
5761
    */
 
5762
    init_dynamic_string(&ds_sorted, "", 1024, 1024);
5276
5763
    save_ds= ds; /* Remember original ds */
5277
5764
    ds= &ds_sorted;
5278
5765
  }
5287
5774
  if (display_result_sorted)
5288
5775
  {
5289
5776
    /* Sort the result set and append it to result */
5290
 
    append_sorted(save_ds, &ds_sorted);
 
5777
    dynstr_append_sorted(save_ds, &ds_sorted);
5291
5778
    ds= save_ds;
 
5779
    dynstr_free(&ds_sorted);
5292
5780
  }
5293
5781
 
5294
5782
  if (command->require_file[0])
5300
5788
    check_require(ds, command->require_file);
5301
5789
  }
5302
5790
 
5303
 
  return;
 
5791
  dynstr_free(&ds_warnings);
 
5792
  if (ds == &ds_result)
 
5793
    dynstr_free(&ds_result);
 
5794
  if (command->type == Q_EVAL)
 
5795
    dynstr_free(&eval_query);
 
5796
  DBUG_VOID_RETURN;
5304
5797
}
5305
5798
 
5306
5799
 
5310
5803
{
5311
5804
  char save;
5312
5805
  uint type;
5313
 
 
 
5806
  DBUG_ENTER("get_command_type");
5314
5807
 
5315
5808
  if (*command->query == '}')
5316
5809
  {
5317
5810
    command->type = Q_END_BLOCK;
5318
 
    return;
 
5811
    DBUG_VOID_RETURN;
5319
5812
  }
5320
5813
 
5321
5814
  save= command->query[command->first_word_len];
5324
5817
  command->query[command->first_word_len]= save;
5325
5818
  if (type > 0)
5326
5819
  {
5327
 
    command->type=(enum enum_commands) type;    /* Found command */
 
5820
    command->type=(enum enum_commands) type;            /* Found command */
5328
5821
 
5329
5822
    /*
5330
5823
      Look for case where "query" was explicitly specified to
5338
5831
  }
5339
5832
  else
5340
5833
  {
5341
 
    /* No drizzletest command matched */
 
5834
    /* No mysqltest command matched */
5342
5835
 
5343
5836
    if (command->type != Q_COMMENT_WITH_COMMAND)
5344
5837
    {
5345
 
      /* A query that will sent to drizzled */
 
5838
      /* A query that will sent to mysqld */
5346
5839
      command->type= Q_QUERY;
5347
5840
    }
5348
5841
    else
5349
5842
    {
5350
 
      /* -- comment that didn't contain a drizzletest command */
 
5843
      /* -- comment that didn't contain a mysqltest command */
5351
5844
      command->type= Q_COMMENT;
5352
 
      warning_msg("Suspicious command '--%s' detected, was this intentional? " \
 
5845
      warning_msg("Suspicious command '--%s' detected, was this intentional? "\
5353
5846
                  "Use # instead of -- to avoid this warning",
5354
5847
                  command->query);
5355
5848
 
5375
5868
  /* Set expected error on command */
5376
5869
  memcpy(&command->expected_errors, &saved_expected_errors,
5377
5870
         sizeof(saved_expected_errors));
 
5871
  DBUG_PRINT("info", ("There are %d expected errors",
 
5872
                      command->expected_errors.count));
5378
5873
  command->abort_on_error= (command->expected_errors.count == 0 &&
5379
5874
                            abort_on_error);
5380
5875
 
5381
 
  return;
 
5876
  DBUG_VOID_RETURN;
5382
5877
}
5383
5878
 
5384
5879
 
5396
5891
                          int line)
5397
5892
{
5398
5893
  char buf[32], *end;
5399
 
  uint64_t timer= timer_now();
 
5894
  ulonglong timer= timer_now();
5400
5895
  if (!progress_start)
5401
5896
    progress_start= timer;
5402
5897
  timer-= progress_start;
5403
5898
 
5404
5899
  /* Milliseconds since start */
5405
 
  end= int64_t2str(timer, buf, 10);
5406
 
  ds_progress.append(buf, (int)(end-buf));
5407
 
  ds_progress.append("\t", 1);
 
5900
  end= longlong2str(timer, buf, 10);
 
5901
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5902
  dynstr_append_mem(&ds_progress, "\t", 1);
5408
5903
 
5409
5904
  /* Parser line number */
5410
5905
  end= int10_to_str(line, buf, 10);
5411
 
  ds_progress.append(buf, (int)(end-buf));
5412
 
  ds_progress.append("\t", 1);
 
5906
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5907
  dynstr_append_mem(&ds_progress, "\t", 1);
5413
5908
 
5414
5909
  /* Filename */
5415
 
  ds_progress.append(cur_file->file_name);
5416
 
  ds_progress.append(":", 1);
 
5910
  dynstr_append(&ds_progress, cur_file->file_name);
 
5911
  dynstr_append_mem(&ds_progress, ":", 1);
5417
5912
 
5418
5913
  /* Line in file */
5419
5914
  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);
 
5915
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5916
 
 
5917
 
 
5918
  dynstr_append_mem(&ds_progress, "\n", 1);
5424
5919
 
5425
5920
}
5426
5921
 
5428
5923
int main(int argc, char **argv)
5429
5924
{
5430
5925
  struct st_command *command;
5431
 
  bool q_send_flag= 0, abort_flag= 0;
 
5926
  my_bool q_send_flag= 0, abort_flag= 0;
5432
5927
  uint command_executed= 0, last_command_executed= 0;
5433
5928
  char save_file[FN_REFLEN];
5434
5929
  struct stat res_info;
5446
5941
    (sizeof(connections)/sizeof(struct st_connection)) - 1;
5447
5942
  next_con= connections + 1;
5448
5943
 
 
5944
#ifdef EMBEDDED_LIBRARY
 
5945
  /* set appropriate stack for the 'query' threads */
 
5946
  (void) pthread_attr_init(&cn_thd_attrib);
 
5947
  pthread_attr_setstacksize(&cn_thd_attrib, DEFAULT_THREAD_STACK);
 
5948
#endif /*EMBEDDED_LIBRARY*/
 
5949
 
5449
5950
  /* Init file stack */
5450
5951
  memset(file_stack, 0, sizeof(file_stack));
5451
5952
  file_stack_end=
5457
5958
  block_stack_end=
5458
5959
    block_stack + (sizeof(block_stack)/sizeof(struct st_block)) - 1;
5459
5960
  cur_block= block_stack;
5460
 
  cur_block->ok= true; /* Outer block should always be executed */
 
5961
  cur_block->ok= TRUE; /* Outer block should always be executed */
5461
5962
  cur_block->cmd= cmd_none;
5462
5963
 
 
5964
  my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
 
5965
 
5463
5966
  if (hash_init(&var_hash, charset_info,
5464
5967
                1024, 0, 0, get_var_key, var_free, MYF(0)))
5465
5968
    die("Variable hash initialization failed");
5466
5969
 
5467
 
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
 
5970
  var_set_string("$MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
5468
5971
 
5469
5972
  memset(&master_pos, 0, sizeof(master_pos));
5470
5973
 
5473
5976
 
5474
5977
  init_builtin_echo();
5475
5978
 
5476
 
  ds_res.reserve(65536);
5477
 
  ds_progress.reserve(2048);
5478
 
  ds_warning_messages.reserve(2048);
5479
 
 
 
5979
  init_dynamic_string(&ds_res, "", 65536, 65536);
 
5980
  init_dynamic_string(&ds_progress, "", 0, 2048);
 
5981
  init_dynamic_string(&ds_warning_messages, "", 0, 2048);
5480
5982
  parse_args(argc, argv);
5481
5983
 
 
5984
  DBUG_PRINT("info",("result_file: '%s'",
 
5985
                     result_file_name ? result_file_name : ""));
 
5986
  if (mysql_server_init(embedded_server_arg_count,
 
5987
                        embedded_server_args,
 
5988
                        (char**) embedded_server_groups))
 
5989
    die("Can't initialize MySQL server");
5482
5990
  server_initialized= 1;
5483
5991
  if (cur_file == file_stack && cur_file->file == 0)
5484
5992
  {
5487
5995
    cur_file->lineno= 1;
5488
5996
  }
5489
5997
  cur_con= connections;
5490
 
  if (!( drizzle_create(&cur_con->drizzle)))
5491
 
    die("Failed in drizzle_create()");
 
5998
  if (!( mysql_init(&cur_con->mysql)))
 
5999
    die("Failed in mysql_init()");
5492
6000
  if (opt_compress)
5493
 
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
5494
 
  drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
6001
    mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS);
 
6002
  mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
 
6003
  mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME,
 
6004
                charset_info->csname);
 
6005
  int opt_protocol= MYSQL_PROTOCOL_TCP;
 
6006
  mysql_options(&cur_con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
6007
  if (opt_charsets_dir)
 
6008
    mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR,
 
6009
                  opt_charsets_dir);
5495
6010
 
5496
6011
  if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5497
6012
    die("Out of memory");
5498
6013
 
5499
 
  safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
 
6014
  safe_connect(&cur_con->mysql, cur_con->name, opt_host, opt_user, opt_pass,
5500
6015
               opt_db, opt_port);
5501
6016
 
5502
6017
  /* Use all time until exit if no explicit 'start_timer' */
5503
6018
  timer_start= timer_now();
5504
6019
 
5505
6020
  /*
5506
 
    Initialize $drizzle_errno with -1, so we can
 
6021
    Initialize $mysql_errno with -1, so we can
5507
6022
    - distinguish it from valid values ( >= 0 ) and
5508
6023
    - detect if there was never a command sent to the server
5509
6024
  */
5510
6025
  var_set_errno(-1);
5511
6026
 
5512
 
  /* Update $drizzle_get_server_version to that of current connection */
5513
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
6027
  /* Update $mysql_get_server_version to that of current connection */
 
6028
  var_set_mysql_get_server_version(&cur_con->mysql);
5514
6029
 
5515
6030
  if (opt_include)
5516
6031
  {
5539
6054
      case Q_CONNECT:
5540
6055
        do_connect(command);
5541
6056
        break;
5542
 
      case Q_CONNECTION:
5543
 
        select_connection(command);
5544
 
        break;
 
6057
      case Q_CONNECTION: select_connection(command); break;
5545
6058
      case Q_DISCONNECT:
5546
6059
      case Q_DIRTY_CLOSE:
5547
 
        do_close_connection(command); break;
 
6060
        do_close_connection(command); break;
5548
6061
      case Q_ENABLE_QUERY_LOG:   disable_query_log=0; break;
5549
6062
      case Q_DISABLE_QUERY_LOG:  disable_query_log=1; break;
5550
6063
      case Q_ENABLE_ABORT_ON_ERROR:  abort_on_error=1; break;
5580
6093
      case Q_PERL: do_perl(command); break;
5581
6094
      case Q_DELIMITER:
5582
6095
        do_delimiter(command);
5583
 
        break;
 
6096
        break;
5584
6097
      case Q_DISPLAY_VERTICAL_RESULTS:
5585
 
        display_result_vertically= true;
 
6098
        display_result_vertically= TRUE;
5586
6099
        break;
5587
6100
      case Q_DISPLAY_HORIZONTAL_RESULTS:
5588
 
        display_result_vertically= false;
 
6101
        display_result_vertically= FALSE;
5589
6102
        break;
5590
6103
      case Q_SORTED_RESULT:
5591
6104
        /*
5592
6105
          Turn on sorting of result set, will be reset after next
5593
6106
          command
5594
6107
        */
5595
 
        display_result_sorted= true;
 
6108
        display_result_sorted= TRUE;
5596
6109
        break;
5597
6110
      case Q_LET: do_let(command); break;
5598
6111
      case Q_EVAL_RESULT:
5600
6113
      case Q_EVAL:
5601
6114
      case Q_QUERY_VERTICAL:
5602
6115
      case Q_QUERY_HORIZONTAL:
5603
 
        if (command->query == command->query_buf)
 
6116
        if (command->query == command->query_buf)
5604
6117
        {
5605
6118
          /* Skip the first part of command, i.e query_xxx */
5606
 
          command->query= command->first_argument;
 
6119
          command->query= command->first_argument;
5607
6120
          command->first_word_len= 0;
5608
6121
        }
5609
 
        /* fall through */
 
6122
        /* fall through */
5610
6123
      case Q_QUERY:
5611
6124
      case Q_REAP:
5612
6125
      {
5613
 
        bool old_display_result_vertically= display_result_vertically;
 
6126
        my_bool old_display_result_vertically= display_result_vertically;
5614
6127
        /* Default is full query, both reap and send  */
5615
6128
        int flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
5616
6129
 
5628
6141
        /* Check for special property for this query */
5629
6142
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5630
6143
 
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++;
 
6144
        if (save_file[0])
 
6145
        {
 
6146
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
 
6147
          save_file[0]= 0;
 
6148
        }
 
6149
        run_query(cur_con, command, flags);
 
6150
        command_executed++;
5638
6151
        command->last_argument= command->end;
5639
6152
 
5640
6153
        /* Restore settings */
5641
 
        display_result_vertically= old_display_result_vertically;
 
6154
        display_result_vertically= old_display_result_vertically;
5642
6155
 
5643
 
        break;
 
6156
        break;
5644
6157
      }
5645
6158
      case Q_SEND:
5646
6159
        if (!*command->first_argument)
5654
6167
        }
5655
6168
 
5656
6169
        /* Remove "send" if this is first iteration */
5657
 
        if (command->query == command->query_buf)
5658
 
          command->query= command->first_argument;
 
6170
        if (command->query == command->query_buf)
 
6171
          command->query= command->first_argument;
5659
6172
 
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
 
6173
        /*
 
6174
          run_query() can execute a query partially, depending on the flags.
 
6175
          QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5663
6176
          the query and read the result some time later when reap instruction
5664
 
          is given on this connection.
 
6177
          is given on this connection.
5665
6178
        */
5666
 
        run_query(cur_con, command, QUERY_SEND_FLAG);
5667
 
        command_executed++;
 
6179
        run_query(cur_con, command, QUERY_SEND_FLAG);
 
6180
        command_executed++;
5668
6181
        command->last_argument= command->end;
5669
 
        break;
 
6182
        break;
5670
6183
      case Q_REQUIRE:
5671
 
        do_get_file_name(command, save_file, sizeof(save_file));
5672
 
        break;
 
6184
        do_get_file_name(command, save_file, sizeof(save_file));
 
6185
        break;
5673
6186
      case Q_ERROR:
5674
6187
        do_get_errcodes(command);
5675
 
        break;
 
6188
        break;
5676
6189
      case Q_REPLACE:
5677
 
        do_get_replace(command);
5678
 
        break;
 
6190
        do_get_replace(command);
 
6191
        break;
5679
6192
      case Q_REPLACE_REGEX:
5680
6193
        do_get_replace_regex(command);
5681
6194
        break;
5682
6195
      case Q_REPLACE_COLUMN:
5683
 
        do_get_replace_column(command);
5684
 
        break;
 
6196
        do_get_replace_column(command);
 
6197
        break;
5685
6198
      case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5686
6199
      case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5687
6200
      case Q_SYNC_SLAVE_WITH_MASTER:
5688
6201
      {
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;
 
6202
        do_save_master_pos();
 
6203
        if (*command->first_argument)
 
6204
          select_connection(command);
 
6205
        else
 
6206
          select_connection_name("slave");
 
6207
        do_sync_with_master2(0);
 
6208
        break;
5696
6209
      }
5697
 
      case Q_COMMENT:        /* Ignore row */
 
6210
      case Q_COMMENT:                           /* Ignore row */
5698
6211
        command->last_argument= command->end;
5699
 
        break;
 
6212
        break;
5700
6213
      case Q_PING:
5701
 
        (void) drizzle_ping(&cur_con->drizzle);
5702
 
        break;
 
6214
        (void) mysql_ping(&cur_con->mysql);
 
6215
        break;
5703
6216
      case Q_EXEC:
5704
 
        do_exec(command);
5705
 
        command_executed++;
5706
 
        break;
 
6217
        do_exec(command);
 
6218
        command_executed++;
 
6219
        break;
5707
6220
      case Q_START_TIMER:
5708
 
        /* Overwrite possible earlier start of timer */
5709
 
        timer_start= timer_now();
5710
 
        break;
 
6221
        /* Overwrite possible earlier start of timer */
 
6222
        timer_start= timer_now();
 
6223
        break;
5711
6224
      case Q_END_TIMER:
5712
 
        /* End timer before ending drizzletest */
5713
 
        timer_output();
5714
 
        break;
 
6225
        /* End timer before ending mysqltest */
 
6226
        timer_output();
 
6227
        break;
5715
6228
      case Q_CHARACTER_SET:
5716
 
        do_set_charset(command);
5717
 
        break;
 
6229
        do_set_charset(command);
 
6230
        break;
5718
6231
      case Q_DISABLE_RECONNECT:
5719
 
        set_reconnect(&cur_con->drizzle, 0);
 
6232
        set_reconnect(&cur_con->mysql, 0);
5720
6233
        break;
5721
6234
      case Q_ENABLE_RECONNECT:
5722
 
        set_reconnect(&cur_con->drizzle, 1);
 
6235
        set_reconnect(&cur_con->mysql, 1);
5723
6236
        break;
5724
6237
      case Q_DISABLE_PARSING:
5725
6238
        if (parsing_disabled == 0)
5791
6304
      free_all_replace();
5792
6305
 
5793
6306
      /* Also reset "sorted_result" */
5794
 
      display_result_sorted= false;
 
6307
      display_result_sorted= FALSE;
5795
6308
    }
5796
6309
    last_command_executed= command_executed;
5797
6310
 
5810
6323
    Time to compare result or save it to record file.
5811
6324
    The entire output from test is now kept in ds_res.
5812
6325
  */
5813
 
  if (ds_res.length())
 
6326
  if (ds_res.length)
5814
6327
  {
5815
6328
    if (result_file_name)
5816
6329
    {
5818
6331
 
5819
6332
      if (record)
5820
6333
      {
5821
 
        /* Recording - dump the output from test to result file */
5822
 
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
 
6334
        /* Recording - dump the output from test to result file */
 
6335
        str_to_file(result_file_name, ds_res.str, ds_res.length);
5823
6336
      }
5824
6337
      else
5825
6338
      {
5826
 
        /* Check that the output from test is equal to result file
5827
 
           - detect missing result file
5828
 
           - detect zero size result file
 
6339
        /* Check that the output from test is equal to result file
 
6340
           - detect missing result file
 
6341
           - detect zero size result file
5829
6342
        */
5830
 
        check_result(&ds_res);
 
6343
        check_result(&ds_res);
5831
6344
      }
5832
6345
    }
5833
6346
    else
5834
6347
    {
5835
6348
      /* No result_file_name specified to compare with, print to stdout */
5836
 
      printf("%s", ds_res.c_str());
 
6349
      printf("%s", ds_res.str);
5837
6350
    }
5838
6351
  }
5839
6352
  else
5858
6371
    dump_progress();
5859
6372
 
5860
6373
  /* Dump warning messages */
5861
 
  if (result_file_name && ds_warning_messages.length())
 
6374
  if (result_file_name && ds_warning_messages.length)
5862
6375
    dump_warning_messages();
5863
6376
 
5864
6377
  timer_output();
5876
6389
  before executing any commands. The time we measure is
5877
6390
 
5878
6391
  - If no explicit 'start_timer' or 'end_timer' is given in the
5879
 
  test case, the timer measure how long we execute in drizzletest.
 
6392
  test case, the timer measure how long we execute in mysqltest.
5880
6393
 
5881
6394
  - If only 'start_timer' is given we measure how long we execute
5882
 
  from that point until we terminate drizzletest.
 
6395
  from that point until we terminate mysqltest.
5883
6396
 
5884
6397
  - 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
 
6398
  from that we enter mysqltest to the 'end_timer' is command is
5886
6399
  executed.
5887
6400
 
5888
6401
  - If both 'start_timer' and 'end_timer' are given we measure
5894
6407
  if (timer_file)
5895
6408
  {
5896
6409
    char buf[32], *end;
5897
 
    uint64_t timer= timer_now() - timer_start;
5898
 
    end= int64_t2str(timer, buf, 10);
 
6410
    ulonglong timer= timer_now() - timer_start;
 
6411
    end= longlong2str(timer, buf, 10);
5899
6412
    str_to_file(timer_file,buf, (int) (end-buf));
5900
6413
    /* Timer has been written to the file, don't use it anymore */
5901
6414
    timer_file= 0;
5903
6416
}
5904
6417
 
5905
6418
 
5906
 
uint64_t timer_now(void)
 
6419
ulonglong timer_now(void)
5907
6420
{
5908
6421
  return my_micro_time() / 1000;
5909
6422
}
5921
6434
{
5922
6435
  char *from= command->first_argument;
5923
6436
  char *buff, *start;
5924
 
 
 
6437
  DBUG_ENTER("get_replace_columns");
5925
6438
 
5926
6439
  free_replace_column();
5927
6440
  if (!*from)
5940
6453
    if (!*from)
5941
6454
      die("Wrong number of arguments to replace_column in '%s'", command->query);
5942
6455
    to= get_string(&buff, &from, command);
5943
 
    free(replace_column[column_number-1]);
 
6456
    my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
5944
6457
    replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
5945
6458
    set_if_bigger(max_replace_column, column_number);
5946
6459
  }
5947
 
  free(start);
 
6460
  my_free(start, MYF(0));
5948
6461
  command->last_argument= command->end;
5949
6462
}
5950
6463
 
5956
6469
  {
5957
6470
    if (replace_column[i])
5958
6471
    {
5959
 
      free(replace_column[i]);
 
6472
      my_free(replace_column[i], 0);
5960
6473
      replace_column[i]= 0;
5961
6474
    }
5962
6475
  }
5971
6484
 
5972
6485
/* Definitions for replace result */
5973
6486
 
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;
 
6487
typedef struct st_pointer_array {               /* when using array-strings */
 
6488
  TYPELIB typelib;                              /* Pointer to strings */
 
6489
  uchar *str;                                   /* Strings is here */
 
6490
  int7  *flag;                                  /* Flag about each var. */
 
6491
  uint  array_allocs,max_count,length,max_length;
5979
6492
} POINTER_ARRAY;
5980
6493
 
5981
6494
struct st_replace;
5982
6495
struct st_replace *init_replace(char * *from, char * *to, uint count,
5983
 
                                char * word_end_chars);
 
6496
                                char * word_end_chars);
5984
6497
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5985
 
void replace_strings_append(struct st_replace *rep, string* ds,
 
6498
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5986
6499
                            const char *from, int len);
5987
6500
void free_pointer_array(POINTER_ARRAY *pa);
5988
6501
 
6003
6516
  char *buff, *start;
6004
6517
  char word_end_chars[256], *pos;
6005
6518
  POINTER_ARRAY to_array, from_array;
6006
 
 
 
6519
  DBUG_ENTER("get_replace");
6007
6520
 
6008
6521
  free_replace();
6009
6522
 
6010
 
  memset(&to_array, 0, sizeof(to_array));
6011
 
  memset(&from_array, 0, sizeof(from_array));
 
6523
  bzero((char*) &to_array,sizeof(to_array));
 
6524
  bzero((char*) &from_array,sizeof(from_array));
6012
6525
  if (!*from)
6013
6526
    die("Missing argument in %s", command->query);
6014
6527
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6026
6539
  for (i= 1,pos= word_end_chars ; i < 256 ; i++)
6027
6540
    if (my_isspace(charset_info,i))
6028
6541
      *pos++= i;
6029
 
  *pos=0;          /* End pointer */
 
6542
  *pos=0;                                       /* End pointer */
6030
6543
  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)))
 
6544
                                  (char**) to_array.typelib.type_names,
 
6545
                                  (uint) from_array.typelib.count,
 
6546
                                  word_end_chars)))
6034
6547
    die("Can't initialize replace from '%s'", command->query);
6035
6548
  free_pointer_array(&from_array);
6036
6549
  free_pointer_array(&to_array);
6037
 
  free(start);
 
6550
  my_free(start, MYF(0));
6038
6551
  command->last_argument= command->end;
6039
 
  return;
 
6552
  DBUG_VOID_RETURN;
6040
6553
}
6041
6554
 
6042
6555
 
6043
6556
void free_replace()
6044
6557
{
6045
 
 
 
6558
  DBUG_ENTER("free_replace");
6046
6559
  if (glob_replace)
6047
6560
  {
6048
 
    free(glob_replace);
 
6561
    my_free(glob_replace,MYF(0));
6049
6562
    glob_replace=0;
6050
6563
  }
6051
 
  return;
 
6564
  DBUG_VOID_RETURN;
6052
6565
}
6053
6566
 
6054
6567
 
6055
6568
typedef struct st_replace {
6056
 
  bool found;
 
6569
  my_bool found;
6057
6570
  struct st_replace *next[256];
6058
6571
} REPLACE;
6059
6572
 
6060
6573
typedef struct st_replace_found {
6061
 
  bool found;
 
6574
  my_bool found;
6062
6575
  char *replace_string;
6063
6576
  uint to_offset;
6064
6577
  int from_offset;
6065
6578
} REPLACE_STRING;
6066
6579
 
6067
6580
 
6068
 
void replace_strings_append(REPLACE *rep, string* ds,
6069
 
                            const char *str, int len)
 
6581
void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
 
6582
                            const char *str,
 
6583
                            int len __attribute__((unused)))
6070
6584
{
6071
6585
  register REPLACE *rep_pos;
6072
6586
  register REPLACE_STRING *rep_str;
6073
6587
  const char *start, *from;
6074
 
 
 
6588
  DBUG_ENTER("replace_strings_append");
6075
6589
 
6076
6590
  start= from= str;
6077
6591
  rep_pos=rep+1;
6078
6592
  for (;;)
6079
6593
  {
6080
6594
    /* Loop through states */
 
6595
    DBUG_PRINT("info", ("Looping through states"));
6081
6596
    while (!rep_pos->found)
6082
 
      rep_pos= rep_pos->next[(unsigned char) *from++];
 
6597
      rep_pos= rep_pos->next[(uchar) *from++];
6083
6598
 
6084
6599
    /* Does this state contain a string to be replaced */
6085
6600
    if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6086
6601
    {
6087
6602
      /* No match found */
6088
 
      ds->append(start, from - start - 1);
6089
 
      return;
 
6603
      dynstr_append_mem(ds, start, from - start - 1);
 
6604
      DBUG_PRINT("exit", ("Found no more string to replace, appended: %s", start));
 
6605
      DBUG_VOID_RETURN;
6090
6606
    }
6091
6607
 
 
6608
    /* Found a string that needs to be replaced */
 
6609
    DBUG_PRINT("info", ("found: %d, to_offset: %d, from_offset: %d, string: %s",
 
6610
                        rep_str->found, rep_str->to_offset,
 
6611
                        rep_str->from_offset, rep_str->replace_string));
 
6612
 
6092
6613
    /* Append part of original string before replace string */
6093
 
    ds->append(start, (from - rep_str->to_offset) - start);
 
6614
    dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6094
6615
 
6095
6616
    /* Append replace string */
6096
 
    ds->append(rep_str->replace_string,
6097
 
               strlen(rep_str->replace_string));
 
6617
    dynstr_append_mem(ds, rep_str->replace_string,
 
6618
                      strlen(rep_str->replace_string));
6098
6619
 
6099
6620
    if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6100
 
      return;
6101
 
 
6102
 
    assert(from <= str+len);
 
6621
    {
 
6622
      /* End of from string */
 
6623
      DBUG_PRINT("exit", ("Found end of from string"));
 
6624
      DBUG_VOID_RETURN;
 
6625
    }
 
6626
    DBUG_ASSERT(from <= str+len);
6103
6627
    start= from;
6104
6628
    rep_pos=rep;
6105
6629
  }
6203
6727
  /* for each regexp substitution statement */
6204
6728
  while (p < expr_end)
6205
6729
  {
6206
 
    memset(&reg, 0, sizeof(reg));
 
6730
    bzero(&reg,sizeof(reg));
6207
6731
    /* find the start of the statement */
6208
6732
    while (p < expr_end)
6209
6733
    {
6245
6769
      reg.icase= 1;
6246
6770
 
6247
6771
    /* done parsing the statement, now place it in regex_arr */
6248
 
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6772
    if (insert_dynamic(&res->regex_arr,(uchar*) &reg))
6249
6773
      die("Out of memory");
6250
6774
  }
6251
6775
  res->odd_buf_len= res->even_buf_len= 8192;
6256
6780
  return res;
6257
6781
 
6258
6782
err:
6259
 
  free(res);
 
6783
  my_free(res,0);
6260
6784
  die("Error parsing replace_regex \"%s\"", expr);
6261
6785
  return 0;
6262
6786
}
6297
6821
    struct st_regex re;
6298
6822
    char* save_out_buf= out_buf;
6299
6823
 
6300
 
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6824
    get_dynamic(&r->regex_arr,(uchar*)&re,i);
6301
6825
 
6302
6826
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6303
6827
                     in_buf, re.icase))
6315
6839
      if (in_buf == val)
6316
6840
        in_buf= r->odd_buf;
6317
6841
 
6318
 
      std::swap(in_buf,out_buf);
 
6842
      swap_variables(char*,in_buf,out_buf);
6319
6843
 
6320
6844
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
6321
6845
        &r->odd_buf_len;
6348
6872
  if (glob_replace_regex)
6349
6873
  {
6350
6874
    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);
 
6875
    my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6876
    my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6877
    my_free(glob_replace_regex,MYF(0));
6354
6878
    glob_replace_regex=0;
6355
6879
  }
6356
6880
}
6402
6926
    return 1;
6403
6927
  }
6404
6928
  strcpy(new_buf, new_str);
6405
 
  *buf_p= new_buf;
 
6929
  buf_p= &new_buf;
6406
6930
 
6407
6931
  return 0;
6408
6932
}
6416
6940
#define LAST_CHAR_CODE 259
6417
6941
 
6418
6942
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 */
 
6943
  uint  *bits;                          /* Pointer to used sets */
 
6944
  short next[LAST_CHAR_CODE];           /* Pointer to next sets */
 
6945
  uint  found_len;                      /* Best match to date */
 
6946
  int   found_offset;
 
6947
  uint  table_offset;
 
6948
  uint  size_of_bits;                   /* For convinience */
6425
6949
} REP_SET;
6426
6950
 
6427
6951
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;
 
6952
  uint          count;                  /* Number of sets */
 
6953
  uint          extra;                  /* Extra sets in buffer */
 
6954
  uint          invisible;              /* Sets not chown */
 
6955
  uint          size_of_bits;
 
6956
  REP_SET       *set,*set_buffer;
 
6957
  uint          *bit_buffer;
6434
6958
} REP_SETS;
6435
6959
 
6436
6960
typedef struct st_found_set {
6481
7005
/* Init a replace structure for further calls */
6482
7006
 
6483
7007
REPLACE *init_replace(char * *from, char * *to,uint count,
6484
 
                      char * word_end_chars)
 
7008
                      char * word_end_chars)
6485
7009
{
6486
7010
  static const int SPACE_CHAR= 256;
6487
7011
  static const int START_OF_LINE= 257;
6497
7021
  REPLACE *replace;
6498
7022
  FOUND_SET *found_set;
6499
7023
  REPLACE_STRING *rep_str;
6500
 
 
 
7024
  DBUG_ENTER("init_replace");
6501
7025
 
6502
7026
  /* Count number of states */
6503
7027
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6506
7030
    if (!len)
6507
7031
    {
6508
7032
      errno=EINVAL;
6509
 
      return(0);
 
7033
      DBUG_RETURN(0);
6510
7034
    }
6511
7035
    states+=len+1;
6512
7036
    result_len+=(uint) strlen(to[i])+1;
6513
7037
    if (len > max_length)
6514
7038
      max_length=len;
6515
7039
  }
6516
 
  memset(is_word_end, 0, sizeof(is_word_end));
 
7040
  bzero((char*) is_word_end,sizeof(is_word_end));
6517
7041
  for (i=0 ; word_end_chars[i] ; i++)
6518
 
    is_word_end[(unsigned char) word_end_chars[i]]=1;
 
7042
    is_word_end[(uchar) word_end_chars[i]]=1;
6519
7043
 
6520
7044
  if (init_sets(&sets,states))
6521
 
    return(0);
 
7045
    DBUG_RETURN(0);
6522
7046
  found_sets=0;
6523
7047
  if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
6524
 
                                          MYF(MY_WME))))
 
7048
                                          MYF(MY_WME))))
6525
7049
  {
6526
7050
    free_sets(&sets);
6527
 
    return(0);
 
7051
    DBUG_RETURN(0);
6528
7052
  }
6529
 
  make_new_set(&sets);      /* Set starting set */
6530
 
  make_sets_invisible(&sets);      /* Hide previus sets */
 
7053
  VOID(make_new_set(&sets));                    /* Set starting set */
 
7054
  make_sets_invisible(&sets);                   /* Hide previus sets */
6531
7055
  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 */
 
7056
  word_states=make_new_set(&sets);              /* Start of new word */
 
7057
  start_states=make_new_set(&sets);             /* This is first state */
6534
7058
  if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6535
7059
  {
6536
7060
    free_sets(&sets);
6537
 
    free(found_set);
6538
 
    return(0);
 
7061
    my_free(found_set,MYF(0));
 
7062
    DBUG_RETURN(0);
6539
7063
  }
6540
7064
 
6541
7065
  /* Init follow_ptr[] */
6546
7070
      internal_set_bit(start_states,states+1);
6547
7071
      if (!from[i][2])
6548
7072
      {
6549
 
        start_states->table_offset=i;
6550
 
        start_states->found_offset=1;
 
7073
        start_states->table_offset=i;
 
7074
        start_states->found_offset=1;
6551
7075
      }
6552
7076
    }
6553
7077
    else if (from[i][0] == '\\' && from[i][1] == '$')
6554
7078
    {
6555
7079
      internal_set_bit(start_states,states);
6556
7080
      internal_set_bit(word_states,states);
6557
 
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
 
7081
      if (!from[i][2] && start_states->table_offset == (uint) ~0)
6558
7082
      {
6559
 
        start_states->table_offset=i;
6560
 
        start_states->found_offset=0;
 
7083
        start_states->table_offset=i;
 
7084
        start_states->found_offset=0;
6561
7085
      }
6562
7086
    }
6563
7087
    else
6564
7088
    {
6565
7089
      internal_set_bit(word_states,states);
6566
7090
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6567
 
        internal_set_bit(start_states,states+1);
 
7091
        internal_set_bit(start_states,states+1);
6568
7092
      else
6569
 
        internal_set_bit(start_states,states);
 
7093
        internal_set_bit(start_states,states);
6570
7094
    }
6571
7095
    for (pos=from[i], len=0; *pos ; pos++)
6572
7096
    {
6573
7097
      if (*pos == '\\' && *(pos+1))
6574
7098
      {
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
 
        }
 
7099
        pos++;
 
7100
        switch (*pos) {
 
7101
        case 'b':
 
7102
          follow_ptr->chr = SPACE_CHAR;
 
7103
          break;
 
7104
        case '^':
 
7105
          follow_ptr->chr = START_OF_LINE;
 
7106
          break;
 
7107
        case '$':
 
7108
          follow_ptr->chr = END_OF_LINE;
 
7109
          break;
 
7110
        case 'r':
 
7111
          follow_ptr->chr = '\r';
 
7112
          break;
 
7113
        case 't':
 
7114
          follow_ptr->chr = '\t';
 
7115
          break;
 
7116
        case 'v':
 
7117
          follow_ptr->chr = '\v';
 
7118
          break;
 
7119
        default:
 
7120
          follow_ptr->chr = (uchar) *pos;
 
7121
          break;
 
7122
        }
6599
7123
      }
6600
7124
      else
6601
 
        follow_ptr->chr= (unsigned char) *pos;
 
7125
        follow_ptr->chr= (uchar) *pos;
6602
7126
      follow_ptr->table_offset=i;
6603
7127
      follow_ptr->len= ++len;
6604
7128
      follow_ptr++;
6614
7138
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6615
7139
  {
6616
7140
    set=sets.set+set_nr;
6617
 
    default_state= 0;        /* Start from beginning */
 
7141
    default_state= 0;                           /* Start from beginning */
6618
7142
 
6619
7143
    /* If end of found-string not found or start-set with current set */
6620
7144
 
6621
 
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
 
7145
    for (i= (uint) ~0; (i=get_next_bit(set,i)) ;)
6622
7146
    {
6623
7147
      if (!follow[i].chr)
6624
7148
      {
6625
 
        if (! default_state)
6626
 
          default_state= find_found(found_set,set->table_offset,
6627
 
                                    set->found_offset+1);
 
7149
        if (! default_state)
 
7150
          default_state= find_found(found_set,set->table_offset,
 
7151
                                    set->found_offset+1);
6628
7152
      }
6629
7153
    }
6630
 
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
 
7154
    copy_bits(sets.set+used_sets,set);          /* Save set for changes */
6631
7155
    if (!default_state)
6632
 
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
 
7156
      or_bits(sets.set+used_sets,sets.set);     /* Can restart from start */
6633
7157
 
6634
7158
    /* 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)) ;)
 
7159
    bzero((char*) used_chars,sizeof(used_chars));
 
7160
    for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6637
7161
    {
6638
7162
      used_chars[follow[i].chr]=1;
6639
7163
      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;
 
7164
           follow[i].len > 1) || follow[i].chr == END_OF_LINE)
 
7165
        used_chars[0]=1;
6642
7166
    }
6643
7167
 
6644
7168
    /* Mark word_chars used if \b is in state */
6645
7169
    if (used_chars[SPACE_CHAR])
6646
7170
      for (pos= word_end_chars ; *pos ; pos++)
6647
 
        used_chars[(int) (unsigned char) *pos] = 1;
 
7171
        used_chars[(int) (uchar) *pos] = 1;
6648
7172
 
6649
7173
    /* Handle other used characters */
6650
7174
    for (chr= 0 ; chr < 256 ; chr++)
6651
7175
    {
6652
7176
      if (! used_chars[chr])
6653
 
        set->next[chr]= chr ? default_state : -1;
 
7177
        set->next[chr]= chr ? default_state : -1;
6654
7178
      else
6655
7179
      {
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;
 
7180
        new_set=make_new_set(&sets);
 
7181
        set=sets.set+set_nr;                    /* if realloc */
 
7182
        new_set->table_offset=set->table_offset;
 
7183
        new_set->found_len=set->found_len;
 
7184
        new_set->found_offset=set->found_offset+1;
 
7185
        found_end=0;
6662
7186
 
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);
 
7187
        for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
 
7188
        {
 
7189
          if (!follow[i].chr || follow[i].chr == chr ||
 
7190
              (follow[i].chr == SPACE_CHAR &&
 
7191
               (is_word_end[chr] ||
 
7192
                (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
 
7193
              (follow[i].chr == END_OF_LINE && ! chr))
 
7194
          {
 
7195
            if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
 
7196
                follow[i].len > found_end)
 
7197
              found_end=follow[i].len;
 
7198
            if (chr && follow[i].chr)
 
7199
              internal_set_bit(new_set,i+1);            /* To next set */
 
7200
            else
 
7201
              internal_set_bit(new_set,i);
 
7202
          }
 
7203
        }
 
7204
        if (found_end)
 
7205
        {
 
7206
          new_set->found_len=0;                 /* Set for testing if first */
 
7207
          bits_set=0;
 
7208
          for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
 
7209
          {
 
7210
            if ((follow[i].chr == SPACE_CHAR ||
 
7211
                 follow[i].chr == END_OF_LINE) && ! chr)
 
7212
              bit_nr=i+1;
 
7213
            else
 
7214
              bit_nr=i;
 
7215
            if (follow[bit_nr-1].len < found_end ||
 
7216
                (new_set->found_len &&
 
7217
                 (chr == 0 || !follow[bit_nr].chr)))
 
7218
              internal_clear_bit(new_set,i);
 
7219
            else
 
7220
            {
 
7221
              if (chr == 0 || !follow[bit_nr].chr)
 
7222
              {                                 /* best match  */
 
7223
                new_set->table_offset=follow[bit_nr].table_offset;
 
7224
                if (chr || (follow[i].chr == SPACE_CHAR ||
 
7225
                            follow[i].chr == END_OF_LINE))
 
7226
                  new_set->found_offset=found_end;      /* New match */
 
7227
                new_set->found_len=found_end;
 
7228
              }
 
7229
              bits_set++;
 
7230
            }
 
7231
          }
 
7232
          if (bits_set == 1)
 
7233
          {
 
7234
            set->next[chr] = find_found(found_set,
 
7235
                                        new_set->table_offset,
 
7236
                                        new_set->found_offset);
 
7237
            free_last_set(&sets);
 
7238
          }
 
7239
          else
 
7240
            set->next[chr] = find_set(&sets,new_set);
 
7241
        }
 
7242
        else
 
7243
          set->next[chr] = find_set(&sets,new_set);
6720
7244
      }
6721
7245
    }
6722
7246
  }
6724
7248
  /* Alloc replace structure for the replace-state-machine */
6725
7249
 
6726
7250
  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))))
 
7251
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
 
7252
                                    sizeof(char *)*count+result_len,
 
7253
                                    MYF(MY_WME | MY_ZEROFILL))))
6730
7254
  {
6731
7255
    rep_str=(REPLACE_STRING*) (replace+sets.count);
6732
7256
    to_array= (char **) (rep_str+found_sets+1);
6734
7258
    for (i=0 ; i < count ; i++)
6735
7259
    {
6736
7260
      to_array[i]=to_pos;
6737
 
      to_pos=my_stpcpy(to_pos,to[i])+1;
 
7261
      to_pos=strmov(to_pos,to[i])+1;
6738
7262
    }
6739
7263
    rep_str[0].found=1;
6740
7264
    rep_str[0].replace_string=0;
6741
7265
    for (i=1 ; i <= found_sets ; i++)
6742
7266
    {
6743
7267
      pos=from[found_set[i-1].table_offset];
6744
 
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
 
7268
      rep_str[i].found= !bcmp((const uchar*) pos,
 
7269
                              (const uchar*) "\\^", 3) ? 2 : 1;
6745
7270
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
6746
7271
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
6747
7272
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6748
 
        end_of_word(pos);
 
7273
        end_of_word(pos);
6749
7274
    }
6750
7275
    for (i=0 ; i < sets.count ; i++)
6751
7276
    {
6752
7277
      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));
 
7278
        if (sets.set[i].next[j] >= 0)
 
7279
          replace[i].next[j]=replace+sets.set[i].next[j];
 
7280
        else
 
7281
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6757
7282
    }
6758
7283
  }
6759
 
  free(follow);
 
7284
  my_free(follow,MYF(0));
6760
7285
  free_sets(&sets);
6761
 
  free(found_set);
6762
 
  return(replace);
 
7286
  my_free(found_set,MYF(0));
 
7287
  DBUG_PRINT("exit",("Replace table has %d states",sets.count));
 
7288
  DBUG_RETURN(replace);
6763
7289
}
6764
7290
 
6765
7291
 
6766
7292
int init_sets(REP_SETS *sets,uint states)
6767
7293
{
6768
 
  memset(sets, 0, sizeof(*sets));
 
7294
  bzero((char*) sets,sizeof(*sets));
6769
7295
  sets->size_of_bits=((states+7)/8);
6770
7296
  if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
6771
 
                                              MYF(MY_WME))))
 
7297
                                              MYF(MY_WME))))
6772
7298
    return 1;
6773
7299
  if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
6774
 
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
 
7300
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
6775
7301
  {
6776
 
    free(sets->set);
 
7302
    my_free(sets->set,MYF(0));
6777
7303
    return 1;
6778
7304
  }
6779
7305
  return 0;
6796
7322
  {
6797
7323
    sets->extra--;
6798
7324
    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);
 
7325
    bzero((char*) set->bits,sizeof(uint)*sets->size_of_bits);
 
7326
    bzero((char*) &set->next[0],sizeof(set->next[0])*LAST_CHAR_CODE);
6801
7327
    set->found_offset=0;
6802
7328
    set->found_len=0;
6803
 
    set->table_offset= UINT32_MAX;
 
7329
    set->table_offset= (uint) ~0;
6804
7330
    set->size_of_bits=sets->size_of_bits;
6805
7331
    return set;
6806
7332
  }
6807
7333
  count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6808
 
  if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
 
7334
  if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6809
7335
                                  sizeof(REP_SET)*count,
6810
 
                                  MYF(MY_WME))))
 
7336
                                  MYF(MY_WME))))
6811
7337
    return 0;
6812
7338
  sets->set_buffer=set;
6813
7339
  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))))
 
7340
  if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
 
7341
                                      (sizeof(uint)*sets->size_of_bits)*count,
 
7342
                                      MYF(MY_WME))))
6817
7343
    return 0;
6818
7344
  sets->bit_buffer=bit_buffer;
6819
7345
  for (i=0 ; i < count ; i++)
6834
7360
 
6835
7361
void free_sets(REP_SETS *sets)
6836
7362
{
6837
 
  free(sets->set_buffer);
6838
 
  free(sets->bit_buffer);
 
7363
  my_free(sets->set_buffer,MYF(0));
 
7364
  my_free(sets->bit_buffer,MYF(0));
6839
7365
  return;
6840
7366
}
6841
7367
 
6862
7388
 
6863
7389
void copy_bits(REP_SET *to,REP_SET *from)
6864
7390
{
6865
 
  memcpy(to->bits,from->bits,
6866
 
         (size_t) (sizeof(uint) * to->size_of_bits));
 
7391
  memcpy((uchar*) to->bits,(uchar*) from->bits,
 
7392
         (size_t) (sizeof(uint) * to->size_of_bits));
6867
7393
}
6868
7394
 
6869
7395
int cmp_bits(REP_SET *set1,REP_SET *set2)
6870
7396
{
6871
 
  return memcmp(set1->bits,set2->bits, sizeof(uint) * set1->size_of_bits);
 
7397
  return bcmp((uchar*) set1->bits,(uchar*) set2->bits,
 
7398
              sizeof(uint) * set1->size_of_bits);
6872
7399
}
6873
7400
 
6874
7401
 
6910
7437
      return i;
6911
7438
    }
6912
7439
  }
6913
 
  return i;        /* return new postion */
 
7440
  return i;                             /* return new postion */
6914
7441
}
6915
7442
 
6916
7443
/* find if there is a found_set with same table_offset & found_offset
6925
7452
  int i;
6926
7453
  for (i=0 ; (uint) i < found_sets ; i++)
6927
7454
    if (found_set[i].table_offset == table_offset &&
6928
 
        found_set[i].found_offset == found_offset)
 
7455
        found_set[i].found_offset == found_offset)
6929
7456
      return -i-2;
6930
7457
  found_set[i].table_offset=table_offset;
6931
7458
  found_set[i].found_offset=found_offset;
6932
7459
  found_sets++;
6933
 
  return -i-2;        /* return new postion */
 
7460
  return -i-2;                          /* return new postion */
6934
7461
}
6935
7462
 
6936
7463
/* Return 1 if regexp starts with \b or ends with \b*/
6937
7464
 
6938
7465
uint start_at_word(char * pos)
6939
7466
{
6940
 
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
6941
 
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
 
7467
  return (((!bcmp((const uchar*) pos, (const uchar*) "\\b",2) && pos[2]) ||
 
7468
           !bcmp((const uchar*) pos, (const uchar*) "\\^", 2)) ? 1 : 0);
6942
7469
}
6943
7470
 
6944
7471
uint end_of_word(char * pos)
6945
7472
{
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;
 
7473
  char * end=strend(pos);
 
7474
  return ((end > pos+2 && !bcmp((const uchar*) end-2,
 
7475
                                (const uchar*) "\\b", 2)) ||
 
7476
          (end >= pos+2 && !bcmp((const uchar*) end-2,
 
7477
                                (const uchar*) "\\$",2))) ? 1 : 0;
6949
7478
}
6950
7479
 
6951
7480
/****************************************************************************
6952
7481
 * Handle replacement of strings
6953
7482
 ****************************************************************************/
6954
7483
 
6955
 
#define PC_MALLOC    256  /* Bytes for pointers */
6956
 
#define PS_MALLOC    512  /* Bytes for data */
 
7484
#define PC_MALLOC               256     /* Bytes for pointers */
 
7485
#define PS_MALLOC               512     /* Bytes for data */
6957
7486
 
6958
7487
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6959
7488
{
6960
7489
  uint i,length,old_count;
6961
 
  unsigned char *new_pos;
 
7490
  uchar *new_pos;
6962
7491
  const char **new_array;
6963
 
 
 
7492
  DBUG_ENTER("insert_pointer_name");
6964
7493
 
6965
7494
  if (! pa->typelib.count)
6966
7495
  {
6967
7496
    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))))
 
7497
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
 
7498
                     (sizeof(char *)+sizeof(*pa->flag))*
 
7499
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
 
7500
      DBUG_RETURN(-1);
 
7501
    if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
 
7502
                                     MYF(MY_WME))))
6974
7503
    {
6975
 
      free((char*) pa->typelib.type_names);
6976
 
      return (-1);
 
7504
      my_free((char*) pa->typelib.type_names,MYF(0));
 
7505
      DBUG_RETURN (-1);
6977
7506
    }
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);
 
7507
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
 
7508
                                               sizeof(*pa->flag));
 
7509
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6981
7510
    pa->length=0;
6982
7511
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6983
7512
    pa->array_allocs=1;
6985
7514
  length=(uint) strlen(name)+1;
6986
7515
  if (pa->length+length >= pa->max_length)
6987
7516
  {
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);
 
7517
    if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
 
7518
                                      (uint) (pa->max_length+PS_MALLOC),
 
7519
                                      MYF(MY_WME))))
 
7520
      DBUG_RETURN(1);
6992
7521
    if (new_pos != pa->str)
6993
7522
    {
6994
7523
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
6995
7524
      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*);
 
7525
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
 
7526
                                              char*);
6998
7527
      pa->str=new_pos;
6999
7528
    }
7000
7529
    pa->max_length+=PS_MALLOC;
7004
7533
    int len;
7005
7534
    pa->array_allocs++;
7006
7535
    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)),
 
7536
    if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
 
7537
                                               (uint) len/
 
7538
                                               (sizeof(uchar*)+sizeof(*pa->flag))*
 
7539
                                               (sizeof(uchar*)+sizeof(*pa->flag)),
7011
7540
                                               MYF(MY_WME))))
7012
 
      return(1);
 
7541
      DBUG_RETURN(1);
7013
7542
    pa->typelib.type_names=new_array;
7014
7543
    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));
 
7544
    pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
 
7545
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
 
7546
    memcpy((uchar*) pa->flag,(char *) (pa->typelib.type_names+old_count),
 
7547
           old_count*sizeof(*pa->flag));
7019
7548
  }
7020
 
  pa->flag[pa->typelib.count]=0;      /* Reset flag */
 
7549
  pa->flag[pa->typelib.count]=0;                        /* Reset flag */
7021
7550
  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);
 
7551
  pa->typelib.type_names[pa->typelib.count]= NullS;     /* Put end-mark */
 
7552
  VOID(strmov((char*) pa->str+pa->length,name));
7024
7553
  pa->length+=length;
7025
 
  return(0);
 
7554
  DBUG_RETURN(0);
7026
7555
} /* insert_pointer_name */
7027
7556
 
7028
7557
 
7033
7562
  if (pa->typelib.count)
7034
7563
  {
7035
7564
    pa->typelib.count=0;
7036
 
    free((char*) pa->typelib.type_names);
 
7565
    my_free((char*) pa->typelib.type_names,MYF(0));
7037
7566
    pa->typelib.type_names=0;
7038
 
    free(pa->str);
 
7567
    my_free(pa->str,MYF(0));
7039
7568
  }
7040
7569
} /* free_pointer_array */
7041
7570
 
7043
7572
/* Functions that uses replace and replace_regex */
7044
7573
 
7045
7574
/* Append the string to ds, with optional replace */
7046
 
void replace_append_mem(string *ds,
7047
 
                        const char *val, int len)
 
7575
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
 
7576
                               const char *val, int len)
7048
7577
{
7049
 
  char *v= strdup(val);
7050
 
 
7051
7578
  if (glob_replace_regex)
7052
7579
  {
7053
7580
    /* Regex replace */
7054
 
    if (!multi_reg_replace(glob_replace_regex, v))
 
7581
    if (!multi_reg_replace(glob_replace_regex, (char*)val))
7055
7582
    {
7056
 
      v= glob_replace_regex->buf;
7057
 
      len= strlen(v);
 
7583
      val= glob_replace_regex->buf;
 
7584
      len= strlen(val);
7058
7585
    }
7059
7586
  }
7060
7587
 
7061
7588
  if (glob_replace)
7062
7589
  {
7063
7590
    /* Normal replace */
7064
 
    replace_strings_append(glob_replace, ds, v, len);
 
7591
    replace_strings_append(glob_replace, ds, val, len);
7065
7592
  }
7066
7593
  else
7067
 
  {
7068
 
    ds->append(v, len);
7069
 
  }
 
7594
    dynstr_append_mem(ds, val, len);
7070
7595
}
7071
7596
 
7072
7597
 
7073
7598
/* Append zero-terminated string to ds, with optional replace */
7074
 
void replace_append(string *ds, const char *val)
 
7599
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7075
7600
{
7076
 
  replace_append_mem(ds, val, strlen(val));
 
7601
  replace_dynstr_append_mem(ds, val, strlen(val));
7077
7602
}
7078
7603
 
7079
7604
/* Append uint to ds, with optional replace */
7080
 
void replace_append_uint(string *ds, uint val)
 
7605
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7081
7606
{
7082
7607
  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
 
 
 
7608
  char *end= longlong10_to_str(val, buff, 10);
 
7609
  replace_dynstr_append_mem(ds, buff, end - buff);
7086
7610
}
7087
7611
 
7088
7612
 
7099
7623
 
7100
7624
*/
7101
7625
 
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;
 
7626
static int comp_lines(const char **a, const char **b)
 
7627
{
 
7628
  return (strcmp(*a,*b));
 
7629
}
 
7630
 
 
7631
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
 
7632
{
 
7633
  unsigned i;
 
7634
  char *start= ds_input->str;
 
7635
  DYNAMIC_ARRAY lines;
 
7636
  DBUG_ENTER("dynstr_append_sorted");
 
7637
 
 
7638
  if (!*start)
 
7639
    DBUG_VOID_RETURN;  /* No input */
 
7640
 
 
7641
  my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
 
7642
 
 
7643
  /* First line is result header, skip past it */
 
7644
  while (*start && *start != '\n')
 
7645
    start++;
 
7646
  start++; /* Skip past \n */
 
7647
  dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
7119
7648
 
7120
7649
  /* Insert line(s) in array */
7121
 
  do {
 
7650
  while (*start)
 
7651
  {
 
7652
    char* line_end= (char*)start;
7122
7653
 
7123
 
    eol_pos= ds_input->find_first_of('\n', start_pos);
7124
7654
    /* 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);
 
7655
    while (*line_end && *line_end != '\n')
 
7656
      line_end++;
 
7657
    *line_end= 0;
 
7658
 
 
7659
    /* Insert pointer to the line in array */
 
7660
    if (insert_dynamic(&lines, (uchar*) &start))
 
7661
      die("Out of memory inserting lines to sort");
 
7662
 
 
7663
    start= line_end+1;
 
7664
  }
 
7665
 
 
7666
  /* Sort array */
 
7667
  qsort(lines.buffer, lines.elements,
 
7668
        sizeof(char**), (qsort_cmp)comp_lines);
7129
7669
 
7130
7670
  /* Create new result */
7131
 
  while (!lines.empty()) {
7132
 
    ds->append(lines.top());
7133
 
    lines.pop();
 
7671
  for (i= 0; i < lines.elements ; i++)
 
7672
  {
 
7673
    const char **line= dynamic_element(&lines, i, const char**);
 
7674
    dynstr_append(ds, *line);
 
7675
    dynstr_append(ds, "\n");
7134
7676
  }
7135
7677
 
7136
 
  return;
 
7678
  delete_dynamic(&lines);
 
7679
  DBUG_VOID_RETURN;
7137
7680
}