~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

Merge/fix in FAQ.

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"
40
 
 
41
 
#include "config.h"
42
 
 
43
 
#include <queue>
44
 
#include <map>
45
 
#include <string>
46
 
 
47
35
#include <pcrecpp.h>
48
36
 
49
37
#include "client_priv.h"
50
 
#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>
51
43
#include <stdarg.h>
52
 
 
53
 
#include "errname.h"
54
 
 
55
 
using namespace std;
 
44
#include <violite.h>
 
45
 
56
46
 
57
47
#define MAX_VAR_NAME_LENGTH    256
58
48
#define MAX_COLUMNS            256
64
54
#define QUERY_REAP_FLAG  2
65
55
 
66
56
enum {
 
57
  OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
67
58
  OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
68
59
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
69
60
};
89
80
static bool server_initialized= 0;
90
81
static bool is_windows= 0;
91
82
static char **default_argv;
92
 
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
 
83
static const char *load_default_groups[]= { "mysqltest", "client", 0 };
93
84
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
94
85
 
95
86
static uint start_lineno= 0; /* Start line of current command */
133
124
static struct st_test_file* file_stack_end;
134
125
 
135
126
 
136
 
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
 
127
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
 
128
 
 
129
static const char *embedded_server_groups[]=
 
130
{
 
131
  "server",
 
132
  "embedded",
 
133
  "mysqltest_SERVER",
 
134
  NullS
 
135
};
137
136
 
138
137
static int embedded_server_arg_count=0;
139
138
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
149
148
 
150
149
static uint64_t progress_start= 0;
151
150
 
152
 
vector<struct st_command*> q_lines;
 
151
DYNAMIC_ARRAY q_lines;
153
152
 
154
153
typedef struct {
155
154
  int read_lines,current_line;
159
158
typedef struct
160
159
{
161
160
  char file[FN_REFLEN];
162
 
  uint32_t pos;
 
161
  ulong pos;
163
162
} master_pos_st;
164
163
 
165
164
master_pos_st master_pos;
187
186
 
188
187
struct st_connection
189
188
{
190
 
  DRIZZLE drizzle;
 
189
  MYSQL mysql;
191
190
  /* Used when creating views and sp, to avoid implicit commit */
192
 
  DRIZZLE *util_drizzle;
 
191
  MYSQL* util_mysql;
193
192
  char *name;
194
193
};
195
194
struct st_connection connections[128];
196
195
struct st_connection* cur_con= NULL, *next_con, *connections_end;
197
196
 
198
197
/*
199
 
  List of commands in drizzletest
 
198
  List of commands in mysqltest
200
199
  Must match the "command_names" array
201
200
  Add new commands before Q_UNKNOWN!
202
201
*/
203
202
enum enum_commands {
204
203
  Q_CONNECTION=1,     Q_QUERY,
205
 
  Q_CONNECT,      Q_SLEEP, Q_REAL_SLEEP,
206
 
  Q_INC,        Q_DEC,
207
 
  Q_SOURCE,      Q_DISCONNECT,
208
 
  Q_LET,        Q_ECHO,
209
 
  Q_WHILE,      Q_END_BLOCK,
210
 
  Q_SYSTEM,      Q_RESULT,
211
 
  Q_REQUIRE,      Q_SAVE_MASTER_POS,
 
204
  Q_CONNECT,        Q_SLEEP, Q_REAL_SLEEP,
 
205
  Q_INC,                    Q_DEC,
 
206
  Q_SOURCE,         Q_DISCONNECT,
 
207
  Q_LET,                    Q_ECHO,
 
208
  Q_WHILE,          Q_END_BLOCK,
 
209
  Q_SYSTEM,         Q_RESULT,
 
210
  Q_REQUIRE,        Q_SAVE_MASTER_POS,
212
211
  Q_SYNC_WITH_MASTER,
213
212
  Q_SYNC_SLAVE_WITH_MASTER,
214
213
  Q_ERROR,
215
 
  Q_SEND,        Q_REAP,
216
 
  Q_DIRTY_CLOSE,      Q_REPLACE, Q_REPLACE_COLUMN,
217
 
  Q_PING,        Q_EVAL,
 
214
  Q_SEND,                   Q_REAP,
 
215
  Q_DIRTY_CLOSE,            Q_REPLACE, Q_REPLACE_COLUMN,
 
216
  Q_PING,                   Q_EVAL,
218
217
  Q_EVAL_RESULT,
219
218
  Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
220
219
  Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
236
235
  Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
237
236
  Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
238
237
 
239
 
  Q_UNKNOWN,             /* Unknown command.   */
240
 
  Q_COMMENT,             /* Comments, ignored. */
 
238
  Q_UNKNOWN,                           /* Unknown command.   */
 
239
  Q_COMMENT,                           /* Comments, ignored. */
241
240
  Q_COMMENT_WITH_COMMAND
242
241
};
243
242
 
309
308
  "copy_file",
310
309
  "perl",
311
310
  "die",
312
 
 
 
311
               
313
312
  /* Don't execute any more commands, compare result */
314
313
  "exit",
315
314
  "skip",
368
367
};
369
368
 
370
369
TYPELIB command_typelib= {array_elements(command_names),"",
371
 
                          command_names, 0};
 
370
                          command_names, 0};
372
371
 
373
 
string ds_res, ds_progress, ds_warning_messages;
 
372
DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
374
373
 
375
374
char builtin_echo[FN_REFLEN];
376
375
 
377
376
void die(const char *fmt, ...)
378
 
  __attribute__((format(printf, 1, 2)));
 
377
  ATTRIBUTE_FORMAT(printf, 1, 2);
379
378
void abort_not_supported_test(const char *fmt, ...)
380
 
  __attribute__((format(printf, 1, 2)));
 
379
  ATTRIBUTE_FORMAT(printf, 1, 2);
381
380
void verbose_msg(const char *fmt, ...)
382
 
  __attribute__((format(printf, 1, 2)));
 
381
  ATTRIBUTE_FORMAT(printf, 1, 2);
383
382
void warning_msg(const char *fmt, ...)
384
 
  __attribute__((format(printf, 1, 2)));
 
383
  ATTRIBUTE_FORMAT(printf, 1, 2);
385
384
void log_msg(const char *fmt, ...)
386
 
  __attribute__((format(printf, 1, 2)));
 
385
  ATTRIBUTE_FORMAT(printf, 1, 2);
387
386
 
388
387
VAR* var_from_env(const char *, const char *);
389
388
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
394
393
void eval_expr(VAR* v, const char *p, const char** p_end);
395
394
bool match_delimiter(int c, const char *delim, uint length);
396
395
void dump_result_to_reject_file(char *buf, int size);
397
 
void dump_result_to_log_file(const char *buf, int size);
 
396
void dump_result_to_log_file(char *buf, int size);
398
397
void dump_warning_messages(void);
399
398
void dump_progress(void);
400
399
 
401
 
void do_eval(string *query_eval, const char *query,
 
400
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
402
401
             const char *query_end, bool pass_through_escape_chars);
403
 
void str_to_file(const char *fname, const char *str, int size);
404
 
void str_to_file2(const char *fname, const char *str, int size, bool append);
 
402
void str_to_file(const char *fname, char *str, int size);
 
403
void str_to_file2(const char *fname, char *str, int size, bool append);
405
404
 
406
405
/* For replace_column */
407
406
static char *replace_column[MAX_COLUMNS];
427
426
  free_replace_column();
428
427
}
429
428
 
430
 
void replace_append_mem(string *ds, const char *val,
431
 
                        int len);
432
 
void replace_append(string *ds, const char *val);
433
 
void replace_append_uint(string *ds, uint val);
434
 
void append_sorted(string* ds, string* ds_input);
 
429
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
 
430
                               int len);
 
431
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
 
432
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
 
433
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input);
435
434
 
436
435
void handle_error(struct st_command*,
437
436
                  unsigned int err_errno, const char *err_error,
438
 
                  const char *err_sqlstate, string *ds);
 
437
                  const char *err_sqlstate, DYNAMIC_STRING *ds);
439
438
void handle_no_error(struct st_command*);
440
439
 
441
 
 
442
 
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
443
 
 
444
 
void do_eval(string *query_eval, const char *query,
 
440
#ifdef EMBEDDED_LIBRARY
 
441
 
 
442
/* attributes of the query thread */
 
443
pthread_attr_t cn_thd_attrib;
 
444
 
 
445
/*
 
446
  send_one_query executes query in separate thread, which is
 
447
  necessary in embedded library to run 'send' in proper way.
 
448
  This implementation doesn't handle errors returned
 
449
  by mysql_send_query. It's technically possible, though
 
450
  I don't see where it is needed.
 
451
*/
 
452
pthread_handler_t send_one_query(void *arg)
 
453
{
 
454
  struct st_connection *cn= (struct st_connection*)arg;
 
455
 
 
456
  mysql_thread_init();
 
457
  VOID(mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len));
 
458
 
 
459
  mysql_thread_end();
 
460
  pthread_mutex_lock(&cn->mutex);
 
461
  cn->query_done= 1;
 
462
  VOID(pthread_cond_signal(&cn->cond));
 
463
  pthread_mutex_unlock(&cn->mutex);
 
464
  pthread_exit(0);
 
465
  return 0;
 
466
}
 
467
 
 
468
static int do_send_query(struct st_connection *cn, const char *q, int q_len,
 
469
                         int flags)
 
470
{
 
471
  pthread_t tid;
 
472
 
 
473
  if (flags & QUERY_REAP_FLAG)
 
474
    return mysql_send_query(&cn->mysql, q, q_len);
 
475
 
 
476
  if (pthread_mutex_init(&cn->mutex, NULL) ||
 
477
      pthread_cond_init(&cn->cond, NULL))
 
478
    die("Error in the thread library");
 
479
 
 
480
  cn->cur_query= q;
 
481
  cn->cur_query_len= q_len;
 
482
  cn->query_done= 0;
 
483
  if (pthread_create(&tid, &cn_thd_attrib, send_one_query, (void*)cn))
 
484
    die("Cannot start new thread for query");
 
485
 
 
486
  return 0;
 
487
}
 
488
 
 
489
static void wait_query_thread_end(struct st_connection *con)
 
490
{
 
491
  if (!con->query_done)
 
492
  {
 
493
    pthread_mutex_lock(&con->mutex);
 
494
    while (!con->query_done)
 
495
      pthread_cond_wait(&con->cond, &con->mutex);
 
496
    pthread_mutex_unlock(&con->mutex);
 
497
  }
 
498
}
 
499
 
 
500
#else /*EMBEDDED_LIBRARY*/
 
501
 
 
502
#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q, q_len)
 
503
 
 
504
#endif /*EMBEDDED_LIBRARY*/
 
505
 
 
506
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
445
507
             const char *query_end, bool pass_through_escape_chars)
446
508
{
447
509
  const char *p;
456
518
    case '$':
457
519
      if (escaped)
458
520
      {
459
 
        escaped= 0;
460
 
        query_eval->append(p, 1);
 
521
        escaped= 0;
 
522
        dynstr_append_mem(query_eval, p, 1);
461
523
      }
462
524
      else
463
525
      {
464
 
        if (!(v= var_get(p, &p, 0, 0)))
465
 
          die("Bad variable in eval");
466
 
        query_eval->append(v->str_val, v->str_val_len);
 
526
        if (!(v= var_get(p, &p, 0, 0)))
 
527
          die("Bad variable in eval");
 
528
        dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
467
529
      }
468
530
      break;
469
531
    case '\\':
470
532
      next_c= *(p+1);
471
533
      if (escaped)
472
534
      {
473
 
        escaped= 0;
474
 
        query_eval->append(p, 1);
 
535
        escaped= 0;
 
536
        dynstr_append_mem(query_eval, p, 1);
475
537
      }
476
538
      else if (next_c == '\\' || next_c == '$' || next_c == '"')
477
539
      {
478
540
        /* Set escaped only if next char is \, " or $ */
479
 
        escaped= 1;
 
541
        escaped= 1;
480
542
 
481
543
        if (pass_through_escape_chars)
482
544
        {
483
545
          /* The escape char should be added to the output string. */
484
 
          query_eval->append(p, 1);
 
546
          dynstr_append_mem(query_eval, p, 1);
485
547
        }
486
548
      }
487
549
      else
488
 
        query_eval->append(p, 1);
 
550
        dynstr_append_mem(query_eval, p, 1);
489
551
      break;
490
552
    default:
491
553
      escaped= 0;
492
 
      query_eval->append(p, 1);
 
554
      dynstr_append_mem(query_eval, p, 1);
493
555
      break;
494
556
    }
495
557
  }
498
560
 
499
561
 
500
562
/*
501
 
  Concatenates any number of strings, escapes any OS quote in the result then
502
 
  surround the whole affair in another set of quotes which is finally appended
503
 
  to specified string.  This function is especially useful when
504
 
  building strings to be executed with the system() function.
505
 
 
506
 
  @param str string which will have addtional strings appended.
507
 
  @param append string to be appended.
508
 
  @param ... Optional. Additional string(s) to be appended.
509
 
 
510
 
  @note The final argument in the list must be NULL even if no additional
511
 
  options are passed.
512
 
*/
513
 
 
514
 
void append_os_quoted(string *str, const char *append, ...)
515
 
{
516
 
  const char *quote_str= "\'";
517
 
  const uint  quote_len= 1;
518
 
 
519
 
  va_list dirty_text;
520
 
 
521
 
  str->append(quote_str, quote_len); /* Leading quote */
522
 
  va_start(dirty_text, append);
523
 
  while (append != NULL)
524
 
  {
525
 
    const char  *cur_pos= append;
526
 
    const char *next_pos= cur_pos;
527
 
 
528
 
    /* Search for quote in each string and replace with escaped quote */
529
 
    while((next_pos= strrchr(cur_pos, quote_str[0])) != NULL)
530
 
    {
531
 
      str->append(cur_pos, next_pos - cur_pos);
532
 
      str->append("\\", 1);
533
 
      str->append(quote_str, quote_len);
534
 
      cur_pos= next_pos + 1;
535
 
    }
536
 
    str->append(cur_pos, next_pos - cur_pos);
537
 
    append= va_arg(dirty_text, char *);
538
 
  }
539
 
  va_end(dirty_text);
540
 
  str->append(quote_str, quote_len); /* Trailing quote */
541
 
}
542
 
 
543
 
 
544
 
/*
545
563
  Run query and dump the result to stdout in vertical format
546
564
 
547
565
  NOTE! This function should be safe to call when an error
549
567
 
550
568
  SYNOPSIS
551
569
  show_query
552
 
  drizzle - connection to use
 
570
  mysql - connection to use
553
571
  query - query to run
554
572
 
555
573
*/
556
574
 
557
 
static void show_query(DRIZZLE *drizzle, const char* query)
 
575
static void show_query(MYSQL* mysql, const char* query)
558
576
{
559
 
  DRIZZLE_RES* res;
560
 
 
561
 
 
562
 
  if (!drizzle)
 
577
  MYSQL_RES* res;
 
578
 
 
579
 
 
580
  if (!mysql)
563
581
    return;
564
582
 
565
 
  if (drizzle_query(drizzle, query))
 
583
  if (mysql_query(mysql, query))
566
584
  {
567
585
    log_msg("Error running query '%s': %d %s",
568
 
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
 
586
            query, mysql_errno(mysql), mysql_error(mysql));
569
587
    return;
570
588
  }
571
589
 
572
 
  if ((res= drizzle_store_result(drizzle)) == NULL)
 
590
  if ((res= mysql_store_result(mysql)) == NULL)
573
591
  {
574
592
    /* No result set returned */
575
593
    return;
576
594
  }
577
595
 
578
596
  {
579
 
    DRIZZLE_ROW row;
 
597
    MYSQL_ROW row;
580
598
    unsigned int i;
581
599
    unsigned int row_num= 0;
582
 
    unsigned int num_fields= drizzle_num_fields(res);
583
 
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
600
    unsigned int num_fields= mysql_num_fields(res);
 
601
    MYSQL_FIELD *fields= mysql_fetch_fields(res);
584
602
 
585
603
    fprintf(stderr, "=== %s ===\n", query);
586
 
    while ((row= drizzle_fetch_row(res)))
 
604
    while ((row= mysql_fetch_row(res)))
587
605
    {
588
 
      uint32_t *lengths= drizzle_fetch_lengths(res);
 
606
      uint32_t *lengths= mysql_fetch_lengths(res);
589
607
      row_num++;
590
608
 
591
609
      fprintf(stderr, "---- %d. ----\n", row_num);
600
618
      fprintf(stderr, "=");
601
619
    fprintf(stderr, "\n\n");
602
620
  }
603
 
  drizzle_free_result(res);
 
621
  mysql_free_result(res);
604
622
 
605
623
  return;
606
624
}
615
633
 
616
634
  SYNOPSIS
617
635
  show_warnings_before_error
618
 
  drizzle - connection to use
 
636
  mysql - connection to use
619
637
 
620
638
*/
621
639
 
622
 
static void show_warnings_before_error(DRIZZLE *drizzle)
 
640
static void show_warnings_before_error(MYSQL* mysql)
623
641
{
624
 
  DRIZZLE_RES* res;
 
642
  MYSQL_RES* res;
625
643
  const char* query= "SHOW WARNINGS";
626
644
 
627
645
 
628
 
  if (!drizzle)
 
646
  if (!mysql)
629
647
    return;
630
648
 
631
 
  if (drizzle_query(drizzle, query))
 
649
  if (mysql_query(mysql, query))
632
650
  {
633
651
    log_msg("Error running query '%s': %d %s",
634
 
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
 
652
            query, mysql_errno(mysql), mysql_error(mysql));
635
653
    return;
636
654
  }
637
655
 
638
 
  if ((res= drizzle_store_result(drizzle)) == NULL)
 
656
  if ((res= mysql_store_result(mysql)) == NULL)
639
657
  {
640
658
    /* No result set returned */
641
659
    return;
642
660
  }
643
661
 
644
 
  if (drizzle_num_rows(res) <= 1)
 
662
  if (mysql_num_rows(res) <= 1)
645
663
  {
646
664
    /* Don't display the last row, it's "last error" */
647
665
  }
648
666
  else
649
667
  {
650
 
    DRIZZLE_ROW row;
 
668
    MYSQL_ROW row;
651
669
    unsigned int row_num= 0;
652
 
    unsigned int num_fields= drizzle_num_fields(res);
 
670
    unsigned int num_fields= mysql_num_fields(res);
653
671
 
654
672
    fprintf(stderr, "\nWarnings from just before the error:\n");
655
 
    while ((row= drizzle_fetch_row(res)))
 
673
    while ((row= mysql_fetch_row(res)))
656
674
    {
657
675
      uint32_t i;
658
 
      uint32_t *lengths= drizzle_fetch_lengths(res);
 
676
      uint32_t *lengths= mysql_fetch_lengths(res);
659
677
 
660
 
      if (++row_num >= drizzle_num_rows(res))
 
678
      if (++row_num >= mysql_num_rows(res))
661
679
      {
662
680
        /* Don't display the last row, it's "last error" */
663
681
        break;
671
689
      fprintf(stderr, "\n");
672
690
    }
673
691
  }
674
 
  drizzle_free_result(res);
 
692
  mysql_free_result(res);
675
693
 
676
694
  return;
677
695
}
687
705
  const char *argname;       /* Name of argument   */
688
706
  enum arg_type type;        /* Type of argument   */
689
707
  bool required;          /* Argument required  */
690
 
  string *ds;        /* Storage for argument */
 
708
  DYNAMIC_STRING *ds;        /* Storage for argument */
691
709
  const char *description;   /* Description of the argument */
692
710
};
693
711
 
717
735
        ptr++;
718
736
      if (ptr > start)
719
737
      {
 
738
        init_dynamic_string(arg->ds, 0, ptr-start, 32);
720
739
        do_eval(arg->ds, start, ptr, false);
721
740
      }
722
741
      else
723
742
      {
724
743
        /* Empty string */
725
 
        arg->ds->erase();
 
744
        init_dynamic_string(arg->ds, "", 0, 0);
726
745
      }
727
746
      command->last_argument= (char*)ptr;
728
747
 
734
753
      /* Rest of line */
735
754
    case ARG_REST:
736
755
      start= ptr;
 
756
      init_dynamic_string(arg->ds, 0, command->query_len, 256);
737
757
      do_eval(arg->ds, start, command->end, false);
738
758
      command->last_argument= command->end;
739
759
      break;
744
764
    }
745
765
 
746
766
    /* Check required arg */
747
 
    if (arg->ds->length() == 0 && arg->required)
 
767
    if (arg->ds->length == 0 && arg->required)
748
768
      die("Missing required argument '%s' to command '%.*s'", arg->argname,
749
769
          command->first_word_len, command->query);
750
770
 
800
820
 
801
821
  for (--next_con; next_con >= connections; --next_con)
802
822
  {
803
 
    drizzle_close(&next_con->drizzle);
804
 
    if (next_con->util_drizzle)
805
 
      drizzle_close(next_con->util_drizzle);
806
 
    free(next_con->name);
 
823
    mysql_close(&next_con->mysql);
 
824
    if (next_con->util_mysql)
 
825
      mysql_close(next_con->util_mysql);
 
826
    my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
807
827
  }
808
828
  return;
809
829
}
818
838
    {
819
839
      my_fclose(cur_file->file, MYF(0));
820
840
    }
821
 
    free((unsigned char*) cur_file->file_name);
 
841
    my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
822
842
    cur_file->file_name= 0;
823
843
  }
824
844
  return;
834
854
  close_files();
835
855
  hash_free(&var_hash);
836
856
 
837
 
  vector<struct st_command *>::iterator iter;
838
 
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
 
857
  for (i= 0 ; i < q_lines.elements ; i++)
839
858
  {
840
 
    struct st_command * q_line= *(iter.base());
841
 
    if (q_line->query_buf != NULL)
842
 
    {
843
 
      free(q_line->query_buf);
844
 
    }
845
 
    free(q_line);
 
859
    struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
 
860
    my_free((*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
 
861
    my_free((*q),MYF(0));
846
862
  }
847
 
 
848
863
  for (i= 0; i < 10; i++)
849
864
  {
850
865
    if (var_reg[i].alloced_len)
851
 
      free(var_reg[i].str_val);
 
866
      my_free(var_reg[i].str_val, MYF(MY_WME));
852
867
  }
853
868
  while (embedded_server_arg_count > 1)
854
 
    free(embedded_server_args[--embedded_server_arg_count]);
855
 
 
 
869
    my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
 
870
  delete_dynamic(&q_lines);
 
871
  dynstr_free(&ds_res);
 
872
  dynstr_free(&ds_progress);
 
873
  dynstr_free(&ds_warning_messages);
856
874
  free_all_replace();
857
 
  free(opt_pass);
 
875
  my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
858
876
  free_defaults(default_argv);
859
877
 
 
878
  /* Only call mysql_server_end if mysql_server_init has been called */
 
879
  if (server_initialized)
 
880
    mysql_server_end();
 
881
 
860
882
  return;
861
883
}
862
884
 
876
898
      break;
877
899
    case 62:
878
900
      printf("skipped\n");
879
 
      break;
 
901
    break;
880
902
    default:
881
903
      printf("unknown exit code: %d\n", exit_code);
882
904
      assert(0);
901
923
  dying= 1;
902
924
 
903
925
  /* Print the error message */
904
 
  fprintf(stderr, "drizzletest: ");
 
926
  fprintf(stderr, "mysqltest: ");
905
927
  if (cur_file && cur_file != file_stack)
906
928
    fprintf(stderr, "In included file \"%s\": ",
907
929
            cur_file->file_name);
919
941
  fflush(stderr);
920
942
 
921
943
  /* Show results from queries just before failure */
922
 
  if (ds_res.length() && opt_tail_lines)
 
944
  if (ds_res.length && opt_tail_lines)
923
945
  {
924
946
    int tail_lines= opt_tail_lines;
925
 
    const char* show_from= ds_res.c_str() + ds_res.length() - 1;
926
 
    while(show_from > ds_res.c_str() && tail_lines > 0 )
 
947
    char* show_from= ds_res.str + ds_res.length - 1;
 
948
    while(show_from > ds_res.str && tail_lines > 0 )
927
949
    {
928
950
      show_from--;
929
951
      if (*show_from == '\n')
930
952
        tail_lines--;
931
953
    }
932
954
    fprintf(stderr, "\nThe result from queries just before the failure was:\n");
933
 
    if (show_from > ds_res.c_str())
 
955
    if (show_from > ds_res.str)
934
956
      fprintf(stderr, "< snip >");
935
957
    fprintf(stderr, "%s", show_from);
936
958
    fflush(stderr);
937
959
  }
938
960
 
939
961
  /* Dump the result that has been accumulated so far to .log file */
940
 
  if (result_file_name && ds_res.length())
941
 
    dump_result_to_log_file(ds_res.c_str(), ds_res.length());
 
962
  if (result_file_name && ds_res.length)
 
963
    dump_result_to_log_file(ds_res.str, ds_res.length);
942
964
 
943
965
  /* Dump warning messages */
944
 
  if (result_file_name && ds_warning_messages.length())
 
966
  if (result_file_name && ds_warning_messages.length)
945
967
    dump_warning_messages();
946
968
 
947
969
  /*
949
971
    been produced prior to the error
950
972
  */
951
973
  if (cur_con)
952
 
    show_warnings_before_error(&cur_con->drizzle);
 
974
    show_warnings_before_error(&cur_con->mysql);
953
975
 
954
976
  cleanup_and_exit(1);
955
977
}
996
1018
    return;
997
1019
 
998
1020
  va_start(args, fmt);
999
 
  fprintf(stderr, "drizzletest: ");
 
1021
  fprintf(stderr, "mysqltest: ");
1000
1022
  if (cur_file && cur_file != file_stack)
1001
1023
    fprintf(stderr, "In included file \"%s\": ",
1002
1024
            cur_file->file_name);
1018
1040
 
1019
1041
 
1020
1042
  va_start(args, fmt);
1021
 
  ds_warning_messages.append("drizzletest: ");
 
1043
  dynstr_append(&ds_warning_messages, "mysqltest: ");
1022
1044
  if (start_lineno != 0)
1023
1045
  {
1024
 
    ds_warning_messages.append("Warning detected ");
 
1046
    dynstr_append(&ds_warning_messages, "Warning detected ");
1025
1047
    if (cur_file && cur_file != file_stack)
1026
1048
    {
1027
1049
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1028
 
                    cur_file->file_name);
1029
 
      ds_warning_messages.append(buff, len);
 
1050
                       cur_file->file_name);
 
1051
      dynstr_append_mem(&ds_warning_messages,
 
1052
                        buff, len);
1030
1053
    }
1031
1054
    len= snprintf(buff, sizeof(buff), "at line %d: ",
1032
 
                  start_lineno);
1033
 
    ds_warning_messages.append(buff, len);
 
1055
                     start_lineno);
 
1056
    dynstr_append_mem(&ds_warning_messages,
 
1057
                      buff, len);
1034
1058
  }
1035
1059
 
1036
1060
  len= vsnprintf(buff, sizeof(buff), fmt, args);
1037
 
  ds_warning_messages.append(buff, len);
 
1061
  dynstr_append_mem(&ds_warning_messages, buff, len);
1038
1062
 
1039
 
  ds_warning_messages.append("\n");
 
1063
  dynstr_append(&ds_warning_messages, "\n");
1040
1064
  va_end(args);
1041
1065
 
1042
1066
  return;
1054
1078
  len= vsnprintf(buff, sizeof(buff)-1, fmt, args);
1055
1079
  va_end(args);
1056
1080
 
1057
 
  ds_res.append(buff, len);
1058
 
  ds_res.append("\n");
 
1081
  dynstr_append_mem(&ds_res, buff, len);
 
1082
  dynstr_append(&ds_res, "\n");
1059
1083
 
1060
1084
  return;
1061
1085
}
1071
1095
 
1072
1096
*/
1073
1097
 
1074
 
static void cat_file(string* ds, const char* filename)
 
1098
static void cat_file(DYNAMIC_STRING* ds, const char* filename)
1075
1099
{
1076
1100
  int fd;
1077
1101
  uint len;
1079
1103
 
1080
1104
  if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
1081
1105
    die("Failed to open file '%s'", filename);
1082
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1106
  while((len= my_read(fd, (uchar*)&buff,
1083
1107
                      sizeof(buff), MYF(0))) > 0)
1084
1108
  {
1085
1109
    char *p= buff, *start= buff;
1091
1115
        /* Add fake newline instead of cr and output the line */
1092
1116
        *p= '\n';
1093
1117
        p++; /* Step past the "fake" newline */
1094
 
        ds->append(start, p-start);
 
1118
        dynstr_append_mem(ds, start, p-start);
1095
1119
        p++; /* Step past the "fake" newline */
1096
1120
        start= p;
1097
1121
      }
1098
1122
      else
1099
1123
        p++;
1100
1124
    }
1101
 
    /* Output any chars that might be left */
1102
 
    ds->append(start, p-start);
 
1125
    /* Output any chars that migh be left */
 
1126
    dynstr_append_mem(ds, start, p-start);
1103
1127
  }
1104
1128
  my_close(fd, MYF(0));
1105
1129
}
1111
1135
  SYNOPSIS
1112
1136
  run_command
1113
1137
  cmd - command to execute(should be properly quoted
1114
 
  result - pointer to string where to store the result
 
1138
  ds_res- pointer to dynamic string where to store the result
1115
1139
 
1116
1140
*/
1117
1141
 
1118
 
static int run_command(const char * cmd, string * result)
 
1142
static int run_command(char* cmd,
 
1143
                       DYNAMIC_STRING *ds_res)
1119
1144
{
1120
 
  assert(result!=NULL);
1121
1145
  char buf[512]= {0};
1122
1146
  FILE *res_file;
1123
1147
  int error;
1127
1151
 
1128
1152
  while (fgets(buf, sizeof(buf), res_file))
1129
1153
  {
1130
 
    /* Save the output of this command in the supplied string */
1131
 
    result->append(buf);
 
1154
    if(ds_res)
 
1155
    {
 
1156
      /* Save the output of this command in the supplied string */
 
1157
      dynstr_append(ds_res, buf);
 
1158
    }
 
1159
    else
 
1160
    {
 
1161
      /* Print it directly on screen */
 
1162
      fprintf(stdout, "%s", buf);
 
1163
    }
1132
1164
  }
1133
1165
 
1134
1166
  error= pclose(res_file);
1142
1174
  SYNOPSIS
1143
1175
  run_tool
1144
1176
  tool_path - the name of the tool to run
1145
 
  result - pointer to dynamic string where to store the result
 
1177
  ds_res - pointer to dynamic string where to store the result
1146
1178
  ... - variable number of arguments that will be properly
1147
 
  quoted and appended after the tool's name
 
1179
        quoted and appended after the tool's name
1148
1180
 
1149
1181
*/
1150
1182
 
1151
 
static int run_tool(const char *tool_path, string * result, ...)
 
1183
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1152
1184
{
1153
1185
  int ret;
1154
1186
  const char* arg;
1155
1187
  va_list args;
1156
 
  string ds_cmdline;
1157
 
 
1158
 
 
1159
 
  append_os_quoted(&ds_cmdline, tool_path);
1160
 
  ds_cmdline.append(" ");
1161
 
 
1162
 
  va_start(args, result);
 
1188
  DYNAMIC_STRING ds_cmdline;
 
1189
 
 
1190
  if (init_dynamic_string(&ds_cmdline, "", FN_REFLEN, FN_REFLEN))
 
1191
    die("Out of memory");
 
1192
 
 
1193
  dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
 
1194
  dynstr_append(&ds_cmdline, " ");
 
1195
 
 
1196
  va_start(args, ds_res);
1163
1197
 
1164
1198
  while ((arg= va_arg(args, char *)))
1165
1199
  {
1166
1200
    /* Options should be os quoted */
1167
1201
    if (strncmp(arg, "--", 2) == 0)
1168
 
      append_os_quoted(&ds_cmdline, arg, NULL);
 
1202
      dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1169
1203
    else
1170
 
      ds_cmdline.append(arg);
1171
 
    ds_cmdline.append(" ");
 
1204
      dynstr_append(&ds_cmdline, arg);
 
1205
    dynstr_append(&ds_cmdline, " ");
1172
1206
  }
1173
1207
 
1174
1208
  va_end(args);
1175
1209
 
1176
 
  ret= run_command(ds_cmdline.c_str(), result);
 
1210
  ret= run_command(ds_cmdline.str, ds_res);
 
1211
  dynstr_free(&ds_cmdline);
1177
1212
  return(ret);
1178
1213
}
1179
1214
 
1191
1226
 
1192
1227
*/
1193
1228
 
1194
 
static void show_diff(string* ds,
 
1229
static void show_diff(DYNAMIC_STRING* ds,
1195
1230
                      const char* filename1, const char* filename2)
1196
1231
{
1197
1232
 
1198
 
  string ds_tmp;
 
1233
  DYNAMIC_STRING ds_tmp;
 
1234
 
 
1235
  if (init_dynamic_string(&ds_tmp, "", 256, 256))
 
1236
    die("Out of memory");
1199
1237
 
1200
1238
  /* First try with unified diff */
1201
1239
  if (run_tool("diff",
1206
1244
               "2>&1",
1207
1245
               NULL) > 1) /* Most "diff" tools return >1 if error */
1208
1246
  {
1209
 
    ds_tmp= "";
 
1247
    dynstr_set(&ds_tmp, "");
1210
1248
 
1211
1249
    /* Fallback to context diff with "diff -c" */
1212
1250
    if (run_tool("diff",
1221
1259
        Fallback to dump both files to result file and inform
1222
1260
        about installing "diff"
1223
1261
      */
1224
 
      ds_tmp= "";
1225
 
 
1226
 
      ds_tmp.append(
1227
 
                    "\n"
1228
 
                    "The two files differ but it was not possible to execute 'diff' in\n"
1229
 
                    "order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1230
 
                    "Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
1231
 
                    "To get a better report you should install 'diff' on your system, which you\n"
1232
 
                    "for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1233
 
                    "\n");
1234
 
 
1235
 
      ds_tmp.append(" --- ");
1236
 
      ds_tmp.append(filename1);
1237
 
      ds_tmp.append(" >>>\n");
 
1262
      dynstr_set(&ds_tmp, "");
 
1263
 
 
1264
      dynstr_append(&ds_tmp,
 
1265
"\n"
 
1266
"The two files differ but it was not possible to execute 'diff' in\n"
 
1267
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
 
1268
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
 
1269
"To get a better report you should install 'diff' on your system, which you\n"
 
1270
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
 
1271
"\n");
 
1272
 
 
1273
      dynstr_append(&ds_tmp, " --- ");
 
1274
      dynstr_append(&ds_tmp, filename1);
 
1275
      dynstr_append(&ds_tmp, " >>>\n");
1238
1276
      cat_file(&ds_tmp, filename1);
1239
 
      ds_tmp.append("<<<\n --- ");
1240
 
      ds_tmp.append(filename1);
1241
 
      ds_tmp.append(" >>>\n");
 
1277
      dynstr_append(&ds_tmp, "<<<\n --- ");
 
1278
      dynstr_append(&ds_tmp, filename1);
 
1279
      dynstr_append(&ds_tmp, " >>>\n");
1242
1280
      cat_file(&ds_tmp, filename2);
1243
 
      ds_tmp.append("<<<<\n");
 
1281
      dynstr_append(&ds_tmp, "<<<<\n");
1244
1282
    }
1245
1283
  }
1246
1284
 
1247
1285
  if (ds)
1248
1286
  {
1249
1287
    /* Add the diff to output */
1250
 
    ds->append(ds_tmp.c_str(), ds_tmp.length());
 
1288
    dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1251
1289
  }
1252
1290
  else
1253
1291
  {
1254
1292
    /* Print diff directly to stdout */
1255
 
    fprintf(stderr, "%s\n", ds_tmp.c_str());
 
1293
    fprintf(stderr, "%s\n", ds_tmp.str);
1256
1294
  }
 
1295
 
 
1296
  dynstr_free(&ds_tmp);
1257
1297
 
1258
1298
}
1259
1299
 
1260
1300
 
1261
1301
enum compare_files_result_enum {
1262
 
  RESULT_OK= 0,
1263
 
  RESULT_CONTENT_MISMATCH= 1,
1264
 
  RESULT_LENGTH_MISMATCH= 2
 
1302
   RESULT_OK= 0,
 
1303
   RESULT_CONTENT_MISMATCH= 1,
 
1304
   RESULT_LENGTH_MISMATCH= 2
1265
1305
};
1266
1306
 
1267
1307
/*
1290
1330
    my_close(fd, MYF(0));
1291
1331
    die("Failed to open second file: '%s'", filename2);
1292
1332
  }
1293
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1333
  while((len= my_read(fd, (uchar*)&buff,
1294
1334
                      sizeof(buff), MYF(0))) > 0)
1295
1335
  {
1296
 
    if ((len2= my_read(fd2, (unsigned char*)&buff2,
 
1336
    if ((len2= my_read(fd2, (uchar*)&buff2,
1297
1337
                       sizeof(buff2), MYF(0))) < len)
1298
1338
    {
1299
1339
      /* File 2 was smaller */
1313
1353
      break;
1314
1354
    }
1315
1355
  }
1316
 
  if (!error && my_read(fd2, (unsigned char*)&buff2,
 
1356
  if (!error && my_read(fd2, (uchar*)&buff2,
1317
1357
                        sizeof(buff2), MYF(0)) > 0)
1318
1358
  {
1319
1359
    /* File 1 was smaller */
1359
1399
  Compare content of the string in ds to content of file fname
1360
1400
 
1361
1401
  SYNOPSIS
1362
 
  string_cmp
 
1402
  dyn_string_cmp
1363
1403
  ds - Dynamic string containing the string o be compared
1364
1404
  fname - Name of file to compare with
1365
1405
 
1367
1407
  See 'compare_files2'
1368
1408
*/
1369
1409
 
1370
 
static int string_cmp(string* ds, const char *fname)
 
1410
static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
1371
1411
{
1372
1412
  int error;
1373
1413
  File fd;
1379
1419
    die("Failed to create temporary file for ds");
1380
1420
 
1381
1421
  /* Write ds to temporary file and set file pos to beginning*/
1382
 
  if (my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
 
1422
  if (my_write(fd, (uchar *) ds->str, ds->length,
1383
1423
               MYF(MY_FNABP | MY_WME)) ||
1384
1424
      my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1385
1425
  {
1411
1451
 
1412
1452
*/
1413
1453
 
1414
 
static void check_result(string* ds)
 
1454
static void check_result(DYNAMIC_STRING* ds)
1415
1455
{
1416
1456
  const char* mess= "Result content mismatch\n";
1417
1457
 
1421
1461
  if (access(result_file_name, F_OK) != 0)
1422
1462
    die("The specified result file does not exist: '%s'", result_file_name);
1423
1463
 
1424
 
  switch (string_cmp(ds, result_file_name)) {
 
1464
  switch (dyn_string_cmp(ds, result_file_name)) {
1425
1465
  case RESULT_OK:
1426
1466
    break; /* ok */
1427
1467
  case RESULT_LENGTH_MISMATCH:
1449
1489
      fn_format(reject_file, result_file_name, opt_logdir,
1450
1490
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1451
1491
    }
1452
 
    str_to_file(reject_file, ds->c_str(), ds->length());
 
1492
    str_to_file(reject_file, ds->str, ds->length);
1453
1493
 
1454
 
    ds->erase(); /* Don't create a .log file */
 
1494
    dynstr_set(ds, NULL); /* Don't create a .log file */
1455
1495
 
1456
1496
    show_diff(NULL, result_file_name, reject_file);
1457
1497
    die(mess);
1480
1520
 
1481
1521
*/
1482
1522
 
1483
 
static void check_require(string* ds, const char *fname)
 
1523
static void check_require(DYNAMIC_STRING* ds, const char *fname)
1484
1524
{
1485
1525
 
1486
1526
 
1487
 
  if (string_cmp(ds, fname))
 
1527
  if (dyn_string_cmp(ds, fname))
1488
1528
  {
1489
1529
    char reason[FN_REFLEN];
1490
1530
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1495
1535
 
1496
1536
 
1497
1537
/*
1498
 
  Remove surrounding chars from string
 
1538
   Remove surrounding chars from string
1499
1539
 
1500
 
  Return 1 if first character is found but not last
 
1540
   Return 1 if first character is found but not last
1501
1541
*/
1502
1542
static int strip_surrounding(char* str, char c1, char c2)
1503
1543
{
1512
1552
    *ptr= ' ';
1513
1553
 
1514
1554
    /* Last non space charecter should be c2 */
1515
 
    ptr= strchr(str, '\0')-1;
 
1555
    ptr= strend(str)-1;
1516
1556
    while(*ptr && my_isspace(charset_info, *ptr))
1517
1557
      ptr--;
1518
1558
    if (*ptr == c2)
1533
1573
static void strip_parentheses(struct st_command *command)
1534
1574
{
1535
1575
  if (strip_surrounding(command->first_argument, '(', ')'))
1536
 
    die("%.*s - argument list started with '%c' must be ended with '%c'",
1537
 
        command->first_word_len, command->query, '(', ')');
 
1576
      die("%.*s - argument list started with '%c' must be ended with '%c'",
 
1577
          command->first_word_len, command->query, '(', ')');
1538
1578
}
1539
1579
 
1540
1580
 
1541
 
static unsigned char *get_var_key(const unsigned char* var, size_t *len,
 
1581
static uchar *get_var_key(const uchar* var, size_t *len,
1542
1582
                          bool __attribute__((unused)) t)
1543
1583
{
1544
1584
  register char* key;
1545
1585
  key = ((VAR*)var)->name;
1546
1586
  *len = ((VAR*)var)->name_len;
1547
 
  return (unsigned char*)key;
 
1587
  return (uchar*)key;
1548
1588
}
1549
1589
 
1550
1590
 
1586
1626
 
1587
1627
void var_free(void *v)
1588
1628
{
1589
 
  free(((VAR*) v)->str_val);
1590
 
  free(((VAR*) v)->env_s);
 
1629
  my_free(((VAR*) v)->str_val, MYF(MY_WME));
 
1630
  my_free(((VAR*) v)->env_s, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
1591
1631
  if (((VAR*)v)->alloced)
1592
 
    free(v);
 
1632
    my_free(v, MYF(MY_WME));
1593
1633
}
1594
1634
 
1595
1635
 
1601
1641
    tmp = def_val;
1602
1642
 
1603
1643
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1604
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1644
  my_hash_insert(&var_hash, (uchar*)v);
1605
1645
  return v;
1606
1646
}
1607
1647
 
1608
1648
 
1609
1649
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1610
 
             bool ignore_not_existing)
 
1650
             bool ignore_not_existing)
1611
1651
{
1612
1652
  int digit;
1613
1653
  VAR *v;
1625
1665
    if (var_name == save_var_name)
1626
1666
    {
1627
1667
      if (ignore_not_existing)
1628
 
        return(0);
 
1668
        return(0);
1629
1669
      die("Empty variable");
1630
1670
    }
1631
1671
    length= (uint) (var_name - save_var_name);
1632
1672
    if (length >= MAX_VAR_NAME_LENGTH)
1633
1673
      die("Too long variable name: %s", save_var_name);
1634
1674
 
1635
 
    if (!(v = (VAR*) hash_search(&var_hash, (const unsigned char*) save_var_name,
1636
 
                                 length)))
 
1675
    if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
 
1676
                                            length)))
1637
1677
    {
1638
1678
      char buff[MAX_VAR_NAME_LENGTH+1];
1639
1679
      strmake(buff, save_var_name, length);
1640
1680
      v= var_from_env(buff, "");
1641
1681
    }
1642
 
    var_name--;  /* Point at last character */
 
1682
    var_name--; /* Point at last character */
1643
1683
  }
1644
1684
  else
1645
1685
    v = var_reg + digit;
1664
1704
static VAR *var_obtain(const char *name, int len)
1665
1705
{
1666
1706
  VAR* v;
1667
 
  if ((v = (VAR*)hash_search(&var_hash, (const unsigned char *) name, len)))
 
1707
  if ((v = (VAR*)hash_search(&var_hash, (const uchar *) name, len)))
1668
1708
    return v;
1669
1709
  v = var_init(0, name, len, "", 0);
1670
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1710
  my_hash_insert(&var_hash, (uchar*)v);
1671
1711
  return v;
1672
1712
}
1673
1713
 
1709
1749
      v->str_val_len= strlen(v->str_val);
1710
1750
    }
1711
1751
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
1712
 
             v->name_len, v->name,
1713
 
             v->str_val_len, v->str_val);
 
1752
                v->name_len, v->name,
 
1753
                v->str_val_len, v->str_val);
1714
1754
    if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
1715
1755
      die("Out of memory");
1716
1756
    putenv(v->env_s);
1717
 
    free(old_env_s);
 
1757
    my_free(old_env_s, MYF(MY_ALLOW_ZERO_PTR));
1718
1758
  }
1719
1759
  return;
1720
1760
}
1736
1776
 
1737
1777
/*
1738
1778
  Store an integer (typically the returncode of the last SQL)
1739
 
  statement in the drizzletest builtin variable $drizzle_errno
 
1779
  statement in the mysqltest builtin variable $mysql_errno
1740
1780
*/
1741
1781
 
1742
1782
static void var_set_errno(int sql_errno)
1743
1783
{
1744
 
  var_set_int("$drizzle_errno", sql_errno);
 
1784
  var_set_int("$mysql_errno", sql_errno);
1745
1785
}
1746
1786
 
1747
1787
 
1748
1788
/*
1749
 
  Update $drizzle_get_server_version variable with version
 
1789
  Update $mysql_get_server_version variable with version
1750
1790
  of the currently connected server
1751
1791
*/
1752
1792
 
1753
 
static void var_set_drizzle_get_server_version(DRIZZLE *drizzle)
 
1793
static void var_set_mysql_get_server_version(MYSQL* mysql)
1754
1794
{
1755
 
  var_set_int("$drizzle_get_server_version", drizzle_get_server_version(drizzle));
 
1795
  var_set_int("$mysql_get_server_version", mysql_get_server_version(mysql));
1756
1796
}
1757
1797
 
1758
1798
 
1761
1801
 
1762
1802
  SYNOPSIS
1763
1803
  var_query_set()
1764
 
  var          variable to set from query
 
1804
  var           variable to set from query
1765
1805
  query       start of query string to execute
1766
1806
  query_end   end of the query string to execute
1767
1807
 
1781
1821
 
1782
1822
static void var_query_set(VAR *var, const char *query, const char** query_end)
1783
1823
{
1784
 
  const char *end = (char*)((query_end && *query_end) ?
1785
 
                            *query_end : query + strlen(query));
1786
 
  DRIZZLE_RES *res;
1787
 
  DRIZZLE_ROW row;
1788
 
  DRIZZLE *drizzle= &cur_con->drizzle;
1789
 
  string ds_query;
 
1824
  char *end = (char*)((query_end && *query_end) ?
 
1825
                      *query_end : query + strlen(query));
 
1826
  MYSQL_RES *res;
 
1827
  MYSQL_ROW row;
 
1828
  MYSQL* mysql = &cur_con->mysql;
 
1829
  DYNAMIC_STRING ds_query;
1790
1830
 
1791
1831
 
1792
1832
  while (end > query && *end != '`')
1796
1836
  ++query;
1797
1837
 
1798
1838
  /* Eval the query, thus replacing all environment variables */
 
1839
  init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
1799
1840
  do_eval(&ds_query, query, end, false);
1800
1841
 
1801
 
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1802
 
    die("Error running query '%s': %d %s", ds_query.c_str(),
1803
 
        drizzle_errno(drizzle), drizzle_error(drizzle));
1804
 
  if (!(res= drizzle_store_result(drizzle)))
1805
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
 
1842
  if (mysql_real_query(mysql, ds_query.str, ds_query.length))
 
1843
    die("Error running query '%s': %d %s", ds_query.str,
 
1844
        mysql_errno(mysql), mysql_error(mysql));
 
1845
  if (!(res= mysql_store_result(mysql)))
 
1846
    die("Query '%s' didn't return a result set", ds_query.str);
 
1847
  dynstr_free(&ds_query);
1806
1848
 
1807
 
  if ((row= drizzle_fetch_row(res)) && row[0])
 
1849
  if ((row= mysql_fetch_row(res)) && row[0])
1808
1850
  {
1809
1851
    /*
1810
1852
      Concatenate all fields in the first row with tab in between
1811
1853
      and assign that string to the $variable
1812
1854
    */
1813
 
    string result;
 
1855
    DYNAMIC_STRING result;
1814
1856
    uint32_t i;
1815
1857
    uint32_t *lengths;
1816
1858
 
1817
 
    lengths= drizzle_fetch_lengths(res);
1818
 
    for (i= 0; i < drizzle_num_fields(res); i++)
 
1859
    init_dynamic_string(&result, "", 512, 512);
 
1860
    lengths= mysql_fetch_lengths(res);
 
1861
    for (i= 0; i < mysql_num_fields(res); i++)
1819
1862
    {
1820
1863
      if (row[i])
1821
1864
      {
1822
1865
        /* Add column to tab separated string */
1823
 
        result.append(row[i], lengths[i]);
 
1866
        dynstr_append_mem(&result, row[i], lengths[i]);
1824
1867
      }
1825
 
      result.append("\t", 1);
 
1868
      dynstr_append_mem(&result, "\t", 1);
1826
1869
    }
1827
 
    end= result.c_str() + result.length()-1;
1828
 
    eval_expr(var, result.c_str(), (const char**) &end);
 
1870
    end= result.str + result.length-1;
 
1871
    eval_expr(var, result.str, (const char**) &end);
 
1872
    dynstr_free(&result);
1829
1873
  }
1830
1874
  else
1831
1875
    eval_expr(var, "", 0);
1832
1876
 
1833
 
  drizzle_free_result(res);
 
1877
  mysql_free_result(res);
1834
1878
  return;
1835
1879
}
1836
1880
 
1851
1895
 
1852
1896
  <query to run> -    The query that should be sent to the server
1853
1897
  <column name> -     Name of the column that holds the field be compared
1854
 
  against the expected value
 
1898
                      against the expected value
1855
1899
  <row no> -          Number of the row that holds the field to be
1856
 
  compared against the expected value
 
1900
                      compared against the expected value
1857
1901
 
1858
1902
*/
1859
1903
 
1861
1905
{
1862
1906
  long row_no;
1863
1907
  int col_no= -1;
1864
 
  DRIZZLE_RES* res;
1865
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
1908
  MYSQL_RES* res;
 
1909
  MYSQL* mysql= &cur_con->mysql;
1866
1910
 
1867
 
  string ds_query;
1868
 
  string ds_col;
1869
 
  string ds_row;
 
1911
  static DYNAMIC_STRING ds_query;
 
1912
  static DYNAMIC_STRING ds_col;
 
1913
  static DYNAMIC_STRING ds_row;
1870
1914
  const struct command_arg query_get_value_args[] = {
1871
1915
    {"query", ARG_STRING, true, &ds_query, "Query to run"},
1872
1916
    {"column name", ARG_STRING, true, &ds_col, "Name of column"},
1881
1925
                     ',');
1882
1926
 
1883
1927
  /* Convert row number to int */
1884
 
  if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1885
 
    die("Invalid row number: '%s'", ds_row.c_str());
 
1928
  if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
 
1929
    die("Invalid row number: '%s'", ds_row.str);
 
1930
  dynstr_free(&ds_row);
1886
1931
 
1887
1932
  /* Remove any surrounding "'s from the query - if there is any */
1888
 
  // (Don't get me started on this)
1889
 
  char * unstripped_query= strdup(ds_query.c_str());
1890
 
  if (strip_surrounding(unstripped_query, '"', '"'))
1891
 
    die("Mismatched \"'s around query '%s'", ds_query.c_str());
1892
 
  ds_query= unstripped_query;
 
1933
  if (strip_surrounding(ds_query.str, '"', '"'))
 
1934
    die("Mismatched \"'s around query '%s'", ds_query.str);
1893
1935
 
1894
1936
  /* Run the query */
1895
 
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1896
 
    die("Error running query '%s': %d %s", ds_query.c_str(),
1897
 
        drizzle_errno(drizzle), drizzle_error(drizzle));
1898
 
  if (!(res= drizzle_store_result(drizzle)))
1899
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
 
1937
  if (mysql_real_query(mysql, ds_query.str, ds_query.length))
 
1938
    die("Error running query '%s': %d %s", ds_query.str,
 
1939
        mysql_errno(mysql), mysql_error(mysql));
 
1940
  if (!(res= mysql_store_result(mysql)))
 
1941
    die("Query '%s' didn't return a result set", ds_query.str);
1900
1942
 
1901
1943
  {
1902
1944
    /* Find column number from the given column name */
1903
1945
    uint i;
1904
 
    uint num_fields= drizzle_num_fields(res);
1905
 
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
1946
    uint num_fields= mysql_num_fields(res);
 
1947
    MYSQL_FIELD *fields= mysql_fetch_fields(res);
1906
1948
 
1907
1949
    for (i= 0; i < num_fields; i++)
1908
1950
    {
1909
 
      if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
1910
 
          strlen(fields[i].name) == ds_col.length())
 
1951
      if (strcmp(fields[i].name, ds_col.str) == 0 &&
 
1952
          strlen(fields[i].name) == ds_col.length)
1911
1953
      {
1912
1954
        col_no= i;
1913
1955
        break;
1915
1957
    }
1916
1958
    if (col_no == -1)
1917
1959
    {
1918
 
      drizzle_free_result(res);
 
1960
      mysql_free_result(res);
1919
1961
      die("Could not find column '%s' in the result of '%s'",
1920
 
          ds_col.c_str(), ds_query.c_str());
 
1962
          ds_col.str, ds_query.str);
1921
1963
    }
1922
1964
  }
 
1965
  dynstr_free(&ds_col);
1923
1966
 
1924
1967
  {
1925
1968
    /* Get the value */
1926
 
    DRIZZLE_ROW row;
 
1969
    MYSQL_ROW row;
1927
1970
    long rows= 0;
1928
1971
    const char* value= "No such row";
1929
1972
 
1930
 
    while ((row= drizzle_fetch_row(res)))
 
1973
    while ((row= mysql_fetch_row(res)))
1931
1974
    {
1932
1975
      if (++rows == row_no)
1933
1976
      {
1943
1986
    }
1944
1987
    eval_expr(var, value, 0);
1945
1988
  }
1946
 
  drizzle_free_result(res);
 
1989
  dynstr_free(&ds_query);
 
1990
  mysql_free_result(res);
1947
1991
 
1948
1992
  return;
1949
1993
}
2013
2057
        MIN_VAR_ALLOC : new_val_len + 1;
2014
2058
      if (!(v->str_val =
2015
2059
            v->str_val ? (char *)my_realloc(v->str_val, v->alloced_len+1,
2016
 
                                            MYF(MY_WME)) :
 
2060
                                    MYF(MY_WME)) :
2017
2061
            (char *)my_malloc(v->alloced_len+1, MYF(MY_WME))))
2018
2062
        die("Out of memory");
2019
2063
    }
2033
2077
 
2034
2078
  if (!test_if_hard_path(name))
2035
2079
  {
2036
 
    strxmov(buff, opt_basedir, name, NULL);
 
2080
    strxmov(buff, opt_basedir, name, NullS);
2037
2081
    name=buff;
2038
2082
  }
2039
2083
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2057
2101
 
2058
2102
  SYNOPSIS
2059
2103
  do_source()
2060
 
  query  called command
 
2104
  query called command
2061
2105
 
2062
2106
  DESCRIPTION
2063
2107
  source <file_name>
2068
2112
 
2069
2113
static void do_source(struct st_command *command)
2070
2114
{
2071
 
  string ds_filename;
 
2115
  static DYNAMIC_STRING ds_filename;
2072
2116
  const struct command_arg source_args[] = {
2073
2117
    { "filename", ARG_STRING, true, &ds_filename, "File to source" }
2074
2118
  };
2086
2130
    ; /* Do nothing */
2087
2131
  else
2088
2132
  {
2089
 
    open_file(ds_filename.c_str());
 
2133
    open_file(ds_filename.str);
2090
2134
  }
2091
2135
 
 
2136
  dynstr_free(&ds_filename);
2092
2137
  return;
2093
2138
}
2094
2139
 
2095
2140
 
 
2141
static FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
 
2142
{
 
2143
  return popen(ds_cmd->str, mode);
 
2144
}
 
2145
 
 
2146
 
2096
2147
static void init_builtin_echo(void)
2097
2148
{
2098
2149
  builtin_echo[0]= 0;
2104
2155
  Replace a substring
2105
2156
 
2106
2157
  SYNOPSIS
2107
 
  replace
2108
 
  ds_str      The string to search and perform the replace in
2109
 
  search_str  The string to search for
2110
 
  search_len  Length of the string to search for
2111
 
  replace_str The string to replace with
2112
 
  replace_len Length of the string to replace with
 
2158
    replace
 
2159
    ds_str      The string to search and perform the replace in
 
2160
    search_str  The string to search for
 
2161
    search_len  Length of the string to search for
 
2162
    replace_str The string to replace with
 
2163
    replace_len Length of the string to replace with
2113
2164
 
2114
2165
  RETURN
2115
 
  0 String replaced
2116
 
  1 Could not find search_str in str
 
2166
    0 String replaced
 
2167
    1 Could not find search_str in str
2117
2168
*/
2118
2169
 
2119
 
static int replace(string *ds_str,
2120
 
                   const char *search_str, uint32_t search_len,
2121
 
                   const char *replace_str, uint32_t replace_len)
 
2170
static int replace(DYNAMIC_STRING *ds_str,
 
2171
                   const char *search_str, ulong search_len,
 
2172
                   const char *replace_str, ulong replace_len)
2122
2173
{
2123
 
  string ds_tmp;
2124
 
  const char *start= strstr(ds_str->c_str(), search_str);
 
2174
  DYNAMIC_STRING ds_tmp;
 
2175
  const char *start= strstr(ds_str->str, search_str);
2125
2176
  if (!start)
2126
2177
    return 1;
2127
 
  ds_tmp.append(ds_str->c_str(), start - ds_str->c_str());
2128
 
  ds_tmp.append(replace_str, replace_len);
2129
 
  ds_tmp.append(start + search_len);
2130
 
  *ds_str= ds_tmp;
 
2178
  init_dynamic_string(&ds_tmp, "",
 
2179
                      ds_str->length + replace_len, 256);
 
2180
  dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
 
2181
  dynstr_append_mem(&ds_tmp, replace_str, replace_len);
 
2182
  dynstr_append(&ds_tmp, start + search_len);
 
2183
  dynstr_set(ds_str, ds_tmp.str);
 
2184
  dynstr_free(&ds_tmp);
2131
2185
  return 0;
2132
2186
}
2133
2187
 
2137
2191
 
2138
2192
  SYNOPSIS
2139
2193
  do_exec()
2140
 
  query  called command
 
2194
  query called command
2141
2195
 
2142
2196
  DESCRIPTION
2143
2197
  exec <command>
2148
2202
  It can thus be used to execute a command that shall fail.
2149
2203
 
2150
2204
  NOTE
2151
 
  Although drizzletest is executed from cygwin shell, the command will be
 
2205
  Although mysqltest is executed from cygwin shell, the command will be
2152
2206
  executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
2153
 
  drizzletest commmand(s) like "remove_file" for that
 
2207
  mysqltest commmand(s) like "remove_file" for that
2154
2208
*/
2155
2209
 
2156
2210
static void do_exec(struct st_command *command)
2159
2213
  char buf[512];
2160
2214
  FILE *res_file;
2161
2215
  char *cmd= command->first_argument;
2162
 
  string ds_cmd;
 
2216
  DYNAMIC_STRING ds_cmd;
2163
2217
 
2164
2218
  /* Skip leading space */
2165
2219
  while (*cmd && my_isspace(charset_info, *cmd))
2168
2222
    die("Missing argument in exec");
2169
2223
  command->last_argument= command->end;
2170
2224
 
 
2225
  init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
2171
2226
  /* Eval the command, thus replacing all environment variables */
2172
2227
  do_eval(&ds_cmd, cmd, command->end, !is_windows);
2173
2228
 
2178
2233
    replace(&ds_cmd, "echo", 4, builtin_echo, strlen(builtin_echo));
2179
2234
  }
2180
2235
 
2181
 
  if (!(res_file= popen(ds_cmd.c_str(), "r")) && command->abort_on_error)
 
2236
  if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
2182
2237
  {
 
2238
    dynstr_free(&ds_cmd);
2183
2239
    die("popen(\"%s\", \"r\") failed", command->first_argument);
2184
2240
  }
2185
2241
 
2191
2247
    }
2192
2248
    else
2193
2249
    {
2194
 
      replace_append(&ds_res, buf);
 
2250
      replace_dynstr_append(&ds_res, buf);
2195
2251
    }
2196
2252
  }
2197
2253
  error= pclose(res_file);
2203
2259
    if (command->abort_on_error)
2204
2260
    {
2205
2261
      log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
2206
 
              ds_cmd.c_str(), error, status, errno);
 
2262
              ds_cmd.str, error, status, errno);
 
2263
      dynstr_free(&ds_cmd);
2207
2264
      die("command \"%s\" failed", command->first_argument);
2208
2265
    }
2209
2266
 
2217
2274
    }
2218
2275
    if (!ok)
2219
2276
    {
 
2277
      dynstr_free(&ds_cmd);
2220
2278
      die("command \"%s\" failed with wrong error: %d",
2221
2279
          command->first_argument, status);
2222
2280
    }
2226
2284
  {
2227
2285
    /* Error code we wanted was != 0, i.e. not an expected success */
2228
2286
    log_msg("exec of '%s failed, error: %d, errno: %d",
2229
 
            ds_cmd.c_str(), error, errno);
 
2287
            ds_cmd.str, error, errno);
 
2288
    dynstr_free(&ds_cmd);
2230
2289
    die("command \"%s\" succeeded - should have failed with errno %d...",
2231
2290
        command->first_argument, command->expected_errors.err[0].code.errnum);
2232
2291
  }
2233
2292
 
 
2293
  dynstr_free(&ds_cmd);
2234
2294
  return;
2235
2295
}
2236
2296
 
2246
2306
 
2247
2307
  SYNOPSIS
2248
2308
  do_modify_var()
2249
 
  query  called command
 
2309
  query called command
2250
2310
  operator    operation to perform on the var
2251
2311
 
2252
2312
  DESCRIPTION
2284
2344
 
2285
2345
 
2286
2346
/*
 
2347
  Wrapper for 'system' function
 
2348
 
 
2349
  NOTE
 
2350
  If mysqltest is executed from cygwin shell, the command will be
 
2351
  executed in the "windows command interpreter" cmd.exe and we prepend "sh"
 
2352
  to make it be executed by cygwins "bash". Thus commands like "rm",
 
2353
  "mkdir" as well as shellscripts can executed by "system" in Windows.
 
2354
 
 
2355
*/
 
2356
 
 
2357
static int my_system(DYNAMIC_STRING* ds_cmd)
 
2358
{
 
2359
  return system(ds_cmd->str);
 
2360
}
 
2361
 
 
2362
 
 
2363
/*
2287
2364
  SYNOPSIS
2288
2365
  do_system
2289
 
  command  called command
 
2366
  command       called command
2290
2367
 
2291
2368
  DESCRIPTION
2292
2369
  system <command>
2298
2375
 
2299
2376
static void do_system(struct st_command *command)
2300
2377
{
2301
 
  string ds_cmd;
 
2378
  DYNAMIC_STRING ds_cmd;
2302
2379
 
2303
2380
 
2304
2381
  if (strlen(command->first_argument) == 0)
2305
2382
    die("Missing arguments to system, nothing to do!");
2306
2383
 
 
2384
  init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
 
2385
 
2307
2386
  /* Eval the system command, thus replacing all environment variables */
2308
2387
  do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2309
2388
 
2310
 
  if (system(ds_cmd.c_str()))
 
2389
  if (my_system(&ds_cmd))
2311
2390
  {
2312
2391
    if (command->abort_on_error)
2313
2392
      die("system command '%s' failed", command->first_argument);
2314
2393
 
2315
2394
    /* If ! abort_on_error, log message and continue */
2316
 
    ds_res.append("system command '");
2317
 
    replace_append(&ds_res, command->first_argument);
2318
 
    ds_res.append("' failed\n");
 
2395
    dynstr_append(&ds_res, "system command '");
 
2396
    replace_dynstr_append(&ds_res, command->first_argument);
 
2397
    dynstr_append(&ds_res, "' failed\n");
2319
2398
  }
2320
2399
 
2321
2400
  command->last_argument= command->end;
 
2401
  dynstr_free(&ds_cmd);
2322
2402
  return;
2323
2403
}
2324
2404
 
2326
2406
/*
2327
2407
  SYNOPSIS
2328
2408
  do_remove_file
2329
 
  command  called command
 
2409
  command       called command
2330
2410
 
2331
2411
  DESCRIPTION
2332
2412
  remove_file <file_name>
2336
2416
static void do_remove_file(struct st_command *command)
2337
2417
{
2338
2418
  int error;
2339
 
  string ds_filename;
 
2419
  static DYNAMIC_STRING ds_filename;
2340
2420
  const struct command_arg rm_args[] = {
2341
2421
    { "filename", ARG_STRING, true, &ds_filename, "File to delete" }
2342
2422
  };
2346
2426
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2347
2427
                     ' ');
2348
2428
 
2349
 
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2429
  error= my_delete(ds_filename.str, MYF(0)) != 0;
2350
2430
  handle_command_error(command, error);
 
2431
  dynstr_free(&ds_filename);
2351
2432
  return;
2352
2433
}
2353
2434
 
2355
2436
/*
2356
2437
  SYNOPSIS
2357
2438
  do_copy_file
2358
 
  command  command handle
 
2439
  command       command handle
2359
2440
 
2360
2441
  DESCRIPTION
2361
2442
  copy_file <from_file> <to_file>
2367
2448
static void do_copy_file(struct st_command *command)
2368
2449
{
2369
2450
  int error;
2370
 
  string ds_from_file;
2371
 
  string ds_to_file;
 
2451
  static DYNAMIC_STRING ds_from_file;
 
2452
  static DYNAMIC_STRING ds_to_file;
2372
2453
  const struct command_arg copy_file_args[] = {
2373
2454
    { "from_file", ARG_STRING, true, &ds_from_file, "Filename to copy from" },
2374
2455
    { "to_file", ARG_STRING, true, &ds_to_file, "Filename to copy to" }
2380
2461
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2381
2462
                     ' ');
2382
2463
 
2383
 
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2464
  error= (my_copy(ds_from_file.str, ds_to_file.str,
2384
2465
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2385
2466
  handle_command_error(command, error);
 
2467
  dynstr_free(&ds_from_file);
 
2468
  dynstr_free(&ds_to_file);
2386
2469
  return;
2387
2470
}
2388
2471
 
2390
2473
/*
2391
2474
  SYNOPSIS
2392
2475
  do_chmod_file
2393
 
  command  command handle
 
2476
  command       command handle
2394
2477
 
2395
2478
  DESCRIPTION
2396
2479
  chmod <octal> <file_name>
2401
2484
static void do_chmod_file(struct st_command *command)
2402
2485
{
2403
2486
  long mode= 0;
2404
 
  string ds_mode;
2405
 
  string ds_file;
 
2487
  static DYNAMIC_STRING ds_mode;
 
2488
  static DYNAMIC_STRING ds_file;
2406
2489
  const struct command_arg chmod_file_args[] = {
2407
 
    { "mode", ARG_STRING, true, &ds_mode, "Mode of file(octal) ex. 0660"},
 
2490
    { "mode", ARG_STRING, true, &ds_mode, "Mode of file(octal) ex. 0660"}, 
2408
2491
    { "filename", ARG_STRING, true, &ds_file, "Filename of file to modify" }
2409
2492
  };
2410
2493
 
2415
2498
                     ' ');
2416
2499
 
2417
2500
  /* Parse what mode to set */
2418
 
  if (ds_mode.length() != 4 ||
2419
 
      str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NULL)
 
2501
  if (ds_mode.length != 4 ||
 
2502
      str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
2420
2503
    die("You must write a 4 digit octal number for mode");
2421
2504
 
2422
 
  handle_command_error(command, chmod(ds_file.c_str(), mode));
 
2505
  handle_command_error(command, chmod(ds_file.str, mode));
 
2506
  dynstr_free(&ds_mode);
 
2507
  dynstr_free(&ds_file);
2423
2508
  return;
2424
2509
}
2425
2510
 
2427
2512
/*
2428
2513
  SYNOPSIS
2429
2514
  do_file_exists
2430
 
  command  called command
 
2515
  command       called command
2431
2516
 
2432
2517
  DESCRIPTION
2433
2518
  fiile_exist <file_name>
2437
2522
static void do_file_exist(struct st_command *command)
2438
2523
{
2439
2524
  int error;
2440
 
  string ds_filename;
 
2525
  static DYNAMIC_STRING ds_filename;
2441
2526
  const struct command_arg file_exist_args[] = {
2442
2527
    { "filename", ARG_STRING, true, &ds_filename, "File to check if it exist" }
2443
2528
  };
2448
2533
                     sizeof(file_exist_args)/sizeof(struct command_arg),
2449
2534
                     ' ');
2450
2535
 
2451
 
  error= (access(ds_filename.c_str(), F_OK) != 0);
 
2536
  error= (access(ds_filename.str, F_OK) != 0);
2452
2537
  handle_command_error(command, error);
 
2538
  dynstr_free(&ds_filename);
2453
2539
  return;
2454
2540
}
2455
2541
 
2457
2543
/*
2458
2544
  SYNOPSIS
2459
2545
  do_mkdir
2460
 
  command  called command
 
2546
  command       called command
2461
2547
 
2462
2548
  DESCRIPTION
2463
2549
  mkdir <dir_name>
2467
2553
static void do_mkdir(struct st_command *command)
2468
2554
{
2469
2555
  int error;
2470
 
  string ds_dirname;
 
2556
  static DYNAMIC_STRING ds_dirname;
2471
2557
  const struct command_arg mkdir_args[] = {
2472
2558
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
2473
2559
  };
2477
2563
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2478
2564
                     ' ');
2479
2565
 
2480
 
  error= my_mkdir(ds_dirname.c_str(), 0777, MYF(0)) != 0;
 
2566
  error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
2481
2567
  handle_command_error(command, error);
 
2568
  dynstr_free(&ds_dirname);
2482
2569
  return;
2483
2570
}
2484
2571
 
2485
2572
/*
2486
2573
  SYNOPSIS
2487
2574
  do_rmdir
2488
 
  command  called command
 
2575
  command       called command
2489
2576
 
2490
2577
  DESCRIPTION
2491
2578
  rmdir <dir_name>
2495
2582
static void do_rmdir(struct st_command *command)
2496
2583
{
2497
2584
  int error;
2498
 
  string ds_dirname;
 
2585
  static DYNAMIC_STRING ds_dirname;
2499
2586
  const struct command_arg rmdir_args[] = {
2500
2587
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to remove"}
2501
2588
  };
2505
2592
                     rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
2506
2593
                     ' ');
2507
2594
 
2508
 
  error= rmdir(ds_dirname.c_str()) != 0;
 
2595
  error= rmdir(ds_dirname.str) != 0;
2509
2596
  handle_command_error(command, error);
 
2597
  dynstr_free(&ds_dirname);
2510
2598
  return;
2511
2599
}
2512
2600
 
2535
2623
}
2536
2624
 
2537
2625
 
2538
 
static void read_until_delimiter(string *ds,
2539
 
                                 string *ds_delimiter)
 
2626
static void read_until_delimiter(DYNAMIC_STRING *ds,
 
2627
                                 DYNAMIC_STRING *ds_delimiter)
2540
2628
{
2541
2629
  char c;
2542
2630
 
2543
 
  if (ds_delimiter->length() > MAX_DELIMITER_LENGTH)
 
2631
  if (ds_delimiter->length > MAX_DELIMITER_LENGTH)
2544
2632
    die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
2545
2633
 
2546
2634
  /* Read from file until delimiter is found */
2567
2655
 
2568
2656
    if (feof(cur_file->file))
2569
2657
      die("End of file encountered before '%s' delimiter was found",
2570
 
          ds_delimiter->c_str());
 
2658
          ds_delimiter->str);
2571
2659
 
2572
 
    if (match_delimiter(c, ds_delimiter->c_str(), ds_delimiter->length()))
 
2660
    if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
2573
2661
      break;
2574
2662
 
2575
 
    ds->push_back(c);
 
2663
    dynstr_append_mem(ds, (const char*)&c, 1);
2576
2664
  }
2577
2665
  return;
2578
2666
}
2580
2668
 
2581
2669
static void do_write_file_command(struct st_command *command, bool append)
2582
2670
{
2583
 
  string ds_content;
2584
 
  string ds_filename;
2585
 
  string ds_delimiter;
 
2671
  static DYNAMIC_STRING ds_content;
 
2672
  static DYNAMIC_STRING ds_filename;
 
2673
  static DYNAMIC_STRING ds_delimiter;
2586
2674
  const struct command_arg write_file_args[] = {
2587
2675
    { "filename", ARG_STRING, true, &ds_filename, "File to write to" },
2588
2676
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
2596
2684
                     ' ');
2597
2685
 
2598
2686
  /* If no delimiter was provided, use EOF */
2599
 
  if (ds_delimiter.length() == 0)
2600
 
    ds_delimiter= "EOF";
 
2687
  if (ds_delimiter.length == 0)
 
2688
    dynstr_set(&ds_delimiter, "EOF");
2601
2689
 
2602
 
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
 
2690
  if (!append && access(ds_filename.str, F_OK) == 0)
2603
2691
  {
2604
2692
    /* The file should not be overwritten */
2605
 
    die("File already exist: '%s'", ds_filename.c_str());
 
2693
    die("File already exist: '%s'", ds_filename.str);
2606
2694
  }
2607
2695
 
 
2696
  init_dynamic_string(&ds_content, "", 1024, 1024);
2608
2697
  read_until_delimiter(&ds_content, &ds_delimiter);
2609
 
  str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2610
 
               ds_content.length(), append);
 
2698
  str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
 
2699
  dynstr_free(&ds_content);
 
2700
  dynstr_free(&ds_filename);
 
2701
  dynstr_free(&ds_delimiter);
2611
2702
  return;
2612
2703
}
2613
2704
 
2615
2706
/*
2616
2707
  SYNOPSIS
2617
2708
  do_write_file
2618
 
  command  called command
 
2709
  command       called command
2619
2710
 
2620
2711
  DESCRIPTION
2621
2712
  write_file <file_name> [<delimiter>];
2648
2739
/*
2649
2740
  SYNOPSIS
2650
2741
  do_append_file
2651
 
  command  called command
 
2742
  command       called command
2652
2743
 
2653
2744
  DESCRIPTION
2654
2745
  append_file <file_name> [<delimiter>];
2679
2770
/*
2680
2771
  SYNOPSIS
2681
2772
  do_cat_file
2682
 
  command  called command
 
2773
  command       called command
2683
2774
 
2684
2775
  DESCRIPTION
2685
2776
  cat_file <file_name>;
2690
2781
 
2691
2782
static void do_cat_file(struct st_command *command)
2692
2783
{
2693
 
  static string ds_filename;
 
2784
  static DYNAMIC_STRING ds_filename;
2694
2785
  const struct command_arg cat_file_args[] = {
2695
2786
    { "filename", ARG_STRING, true, &ds_filename, "File to read from" }
2696
2787
  };
2702
2793
                     sizeof(cat_file_args)/sizeof(struct command_arg),
2703
2794
                     ' ');
2704
2795
 
2705
 
  cat_file(&ds_res, ds_filename.c_str());
 
2796
  cat_file(&ds_res, ds_filename.str);
2706
2797
 
 
2798
  dynstr_free(&ds_filename);
2707
2799
  return;
2708
2800
}
2709
2801
 
2711
2803
/*
2712
2804
  SYNOPSIS
2713
2805
  do_diff_files
2714
 
  command  called command
 
2806
  command       called command
2715
2807
 
2716
2808
  DESCRIPTION
2717
2809
  diff_files <file1> <file2>;
2723
2815
static void do_diff_files(struct st_command *command)
2724
2816
{
2725
2817
  int error= 0;
2726
 
  string ds_filename;
2727
 
  string ds_filename2;
 
2818
  static DYNAMIC_STRING ds_filename;
 
2819
  static DYNAMIC_STRING ds_filename2;
2728
2820
  const struct command_arg diff_file_args[] = {
2729
2821
    { "file1", ARG_STRING, true, &ds_filename, "First file to diff" },
2730
2822
    { "file2", ARG_STRING, true, &ds_filename2, "Second file to diff" }
2737
2829
                     sizeof(diff_file_args)/sizeof(struct command_arg),
2738
2830
                     ' ');
2739
2831
 
2740
 
  if ((error= compare_files(ds_filename.c_str(), ds_filename2.c_str())))
 
2832
  if ((error= compare_files(ds_filename.str, ds_filename2.str)))
2741
2833
  {
2742
2834
    /* Compare of the two files failed, append them to output
2743
2835
       so the failure can be analyzed
2744
2836
    */
2745
 
    show_diff(&ds_res, ds_filename.c_str(), ds_filename2.c_str());
 
2837
    show_diff(&ds_res, ds_filename.str, ds_filename2.str);
2746
2838
  }
2747
2839
 
 
2840
  dynstr_free(&ds_filename);
 
2841
  dynstr_free(&ds_filename2);
2748
2842
  handle_command_error(command, error);
2749
2843
  return;
2750
2844
}
2767
2861
/*
2768
2862
  SYNOPSIS
2769
2863
  do_send_quit
2770
 
  command  called command
 
2864
  command       called command
2771
2865
 
2772
2866
  DESCRIPTION
2773
2867
  Sends a simple quit command to the server for the named connection.
2792
2886
  if (!(con= find_connection_by_name(name)))
2793
2887
    die("connection '%s' not found in connection pool", name);
2794
2888
 
2795
 
  simple_command(&con->drizzle,COM_QUIT,0,0,1);
 
2889
  simple_command(&con->mysql,COM_QUIT,0,0,1);
2796
2890
 
2797
2891
  return;
2798
2892
}
2816
2910
 
2817
2911
static void do_change_user(struct st_command *command)
2818
2912
{
2819
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
2913
  MYSQL *mysql = &cur_con->mysql;
2820
2914
  /* static keyword to make the NetWare compiler happy. */
2821
 
  string ds_user, ds_passwd, ds_db;
 
2915
  static DYNAMIC_STRING ds_user, ds_passwd, ds_db;
2822
2916
  const struct command_arg change_user_args[] = {
2823
2917
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
2824
2918
    { "password", ARG_STRING, false, &ds_passwd, "Password used when connecting" },
2832
2926
                     sizeof(change_user_args)/sizeof(struct command_arg),
2833
2927
                     ',');
2834
2928
 
2835
 
  if (!ds_user.length())
2836
 
    ds_user= drizzle->user;
2837
 
 
2838
 
  if (!ds_passwd.length())
2839
 
    ds_passwd= drizzle->passwd;
2840
 
 
2841
 
  if (!ds_db.length())
2842
 
    ds_db= drizzle->db;
2843
 
 
2844
 
  if (drizzle_change_user(drizzle, ds_user.c_str(),
2845
 
                          ds_passwd.c_str(), ds_db.c_str()))
2846
 
    die("change user failed: %s", drizzle_error(drizzle));
2847
 
 
 
2929
  if (!ds_user.length)
 
2930
    dynstr_set(&ds_user, mysql->user);
 
2931
 
 
2932
  if (!ds_passwd.length)
 
2933
    dynstr_set(&ds_passwd, mysql->passwd);
 
2934
 
 
2935
  if (!ds_db.length)
 
2936
    dynstr_set(&ds_db, mysql->db);
 
2937
 
 
2938
  if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str))
 
2939
    die("change user failed: %s", mysql_error(mysql));
 
2940
 
 
2941
  dynstr_free(&ds_user);
 
2942
  dynstr_free(&ds_passwd);
 
2943
  dynstr_free(&ds_db);
2848
2944
 
2849
2945
  return;
2850
2946
}
2853
2949
/*
2854
2950
  SYNOPSIS
2855
2951
  do_perl
2856
 
  command  command handle
 
2952
  command       command handle
2857
2953
 
2858
2954
  DESCRIPTION
2859
2955
  perl [<delimiter>];
2876
2972
  FILE *res_file;
2877
2973
  char buf[FN_REFLEN];
2878
2974
  char temp_file_path[FN_REFLEN];
2879
 
  string ds_script;
2880
 
  string ds_delimiter;
 
2975
  static DYNAMIC_STRING ds_script;
 
2976
  static DYNAMIC_STRING ds_delimiter;
2881
2977
  const struct command_arg perl_args[] = {
2882
2978
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
2883
2979
  };
2890
2986
                     ' ');
2891
2987
 
2892
2988
  /* If no delimiter was provided, use EOF */
2893
 
  if (ds_delimiter.length() == 0)
2894
 
    ds_delimiter= "EOF";
 
2989
  if (ds_delimiter.length == 0)
 
2990
    dynstr_set(&ds_delimiter, "EOF");
2895
2991
 
 
2992
  init_dynamic_string(&ds_script, "", 1024, 1024);
2896
2993
  read_until_delimiter(&ds_script, &ds_delimiter);
2897
2994
 
2898
2995
  /* Create temporary file name */
2902
2999
    die("Failed to create temporary file for perl command");
2903
3000
  my_close(fd, MYF(0));
2904
3001
 
2905
 
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
 
3002
  str_to_file(temp_file_path, ds_script.str, ds_script.length);
2906
3003
 
2907
3004
  /* Format the "perl <filename>" command */
2908
3005
  snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
2915
3012
    if (disable_result_log)
2916
3013
      buf[strlen(buf)-1]=0;
2917
3014
    else
2918
 
      replace_append(&ds_res, buf);
 
3015
      replace_dynstr_append(&ds_res, buf);
2919
3016
  }
2920
3017
  error= pclose(res_file);
2921
3018
 
2923
3020
  my_delete(temp_file_path, MYF(0));
2924
3021
 
2925
3022
  handle_command_error(command, WEXITSTATUS(error));
 
3023
  dynstr_free(&ds_script);
 
3024
  dynstr_free(&ds_delimiter);
2926
3025
  return;
2927
3026
}
2928
3027
 
2930
3029
/*
2931
3030
  Print the content between echo and <delimiter> to result file.
2932
3031
  Evaluate all variables in the string before printing, allow
2933
 
  for variable names to be escaped using        \
 
3032
  for variable names to be escaped using \
2934
3033
 
2935
3034
  SYNOPSIS
2936
3035
  do_echo()
2953
3052
 
2954
3053
static int do_echo(struct st_command *command)
2955
3054
{
2956
 
  string ds_echo;
2957
 
 
2958
 
 
 
3055
  DYNAMIC_STRING ds_echo;
 
3056
 
 
3057
 
 
3058
  init_dynamic_string(&ds_echo, "", command->query_len, 256);
2959
3059
  do_eval(&ds_echo, command->first_argument, command->end, false);
2960
 
  ds_res.append(ds_echo.c_str(), ds_echo.length());
2961
 
  ds_res.append("\n");
 
3060
  dynstr_append_mem(&ds_res, ds_echo.str, ds_echo.length);
 
3061
  dynstr_append_mem(&ds_res, "\n", 1);
 
3062
  dynstr_free(&ds_echo);
2962
3063
  command->last_argument= command->end;
2963
3064
  return(0);
2964
3065
}
2968
3069
do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
2969
3070
{
2970
3071
  static int SLAVE_POLL_INTERVAL= 300000;
2971
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3072
  MYSQL* mysql = &cur_con->mysql;
2972
3073
  for (;;)
2973
3074
  {
2974
 
    DRIZZLE_RES *res= NULL;
2975
 
    DRIZZLE_ROW row;
 
3075
    MYSQL_RES *res= NULL;
 
3076
    MYSQL_ROW row;
2976
3077
    int done;
2977
3078
 
2978
 
    if (drizzle_query(drizzle,"show status like 'Slave_running'") ||
2979
 
        !(res=drizzle_store_result(drizzle)))
 
3079
    if (mysql_query(mysql,"show status like 'Slave_running'") ||
 
3080
        !(res=mysql_store_result(mysql)))
2980
3081
      die("Query failed while probing slave for stop: %s",
2981
 
          drizzle_error(drizzle));
2982
 
    if (!(row=drizzle_fetch_row(res)) || !row[1])
 
3082
          mysql_error(mysql));
 
3083
    if (!(row=mysql_fetch_row(res)) || !row[1])
2983
3084
    {
2984
 
      drizzle_free_result(res);
 
3085
      mysql_free_result(res);
2985
3086
      die("Strange result from query while probing slave for stop");
2986
3087
    }
2987
3088
    done = !strcmp(row[1],"OFF");
2988
 
    drizzle_free_result(res);
 
3089
    mysql_free_result(res);
2989
3090
    if (done)
2990
3091
      break;
2991
3092
    my_sleep(SLAVE_POLL_INTERVAL);
2996
3097
 
2997
3098
static void do_sync_with_master2(long offset)
2998
3099
{
2999
 
  DRIZZLE_RES *res;
3000
 
  DRIZZLE_ROW row;
3001
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3100
  MYSQL_RES *res;
 
3101
  MYSQL_ROW row;
 
3102
  MYSQL *mysql= &cur_con->mysql;
3002
3103
  char query_buf[FN_REFLEN+128];
3003
3104
  int tries= 0;
3004
3105
 
3006
3107
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3007
3108
 
3008
3109
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3009
 
          master_pos.pos + offset);
 
3110
          master_pos.pos + offset);
3010
3111
 
3011
3112
wait_for_position:
3012
3113
 
3013
 
  if (drizzle_query(drizzle, query_buf))
3014
 
    die("failed in '%s': %d: %s", query_buf, drizzle_errno(drizzle),
3015
 
        drizzle_error(drizzle));
 
3114
  if (mysql_query(mysql, query_buf))
 
3115
    die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
 
3116
        mysql_error(mysql));
3016
3117
 
3017
 
  if (!(res= drizzle_store_result(drizzle)))
3018
 
    die("drizzle_store_result() returned NULL for '%s'", query_buf);
3019
 
  if (!(row= drizzle_fetch_row(res)))
 
3118
  if (!(res= mysql_store_result(mysql)))
 
3119
    die("mysql_store_result() returned NULL for '%s'", query_buf);
 
3120
  if (!(row= mysql_fetch_row(res)))
3020
3121
  {
3021
 
    drizzle_free_result(res);
 
3122
    mysql_free_result(res);
3022
3123
    die("empty result in %s", query_buf);
3023
3124
  }
3024
3125
  if (!row[0])
3027
3128
      It may be that the slave SQL thread has not started yet, though START
3028
3129
      SLAVE has been issued ?
3029
3130
    */
3030
 
    drizzle_free_result(res);
 
3131
    mysql_free_result(res);
3031
3132
    if (tries++ == 30)
3032
3133
    {
3033
 
      show_query(drizzle, "SHOW MASTER STATUS");
3034
 
      show_query(drizzle, "SHOW SLAVE STATUS");
 
3134
      show_query(mysql, "SHOW MASTER STATUS");
 
3135
      show_query(mysql, "SHOW SLAVE STATUS");
3035
3136
      die("could not sync with master ('%s' returned NULL)", query_buf);
3036
3137
    }
3037
3138
    sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
3038
3139
    goto wait_for_position;
3039
3140
  }
3040
 
  drizzle_free_result(res);
 
3141
  mysql_free_result(res);
3041
3142
  return;
3042
3143
}
3043
3144
 
3063
3164
 
3064
3165
/*
3065
3166
  when ndb binlog is on, this call will wait until last updated epoch
3066
 
  (locally in the drizzled) has been received into the binlog
 
3167
  (locally in the mysqld) has been received into the binlog
3067
3168
*/
3068
3169
static int do_save_master_pos(void)
3069
3170
{
3070
 
  DRIZZLE_RES *res;
3071
 
  DRIZZLE_ROW row;
3072
 
  DRIZZLE *drizzle= &cur_con->drizzle;
 
3171
  MYSQL_RES *res;
 
3172
  MYSQL_ROW row;
 
3173
  MYSQL *mysql = &cur_con->mysql;
3073
3174
  const char *query;
3074
3175
 
3075
3176
 
3076
 
  if (drizzle_query(drizzle, query= "show master status"))
 
3177
  if (mysql_query(mysql, query= "show master status"))
3077
3178
    die("failed in 'show master status': %d %s",
3078
 
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
3179
        mysql_errno(mysql), mysql_error(mysql));
3079
3180
 
3080
 
  if (!(res = drizzle_store_result(drizzle)))
3081
 
    die("drizzle_store_result() retuned NULL for '%s'", query);
3082
 
  if (!(row = drizzle_fetch_row(res)))
 
3181
  if (!(res = mysql_store_result(mysql)))
 
3182
    die("mysql_store_result() retuned NULL for '%s'", query);
 
3183
  if (!(row = mysql_fetch_row(res)))
3083
3184
    die("empty result in show master status");
3084
 
  my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
 
3185
  strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
3085
3186
  master_pos.pos = strtoul(row[1], (char**) 0, 10);
3086
 
  drizzle_free_result(res);
 
3187
  mysql_free_result(res);
3087
3188
  return(0);
3088
3189
}
3089
3190
 
3093
3194
 
3094
3195
  SYNOPSIS
3095
3196
  do_let()
3096
 
  query  called command
 
3197
  query called command
3097
3198
 
3098
3199
  DESCRIPTION
3099
3200
  let $<var_name>=<var_val><delimiter>
3111
3212
{
3112
3213
  char *p= command->first_argument;
3113
3214
  char *var_name, *var_name_end;
3114
 
  string let_rhs_expr;
3115
 
 
 
3215
  DYNAMIC_STRING let_rhs_expr;
 
3216
 
 
3217
 
 
3218
  init_dynamic_string(&let_rhs_expr, "", 512, 2048);
3116
3219
 
3117
3220
  /* Find <var_name> */
3118
3221
  if (!*p)
3137
3240
 
3138
3241
  command->last_argument= command->end;
3139
3242
  /* Assign var_val to var_name */
3140
 
  var_set(var_name, var_name_end, let_rhs_expr.c_str(),
3141
 
          (let_rhs_expr.c_str() + let_rhs_expr.length()));
 
3243
  var_set(var_name, var_name_end, let_rhs_expr.str,
 
3244
          (let_rhs_expr.str + let_rhs_expr.length));
 
3245
  dynstr_free(&let_rhs_expr);
3142
3246
  return;
3143
3247
}
3144
3248
 
3148
3252
 
3149
3253
  SYNOPSIS
3150
3254
  do_sleep()
3151
 
  q         called command
 
3255
  q            called command
3152
3256
  real_sleep   use the value from opt_sleep as number of seconds to sleep
3153
 
  if real_sleep is false
 
3257
               if real_sleep is false
3154
3258
 
3155
3259
  DESCRIPTION
3156
3260
  sleep <seconds>
3191
3295
    sleep_val= opt_sleep;
3192
3296
 
3193
3297
  if (sleep_val)
3194
 
    my_sleep((uint32_t) (sleep_val * 1000000L));
 
3298
    my_sleep((ulong) (sleep_val * 1000000L));
3195
3299
  command->last_argument= sleep_end;
3196
3300
  return 0;
3197
3301
}
3198
3302
 
3199
3303
 
3200
3304
static void do_get_file_name(struct st_command *command,
3201
 
                             char* dest, uint dest_max_len)
 
3305
                      char* dest, uint dest_max_len)
3202
3306
{
3203
3307
  char *p= command->first_argument, *name;
3204
3308
  if (!*p)
3232
3336
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3233
3337
}
3234
3338
 
 
3339
 
 
3340
/* List of error names to error codes, available from 5.0 */
 
3341
typedef struct
 
3342
{
 
3343
  const char *name;
 
3344
  uint        code;
 
3345
} st_error;
 
3346
 
 
3347
static st_error global_error_names[] =
 
3348
{
 
3349
#include <mysqld_ername.h>
 
3350
  { 0, 0 }
 
3351
};
 
3352
 
3235
3353
static uint get_errcode_from_name(char *error_name, char *error_end)
3236
3354
{
3237
3355
  /* SQL error as string */
3299
3417
        if (my_isdigit(charset_info, *p) || my_isupper(charset_info, *p))
3300
3418
          *to_ptr++= *p++;
3301
3419
        else
3302
 
          die("The sqlstate may only consist of digits[0-9] "   \
 
3420
          die("The sqlstate may only consist of digits[0-9] " \
3303
3421
              "and _uppercase_ letters");
3304
3422
      }
3305
3423
 
3329
3447
      while (*p && p != end)
3330
3448
      {
3331
3449
        if (!my_isdigit(charset_info, *p))
3332
 
          die("Invalid argument to error: '%s' - "              \
 
3450
          die("Invalid argument to error: '%s' - "\
3333
3451
              "the errno may only consist of digits[0-9]",
3334
3452
              command->first_argument);
3335
3453
        p++;
3337
3455
 
3338
3456
      /* Convert the sting to int */
3339
3457
      if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
3340
 
        die("Invalid argument to error: '%s'", command->first_argument);
 
3458
        die("Invalid argument to error: '%s'", command->first_argument);
3341
3459
 
3342
3460
      to->code.errnum= (uint) val;
3343
3461
      to->type= ERR_ERRNO;
3387
3505
  if (*from == '"' || *from == '\'')
3388
3506
    sep= *from++;
3389
3507
  else
3390
 
    sep=' ';        /* Separated with space */
 
3508
    sep=' ';                            /* Separated with space */
3391
3509
 
3392
3510
  for ( ; (c=*from) ; from++)
3393
3511
  {
3394
3512
    if (c == '\\' && from[1])
3395
 
    {          /* Escaped character */
 
3513
    {                                   /* Escaped character */
3396
3514
      /* We can't translate \0 -> ASCII 0 as replace can't handle ASCII 0 */
3397
3515
      switch (*++from) {
3398
3516
      case 'n':
3399
 
        *to++= '\n';
3400
 
        break;
 
3517
        *to++= '\n';
 
3518
        break;
3401
3519
      case 't':
3402
 
        *to++= '\t';
3403
 
        break;
 
3520
        *to++= '\t';
 
3521
        break;
3404
3522
      case 'r':
3405
 
        *to++ = '\r';
3406
 
        break;
 
3523
        *to++ = '\r';
 
3524
        break;
3407
3525
      case 'b':
3408
 
        *to++ = '\b';
3409
 
        break;
3410
 
      case 'Z':        /* ^Z must be escaped on Win32 */
3411
 
        *to++='\032';
3412
 
        break;
 
3526
        *to++ = '\b';
 
3527
        break;
 
3528
      case 'Z':                         /* ^Z must be escaped on Win32 */
 
3529
        *to++='\032';
 
3530
        break;
3413
3531
      default:
3414
 
        *to++ = *from;
3415
 
        break;
 
3532
        *to++ = *from;
 
3533
        break;
3416
3534
      }
3417
3535
    }
3418
3536
    else if (c == sep)
3419
3537
    {
3420
3538
      if (c == ' ' || c != *++from)
3421
 
        break;        /* Found end of string */
3422
 
      *to++=c;        /* Copy duplicated separator */
 
3539
        break;                          /* Found end of string */
 
3540
      *to++=c;                          /* Copy duplicated separator */
3423
3541
    }
3424
3542
    else
3425
3543
      *to++=c;
3427
3545
  if (*from != ' ' && *from)
3428
3546
    die("Wrong string argument in %s", command->query);
3429
3547
 
3430
 
  while (my_isspace(charset_info,*from))  /* Point to next string */
 
3548
  while (my_isspace(charset_info,*from))        /* Point to next string */
3431
3549
    from++;
3432
3550
 
3433
 
  *to =0;        /* End of string marker */
3434
 
  *to_ptr= to+1;      /* Store pointer to end */
 
3551
  *to =0;                               /* End of string marker */
 
3552
  *to_ptr= to+1;                        /* Store pointer to end */
3435
3553
  *from_ptr= from;
3436
3554
 
3437
3555
  /* Check if this was a variable */
3440
3558
    const char *end= to;
3441
3559
    VAR *var=var_get(start, &end, 0, 1);
3442
3560
    if (var && to == (char*) end+1)
3443
 
      return(var->str_val);  /* return found variable value */
 
3561
      return(var->str_val);     /* return found variable value */
3444
3562
  }
3445
3563
  return(start);
3446
3564
}
3447
3565
 
3448
3566
 
3449
 
static void set_reconnect(DRIZZLE *drizzle, int val)
 
3567
static void set_reconnect(MYSQL* mysql, int val)
3450
3568
{
3451
3569
  bool reconnect= val;
3452
3570
 
3453
 
  drizzle_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
 
3571
  mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
3454
3572
 
3455
3573
  return;
3456
3574
}
3461
3579
  if (!(cur_con= find_connection_by_name(name)))
3462
3580
    die("connection '%s' not found in connection pool", name);
3463
3581
 
3464
 
  /* Update $drizzle_get_server_version to that of current connection */
3465
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
3582
  /* Update $mysql_get_server_version to that of current connection */
 
3583
  var_set_mysql_get_server_version(&cur_con->mysql);
3466
3584
 
3467
3585
  return(0);
3468
3586
}
3506
3624
 
3507
3625
  if (command->type == Q_DIRTY_CLOSE)
3508
3626
  {
3509
 
    if (con->drizzle.net.vio)
 
3627
    if (con->mysql.net.vio)
3510
3628
    {
3511
 
      net_close(&(con->drizzle.net));
 
3629
      vio_delete(con->mysql.net.vio);
 
3630
      con->mysql.net.vio = 0;
3512
3631
    }
3513
3632
  }
3514
3633
 
3515
 
  drizzle_close(&con->drizzle);
3516
 
 
3517
 
  if (con->util_drizzle)
3518
 
    drizzle_close(con->util_drizzle);
3519
 
  con->util_drizzle= 0;
3520
 
 
3521
 
  free(con->name);
 
3634
  mysql_close(&con->mysql);
 
3635
 
 
3636
  if (con->util_mysql)
 
3637
    mysql_close(con->util_mysql);
 
3638
  con->util_mysql= 0;
 
3639
 
 
3640
  my_free(con->name, MYF(0));
3522
3641
 
3523
3642
  /*
3524
3643
    When the connection is closed set name to "-closed_connection-"
3556
3675
 
3557
3676
*/
3558
3677
 
3559
 
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
3560
 
                         const char *user, const char *pass, const char *db,
3561
 
                         int port)
 
3678
static void safe_connect(MYSQL* mysql, const char *name, const char *host,
 
3679
                  const char *user, const char *pass, const char *db,
 
3680
                  int port)
3562
3681
{
3563
3682
  int failed_attempts= 0;
3564
 
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3565
 
 
3566
 
 
3567
 
  while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3568
 
                         CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
 
3683
  static ulong connection_retry_sleep= 100000; /* Microseconds */
 
3684
 
 
3685
 
 
3686
  while(!mysql_real_connect(mysql, host, user, pass, db, port, NULL,
 
3687
                            CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3569
3688
  {
3570
3689
    /*
3571
3690
      Connect failed
3575
3694
      on protocol/connection type
3576
3695
    */
3577
3696
 
3578
 
    if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
3579
 
         drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
 
3697
    if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
 
3698
         mysql_errno(mysql) == CR_CONNECTION_ERROR) &&
3580
3699
        failed_attempts < opt_max_connect_retries)
3581
3700
    {
3582
3701
      verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3583
 
                  opt_max_connect_retries, drizzle_errno(drizzle),
3584
 
                  drizzle_error(drizzle));
 
3702
                  opt_max_connect_retries, mysql_errno(mysql),
 
3703
                  mysql_error(mysql));
3585
3704
      my_sleep(connection_retry_sleep);
3586
3705
    }
3587
3706
    else
3588
3707
    {
3589
3708
      if (failed_attempts > 0)
3590
3709
        die("Could not open connection '%s' after %d attempts: %d %s", name,
3591
 
            failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
 
3710
            failed_attempts, mysql_errno(mysql), mysql_error(mysql));
3592
3711
      else
3593
3712
        die("Could not open connection '%s': %d %s", name,
3594
 
            drizzle_errno(drizzle), drizzle_error(drizzle));
 
3713
            mysql_errno(mysql), mysql_error(mysql));
3595
3714
    }
3596
3715
    failed_attempts++;
3597
3716
  }
3623
3742
*/
3624
3743
 
3625
3744
static int connect_n_handle_errors(struct st_command *command,
3626
 
                                   DRIZZLE *con, const char* host,
3627
 
                                   const char* user, const char* pass,
3628
 
                                   const char* db, int port, const char* sock)
 
3745
                            MYSQL* con, const char* host,
 
3746
                            const char* user, const char* pass,
 
3747
                            const char* db, int port, const char* sock)
3629
3748
{
 
3749
  DYNAMIC_STRING *ds;
 
3750
 
 
3751
  ds= &ds_res;
3630
3752
 
3631
3753
  /* Only log if an error is expected */
3632
3754
  if (!command->abort_on_error &&
3635
3757
    /*
3636
3758
      Log the connect to result log
3637
3759
    */
3638
 
    ds_res.append("connect(");
3639
 
    replace_append(&ds_res, host);
3640
 
    ds_res.append(",");
3641
 
    replace_append(&ds_res, user);
3642
 
    ds_res.append(",");
3643
 
    replace_append(&ds_res, pass);
3644
 
    ds_res.append(",");
 
3760
    dynstr_append_mem(ds, "connect(", 8);
 
3761
    replace_dynstr_append(ds, host);
 
3762
    dynstr_append_mem(ds, ",", 1);
 
3763
    replace_dynstr_append(ds, user);
 
3764
    dynstr_append_mem(ds, ",", 1);
 
3765
    replace_dynstr_append(ds, pass);
 
3766
    dynstr_append_mem(ds, ",", 1);
3645
3767
    if (db)
3646
 
      replace_append(&ds_res, db);
3647
 
    ds_res.append(",");
3648
 
    replace_append_uint(&ds_res, port);
3649
 
    ds_res.append(",");
 
3768
      replace_dynstr_append(ds, db);
 
3769
    dynstr_append_mem(ds, ",", 1);
 
3770
    replace_dynstr_append_uint(ds, port);
 
3771
    dynstr_append_mem(ds, ",", 1);
3650
3772
    if (sock)
3651
 
      replace_append(&ds_res, sock);
3652
 
    ds_res.append(")");
3653
 
    ds_res.append(delimiter);
3654
 
    ds_res.append("\n");
 
3773
      replace_dynstr_append(ds, sock);
 
3774
    dynstr_append_mem(ds, ")", 1);
 
3775
    dynstr_append_mem(ds, delimiter, delimiter_length);
 
3776
    dynstr_append_mem(ds, "\n", 1);
3655
3777
  }
3656
 
  if (!drizzle_connect(con, host, user, pass, db, port, 0,
3657
 
                       CLIENT_MULTI_STATEMENTS))
 
3778
  if (!mysql_real_connect(con, host, user, pass, db, port, 0,
 
3779
                          CLIENT_MULTI_STATEMENTS))
3658
3780
  {
3659
 
    var_set_errno(drizzle_errno(con));
3660
 
    handle_error(command, drizzle_errno(con), drizzle_error(con),
3661
 
                 drizzle_sqlstate(con), &ds_res);
 
3781
    var_set_errno(mysql_errno(con));
 
3782
    handle_error(command, mysql_errno(con), mysql_error(con),
 
3783
                 mysql_sqlstate(con), ds);
3662
3784
    return 0; /* Not connected */
3663
3785
  }
3664
3786
 
3669
3791
 
3670
3792
 
3671
3793
/*
3672
 
  Open a new connection to DRIZZLE Server with the parameters
 
3794
  Open a new connection to MySQL Server with the parameters
3673
3795
  specified. Make the new connection the current connection.
3674
3796
 
3675
3797
  SYNOPSIS
3676
3798
  do_connect()
3677
 
  q         called command
 
3799
  q            called command
3678
3800
 
3679
3801
  DESCRIPTION
3680
3802
  connect(<name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]]);
3688
3810
  <port> - server port
3689
3811
  <sock> - server socket
3690
3812
  <opts> - options to use for the connection
3691
 
  * SSL - use SSL if available
3692
 
  * COMPRESS - use compression if available
 
3813
   * SSL - use SSL if available
 
3814
   * COMPRESS - use compression if available
3693
3815
 
3694
 
  */
 
3816
*/
3695
3817
 
3696
3818
static void do_connect(struct st_command *command)
3697
3819
{
3698
3820
  int con_port= opt_port;
3699
 
  const char *con_options;
 
3821
  char *con_options;
3700
3822
  bool con_ssl= 0, con_compress= 0;
3701
3823
  struct st_connection* con_slot;
3702
3824
 
3703
 
  string ds_connection_name;
3704
 
  string ds_host;
3705
 
  string ds_user;
3706
 
  string ds_password;
3707
 
  string ds_database;
3708
 
  string ds_port;
3709
 
  string ds_sock;
3710
 
  string ds_options;
 
3825
  static DYNAMIC_STRING ds_connection_name;
 
3826
  static DYNAMIC_STRING ds_host;
 
3827
  static DYNAMIC_STRING ds_user;
 
3828
  static DYNAMIC_STRING ds_password;
 
3829
  static DYNAMIC_STRING ds_database;
 
3830
  static DYNAMIC_STRING ds_port;
 
3831
  static DYNAMIC_STRING ds_sock;
 
3832
  static DYNAMIC_STRING ds_options;
3711
3833
  const struct command_arg connect_args[] = {
3712
3834
    { "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3713
3835
    { "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3726
3848
                     ',');
3727
3849
 
3728
3850
  /* Port */
3729
 
  if (ds_port.length())
 
3851
  if (ds_port.length)
3730
3852
  {
3731
 
    con_port= atoi(ds_port.c_str());
 
3853
    con_port= atoi(ds_port.str);
3732
3854
    if (con_port == 0)
3733
 
      die("Illegal argument for port: '%s'", ds_port.c_str());
 
3855
      die("Illegal argument for port: '%s'", ds_port.str);
3734
3856
  }
3735
3857
 
3736
3858
  /* Sock */
3737
 
  if (!ds_sock.empty())
 
3859
  if (ds_sock.length)
3738
3860
  {
3739
3861
    /*
3740
3862
      If the socket is specified just as a name without path
3741
3863
      append tmpdir in front
3742
3864
    */
3743
 
    if (*ds_sock.c_str() != FN_LIBCHAR)
 
3865
    if (*ds_sock.str != FN_LIBCHAR)
3744
3866
    {
3745
3867
      char buff[FN_REFLEN];
3746
 
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3747
 
      ds_sock= buff;
 
3868
      fn_format(buff, ds_sock.str, TMPDIR, "", 0);
 
3869
      dynstr_set(&ds_sock, buff);
3748
3870
    }
3749
3871
  }
 
3872
  else
 
3873
  {
 
3874
    /* No socket specified, use default */
 
3875
    dynstr_set(&ds_sock, unix_sock);
 
3876
  }
3750
3877
 
3751
3878
  /* Options */
3752
 
  con_options= ds_options.c_str();
 
3879
  con_options= ds_options.str;
3753
3880
  while (*con_options)
3754
3881
  {
3755
 
    const char* end;
 
3882
    char* end;
3756
3883
    /* Step past any spaces in beginning of option*/
3757
3884
    while (*con_options && my_isspace(charset_info, *con_options))
3758
 
      con_options++;
 
3885
     con_options++;
3759
3886
    /* Find end of this option */
3760
3887
    end= con_options;
3761
3888
    while (*end && !my_isspace(charset_info, *end))
3765
3892
    else if (!strncmp(con_options, "COMPRESS", 8))
3766
3893
      con_compress= 1;
3767
3894
    else
3768
 
      die("Illegal option to connect: %.*s",
 
3895
      die("Illegal option to connect: %.*s", 
3769
3896
          (int) (end - con_options), con_options);
3770
3897
    /* Process next option */
3771
3898
    con_options= end;
3772
3899
  }
3773
3900
 
3774
 
  if (find_connection_by_name(ds_connection_name.c_str()))
3775
 
    die("Connection %s already exists", ds_connection_name.c_str());
3776
 
 
 
3901
  if (find_connection_by_name(ds_connection_name.str))
 
3902
    die("Connection %s already exists", ds_connection_name.str);
 
3903
    
3777
3904
  if (next_con != connections_end)
3778
 
  {
3779
3905
    con_slot= next_con;
3780
 
  }
3781
3906
  else
3782
3907
  {
3783
3908
    if (!(con_slot= find_connection_by_name("-closed_connection-")))
3785
3910
          (int) (sizeof(connections)/sizeof(struct st_connection)));
3786
3911
  }
3787
3912
 
3788
 
  if (!drizzle_create(&con_slot->drizzle))
3789
 
    die("Failed on drizzle_create()");
 
3913
#ifdef EMBEDDED_LIBRARY
 
3914
  con_slot->query_done= 1;
 
3915
#endif
 
3916
  if (!mysql_init(&con_slot->mysql))
 
3917
    die("Failed on mysql_init()");
3790
3918
  if (opt_compress || con_compress)
3791
 
    drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NULL);
3792
 
  drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
3919
    mysql_options(&con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
 
3920
  mysql_options(&con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
 
3921
  mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_NAME,
 
3922
                charset_info->csname);
 
3923
  int opt_protocol= MYSQL_PROTOCOL_TCP;
 
3924
  mysql_options(&con_slot->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
3925
  if (opt_charsets_dir)
 
3926
    mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
 
3927
                  opt_charsets_dir);
3793
3928
 
3794
3929
  /* Use default db name */
3795
 
  if (ds_database.length() == 0)
3796
 
    ds_database= opt_db;
 
3930
  if (ds_database.length == 0)
 
3931
    dynstr_set(&ds_database, opt_db);
3797
3932
 
3798
3933
  /* Special database to allow one to connect without a database name */
3799
 
  if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
3800
 
    ds_database= "";
 
3934
  if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
 
3935
    dynstr_set(&ds_database, "");
3801
3936
 
3802
 
  if (connect_n_handle_errors(command, &con_slot->drizzle,
3803
 
                              ds_host.c_str(),ds_user.c_str(),
3804
 
                              ds_password.c_str(), ds_database.c_str(),
3805
 
                              con_port, ds_sock.c_str()))
 
3937
  if (connect_n_handle_errors(command, &con_slot->mysql,
 
3938
                              ds_host.str,ds_user.str,
 
3939
                              ds_password.str, ds_database.str,
 
3940
                              con_port, ds_sock.str))
3806
3941
  {
3807
 
    if (!(con_slot->name= strdup(ds_connection_name.c_str())))
 
3942
    if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3808
3943
      die("Out of memory");
3809
3944
    cur_con= con_slot;
3810
 
 
 
3945
    
3811
3946
    if (con_slot == next_con)
3812
3947
      next_con++; /* if we used the next_con slot, advance the pointer */
3813
3948
  }
3814
3949
 
3815
 
  /* Update $drizzle_get_server_version to that of current connection */
3816
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
3950
  /* Update $mysql_get_server_version to that of current connection */
 
3951
  var_set_mysql_get_server_version(&cur_con->mysql);
3817
3952
 
 
3953
  dynstr_free(&ds_connection_name);
 
3954
  dynstr_free(&ds_host);
 
3955
  dynstr_free(&ds_user);
 
3956
  dynstr_free(&ds_password);
 
3957
  dynstr_free(&ds_database);
 
3958
  dynstr_free(&ds_port);
 
3959
  dynstr_free(&ds_sock);
 
3960
  dynstr_free(&ds_options);
3818
3961
  return;
3819
3962
}
3820
3963
 
3852
3995
  SYNOPSIS
3853
3996
  do_block()
3854
3997
  cmd        Type of block
3855
 
  q         called command
 
3998
  q            called command
3856
3999
 
3857
4000
  DESCRIPTION
3858
4001
  if ([!]<expr>)
3962
4105
    return 0;
3963
4106
 
3964
4107
  for (i= 1; i < length &&
3965
 
         (c= my_getc(cur_file->file)) == *(delim + i);
 
4108
         (c= my_getc(cur_file->file)) == *(delim + i);
3966
4109
       i++)
3967
4110
    tmp[i]= c;
3968
4111
 
3969
4112
  if (i == length)
3970
 
    return 1;          /* Found delimiter */
 
4113
    return 1;                                   /* Found delimiter */
3971
4114
 
3972
4115
  /* didn't find delimiter, push back things that we read */
3973
4116
  my_ungetc(c);
4026
4169
  found_eof:
4027
4170
      if (cur_file->file != stdin)
4028
4171
      {
4029
 
        my_fclose(cur_file->file, MYF(0));
 
4172
        my_fclose(cur_file->file, MYF(0));
4030
4173
        cur_file->file= 0;
4031
4174
      }
4032
 
      free((unsigned char*) cur_file->file_name);
 
4175
      my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
4033
4176
      cur_file->file_name= 0;
4034
4177
      if (cur_file == file_stack)
4035
4178
      {
4061
4204
    case R_NORMAL:
4062
4205
      if (end_of_query(c))
4063
4206
      {
4064
 
        *p= 0;
4065
 
        return(0);
 
4207
        *p= 0;
 
4208
        return(0);
4066
4209
      }
4067
4210
      else if ((c == '{' &&
4068
 
                (!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
4069
 
                                      (unsigned char*) buf, cmin((long)5, p - buf), 0) ||
4070
 
                 !my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
4071
 
                                      (unsigned char*) buf, cmin((long)2, p - buf), 0))))
 
4211
                (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
 
4212
                                      (uchar*) buf, min(5, p - buf), 0) ||
 
4213
                 !my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
 
4214
                                      (uchar*) buf, min(2, p - buf), 0))))
4072
4215
      {
4073
4216
        /* Only if and while commands can be terminated by { */
4074
4217
        *p++= c;
4075
 
        *p= 0;
4076
 
        return(0);
 
4218
        *p= 0;
 
4219
        return(0);
4077
4220
      }
4078
4221
      else if (c == '\'' || c == '"' || c == '`')
4079
4222
      {
4080
4223
        last_quote= c;
4081
 
        state= R_Q;
 
4224
        state= R_Q;
4082
4225
      }
4083
4226
      break;
4084
4227
 
4086
4229
      if (c == '\n')
4087
4230
      {
4088
4231
        /* Comments are terminated by newline */
4089
 
        *p= 0;
4090
 
        return(0);
 
4232
        *p= 0;
 
4233
        return(0);
4091
4234
      }
4092
4235
      break;
4093
4236
 
4095
4238
      if (c == '#' || c == '-')
4096
4239
      {
4097
4240
        /* A # or - in the first position of the line - this is a comment */
4098
 
        state = R_COMMENT;
 
4241
        state = R_COMMENT;
4099
4242
      }
4100
4243
      else if (my_isspace(charset_info, c))
4101
4244
      {
4102
4245
        /* Skip all space at begining of line */
4103
 
        if (c == '\n')
 
4246
        if (c == '\n')
4104
4247
        {
4105
4248
          /* Query hasn't started yet */
4106
 
          start_lineno= cur_file->lineno;
 
4249
          start_lineno= cur_file->lineno;
4107
4250
        }
4108
 
        skip_char= 1;
 
4251
        skip_char= 1;
4109
4252
      }
4110
4253
      else if (end_of_query(c))
4111
4254
      {
4112
 
        *p= 0;
4113
 
        return(0);
 
4255
        *p= 0;
 
4256
        return(0);
4114
4257
      }
4115
4258
      else if (c == '}')
4116
4259
      {
4117
4260
        /* A "}" need to be by itself in the begining of a line to terminate */
4118
4261
        *p++= c;
4119
 
        *p= 0;
4120
 
        return(0);
 
4262
        *p= 0;
 
4263
        return(0);
4121
4264
      }
4122
4265
      else if (c == '\'' || c == '"' || c == '`')
4123
4266
      {
4124
4267
        last_quote= c;
4125
 
        state= R_Q;
 
4268
        state= R_Q;
4126
4269
      }
4127
4270
      else
4128
 
        state= R_NORMAL;
 
4271
        state= R_NORMAL;
4129
4272
      break;
4130
4273
 
4131
4274
    case R_Q:
4132
4275
      if (c == last_quote)
4133
 
        state= R_NORMAL;
 
4276
        state= R_NORMAL;
4134
4277
      else if (c == '\\')
4135
 
        state= R_SLASH_IN_Q;
 
4278
        state= R_SLASH_IN_Q;
4136
4279
      break;
4137
4280
 
4138
4281
    case R_SLASH_IN_Q:
4151
4294
      /* completed before we pass buf_end */
4152
4295
      if ((charlen > 1) && (p + charlen) <= buf_end)
4153
4296
      {
4154
 
        int i;
4155
 
        char* mb_start = p;
4156
 
 
4157
 
        *p++ = c;
4158
 
 
4159
 
        for (i= 1; i < charlen; i++)
4160
 
        {
4161
 
          if (feof(cur_file->file))
4162
 
            goto found_eof;
4163
 
          c= my_getc(cur_file->file);
4164
 
          *p++ = c;
4165
 
        }
4166
 
        if (! my_ismbchar(charset_info, mb_start, p))
4167
 
        {
4168
 
          /* It was not a multiline char, push back the characters */
4169
 
          /* We leave first 'c', i.e. pretend it was a normal char */
4170
 
          while (p > mb_start)
4171
 
            my_ungetc(*--p);
4172
 
        }
 
4297
        int i;
 
4298
        char* mb_start = p;
 
4299
 
 
4300
        *p++ = c;
 
4301
 
 
4302
        for (i= 1; i < charlen; i++)
 
4303
        {
 
4304
          if (feof(cur_file->file))
 
4305
            goto found_eof;
 
4306
          c= my_getc(cur_file->file);
 
4307
          *p++ = c;
 
4308
        }
 
4309
        if (! my_ismbchar(charset_info, mb_start, p))
 
4310
        {
 
4311
          /* It was not a multiline char, push back the characters */
 
4312
          /* We leave first 'c', i.e. pretend it was a normal char */
 
4313
          while (p > mb_start)
 
4314
            my_ungetc(*--p);
 
4315
        }
4173
4316
      }
4174
4317
      else
4175
4318
#endif
4176
 
        *p++= c;
 
4319
        *p++= c;
4177
4320
    }
4178
4321
  }
4179
 
  die("The input buffer is too small for this query.x\n"        \
 
4322
  die("The input buffer is too small for this query.x\n" \
4180
4323
      "check your query or increase MAX_QUERY and recompile");
4181
4324
  return(0);
4182
4325
}
4197
4340
{
4198
4341
  int last_c_was_quote= 0;
4199
4342
  char *p= query, *to= query;
4200
 
  char *end= strchr(query, '\0');
 
4343
  char *end= strend(query);
4201
4344
  char last_c;
4202
4345
 
4203
4346
  while (p <= end)
4236
4379
 
4237
4380
/*
4238
4381
  Check a command that is about to be sent (or should have been
4239
 
  sent if parsing was enabled) to DRIZZLE server for
 
4382
  sent if parsing was enabled) to mysql server for
4240
4383
  suspicious things and generate warnings.
4241
4384
*/
4242
4385
 
4248
4391
  {
4249
4392
    /*
4250
4393
      Look for query's that lines that start with a -- comment
4251
 
      and has a drizzletest command
 
4394
      and has a mysqltest command
4252
4395
    */
4253
4396
    if (ptr[0] == '\n' &&
4254
4397
        ptr[1] && ptr[1] == '-' &&
4269
4412
      *end= 0;
4270
4413
      type= find_type(start, &command_typelib, 1+2);
4271
4414
      if (type)
4272
 
        warning_msg("Embedded drizzletest command '--%s' detected in "
 
4415
        warning_msg("Embedded mysqltest command '--%s' detected in "
4273
4416
                    "query '%s' was this intentional? ",
4274
4417
                    start, command->query);
4275
4418
      *end= save;
4338
4481
  Create a command from a set of lines
4339
4482
 
4340
4483
  SYNOPSIS
4341
 
  read_command()
4342
 
  command_ptr pointer where to return the new query
 
4484
    read_command()
 
4485
    command_ptr pointer where to return the new query
4343
4486
 
4344
4487
  DESCRIPTION
4345
 
  Converts lines returned by read_line into a command, this involves
4346
 
  parsing the first word in the read line to find the command type.
 
4488
    Converts lines returned by read_line into a command, this involves
 
4489
    parsing the first word in the read line to find the command type.
4347
4490
 
4348
4491
  A -- comment may contain a valid query as the first word after the
4349
4492
  comment start. Thus it's always checked to see if that is the case.
4362
4505
 
4363
4506
  if (parser.current_line < parser.read_lines)
4364
4507
  {
4365
 
    *command_ptr= q_lines[parser.current_line];
 
4508
    get_dynamic(&q_lines, (uchar*) command_ptr, parser.current_line) ;
4366
4509
    return(0);
4367
4510
  }
4368
4511
  if (!(*command_ptr= command=
4369
4512
        (struct st_command*) my_malloc(sizeof(*command),
4370
 
                                       MYF(MY_WME|MY_ZEROFILL))))
4371
 
    die(NULL);
4372
 
  q_lines.push_back(command);
 
4513
                                       MYF(MY_WME|MY_ZEROFILL))) ||
 
4514
      insert_dynamic(&q_lines, (uchar*) &command))
 
4515
    die(NullS);
4373
4516
  command->type= Q_UNKNOWN;
4374
4517
 
4375
4518
  read_command_buf[0]= 0;
4409
4552
    p++;
4410
4553
  command->first_argument= p;
4411
4554
 
4412
 
  command->end= strchr(command->query, '\0');
 
4555
  command->end= strend(command->query);
4413
4556
  command->query_len= (command->end - command->query);
4414
4557
  parser.read_lines++;
4415
4558
  return(0);
4453
4596
  {"password", 'p', "Password to use when connecting to server.",
4454
4597
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4455
4598
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
4456
 
   "order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
4457
 
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
 
4599
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
 
4600
#if MYSQL_PORT_DEFAULT == 0
 
4601
   "/etc/services, "
 
4602
#endif
 
4603
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
4458
4604
   (char**) &opt_port,
4459
4605
   (char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4460
4606
  {"quiet", 's', "Suppress all normal output.", (char**) &silent,
4493
4639
};
4494
4640
 
4495
4641
 
 
4642
#include <help_start.h>
 
4643
 
4496
4644
static void print_version(void)
4497
4645
{
4498
4646
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4499
 
         drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
4647
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
4500
4648
}
4501
4649
 
4502
4650
static void usage(void)
4504
4652
  print_version();
4505
4653
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4506
4654
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4507
 
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
 
4655
  printf("Runs a test against the mysql server and compares output with a results file.\n\n");
4508
4656
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4509
4657
  my_print_help(my_long_options);
4510
4658
  printf("  --no-defaults       Don't read default options from any options file.\n");
4511
4659
  my_print_variables(my_long_options);
4512
4660
}
4513
4661
 
 
4662
#include <help_end.h>
 
4663
 
 
4664
 
4514
4665
/*
4515
4666
  Read arguments for embedded server and put them into
4516
4667
  embedded_server_args[]
4523
4674
 
4524
4675
  if (!test_if_hard_path(name))
4525
4676
  {
4526
 
    strxmov(buff, opt_basedir, name, NULL);
 
4677
    strxmov(buff, opt_basedir, name, NullS);
4527
4678
    name=buff;
4528
4679
  }
4529
4680
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
4531
4682
  if (!embedded_server_arg_count)
4532
4683
  {
4533
4684
    embedded_server_arg_count=1;
4534
 
    embedded_server_args[0]= (char*) "";    /* Progname */
 
4685
    embedded_server_args[0]= (char*) "";                /* Progname */
4535
4686
  }
4536
4687
  if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4537
4688
    die("Failed to open file '%s'", buff);
4538
4689
 
4539
4690
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4540
 
         (str=fgets(argument,sizeof(argument), file)))
 
4691
         (str=fgets(argument,sizeof(argument), file)))
4541
4692
  {
4542
 
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
 
4693
    *(strend(str)-1)=0;                         /* Remove end newline */
4543
4694
    if (!(embedded_server_args[embedded_server_arg_count]=
4544
 
          (char*) my_strdup(str,MYF(MY_WME))))
 
4695
          (char*) my_strdup(str,MYF(MY_WME))))
4545
4696
    {
4546
4697
      my_fclose(file,MYF(0));
4547
4698
      die("Out of memory");
4559
4710
 
4560
4711
static bool
4561
4712
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
4562
 
               char *argument)
 
4713
               char *argument)
4563
4714
{
4564
4715
  switch(optid) {
4565
4716
  case 'r':
4570
4721
    char buff[FN_REFLEN];
4571
4722
    if (!test_if_hard_path(argument))
4572
4723
    {
4573
 
      strxmov(buff, opt_basedir, argument, NULL);
 
4724
      strxmov(buff, opt_basedir, argument, NullS);
4574
4725
      argument= buff;
4575
4726
    }
4576
4727
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4587
4738
    static char buff[FN_REFLEN];
4588
4739
    if (!test_if_hard_path(argument))
4589
4740
    {
4590
 
      strxmov(buff, opt_basedir, argument, NULL);
 
4741
      strxmov(buff, opt_basedir, argument, NullS);
4591
4742
      argument= buff;
4592
4743
    }
4593
4744
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4594
4745
    timer_file= buff;
4595
 
    unlink(timer_file);       /* Ignore error, may not exist */
 
4746
    unlink(timer_file);      /* Ignore error, may not exist */
4596
4747
    break;
4597
4748
  }
4598
4749
  case 'p':
4599
4750
    if (argument)
4600
4751
    {
4601
 
      free(opt_pass);
 
4752
      my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
4602
4753
      opt_pass= my_strdup(argument, MYF(MY_FAE));
4603
 
      while (*argument) *argument++= 'x';    /* Destroy argument */
 
4754
      while (*argument) *argument++= 'x';               /* Destroy argument */
4604
4755
      tty_password= 0;
4605
4756
    }
4606
4757
    else
4607
4758
      tty_password= 1;
4608
4759
    break;
4609
4760
  case 't':
4610
 
    my_stpncpy(TMPDIR, argument, sizeof(TMPDIR));
 
4761
    strnmov(TMPDIR, argument, sizeof(TMPDIR));
4611
4762
    break;
4612
4763
  case 'A':
4613
4764
    if (!embedded_server_arg_count)
4652
4803
  if (argc == 1)
4653
4804
    opt_db= *argv;
4654
4805
  if (tty_password)
4655
 
    opt_pass= get_tty_password(NULL);          /* purify tested */
 
4806
    opt_pass= get_tty_password(NullS);          /* purify tested */
4656
4807
  if (debug_info_flag)
4657
4808
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
4658
4809
  if (debug_check_flag)
4672
4823
  append - append to file instead of overwriting old file
4673
4824
*/
4674
4825
 
4675
 
void str_to_file2(const char *fname, const char *str, int size, bool append)
 
4826
void str_to_file2(const char *fname, char *str, int size, bool append)
4676
4827
{
4677
4828
  int fd;
4678
4829
  char buff[FN_REFLEN];
4679
4830
  int flags= O_WRONLY | O_CREAT;
4680
4831
  if (!test_if_hard_path(fname))
4681
4832
  {
4682
 
    strxmov(buff, opt_basedir, fname, NULL);
 
4833
    strxmov(buff, opt_basedir, fname, NullS);
4683
4834
    fname= buff;
4684
4835
  }
4685
4836
  fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4691
4842
    die("Could not open '%s' for writing: errno = %d", buff, errno);
4692
4843
  if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
4693
4844
    die("Could not find end of file '%s': errno = %d", buff, errno);
4694
 
  if (my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
 
4845
  if (my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP)))
4695
4846
    die("write failed");
4696
4847
  my_close(fd, MYF(0));
4697
4848
}
4706
4857
  size - size of content witten to file
4707
4858
*/
4708
4859
 
4709
 
void str_to_file(const char *fname, const char *str, int size)
 
4860
void str_to_file(const char *fname, char *str, int size)
4710
4861
{
4711
4862
  str_to_file2(fname, str, size, false);
4712
4863
}
4713
4864
 
4714
4865
 
4715
 
void dump_result_to_log_file(const char *buf, int size)
 
4866
void dump_result_to_log_file(char *buf, int size)
4716
4867
{
4717
4868
  char log_file[FN_REFLEN];
4718
4869
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
4730
4881
                        opt_logdir, ".progress",
4731
4882
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4732
4883
                        MY_REPLACE_EXT),
4733
 
              ds_progress.c_str(), ds_progress.length());
 
4884
              ds_progress.str, ds_progress.length);
4734
4885
}
4735
4886
 
4736
4887
void dump_warning_messages(void)
4740
4891
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
4741
4892
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4742
4893
                        MY_REPLACE_EXT),
4743
 
              ds_warning_messages.c_str(), ds_warning_messages.length());
 
4894
              ds_warning_messages.str, ds_warning_messages.length);
4744
4895
}
4745
4896
 
4746
4897
 
4748
4899
  Append the result for one field to the dynamic string ds
4749
4900
*/
4750
4901
 
4751
 
static void append_field(string *ds, uint col_idx, const DRIZZLE_FIELD* field,
 
4902
static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
4752
4903
                         const char* val, uint64_t len, bool is_null)
4753
4904
{
4754
4905
  if (col_idx < max_replace_column && replace_column[col_idx])
4765
4916
  if (!display_result_vertically)
4766
4917
  {
4767
4918
    if (col_idx)
4768
 
      ds->append("\t");
4769
 
    replace_append_mem(ds, val, (int)len);
 
4919
      dynstr_append_mem(ds, "\t", 1);
 
4920
    replace_dynstr_append_mem(ds, val, (int)len);
4770
4921
  }
4771
4922
  else
4772
4923
  {
4773
 
    ds->append(field->name);
4774
 
    ds->append("\t");
4775
 
    replace_append_mem(ds, val, (int)len);
4776
 
    ds->append("\n");
 
4924
    dynstr_append(ds, field->name);
 
4925
    dynstr_append_mem(ds, "\t", 1);
 
4926
    replace_dynstr_append_mem(ds, val, (int)len);
 
4927
    dynstr_append_mem(ds, "\n", 1);
4777
4928
  }
4778
4929
}
4779
4930
 
4783
4934
  Values may be converted with 'replace_column'
4784
4935
*/
4785
4936
 
4786
 
static void append_result(string *ds, DRIZZLE_RES *res)
 
4937
static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
4787
4938
{
4788
 
  DRIZZLE_ROW row;
4789
 
  uint32_t num_fields= drizzle_num_fields(res);
4790
 
  const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
4939
  MYSQL_ROW row;
 
4940
  uint32_t num_fields= mysql_num_fields(res);
 
4941
  MYSQL_FIELD *fields= mysql_fetch_fields(res);
4791
4942
  uint32_t *lengths;
4792
4943
 
4793
 
  while ((row = drizzle_fetch_row(res)))
 
4944
  while ((row = mysql_fetch_row(res)))
4794
4945
  {
4795
4946
    uint32_t i;
4796
 
    lengths = drizzle_fetch_lengths(res);
 
4947
    lengths = mysql_fetch_lengths(res);
4797
4948
    for (i = 0; i < num_fields; i++)
4798
4949
      append_field(ds, i, &fields[i],
4799
4950
                   (const char*)row[i], lengths[i], !row[i]);
4800
4951
    if (!display_result_vertically)
4801
 
      ds->append("\n");
4802
 
 
 
4952
      dynstr_append_mem(ds, "\n", 1);
4803
4953
  }
4804
4954
}
4805
4955
 
4808
4958
  Append metadata for fields to output
4809
4959
*/
4810
4960
 
4811
 
static void append_metadata(string *ds,
4812
 
                            const DRIZZLE_FIELD *field,
 
4961
static void append_metadata(DYNAMIC_STRING *ds,
 
4962
                            MYSQL_FIELD *field,
4813
4963
                            uint num_fields)
4814
4964
{
4815
 
  const DRIZZLE_FIELD *field_end;
4816
 
  ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4817
 
             "Column_alias\tType\tLength\tMax length\tIs_null\t"
4818
 
             "Flags\tDecimals\tCharsetnr\n");
 
4965
  MYSQL_FIELD *field_end;
 
4966
  dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
 
4967
                "Column_alias\tType\tLength\tMax length\tIs_null\t"
 
4968
                "Flags\tDecimals\tCharsetnr\n");
4819
4969
 
4820
4970
  for (field_end= field+num_fields ;
4821
4971
       field < field_end ;
4822
4972
       field++)
4823
4973
  {
4824
 
    ds->append(field->catalog,
4825
 
               field->catalog_length);
4826
 
    ds->append("\t", 1);
4827
 
    ds->append(field->db, field->db_length);
4828
 
    ds->append("\t", 1);
4829
 
    ds->append(field->org_table,
4830
 
               field->org_table_length);
4831
 
    ds->append("\t", 1);
4832
 
    ds->append(field->table,
4833
 
               field->table_length);
4834
 
    ds->append("\t", 1);
4835
 
    ds->append(field->org_name,
4836
 
               field->org_name_length);
4837
 
    ds->append("\t", 1);
4838
 
    ds->append(field->name, field->name_length);
4839
 
    ds->append("\t", 1);
4840
 
    replace_append_uint(ds, field->type);
4841
 
    ds->append("\t", 1);
4842
 
    replace_append_uint(ds, field->length);
4843
 
    ds->append("\t", 1);
4844
 
    replace_append_uint(ds, field->max_length);
4845
 
    ds->append("\t", 1);
4846
 
    ds->append((char*) ((field->flags & NOT_NULL_FLAG) ?
4847
 
                        "N" : "Y"), 1);
4848
 
    ds->append("\t", 1);
4849
 
    replace_append_uint(ds, field->flags);
4850
 
    ds->append("\t", 1);
4851
 
    replace_append_uint(ds, field->decimals);
4852
 
    ds->append("\t", 1);
4853
 
    replace_append_uint(ds, field->charsetnr);
4854
 
    ds->append("\n", 1);
 
4974
    dynstr_append_mem(ds, field->catalog,
 
4975
                      field->catalog_length);
 
4976
    dynstr_append_mem(ds, "\t", 1);
 
4977
    dynstr_append_mem(ds, field->db, field->db_length);
 
4978
    dynstr_append_mem(ds, "\t", 1);
 
4979
    dynstr_append_mem(ds, field->org_table,
 
4980
                      field->org_table_length);
 
4981
    dynstr_append_mem(ds, "\t", 1);
 
4982
    dynstr_append_mem(ds, field->table,
 
4983
                      field->table_length);
 
4984
    dynstr_append_mem(ds, "\t", 1);
 
4985
    dynstr_append_mem(ds, field->org_name,
 
4986
                      field->org_name_length);
 
4987
    dynstr_append_mem(ds, "\t", 1);
 
4988
    dynstr_append_mem(ds, field->name, field->name_length);
 
4989
    dynstr_append_mem(ds, "\t", 1);
 
4990
    replace_dynstr_append_uint(ds, field->type);
 
4991
    dynstr_append_mem(ds, "\t", 1);
 
4992
    replace_dynstr_append_uint(ds, field->length);
 
4993
    dynstr_append_mem(ds, "\t", 1);
 
4994
    replace_dynstr_append_uint(ds, field->max_length);
 
4995
    dynstr_append_mem(ds, "\t", 1);
 
4996
    dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
 
4997
                                   "N" : "Y"), 1);
 
4998
    dynstr_append_mem(ds, "\t", 1);
 
4999
    replace_dynstr_append_uint(ds, field->flags);
 
5000
    dynstr_append_mem(ds, "\t", 1);
 
5001
    replace_dynstr_append_uint(ds, field->decimals);
 
5002
    dynstr_append_mem(ds, "\t", 1);
 
5003
    replace_dynstr_append_uint(ds, field->charsetnr);
 
5004
    dynstr_append_mem(ds, "\n", 1);
4855
5005
  }
4856
5006
}
4857
5007
 
4860
5010
  Append affected row count and other info to output
4861
5011
*/
4862
5012
 
4863
 
static void append_info(string *ds, uint64_t affected_rows,
 
5013
static void append_info(DYNAMIC_STRING *ds, uint64_t affected_rows,
4864
5014
                        const char *info)
4865
5015
{
4866
5016
  char buf[40], buff2[21];
4867
5017
  sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
4868
 
  ds->append(buf);
 
5018
  dynstr_append(ds, buf);
4869
5019
  if (info)
4870
5020
  {
4871
 
    ds->append("info: ");
4872
 
    ds->append(info);
4873
 
    ds->append("\n", 1);
 
5021
    dynstr_append(ds, "info: ");
 
5022
    dynstr_append(ds, info);
 
5023
    dynstr_append_mem(ds, "\n", 1);
4874
5024
  }
4875
5025
}
4876
5026
 
4879
5029
  Display the table headings with the names tab separated
4880
5030
*/
4881
5031
 
4882
 
static void append_table_headings(string *ds,
4883
 
                                  const DRIZZLE_FIELD *field,
 
5032
static void append_table_headings(DYNAMIC_STRING *ds,
 
5033
                                  MYSQL_FIELD *field,
4884
5034
                                  uint num_fields)
4885
5035
{
4886
5036
  uint col_idx;
4887
5037
  for (col_idx= 0; col_idx < num_fields; col_idx++)
4888
5038
  {
4889
5039
    if (col_idx)
4890
 
      ds->append("\t", 1);
4891
 
    replace_append(ds, field[col_idx].name);
 
5040
      dynstr_append_mem(ds, "\t", 1);
 
5041
    replace_dynstr_append(ds, field[col_idx].name);
4892
5042
  }
4893
 
  ds->append("\n", 1);
 
5043
  dynstr_append_mem(ds, "\n", 1);
4894
5044
}
4895
5045
 
4896
5046
/*
4900
5050
  Number of warnings appended to ds
4901
5051
*/
4902
5052
 
4903
 
static int append_warnings(string *ds, DRIZZLE *drizzle)
 
5053
static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
4904
5054
{
4905
5055
  uint count;
4906
 
  DRIZZLE_RES *warn_res;
4907
 
 
4908
 
 
4909
 
  if (!(count= drizzle_warning_count(drizzle)))
 
5056
  MYSQL_RES *warn_res;
 
5057
 
 
5058
 
 
5059
  if (!(count= mysql_warning_count(mysql)))
4910
5060
    return(0);
4911
5061
 
4912
5062
  /*
4914
5064
    through PS API we should not issue SHOW WARNINGS until
4915
5065
    we have not read all results...
4916
5066
  */
4917
 
  assert(!drizzle_more_results(drizzle));
4918
 
 
4919
 
  if (drizzle_real_query(drizzle, "SHOW WARNINGS", 13))
4920
 
    die("Error running query \"SHOW WARNINGS\": %s", drizzle_error(drizzle));
4921
 
 
4922
 
  if (!(warn_res= drizzle_store_result(drizzle)))
 
5067
  assert(!mysql_more_results(mysql));
 
5068
 
 
5069
  if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
 
5070
    die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql));
 
5071
 
 
5072
  if (!(warn_res= mysql_store_result(mysql)))
4923
5073
    die("Warning count is %u but didn't get any warnings",
4924
 
        count);
 
5074
        count);
4925
5075
 
4926
5076
  append_result(ds, warn_res);
 
5077
  mysql_free_result(warn_res);
4927
5078
 
4928
5079
  return(count);
4929
5080
}
4930
5081
 
4931
5082
 
4932
5083
/*
4933
 
  Run query using DRIZZLE C API
 
5084
  Run query using MySQL C API
4934
5085
 
4935
5086
  SYNOPSIS
4936
 
  run_query_normal()
4937
 
  drizzle  DRIZZLE handle
4938
 
  command  current command pointer
4939
 
  flags  flags indicating if we should SEND and/or REAP
4940
 
  query  query string to execute
4941
 
  query_len  length query string to execute
4942
 
  ds    output buffer where to store result form query
 
5087
    run_query_normal()
 
5088
    mysql       mysql handle
 
5089
    command     current command pointer
 
5090
    flags       flags indicating if we should SEND and/or REAP
 
5091
    query       query string to execute
 
5092
    query_len   length query string to execute
 
5093
    ds          output buffer where to store result form query
4943
5094
*/
4944
5095
 
4945
5096
static void run_query_normal(struct st_connection *cn,
4946
5097
                             struct st_command *command,
4947
5098
                             int flags, char *query, int query_len,
4948
 
                             string *ds, string *ds_warnings)
 
5099
                             DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4949
5100
{
4950
 
  DRIZZLE_RES *res= 0;
4951
 
  DRIZZLE *drizzle= &cn->drizzle;
 
5101
  MYSQL_RES *res= 0;
 
5102
  MYSQL *mysql= &cn->mysql;
4952
5103
  int err= 0, counter= 0;
4953
5104
 
4954
5105
  if (flags & QUERY_SEND_FLAG)
4955
5106
  {
4956
5107
    /*
4957
 
     * Send the query
4958
 
     */
 
5108
      Send the query
 
5109
    */
4959
5110
    if (do_send_query(cn, query, query_len, flags))
4960
5111
    {
4961
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4962
 
                   drizzle_sqlstate(drizzle), ds);
 
5112
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5113
                   mysql_sqlstate(mysql), ds);
4963
5114
      goto end;
4964
5115
    }
4965
5116
  }
 
5117
#ifdef EMBEDDED_LIBRARY
 
5118
  /*
 
5119
    Here we handle 'reap' command, so we need to check if the
 
5120
    query's thread was finished and probably wait
 
5121
  */
 
5122
  else if (flags & QUERY_REAP_FLAG)
 
5123
    wait_query_thread_end(cn);
 
5124
#endif /*EMBEDDED_LIBRARY*/
4966
5125
  if (!(flags & QUERY_REAP_FLAG))
4967
5126
    return;
4968
5127
 
4969
5128
  do
4970
5129
  {
4971
5130
    /*
4972
 
      When  on first result set, call drizzle_read_query_result to retrieve
 
5131
      When  on first result set, call mysql_read_query_result to retrieve
4973
5132
      answer to the query sent earlier
4974
5133
    */
4975
 
    if ((counter==0) && drizzle_read_query_result(drizzle))
 
5134
    if ((counter==0) && mysql_read_query_result(mysql))
4976
5135
    {
4977
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4978
 
                   drizzle_sqlstate(drizzle), ds);
 
5136
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5137
                   mysql_sqlstate(mysql), ds);
4979
5138
      goto end;
4980
5139
 
4981
5140
    }
4983
5142
    /*
4984
5143
      Store the result of the query if it will return any fields
4985
5144
    */
4986
 
    if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
 
5145
    if (mysql_field_count(mysql) && ((res= mysql_store_result(mysql)) == 0))
4987
5146
    {
4988
 
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4989
 
                   drizzle_sqlstate(drizzle), ds);
 
5147
      handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5148
                   mysql_sqlstate(mysql), ds);
4990
5149
      goto end;
4991
5150
    }
4992
5151
 
4996
5155
 
4997
5156
      if (res)
4998
5157
      {
4999
 
        const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
5000
 
        uint num_fields= drizzle_num_fields(res);
 
5158
        MYSQL_FIELD *fields= mysql_fetch_fields(res);
 
5159
        uint num_fields= mysql_num_fields(res);
5001
5160
 
5002
 
        if (display_metadata)
 
5161
        if (display_metadata)
5003
5162
          append_metadata(ds, fields, num_fields);
5004
5163
 
5005
 
        if (!display_result_vertically)
5006
 
          append_table_headings(ds, fields, num_fields);
 
5164
        if (!display_result_vertically)
 
5165
          append_table_headings(ds, fields, num_fields);
5007
5166
 
5008
 
        append_result(ds, res);
 
5167
        append_result(ds, res);
5009
5168
      }
5010
5169
 
5011
5170
      /*
5012
 
        Need to call drizzle_affected_rows() before the "new"
 
5171
        Need to call mysql_affected_rows() before the "new"
5013
5172
        query to find the warnings
5014
5173
      */
5015
5174
      if (!disable_info)
5016
 
        affected_rows= drizzle_affected_rows(drizzle);
 
5175
        affected_rows= mysql_affected_rows(mysql);
5017
5176
 
5018
5177
      /*
5019
5178
        Add all warnings to the result. We can't do this if we are in
5020
5179
        the middle of processing results from multi-statement, because
5021
5180
        this will break protocol.
5022
5181
      */
5023
 
      if (!disable_warnings && !drizzle_more_results(drizzle))
 
5182
      if (!disable_warnings && !mysql_more_results(mysql))
5024
5183
      {
5025
 
        if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
5026
 
        {
5027
 
          ds->append("Warnings:\n", 10);
5028
 
          ds->append(ds_warnings->c_str(), ds_warnings->length());
5029
 
        }
 
5184
        if (append_warnings(ds_warnings, mysql) || ds_warnings->length)
 
5185
        {
 
5186
          dynstr_append_mem(ds, "Warnings:\n", 10);
 
5187
          dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
 
5188
        }
5030
5189
      }
5031
5190
 
5032
5191
      if (!disable_info)
5033
 
        append_info(ds, affected_rows, drizzle_info(drizzle));
 
5192
        append_info(ds, affected_rows, mysql_info(mysql));
5034
5193
    }
5035
5194
 
5036
5195
    if (res)
5037
5196
    {
5038
 
      drizzle_free_result(res);
 
5197
      mysql_free_result(res);
5039
5198
      res= 0;
5040
5199
    }
5041
5200
    counter++;
5042
 
  } while (!(err= drizzle_next_result(drizzle)));
 
5201
  } while (!(err= mysql_next_result(mysql)));
5043
5202
  if (err > 0)
5044
5203
  {
5045
 
    /* We got an error from drizzle_next_result, maybe expected */
5046
 
    handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5047
 
                 drizzle_sqlstate(drizzle), ds);
 
5204
    /* We got an error from mysql_next_result, maybe expected */
 
5205
    handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 
5206
                 mysql_sqlstate(mysql), ds);
5048
5207
    goto end;
5049
5208
  }
5050
5209
  assert(err == -1); /* Successful and there are no more results */
5055
5214
end:
5056
5215
 
5057
5216
  /*
5058
 
    We save the return code (drizzle_errno(drizzle)) from the last call sent
5059
 
    to the server into the drizzletest builtin variable $drizzle_errno. This
 
5217
    We save the return code (mysql_errno(mysql)) from the last call sent
 
5218
    to the server into the mysqltest builtin variable $mysql_errno. This
5060
5219
    variable then can be used from the test case itself.
5061
5220
  */
5062
 
  var_set_errno(drizzle_errno(drizzle));
 
5221
  var_set_errno(mysql_errno(mysql));
5063
5222
  return;
5064
5223
}
5065
5224
 
5076
5235
  ds    - dynamic string which is used for output buffer
5077
5236
 
5078
5237
  NOTE
5079
 
  If there is an unexpected error this function will abort drizzletest
5080
 
  immediately.
 
5238
    If there is an unexpected error this function will abort mysqltest
 
5239
    immediately.
5081
5240
*/
5082
5241
 
5083
5242
void handle_error(struct st_command *command,
5084
5243
                  unsigned int err_errno, const char *err_error,
5085
 
                  const char *err_sqlstate, string *ds)
 
5244
                  const char *err_sqlstate, DYNAMIC_STRING *ds)
5086
5245
{
5087
5246
  uint i;
5088
5247
 
5089
5248
 
 
5249
 
5090
5250
  if (command->require_file[0])
5091
5251
  {
5092
5252
    /*
5120
5280
        if (command->expected_errors.count == 1)
5121
5281
        {
5122
5282
          /* Only log error if there is one possible error */
5123
 
          ds->append("ERROR ", 6);
5124
 
          replace_append(ds, err_sqlstate);
5125
 
          ds->append(": ", 2);
5126
 
          replace_append(ds, err_error);
5127
 
          ds->append("\n",1);
 
5283
          dynstr_append_mem(ds, "ERROR ", 6);
 
5284
          replace_dynstr_append(ds, err_sqlstate);
 
5285
          dynstr_append_mem(ds, ": ", 2);
 
5286
          replace_dynstr_append(ds, err_error);
 
5287
          dynstr_append_mem(ds,"\n",1);
5128
5288
        }
5129
5289
        /* Don't log error if we may not get an error */
5130
5290
        else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5131
5291
                 (command->expected_errors.err[0].type == ERR_ERRNO &&
5132
5292
                  command->expected_errors.err[0].code.errnum != 0))
5133
 
          ds->append("Got one of the listed errors\n");
 
5293
          dynstr_append(ds,"Got one of the listed errors\n");
5134
5294
      }
5135
5295
      /* OK */
5136
5296
      return;
5139
5299
 
5140
5300
  if (!disable_result_log)
5141
5301
  {
5142
 
    ds->append("ERROR ",6);
5143
 
    replace_append(ds, err_sqlstate);
5144
 
    ds->append(": ", 2);
5145
 
    replace_append(ds, err_error);
5146
 
    ds->append("\n", 1);
 
5302
    dynstr_append_mem(ds, "ERROR ",6);
 
5303
    replace_dynstr_append(ds, err_sqlstate);
 
5304
    dynstr_append_mem(ds, ": ", 2);
 
5305
    replace_dynstr_append(ds, err_error);
 
5306
    dynstr_append_mem(ds, "\n", 1);
5147
5307
  }
5148
5308
 
5149
5309
  if (i)
5155
5315
    else
5156
5316
      die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
5157
5317
          command->query, err_sqlstate, err_error,
5158
 
          command->expected_errors.err[0].code.sqlstate);
 
5318
          command->expected_errors.err[0].code.sqlstate);
5159
5319
  }
5160
5320
 
5161
5321
  return;
5200
5360
  Run query
5201
5361
 
5202
5362
  SYNPOSIS
5203
 
  run_query()
5204
 
  drizzle  DRIZZLE handle
5205
 
  command  currrent command pointer
 
5363
    run_query()
 
5364
     mysql      mysql handle
 
5365
     command    currrent command pointer
5206
5366
 
5207
5367
  flags control the phased/stages of query execution to be performed
5208
5368
  if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
5209
5369
  is on the result will be read - for regular query, both bits must be on
5210
5370
*/
5211
5371
 
5212
 
static void run_query(struct st_connection *cn,
 
5372
static void run_query(struct st_connection *cn, 
5213
5373
                      struct st_command *command,
5214
5374
                      int flags)
5215
5375
{
5216
 
  string *ds= NULL;
5217
 
  string *save_ds= NULL;
5218
 
  string ds_result;
5219
 
  string ds_sorted;
5220
 
  string ds_warnings;
5221
 
  string eval_query;
 
5376
  DYNAMIC_STRING *ds;
 
5377
  DYNAMIC_STRING *save_ds= NULL;
 
5378
  DYNAMIC_STRING ds_result;
 
5379
  DYNAMIC_STRING ds_sorted;
 
5380
  DYNAMIC_STRING ds_warnings;
 
5381
  DYNAMIC_STRING eval_query;
5222
5382
  char *query;
5223
5383
  int query_len;
5224
5384
 
5225
5385
 
 
5386
  init_dynamic_string(&ds_warnings, NULL, 0, 256);
 
5387
 
5226
5388
  /* Scan for warning before sending to server */
5227
5389
  scan_command_for_warnings(command);
5228
5390
 
5231
5393
  */
5232
5394
  if (command->type == Q_EVAL)
5233
5395
  {
 
5396
    init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
5234
5397
    do_eval(&eval_query, command->query, command->end, false);
5235
 
    query = strdup(eval_query.c_str());
5236
 
    query_len = eval_query.length();
 
5398
    query = eval_query.str;
 
5399
    query_len = eval_query.length;
5237
5400
  }
5238
5401
  else
5239
5402
  {
5249
5412
  */
5250
5413
  if (command->require_file[0])
5251
5414
  {
 
5415
    init_dynamic_string(&ds_result, "", 1024, 1024);
5252
5416
    ds= &ds_result;
5253
5417
  }
5254
5418
  else
5255
 
  {
5256
5419
    ds= &ds_res;
5257
 
  }
 
5420
 
5258
5421
  /*
5259
5422
    Log the query into the output buffer
5260
5423
  */
5261
5424
  if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5262
5425
  {
5263
 
    replace_append_mem(ds, query, query_len);
5264
 
    ds->append(delimiter, delimiter_length);
5265
 
    ds->append("\n");
 
5426
    replace_dynstr_append_mem(ds, query, query_len);
 
5427
    dynstr_append_mem(ds, delimiter, delimiter_length);
 
5428
    dynstr_append_mem(ds, "\n", 1);
5266
5429
  }
5267
5430
 
5268
5431
  if (display_result_sorted)
5269
5432
  {
5270
5433
    /*
5271
 
      Collect the query output in a separate string
5272
 
      that can be sorted before it's added to the
5273
 
      global result string
 
5434
       Collect the query output in a separate string
 
5435
       that can be sorted before it's added to the
 
5436
       global result string
5274
5437
    */
 
5438
    init_dynamic_string(&ds_sorted, "", 1024, 1024);
5275
5439
    save_ds= ds; /* Remember original ds */
5276
5440
    ds= &ds_sorted;
5277
5441
  }
5286
5450
  if (display_result_sorted)
5287
5451
  {
5288
5452
    /* Sort the result set and append it to result */
5289
 
    append_sorted(save_ds, &ds_sorted);
 
5453
    dynstr_append_sorted(save_ds, &ds_sorted);
5290
5454
    ds= save_ds;
 
5455
    dynstr_free(&ds_sorted);
5291
5456
  }
5292
5457
 
5293
5458
  if (command->require_file[0])
5299
5464
    check_require(ds, command->require_file);
5300
5465
  }
5301
5466
 
 
5467
  dynstr_free(&ds_warnings);
 
5468
  if (ds == &ds_result)
 
5469
    dynstr_free(&ds_result);
 
5470
  if (command->type == Q_EVAL)
 
5471
    dynstr_free(&eval_query);
5302
5472
  return;
5303
5473
}
5304
5474
 
5323
5493
  command->query[command->first_word_len]= save;
5324
5494
  if (type > 0)
5325
5495
  {
5326
 
    command->type=(enum enum_commands) type;    /* Found command */
 
5496
    command->type=(enum enum_commands) type;            /* Found command */
5327
5497
 
5328
5498
    /*
5329
5499
      Look for case where "query" was explicitly specified to
5337
5507
  }
5338
5508
  else
5339
5509
  {
5340
 
    /* No drizzletest command matched */
 
5510
    /* No mysqltest command matched */
5341
5511
 
5342
5512
    if (command->type != Q_COMMENT_WITH_COMMAND)
5343
5513
    {
5344
 
      /* A query that will sent to drizzled */
 
5514
      /* A query that will sent to mysqld */
5345
5515
      command->type= Q_QUERY;
5346
5516
    }
5347
5517
    else
5348
5518
    {
5349
 
      /* -- comment that didn't contain a drizzletest command */
 
5519
      /* -- comment that didn't contain a mysqltest command */
5350
5520
      command->type= Q_COMMENT;
5351
 
      warning_msg("Suspicious command '--%s' detected, was this intentional? " \
 
5521
      warning_msg("Suspicious command '--%s' detected, was this intentional? "\
5352
5522
                  "Use # instead of -- to avoid this warning",
5353
5523
                  command->query);
5354
5524
 
5402
5572
 
5403
5573
  /* Milliseconds since start */
5404
5574
  end= int64_t2str(timer, buf, 10);
5405
 
  ds_progress.append(buf, (int)(end-buf));
5406
 
  ds_progress.append("\t", 1);
 
5575
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5576
  dynstr_append_mem(&ds_progress, "\t", 1);
5407
5577
 
5408
5578
  /* Parser line number */
5409
5579
  end= int10_to_str(line, buf, 10);
5410
 
  ds_progress.append(buf, (int)(end-buf));
5411
 
  ds_progress.append("\t", 1);
 
5580
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5581
  dynstr_append_mem(&ds_progress, "\t", 1);
5412
5582
 
5413
5583
  /* Filename */
5414
 
  ds_progress.append(cur_file->file_name);
5415
 
  ds_progress.append(":", 1);
 
5584
  dynstr_append(&ds_progress, cur_file->file_name);
 
5585
  dynstr_append_mem(&ds_progress, ":", 1);
5416
5586
 
5417
5587
  /* Line in file */
5418
5588
  end= int10_to_str(cur_file->lineno, buf, 10);
5419
 
  ds_progress.append(buf, (int)(end-buf));
5420
 
 
5421
 
 
5422
 
  ds_progress.append("\n", 1);
 
5589
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5590
 
 
5591
 
 
5592
  dynstr_append_mem(&ds_progress, "\n", 1);
5423
5593
 
5424
5594
}
5425
5595
 
5445
5615
    (sizeof(connections)/sizeof(struct st_connection)) - 1;
5446
5616
  next_con= connections + 1;
5447
5617
 
 
5618
#ifdef EMBEDDED_LIBRARY
 
5619
  /* set appropriate stack for the 'query' threads */
 
5620
  (void) pthread_attr_init(&cn_thd_attrib);
 
5621
  pthread_attr_setstacksize(&cn_thd_attrib, DEFAULT_THREAD_STACK);
 
5622
#endif /*EMBEDDED_LIBRARY*/
 
5623
 
5448
5624
  /* Init file stack */
5449
5625
  memset(file_stack, 0, sizeof(file_stack));
5450
5626
  file_stack_end=
5459
5635
  cur_block->ok= true; /* Outer block should always be executed */
5460
5636
  cur_block->cmd= cmd_none;
5461
5637
 
 
5638
  my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
 
5639
 
5462
5640
  if (hash_init(&var_hash, charset_info,
5463
5641
                1024, 0, 0, get_var_key, var_free, MYF(0)))
5464
5642
    die("Variable hash initialization failed");
5465
5643
 
5466
 
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
 
5644
  var_set_string("$MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
5467
5645
 
5468
5646
  memset(&master_pos, 0, sizeof(master_pos));
5469
5647
 
5472
5650
 
5473
5651
  init_builtin_echo();
5474
5652
 
5475
 
  ds_res.reserve(65536);
5476
 
  ds_progress.reserve(2048);
5477
 
  ds_warning_messages.reserve(2048);
5478
 
 
 
5653
  init_dynamic_string(&ds_res, "", 65536, 65536);
 
5654
  init_dynamic_string(&ds_progress, "", 0, 2048);
 
5655
  init_dynamic_string(&ds_warning_messages, "", 0, 2048);
5479
5656
  parse_args(argc, argv);
5480
5657
 
 
5658
  if (mysql_server_init(embedded_server_arg_count,
 
5659
                        embedded_server_args,
 
5660
                        (char**) embedded_server_groups))
 
5661
    die("Can't initialize MySQL server");
5481
5662
  server_initialized= 1;
5482
5663
  if (cur_file == file_stack && cur_file->file == 0)
5483
5664
  {
5486
5667
    cur_file->lineno= 1;
5487
5668
  }
5488
5669
  cur_con= connections;
5489
 
  if (!( drizzle_create(&cur_con->drizzle)))
5490
 
    die("Failed in drizzle_create()");
 
5670
  if (!( mysql_init(&cur_con->mysql)))
 
5671
    die("Failed in mysql_init()");
5491
5672
  if (opt_compress)
5492
 
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
5493
 
  drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
5673
    mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS);
 
5674
  mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
 
5675
  mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME,
 
5676
                charset_info->csname);
 
5677
  int opt_protocol= MYSQL_PROTOCOL_TCP;
 
5678
  mysql_options(&cur_con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
5679
  if (opt_charsets_dir)
 
5680
    mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR,
 
5681
                  opt_charsets_dir);
5494
5682
 
5495
5683
  if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5496
5684
    die("Out of memory");
5497
5685
 
5498
 
  safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
 
5686
  safe_connect(&cur_con->mysql, cur_con->name, opt_host, opt_user, opt_pass,
5499
5687
               opt_db, opt_port);
5500
5688
 
5501
5689
  /* Use all time until exit if no explicit 'start_timer' */
5502
5690
  timer_start= timer_now();
5503
5691
 
5504
5692
  /*
5505
 
    Initialize $drizzle_errno with -1, so we can
 
5693
    Initialize $mysql_errno with -1, so we can
5506
5694
    - distinguish it from valid values ( >= 0 ) and
5507
5695
    - detect if there was never a command sent to the server
5508
5696
  */
5509
5697
  var_set_errno(-1);
5510
5698
 
5511
 
  /* Update $drizzle_get_server_version to that of current connection */
5512
 
  var_set_drizzle_get_server_version(&cur_con->drizzle);
 
5699
  /* Update $mysql_get_server_version to that of current connection */
 
5700
  var_set_mysql_get_server_version(&cur_con->mysql);
5513
5701
 
5514
5702
  if (opt_include)
5515
5703
  {
5538
5726
      case Q_CONNECT:
5539
5727
        do_connect(command);
5540
5728
        break;
5541
 
      case Q_CONNECTION:
5542
 
        select_connection(command);
5543
 
        break;
 
5729
      case Q_CONNECTION: select_connection(command); break;
5544
5730
      case Q_DISCONNECT:
5545
5731
      case Q_DIRTY_CLOSE:
5546
 
        do_close_connection(command); break;
 
5732
        do_close_connection(command); break;
5547
5733
      case Q_ENABLE_QUERY_LOG:   disable_query_log=0; break;
5548
5734
      case Q_DISABLE_QUERY_LOG:  disable_query_log=1; break;
5549
5735
      case Q_ENABLE_ABORT_ON_ERROR:  abort_on_error=1; break;
5579
5765
      case Q_PERL: do_perl(command); break;
5580
5766
      case Q_DELIMITER:
5581
5767
        do_delimiter(command);
5582
 
        break;
 
5768
        break;
5583
5769
      case Q_DISPLAY_VERTICAL_RESULTS:
5584
5770
        display_result_vertically= true;
5585
5771
        break;
5586
5772
      case Q_DISPLAY_HORIZONTAL_RESULTS:
5587
 
        display_result_vertically= false;
 
5773
        display_result_vertically= false;
5588
5774
        break;
5589
5775
      case Q_SORTED_RESULT:
5590
5776
        /*
5591
5777
          Turn on sorting of result set, will be reset after next
5592
5778
          command
5593
5779
        */
5594
 
        display_result_sorted= true;
 
5780
        display_result_sorted= true;
5595
5781
        break;
5596
5782
      case Q_LET: do_let(command); break;
5597
5783
      case Q_EVAL_RESULT:
5599
5785
      case Q_EVAL:
5600
5786
      case Q_QUERY_VERTICAL:
5601
5787
      case Q_QUERY_HORIZONTAL:
5602
 
        if (command->query == command->query_buf)
 
5788
        if (command->query == command->query_buf)
5603
5789
        {
5604
5790
          /* Skip the first part of command, i.e query_xxx */
5605
 
          command->query= command->first_argument;
 
5791
          command->query= command->first_argument;
5606
5792
          command->first_word_len= 0;
5607
5793
        }
5608
 
        /* fall through */
 
5794
        /* fall through */
5609
5795
      case Q_QUERY:
5610
5796
      case Q_REAP:
5611
5797
      {
5612
 
        bool old_display_result_vertically= display_result_vertically;
 
5798
        bool old_display_result_vertically= display_result_vertically;
5613
5799
        /* Default is full query, both reap and send  */
5614
5800
        int flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
5615
5801
 
5627
5813
        /* Check for special property for this query */
5628
5814
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5629
5815
 
5630
 
        if (save_file[0])
5631
 
        {
5632
 
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
5633
 
          save_file[0]= 0;
5634
 
        }
5635
 
        run_query(cur_con, command, flags);
5636
 
        command_executed++;
 
5816
        if (save_file[0])
 
5817
        {
 
5818
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
 
5819
          save_file[0]= 0;
 
5820
        }
 
5821
        run_query(cur_con, command, flags);
 
5822
        command_executed++;
5637
5823
        command->last_argument= command->end;
5638
5824
 
5639
5825
        /* Restore settings */
5640
 
        display_result_vertically= old_display_result_vertically;
 
5826
        display_result_vertically= old_display_result_vertically;
5641
5827
 
5642
 
        break;
 
5828
        break;
5643
5829
      }
5644
5830
      case Q_SEND:
5645
5831
        if (!*command->first_argument)
5653
5839
        }
5654
5840
 
5655
5841
        /* Remove "send" if this is first iteration */
5656
 
        if (command->query == command->query_buf)
5657
 
          command->query= command->first_argument;
 
5842
        if (command->query == command->query_buf)
 
5843
          command->query= command->first_argument;
5658
5844
 
5659
 
        /*
5660
 
          run_query() can execute a query partially, depending on the flags.
5661
 
          QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
 
5845
        /*
 
5846
          run_query() can execute a query partially, depending on the flags.
 
5847
          QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5662
5848
          the query and read the result some time later when reap instruction
5663
 
          is given on this connection.
 
5849
          is given on this connection.
5664
5850
        */
5665
 
        run_query(cur_con, command, QUERY_SEND_FLAG);
5666
 
        command_executed++;
 
5851
        run_query(cur_con, command, QUERY_SEND_FLAG);
 
5852
        command_executed++;
5667
5853
        command->last_argument= command->end;
5668
 
        break;
 
5854
        break;
5669
5855
      case Q_REQUIRE:
5670
 
        do_get_file_name(command, save_file, sizeof(save_file));
5671
 
        break;
 
5856
        do_get_file_name(command, save_file, sizeof(save_file));
 
5857
        break;
5672
5858
      case Q_ERROR:
5673
5859
        do_get_errcodes(command);
5674
 
        break;
 
5860
        break;
5675
5861
      case Q_REPLACE:
5676
 
        do_get_replace(command);
5677
 
        break;
 
5862
        do_get_replace(command);
 
5863
        break;
5678
5864
      case Q_REPLACE_REGEX:
5679
5865
        do_get_replace_regex(command);
5680
5866
        break;
5681
5867
      case Q_REPLACE_COLUMN:
5682
 
        do_get_replace_column(command);
5683
 
        break;
 
5868
        do_get_replace_column(command);
 
5869
        break;
5684
5870
      case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5685
5871
      case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5686
5872
      case Q_SYNC_SLAVE_WITH_MASTER:
5687
5873
      {
5688
 
        do_save_master_pos();
5689
 
        if (*command->first_argument)
5690
 
          select_connection(command);
5691
 
        else
5692
 
          select_connection_name("slave");
5693
 
        do_sync_with_master2(0);
5694
 
        break;
 
5874
        do_save_master_pos();
 
5875
        if (*command->first_argument)
 
5876
          select_connection(command);
 
5877
        else
 
5878
          select_connection_name("slave");
 
5879
        do_sync_with_master2(0);
 
5880
        break;
5695
5881
      }
5696
 
      case Q_COMMENT:        /* Ignore row */
 
5882
      case Q_COMMENT:                           /* Ignore row */
5697
5883
        command->last_argument= command->end;
5698
 
        break;
 
5884
        break;
5699
5885
      case Q_PING:
5700
 
        (void) drizzle_ping(&cur_con->drizzle);
5701
 
        break;
 
5886
        (void) mysql_ping(&cur_con->mysql);
 
5887
        break;
5702
5888
      case Q_EXEC:
5703
 
        do_exec(command);
5704
 
        command_executed++;
5705
 
        break;
 
5889
        do_exec(command);
 
5890
        command_executed++;
 
5891
        break;
5706
5892
      case Q_START_TIMER:
5707
 
        /* Overwrite possible earlier start of timer */
5708
 
        timer_start= timer_now();
5709
 
        break;
 
5893
        /* Overwrite possible earlier start of timer */
 
5894
        timer_start= timer_now();
 
5895
        break;
5710
5896
      case Q_END_TIMER:
5711
 
        /* End timer before ending drizzletest */
5712
 
        timer_output();
5713
 
        break;
 
5897
        /* End timer before ending mysqltest */
 
5898
        timer_output();
 
5899
        break;
5714
5900
      case Q_CHARACTER_SET:
5715
 
        do_set_charset(command);
5716
 
        break;
 
5901
        do_set_charset(command);
 
5902
        break;
5717
5903
      case Q_DISABLE_RECONNECT:
5718
 
        set_reconnect(&cur_con->drizzle, 0);
 
5904
        set_reconnect(&cur_con->mysql, 0);
5719
5905
        break;
5720
5906
      case Q_ENABLE_RECONNECT:
5721
 
        set_reconnect(&cur_con->drizzle, 1);
 
5907
        set_reconnect(&cur_con->mysql, 1);
5722
5908
        break;
5723
5909
      case Q_DISABLE_PARSING:
5724
5910
        if (parsing_disabled == 0)
5809
5995
    Time to compare result or save it to record file.
5810
5996
    The entire output from test is now kept in ds_res.
5811
5997
  */
5812
 
  if (ds_res.length())
 
5998
  if (ds_res.length)
5813
5999
  {
5814
6000
    if (result_file_name)
5815
6001
    {
5817
6003
 
5818
6004
      if (record)
5819
6005
      {
5820
 
        /* Recording - dump the output from test to result file */
5821
 
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
 
6006
        /* Recording - dump the output from test to result file */
 
6007
        str_to_file(result_file_name, ds_res.str, ds_res.length);
5822
6008
      }
5823
6009
      else
5824
6010
      {
5825
 
        /* Check that the output from test is equal to result file
5826
 
           - detect missing result file
5827
 
           - detect zero size result file
 
6011
        /* Check that the output from test is equal to result file
 
6012
           - detect missing result file
 
6013
           - detect zero size result file
5828
6014
        */
5829
 
        check_result(&ds_res);
 
6015
        check_result(&ds_res);
5830
6016
      }
5831
6017
    }
5832
6018
    else
5833
6019
    {
5834
6020
      /* No result_file_name specified to compare with, print to stdout */
5835
 
      printf("%s", ds_res.c_str());
 
6021
      printf("%s", ds_res.str);
5836
6022
    }
5837
6023
  }
5838
6024
  else
5857
6043
    dump_progress();
5858
6044
 
5859
6045
  /* Dump warning messages */
5860
 
  if (result_file_name && ds_warning_messages.length())
 
6046
  if (result_file_name && ds_warning_messages.length)
5861
6047
    dump_warning_messages();
5862
6048
 
5863
6049
  timer_output();
5875
6061
  before executing any commands. The time we measure is
5876
6062
 
5877
6063
  - If no explicit 'start_timer' or 'end_timer' is given in the
5878
 
  test case, the timer measure how long we execute in drizzletest.
 
6064
  test case, the timer measure how long we execute in mysqltest.
5879
6065
 
5880
6066
  - If only 'start_timer' is given we measure how long we execute
5881
 
  from that point until we terminate drizzletest.
 
6067
  from that point until we terminate mysqltest.
5882
6068
 
5883
6069
  - If only 'end_timer' is given we measure how long we execute
5884
 
  from that we enter drizzletest to the 'end_timer' is command is
 
6070
  from that we enter mysqltest to the 'end_timer' is command is
5885
6071
  executed.
5886
6072
 
5887
6073
  - If both 'start_timer' and 'end_timer' are given we measure
5939
6125
    if (!*from)
5940
6126
      die("Wrong number of arguments to replace_column in '%s'", command->query);
5941
6127
    to= get_string(&buff, &from, command);
5942
 
    free(replace_column[column_number-1]);
 
6128
    my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
5943
6129
    replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
5944
6130
    set_if_bigger(max_replace_column, column_number);
5945
6131
  }
5946
 
  free(start);
 
6132
  my_free(start, MYF(0));
5947
6133
  command->last_argument= command->end;
5948
6134
}
5949
6135
 
5955
6141
  {
5956
6142
    if (replace_column[i])
5957
6143
    {
5958
 
      free(replace_column[i]);
 
6144
      my_free(replace_column[i], 0);
5959
6145
      replace_column[i]= 0;
5960
6146
    }
5961
6147
  }
5970
6156
 
5971
6157
/* Definitions for replace result */
5972
6158
 
5973
 
typedef struct st_pointer_array {    /* when using array-strings */
5974
 
  TYPELIB typelib;        /* Pointer to strings */
5975
 
  unsigned char  *str;          /* Strings is here */
5976
 
  uint8_t *flag;          /* Flag about each var. */
5977
 
  uint  array_allocs,max_count,length,max_length;
 
6159
typedef struct st_pointer_array {               /* when using array-strings */
 
6160
  TYPELIB typelib;                              /* Pointer to strings */
 
6161
  uchar *str;                                   /* Strings is here */
 
6162
  int7  *flag;                                  /* Flag about each var. */
 
6163
  uint  array_allocs,max_count,length,max_length;
5978
6164
} POINTER_ARRAY;
5979
6165
 
5980
6166
struct st_replace;
5981
6167
struct st_replace *init_replace(char * *from, char * *to, uint count,
5982
 
                                char * word_end_chars);
 
6168
                                char * word_end_chars);
5983
6169
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5984
 
void replace_strings_append(struct st_replace *rep, string* ds,
 
6170
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5985
6171
                            const char *from, int len);
5986
6172
void free_pointer_array(POINTER_ARRAY *pa);
5987
6173
 
6006
6192
 
6007
6193
  free_replace();
6008
6194
 
6009
 
  memset(&to_array, 0, sizeof(to_array));
6010
 
  memset(&from_array, 0, sizeof(from_array));
 
6195
  bzero((char*) &to_array,sizeof(to_array));
 
6196
  bzero((char*) &from_array,sizeof(from_array));
6011
6197
  if (!*from)
6012
6198
    die("Missing argument in %s", command->query);
6013
6199
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6025
6211
  for (i= 1,pos= word_end_chars ; i < 256 ; i++)
6026
6212
    if (my_isspace(charset_info,i))
6027
6213
      *pos++= i;
6028
 
  *pos=0;          /* End pointer */
 
6214
  *pos=0;                                       /* End pointer */
6029
6215
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
6030
 
                                   (char**) to_array.typelib.type_names,
6031
 
                                   (uint) from_array.typelib.count,
6032
 
                                   word_end_chars)))
 
6216
                                  (char**) to_array.typelib.type_names,
 
6217
                                  (uint) from_array.typelib.count,
 
6218
                                  word_end_chars)))
6033
6219
    die("Can't initialize replace from '%s'", command->query);
6034
6220
  free_pointer_array(&from_array);
6035
6221
  free_pointer_array(&to_array);
6036
 
  free(start);
 
6222
  my_free(start, MYF(0));
6037
6223
  command->last_argument= command->end;
6038
6224
  return;
6039
6225
}
6044
6230
 
6045
6231
  if (glob_replace)
6046
6232
  {
6047
 
    free(glob_replace);
 
6233
    my_free(glob_replace,MYF(0));
6048
6234
    glob_replace=0;
6049
6235
  }
6050
6236
  return;
6064
6250
} REPLACE_STRING;
6065
6251
 
6066
6252
 
6067
 
void replace_strings_append(REPLACE *rep, string* ds,
6068
 
                            const char *str, int len)
 
6253
void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
 
6254
                            const char *str,
 
6255
                            int len __attribute__((unused)))
6069
6256
{
6070
6257
  register REPLACE *rep_pos;
6071
6258
  register REPLACE_STRING *rep_str;
6078
6265
  {
6079
6266
    /* Loop through states */
6080
6267
    while (!rep_pos->found)
6081
 
      rep_pos= rep_pos->next[(unsigned char) *from++];
 
6268
      rep_pos= rep_pos->next[(uchar) *from++];
6082
6269
 
6083
6270
    /* Does this state contain a string to be replaced */
6084
6271
    if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6085
6272
    {
6086
6273
      /* No match found */
6087
 
      ds->append(start, from - start - 1);
 
6274
      dynstr_append_mem(ds, start, from - start - 1);
6088
6275
      return;
6089
6276
    }
6090
6277
 
6091
6278
    /* Append part of original string before replace string */
6092
 
    ds->append(start, (from - rep_str->to_offset) - start);
 
6279
    dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6093
6280
 
6094
6281
    /* Append replace string */
6095
 
    ds->append(rep_str->replace_string,
6096
 
               strlen(rep_str->replace_string));
 
6282
    dynstr_append_mem(ds, rep_str->replace_string,
 
6283
                      strlen(rep_str->replace_string));
6097
6284
 
6098
6285
    if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6099
6286
      return;
6202
6389
  /* for each regexp substitution statement */
6203
6390
  while (p < expr_end)
6204
6391
  {
6205
 
    memset(&reg, 0, sizeof(reg));
 
6392
    bzero(&reg,sizeof(reg));
6206
6393
    /* find the start of the statement */
6207
6394
    while (p < expr_end)
6208
6395
    {
6244
6431
      reg.icase= 1;
6245
6432
 
6246
6433
    /* done parsing the statement, now place it in regex_arr */
6247
 
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6434
    if (insert_dynamic(&res->regex_arr,(uchar*) &reg))
6248
6435
      die("Out of memory");
6249
6436
  }
6250
6437
  res->odd_buf_len= res->even_buf_len= 8192;
6255
6442
  return res;
6256
6443
 
6257
6444
err:
6258
 
  free(res);
 
6445
  my_free(res,0);
6259
6446
  die("Error parsing replace_regex \"%s\"", expr);
6260
6447
  return 0;
6261
6448
}
6296
6483
    struct st_regex re;
6297
6484
    char* save_out_buf= out_buf;
6298
6485
 
6299
 
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6486
    get_dynamic(&r->regex_arr,(uchar*)&re,i);
6300
6487
 
6301
6488
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6302
6489
                     in_buf, re.icase))
6314
6501
      if (in_buf == val)
6315
6502
        in_buf= r->odd_buf;
6316
6503
 
6317
 
      std::swap(in_buf,out_buf);
 
6504
      swap_variables(char*,in_buf,out_buf);
6318
6505
 
6319
6506
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
6320
6507
        &r->odd_buf_len;
6347
6534
  if (glob_replace_regex)
6348
6535
  {
6349
6536
    delete_dynamic(&glob_replace_regex->regex_arr);
6350
 
    free(glob_replace_regex->even_buf);
6351
 
    free(glob_replace_regex->odd_buf);
6352
 
    free(glob_replace_regex);
 
6537
    my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6538
    my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6539
    my_free(glob_replace_regex,MYF(0));
6353
6540
    glob_replace_regex=0;
6354
6541
  }
6355
6542
}
6415
6602
#define LAST_CHAR_CODE 259
6416
6603
 
6417
6604
typedef struct st_rep_set {
6418
 
  uint  *bits;        /* Pointer to used sets */
6419
 
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6420
 
  uint  found_len;      /* Best match to date */
6421
 
  int  found_offset;
6422
 
  uint  table_offset;
6423
 
  uint  size_of_bits;      /* For convinience */
 
6605
  uint  *bits;                          /* Pointer to used sets */
 
6606
  short next[LAST_CHAR_CODE];           /* Pointer to next sets */
 
6607
  uint  found_len;                      /* Best match to date */
 
6608
  int   found_offset;
 
6609
  uint  table_offset;
 
6610
  uint  size_of_bits;                   /* For convinience */
6424
6611
} REP_SET;
6425
6612
 
6426
6613
typedef struct st_rep_sets {
6427
 
  uint    count;      /* Number of sets */
6428
 
  uint    extra;      /* Extra sets in buffer */
6429
 
  uint    invisible;    /* Sets not chown */
6430
 
  uint    size_of_bits;
6431
 
  REP_SET  *set,*set_buffer;
6432
 
  uint    *bit_buffer;
 
6614
  uint          count;                  /* Number of sets */
 
6615
  uint          extra;                  /* Extra sets in buffer */
 
6616
  uint          invisible;              /* Sets not chown */
 
6617
  uint          size_of_bits;
 
6618
  REP_SET       *set,*set_buffer;
 
6619
  uint          *bit_buffer;
6433
6620
} REP_SETS;
6434
6621
 
6435
6622
typedef struct st_found_set {
6480
6667
/* Init a replace structure for further calls */
6481
6668
 
6482
6669
REPLACE *init_replace(char * *from, char * *to,uint count,
6483
 
                      char * word_end_chars)
 
6670
                      char * word_end_chars)
6484
6671
{
6485
6672
  static const int SPACE_CHAR= 256;
6486
6673
  static const int START_OF_LINE= 257;
6512
6699
    if (len > max_length)
6513
6700
      max_length=len;
6514
6701
  }
6515
 
  memset(is_word_end, 0, sizeof(is_word_end));
 
6702
  bzero((char*) is_word_end,sizeof(is_word_end));
6516
6703
  for (i=0 ; word_end_chars[i] ; i++)
6517
 
    is_word_end[(unsigned char) word_end_chars[i]]=1;
 
6704
    is_word_end[(uchar) word_end_chars[i]]=1;
6518
6705
 
6519
6706
  if (init_sets(&sets,states))
6520
6707
    return(0);
6521
6708
  found_sets=0;
6522
6709
  if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
6523
 
                                          MYF(MY_WME))))
 
6710
                                          MYF(MY_WME))))
6524
6711
  {
6525
6712
    free_sets(&sets);
6526
6713
    return(0);
6527
6714
  }
6528
 
  make_new_set(&sets);      /* Set starting set */
6529
 
  make_sets_invisible(&sets);      /* Hide previus sets */
 
6715
  VOID(make_new_set(&sets));                    /* Set starting set */
 
6716
  make_sets_invisible(&sets);                   /* Hide previus sets */
6530
6717
  used_sets=-1;
6531
 
  word_states=make_new_set(&sets);    /* Start of new word */
6532
 
  start_states=make_new_set(&sets);    /* This is first state */
 
6718
  word_states=make_new_set(&sets);              /* Start of new word */
 
6719
  start_states=make_new_set(&sets);             /* This is first state */
6533
6720
  if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6534
6721
  {
6535
6722
    free_sets(&sets);
6536
 
    free(found_set);
 
6723
    my_free(found_set,MYF(0));
6537
6724
    return(0);
6538
6725
  }
6539
6726
 
6545
6732
      internal_set_bit(start_states,states+1);
6546
6733
      if (!from[i][2])
6547
6734
      {
6548
 
        start_states->table_offset=i;
6549
 
        start_states->found_offset=1;
 
6735
        start_states->table_offset=i;
 
6736
        start_states->found_offset=1;
6550
6737
      }
6551
6738
    }
6552
6739
    else if (from[i][0] == '\\' && from[i][1] == '$')
6553
6740
    {
6554
6741
      internal_set_bit(start_states,states);
6555
6742
      internal_set_bit(word_states,states);
6556
 
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
 
6743
      if (!from[i][2] && start_states->table_offset == (uint) ~0)
6557
6744
      {
6558
 
        start_states->table_offset=i;
6559
 
        start_states->found_offset=0;
 
6745
        start_states->table_offset=i;
 
6746
        start_states->found_offset=0;
6560
6747
      }
6561
6748
    }
6562
6749
    else
6563
6750
    {
6564
6751
      internal_set_bit(word_states,states);
6565
6752
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6566
 
        internal_set_bit(start_states,states+1);
 
6753
        internal_set_bit(start_states,states+1);
6567
6754
      else
6568
 
        internal_set_bit(start_states,states);
 
6755
        internal_set_bit(start_states,states);
6569
6756
    }
6570
6757
    for (pos=from[i], len=0; *pos ; pos++)
6571
6758
    {
6572
6759
      if (*pos == '\\' && *(pos+1))
6573
6760
      {
6574
 
        pos++;
6575
 
        switch (*pos) {
6576
 
        case 'b':
6577
 
          follow_ptr->chr = SPACE_CHAR;
6578
 
          break;
6579
 
        case '^':
6580
 
          follow_ptr->chr = START_OF_LINE;
6581
 
          break;
6582
 
        case '$':
6583
 
          follow_ptr->chr = END_OF_LINE;
6584
 
          break;
6585
 
        case 'r':
6586
 
          follow_ptr->chr = '\r';
6587
 
          break;
6588
 
        case 't':
6589
 
          follow_ptr->chr = '\t';
6590
 
          break;
6591
 
        case 'v':
6592
 
          follow_ptr->chr = '\v';
6593
 
          break;
6594
 
        default:
6595
 
          follow_ptr->chr = (unsigned char) *pos;
6596
 
          break;
6597
 
        }
 
6761
        pos++;
 
6762
        switch (*pos) {
 
6763
        case 'b':
 
6764
          follow_ptr->chr = SPACE_CHAR;
 
6765
          break;
 
6766
        case '^':
 
6767
          follow_ptr->chr = START_OF_LINE;
 
6768
          break;
 
6769
        case '$':
 
6770
          follow_ptr->chr = END_OF_LINE;
 
6771
          break;
 
6772
        case 'r':
 
6773
          follow_ptr->chr = '\r';
 
6774
          break;
 
6775
        case 't':
 
6776
          follow_ptr->chr = '\t';
 
6777
          break;
 
6778
        case 'v':
 
6779
          follow_ptr->chr = '\v';
 
6780
          break;
 
6781
        default:
 
6782
          follow_ptr->chr = (uchar) *pos;
 
6783
          break;
 
6784
        }
6598
6785
      }
6599
6786
      else
6600
 
        follow_ptr->chr= (unsigned char) *pos;
 
6787
        follow_ptr->chr= (uchar) *pos;
6601
6788
      follow_ptr->table_offset=i;
6602
6789
      follow_ptr->len= ++len;
6603
6790
      follow_ptr++;
6613
6800
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6614
6801
  {
6615
6802
    set=sets.set+set_nr;
6616
 
    default_state= 0;        /* Start from beginning */
 
6803
    default_state= 0;                           /* Start from beginning */
6617
6804
 
6618
6805
    /* If end of found-string not found or start-set with current set */
6619
6806
 
6620
 
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
 
6807
    for (i= (uint) ~0; (i=get_next_bit(set,i)) ;)
6621
6808
    {
6622
6809
      if (!follow[i].chr)
6623
6810
      {
6624
 
        if (! default_state)
6625
 
          default_state= find_found(found_set,set->table_offset,
6626
 
                                    set->found_offset+1);
 
6811
        if (! default_state)
 
6812
          default_state= find_found(found_set,set->table_offset,
 
6813
                                    set->found_offset+1);
6627
6814
      }
6628
6815
    }
6629
 
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
 
6816
    copy_bits(sets.set+used_sets,set);          /* Save set for changes */
6630
6817
    if (!default_state)
6631
 
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
 
6818
      or_bits(sets.set+used_sets,sets.set);     /* Can restart from start */
6632
6819
 
6633
6820
    /* Find all chars that follows current sets */
6634
 
    memset(used_chars, 0, sizeof(used_chars));
6635
 
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
 
6821
    bzero((char*) used_chars,sizeof(used_chars));
 
6822
    for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6636
6823
    {
6637
6824
      used_chars[follow[i].chr]=1;
6638
6825
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6639
 
           follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6640
 
        used_chars[0]=1;
 
6826
           follow[i].len > 1) || follow[i].chr == END_OF_LINE)
 
6827
        used_chars[0]=1;
6641
6828
    }
6642
6829
 
6643
6830
    /* Mark word_chars used if \b is in state */
6644
6831
    if (used_chars[SPACE_CHAR])
6645
6832
      for (pos= word_end_chars ; *pos ; pos++)
6646
 
        used_chars[(int) (unsigned char) *pos] = 1;
 
6833
        used_chars[(int) (uchar) *pos] = 1;
6647
6834
 
6648
6835
    /* Handle other used characters */
6649
6836
    for (chr= 0 ; chr < 256 ; chr++)
6650
6837
    {
6651
6838
      if (! used_chars[chr])
6652
 
        set->next[chr]= chr ? default_state : -1;
 
6839
        set->next[chr]= chr ? default_state : -1;
6653
6840
      else
6654
6841
      {
6655
 
        new_set=make_new_set(&sets);
6656
 
        set=sets.set+set_nr;      /* if realloc */
6657
 
        new_set->table_offset=set->table_offset;
6658
 
        new_set->found_len=set->found_len;
6659
 
        new_set->found_offset=set->found_offset+1;
6660
 
        found_end=0;
 
6842
        new_set=make_new_set(&sets);
 
6843
        set=sets.set+set_nr;                    /* if realloc */
 
6844
        new_set->table_offset=set->table_offset;
 
6845
        new_set->found_len=set->found_len;
 
6846
        new_set->found_offset=set->found_offset+1;
 
6847
        found_end=0;
6661
6848
 
6662
 
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6663
 
        {
6664
 
          if (!follow[i].chr || follow[i].chr == chr ||
6665
 
              (follow[i].chr == SPACE_CHAR &&
6666
 
               (is_word_end[chr] ||
6667
 
                (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6668
 
              (follow[i].chr == END_OF_LINE && ! chr))
6669
 
          {
6670
 
            if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6671
 
                follow[i].len > found_end)
6672
 
              found_end=follow[i].len;
6673
 
            if (chr && follow[i].chr)
6674
 
              internal_set_bit(new_set,i+1);    /* To next set */
6675
 
            else
6676
 
              internal_set_bit(new_set,i);
6677
 
          }
6678
 
        }
6679
 
        if (found_end)
6680
 
        {
6681
 
          new_set->found_len=0;      /* Set for testing if first */
6682
 
          bits_set=0;
6683
 
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6684
 
          {
6685
 
            if ((follow[i].chr == SPACE_CHAR ||
6686
 
                 follow[i].chr == END_OF_LINE) && ! chr)
6687
 
              bit_nr=i+1;
6688
 
            else
6689
 
              bit_nr=i;
6690
 
            if (follow[bit_nr-1].len < found_end ||
6691
 
                (new_set->found_len &&
6692
 
                 (chr == 0 || !follow[bit_nr].chr)))
6693
 
              internal_clear_bit(new_set,i);
6694
 
            else
6695
 
            {
6696
 
              if (chr == 0 || !follow[bit_nr].chr)
6697
 
              {          /* best match  */
6698
 
                new_set->table_offset=follow[bit_nr].table_offset;
6699
 
                if (chr || (follow[i].chr == SPACE_CHAR ||
6700
 
                            follow[i].chr == END_OF_LINE))
6701
 
                  new_set->found_offset=found_end;  /* New match */
6702
 
                new_set->found_len=found_end;
6703
 
              }
6704
 
              bits_set++;
6705
 
            }
6706
 
          }
6707
 
          if (bits_set == 1)
6708
 
          {
6709
 
            set->next[chr] = find_found(found_set,
6710
 
                                        new_set->table_offset,
6711
 
                                        new_set->found_offset);
6712
 
            free_last_set(&sets);
6713
 
          }
6714
 
          else
6715
 
            set->next[chr] = find_set(&sets,new_set);
6716
 
        }
6717
 
        else
6718
 
          set->next[chr] = find_set(&sets,new_set);
 
6849
        for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
 
6850
        {
 
6851
          if (!follow[i].chr || follow[i].chr == chr ||
 
6852
              (follow[i].chr == SPACE_CHAR &&
 
6853
               (is_word_end[chr] ||
 
6854
                (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
 
6855
              (follow[i].chr == END_OF_LINE && ! chr))
 
6856
          {
 
6857
            if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
 
6858
                follow[i].len > found_end)
 
6859
              found_end=follow[i].len;
 
6860
            if (chr && follow[i].chr)
 
6861
              internal_set_bit(new_set,i+1);            /* To next set */
 
6862
            else
 
6863
              internal_set_bit(new_set,i);
 
6864
          }
 
6865
        }
 
6866
        if (found_end)
 
6867
        {
 
6868
          new_set->found_len=0;                 /* Set for testing if first */
 
6869
          bits_set=0;
 
6870
          for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
 
6871
          {
 
6872
            if ((follow[i].chr == SPACE_CHAR ||
 
6873
                 follow[i].chr == END_OF_LINE) && ! chr)
 
6874
              bit_nr=i+1;
 
6875
            else
 
6876
              bit_nr=i;
 
6877
            if (follow[bit_nr-1].len < found_end ||
 
6878
                (new_set->found_len &&
 
6879
                 (chr == 0 || !follow[bit_nr].chr)))
 
6880
              internal_clear_bit(new_set,i);
 
6881
            else
 
6882
            {
 
6883
              if (chr == 0 || !follow[bit_nr].chr)
 
6884
              {                                 /* best match  */
 
6885
                new_set->table_offset=follow[bit_nr].table_offset;
 
6886
                if (chr || (follow[i].chr == SPACE_CHAR ||
 
6887
                            follow[i].chr == END_OF_LINE))
 
6888
                  new_set->found_offset=found_end;      /* New match */
 
6889
                new_set->found_len=found_end;
 
6890
              }
 
6891
              bits_set++;
 
6892
            }
 
6893
          }
 
6894
          if (bits_set == 1)
 
6895
          {
 
6896
            set->next[chr] = find_found(found_set,
 
6897
                                        new_set->table_offset,
 
6898
                                        new_set->found_offset);
 
6899
            free_last_set(&sets);
 
6900
          }
 
6901
          else
 
6902
            set->next[chr] = find_set(&sets,new_set);
 
6903
        }
 
6904
        else
 
6905
          set->next[chr] = find_set(&sets,new_set);
6719
6906
      }
6720
6907
    }
6721
6908
  }
6723
6910
  /* Alloc replace structure for the replace-state-machine */
6724
6911
 
6725
6912
  if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+
6726
 
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
6727
 
                                    sizeof(char *)*count+result_len,
6728
 
                                    MYF(MY_WME | MY_ZEROFILL))))
 
6913
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
 
6914
                                    sizeof(char *)*count+result_len,
 
6915
                                    MYF(MY_WME | MY_ZEROFILL))))
6729
6916
  {
6730
6917
    rep_str=(REPLACE_STRING*) (replace+sets.count);
6731
6918
    to_array= (char **) (rep_str+found_sets+1);
6733
6920
    for (i=0 ; i < count ; i++)
6734
6921
    {
6735
6922
      to_array[i]=to_pos;
6736
 
      to_pos=my_stpcpy(to_pos,to[i])+1;
 
6923
      to_pos=strmov(to_pos,to[i])+1;
6737
6924
    }
6738
6925
    rep_str[0].found=1;
6739
6926
    rep_str[0].replace_string=0;
6740
6927
    for (i=1 ; i <= found_sets ; i++)
6741
6928
    {
6742
6929
      pos=from[found_set[i-1].table_offset];
6743
 
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
 
6930
      rep_str[i].found= !bcmp((const uchar*) pos,
 
6931
                              (const uchar*) "\\^", 3) ? 2 : 1;
6744
6932
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
6745
6933
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
6746
6934
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6747
 
        end_of_word(pos);
 
6935
        end_of_word(pos);
6748
6936
    }
6749
6937
    for (i=0 ; i < sets.count ; i++)
6750
6938
    {
6751
6939
      for (j=0 ; j < 256 ; j++)
6752
 
        if (sets.set[i].next[j] >= 0)
6753
 
          replace[i].next[j]=replace+sets.set[i].next[j];
6754
 
        else
6755
 
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
 
6940
        if (sets.set[i].next[j] >= 0)
 
6941
          replace[i].next[j]=replace+sets.set[i].next[j];
 
6942
        else
 
6943
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6756
6944
    }
6757
6945
  }
6758
 
  free(follow);
 
6946
  my_free(follow,MYF(0));
6759
6947
  free_sets(&sets);
6760
 
  free(found_set);
 
6948
  my_free(found_set,MYF(0));
6761
6949
  return(replace);
6762
6950
}
6763
6951
 
6764
6952
 
6765
6953
int init_sets(REP_SETS *sets,uint states)
6766
6954
{
6767
 
  memset(sets, 0, sizeof(*sets));
 
6955
  bzero((char*) sets,sizeof(*sets));
6768
6956
  sets->size_of_bits=((states+7)/8);
6769
6957
  if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
6770
 
                                              MYF(MY_WME))))
 
6958
                                              MYF(MY_WME))))
6771
6959
    return 1;
6772
6960
  if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
6773
 
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
 
6961
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
6774
6962
  {
6775
 
    free(sets->set);
 
6963
    my_free(sets->set,MYF(0));
6776
6964
    return 1;
6777
6965
  }
6778
6966
  return 0;
6795
6983
  {
6796
6984
    sets->extra--;
6797
6985
    set=sets->set+ sets->count++;
6798
 
    memset(set->bits, 0, sizeof(uint)*sets->size_of_bits);
6799
 
    memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
 
6986
    bzero((char*) set->bits,sizeof(uint)*sets->size_of_bits);
 
6987
    bzero((char*) &set->next[0],sizeof(set->next[0])*LAST_CHAR_CODE);
6800
6988
    set->found_offset=0;
6801
6989
    set->found_len=0;
6802
 
    set->table_offset= UINT32_MAX;
 
6990
    set->table_offset= (uint) ~0;
6803
6991
    set->size_of_bits=sets->size_of_bits;
6804
6992
    return set;
6805
6993
  }
6806
6994
  count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6807
 
  if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
 
6995
  if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6808
6996
                                  sizeof(REP_SET)*count,
6809
 
                                  MYF(MY_WME))))
 
6997
                                  MYF(MY_WME))))
6810
6998
    return 0;
6811
6999
  sets->set_buffer=set;
6812
7000
  sets->set=set+sets->invisible;
6813
 
  if (!(bit_buffer=(uint*) my_realloc((unsigned char*) sets->bit_buffer,
6814
 
                                      (sizeof(uint)*sets->size_of_bits)*count,
6815
 
                                      MYF(MY_WME))))
 
7001
  if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
 
7002
                                      (sizeof(uint)*sets->size_of_bits)*count,
 
7003
                                      MYF(MY_WME))))
6816
7004
    return 0;
6817
7005
  sets->bit_buffer=bit_buffer;
6818
7006
  for (i=0 ; i < count ; i++)
6833
7021
 
6834
7022
void free_sets(REP_SETS *sets)
6835
7023
{
6836
 
  free(sets->set_buffer);
6837
 
  free(sets->bit_buffer);
 
7024
  my_free(sets->set_buffer,MYF(0));
 
7025
  my_free(sets->bit_buffer,MYF(0));
6838
7026
  return;
6839
7027
}
6840
7028
 
6861
7049
 
6862
7050
void copy_bits(REP_SET *to,REP_SET *from)
6863
7051
{
6864
 
  memcpy(to->bits,from->bits,
6865
 
         (size_t) (sizeof(uint) * to->size_of_bits));
 
7052
  memcpy((uchar*) to->bits,(uchar*) from->bits,
 
7053
         (size_t) (sizeof(uint) * to->size_of_bits));
6866
7054
}
6867
7055
 
6868
7056
int cmp_bits(REP_SET *set1,REP_SET *set2)
6869
7057
{
6870
 
  return memcmp(set1->bits,set2->bits, sizeof(uint) * set1->size_of_bits);
 
7058
  return bcmp((uchar*) set1->bits,(uchar*) set2->bits,
 
7059
              sizeof(uint) * set1->size_of_bits);
6871
7060
}
6872
7061
 
6873
7062
 
6909
7098
      return i;
6910
7099
    }
6911
7100
  }
6912
 
  return i;        /* return new postion */
 
7101
  return i;                             /* return new postion */
6913
7102
}
6914
7103
 
6915
7104
/* find if there is a found_set with same table_offset & found_offset
6924
7113
  int i;
6925
7114
  for (i=0 ; (uint) i < found_sets ; i++)
6926
7115
    if (found_set[i].table_offset == table_offset &&
6927
 
        found_set[i].found_offset == found_offset)
 
7116
        found_set[i].found_offset == found_offset)
6928
7117
      return -i-2;
6929
7118
  found_set[i].table_offset=table_offset;
6930
7119
  found_set[i].found_offset=found_offset;
6931
7120
  found_sets++;
6932
 
  return -i-2;        /* return new postion */
 
7121
  return -i-2;                          /* return new postion */
6933
7122
}
6934
7123
 
6935
7124
/* Return 1 if regexp starts with \b or ends with \b*/
6936
7125
 
6937
7126
uint start_at_word(char * pos)
6938
7127
{
6939
 
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
6940
 
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
 
7128
  return (((!bcmp((const uchar*) pos, (const uchar*) "\\b",2) && pos[2]) ||
 
7129
           !bcmp((const uchar*) pos, (const uchar*) "\\^", 2)) ? 1 : 0);
6941
7130
}
6942
7131
 
6943
7132
uint end_of_word(char * pos)
6944
7133
{
6945
 
  char * end= strchr(pos, '\0');
6946
 
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
6947
 
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
 
7134
  char * end=strend(pos);
 
7135
  return ((end > pos+2 && !bcmp((const uchar*) end-2,
 
7136
                                (const uchar*) "\\b", 2)) ||
 
7137
          (end >= pos+2 && !bcmp((const uchar*) end-2,
 
7138
                                (const uchar*) "\\$",2))) ? 1 : 0;
6948
7139
}
6949
7140
 
6950
7141
/****************************************************************************
6951
7142
 * Handle replacement of strings
6952
7143
 ****************************************************************************/
6953
7144
 
6954
 
#define PC_MALLOC    256  /* Bytes for pointers */
6955
 
#define PS_MALLOC    512  /* Bytes for data */
 
7145
#define PC_MALLOC               256     /* Bytes for pointers */
 
7146
#define PS_MALLOC               512     /* Bytes for data */
6956
7147
 
6957
7148
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6958
7149
{
6959
7150
  uint i,length,old_count;
6960
 
  unsigned char *new_pos;
 
7151
  uchar *new_pos;
6961
7152
  const char **new_array;
6962
7153
 
6963
7154
 
6964
7155
  if (! pa->typelib.count)
6965
7156
  {
6966
7157
    if (!(pa->typelib.type_names=(const char **)
6967
 
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
6968
 
                     (sizeof(char *)+sizeof(*pa->flag))*
6969
 
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
 
7158
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
 
7159
                     (sizeof(char *)+sizeof(*pa->flag))*
 
7160
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6970
7161
      return(-1);
6971
 
    if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
6972
 
                                      MYF(MY_WME))))
 
7162
    if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
 
7163
                                     MYF(MY_WME))))
6973
7164
    {
6974
 
      free((char*) pa->typelib.type_names);
 
7165
      my_free((char*) pa->typelib.type_names,MYF(0));
6975
7166
      return (-1);
6976
7167
    }
6977
 
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(unsigned char*)+
6978
 
                                               sizeof(*pa->flag));
6979
 
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
 
7168
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
 
7169
                                               sizeof(*pa->flag));
 
7170
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6980
7171
    pa->length=0;
6981
7172
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6982
7173
    pa->array_allocs=1;
6984
7175
  length=(uint) strlen(name)+1;
6985
7176
  if (pa->length+length >= pa->max_length)
6986
7177
  {
6987
 
    if (!(new_pos= (unsigned char*) my_realloc((unsigned char*) pa->str,
6988
 
                                       (uint) (pa->max_length+PS_MALLOC),
6989
 
                                       MYF(MY_WME))))
 
7178
    if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
 
7179
                                      (uint) (pa->max_length+PS_MALLOC),
 
7180
                                      MYF(MY_WME))))
6990
7181
      return(1);
6991
7182
    if (new_pos != pa->str)
6992
7183
    {
6993
7184
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
6994
7185
      for (i=0 ; i < pa->typelib.count ; i++)
6995
 
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
6996
 
                                              char*);
 
7186
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
 
7187
                                              char*);
6997
7188
      pa->str=new_pos;
6998
7189
    }
6999
7190
    pa->max_length+=PS_MALLOC;
7003
7194
    int len;
7004
7195
    pa->array_allocs++;
7005
7196
    len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7006
 
    if (!(new_array=(const char **) my_realloc((unsigned char*) pa->typelib.type_names,
7007
 
                                               (uint) len/
7008
 
                                               (sizeof(unsigned char*)+sizeof(*pa->flag))*
7009
 
                                               (sizeof(unsigned char*)+sizeof(*pa->flag)),
 
7197
    if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
 
7198
                                               (uint) len/
 
7199
                                               (sizeof(uchar*)+sizeof(*pa->flag))*
 
7200
                                               (sizeof(uchar*)+sizeof(*pa->flag)),
7010
7201
                                               MYF(MY_WME))))
7011
7202
      return(1);
7012
7203
    pa->typelib.type_names=new_array;
7013
7204
    old_count=pa->max_count;
7014
 
    pa->max_count=len/(sizeof(unsigned char*) + sizeof(*pa->flag));
7015
 
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
7016
 
    memcpy(pa->flag, pa->typelib.type_names+old_count,
7017
 
           old_count*sizeof(*pa->flag));
 
7205
    pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
 
7206
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
 
7207
    memcpy((uchar*) pa->flag,(char *) (pa->typelib.type_names+old_count),
 
7208
           old_count*sizeof(*pa->flag));
7018
7209
  }
7019
 
  pa->flag[pa->typelib.count]=0;      /* Reset flag */
 
7210
  pa->flag[pa->typelib.count]=0;                        /* Reset flag */
7020
7211
  pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
7021
 
  pa->typelib.type_names[pa->typelib.count]= NULL;  /* Put end-mark */
7022
 
  my_stpcpy((char*) pa->str+pa->length,name);
 
7212
  pa->typelib.type_names[pa->typelib.count]= NullS;     /* Put end-mark */
 
7213
  VOID(strmov((char*) pa->str+pa->length,name));
7023
7214
  pa->length+=length;
7024
7215
  return(0);
7025
7216
} /* insert_pointer_name */
7032
7223
  if (pa->typelib.count)
7033
7224
  {
7034
7225
    pa->typelib.count=0;
7035
 
    free((char*) pa->typelib.type_names);
 
7226
    my_free((char*) pa->typelib.type_names,MYF(0));
7036
7227
    pa->typelib.type_names=0;
7037
 
    free(pa->str);
 
7228
    my_free(pa->str,MYF(0));
7038
7229
  }
7039
7230
} /* free_pointer_array */
7040
7231
 
7042
7233
/* Functions that uses replace and replace_regex */
7043
7234
 
7044
7235
/* Append the string to ds, with optional replace */
7045
 
void replace_append_mem(string *ds,
7046
 
                        const char *val, int len)
 
7236
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
 
7237
                               const char *val, int len)
7047
7238
{
7048
 
  char *v= strdup(val);
7049
 
 
7050
7239
  if (glob_replace_regex)
7051
7240
  {
7052
7241
    /* Regex replace */
7053
 
    if (!multi_reg_replace(glob_replace_regex, v))
 
7242
    if (!multi_reg_replace(glob_replace_regex, (char*)val))
7054
7243
    {
7055
 
      v= glob_replace_regex->buf;
7056
 
      len= strlen(v);
 
7244
      val= glob_replace_regex->buf;
 
7245
      len= strlen(val);
7057
7246
    }
7058
7247
  }
7059
7248
 
7060
7249
  if (glob_replace)
7061
7250
  {
7062
7251
    /* Normal replace */
7063
 
    replace_strings_append(glob_replace, ds, v, len);
 
7252
    replace_strings_append(glob_replace, ds, val, len);
7064
7253
  }
7065
7254
  else
7066
 
  {
7067
 
    ds->append(v, len);
7068
 
  }
 
7255
    dynstr_append_mem(ds, val, len);
7069
7256
}
7070
7257
 
7071
7258
 
7072
7259
/* Append zero-terminated string to ds, with optional replace */
7073
 
void replace_append(string *ds, const char *val)
 
7260
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7074
7261
{
7075
 
  replace_append_mem(ds, val, strlen(val));
 
7262
  replace_dynstr_append_mem(ds, val, strlen(val));
7076
7263
}
7077
7264
 
7078
7265
/* Append uint to ds, with optional replace */
7079
 
void replace_append_uint(string *ds, uint val)
 
7266
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7080
7267
{
7081
7268
  char buff[22]; /* This should be enough for any int */
7082
7269
  char *end= int64_t10_to_str(val, buff, 10);
7083
 
  replace_append_mem(ds, buff, end - buff);
7084
 
 
 
7270
  replace_dynstr_append_mem(ds, buff, end - buff);
7085
7271
}
7086
7272
 
7087
7273
 
7098
7284
 
7099
7285
*/
7100
7286
 
7101
 
 
7102
 
void append_sorted(string* ds, string *ds_input)
7103
 
{
7104
 
  priority_queue<string> lines;
7105
 
 
7106
 
  if (ds_input->empty())
 
7287
static int comp_lines(const char **a, const char **b)
 
7288
{
 
7289
  return (strcmp(*a,*b));
 
7290
}
 
7291
 
 
7292
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
 
7293
{
 
7294
  unsigned i;
 
7295
  char *start= ds_input->str;
 
7296
  DYNAMIC_ARRAY lines;
 
7297
 
 
7298
 
 
7299
  if (!*start)
7107
7300
    return;  /* No input */
7108
7301
 
7109
 
  unsigned long eol_pos= 0;
7110
 
 
7111
 
  eol_pos= ds_input->find_first_of('\n', 0);
7112
 
  if (eol_pos == string::npos)
7113
 
    return; // We should have at least one header here
7114
 
 
7115
 
  ds->append(ds_input->substr(0, eol_pos));
7116
 
 
7117
 
  unsigned long start_pos= eol_pos+1;
 
7302
  my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
 
7303
 
 
7304
  /* First line is result header, skip past it */
 
7305
  while (*start && *start != '\n')
 
7306
    start++;
 
7307
  start++; /* Skip past \n */
 
7308
  dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
7118
7309
 
7119
7310
  /* Insert line(s) in array */
7120
 
  do {
 
7311
  while (*start)
 
7312
  {
 
7313
    char* line_end= (char*)start;
7121
7314
 
7122
 
    eol_pos= ds_input->find_first_of('\n', start_pos);
7123
7315
    /* Find end of line */
7124
 
    lines.push(ds_input->substr(start_pos, eol_pos-start_pos));
7125
 
    start_pos= eol_pos+1;
7126
 
 
7127
 
  } while ( eol_pos != string::npos);
 
7316
    while (*line_end && *line_end != '\n')
 
7317
      line_end++;
 
7318
    *line_end= 0;
 
7319
 
 
7320
    /* Insert pointer to the line in array */
 
7321
    if (insert_dynamic(&lines, (uchar*) &start))
 
7322
      die("Out of memory inserting lines to sort");
 
7323
 
 
7324
    start= line_end+1;
 
7325
  }
 
7326
 
 
7327
  /* Sort array */
 
7328
  qsort(lines.buffer, lines.elements,
 
7329
        sizeof(char**), (qsort_cmp)comp_lines);
7128
7330
 
7129
7331
  /* Create new result */
7130
 
  while (!lines.empty()) {
7131
 
    ds->append(lines.top());
7132
 
    lines.pop();
 
7332
  for (i= 0; i < lines.elements ; i++)
 
7333
  {
 
7334
    const char **line= dynamic_element(&lines, i, const char**);
 
7335
    dynstr_append(ds, *line);
 
7336
    dynstr_append(ds, "\n");
7133
7337
  }
7134
7338
 
 
7339
  delete_dynamic(&lines);
7135
7340
  return;
7136
7341
}