~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Jay Pipes
  • Date: 2008-07-17 17:54:00 UTC
  • mto: This revision was merged to the branch mainline in revision 182.
  • Revision ID: jay@mysql.com-20080717175400-xm2aazihjra8mdzq
Removal of DBUG from libdrizzle/ - Round 2

Show diffs side-by-side

added added

removed removed

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