~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Mats Kindahl
  • Date: 2008-08-07 06:24:22 UTC
  • mfrom: (265 drizzle)
  • mto: (264.1.19 codestyle)
  • mto: This revision was merged to the branch mainline in revision 266.
  • Revision ID: mats@mysql.com-20080807062422-20kyv6ssp4grfm0s
Manual merge of lp:drizzle into ~mkindahl/remove-mem-casts.

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) 2008 Drizzle Open Source Development Team 
 
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
17
  drizzletest
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
38
#include <mysys/hash.h>
52
39
#include <stdarg.h>
 
40
#include <vio/violite.h>
53
41
 
54
42
#include "errname.h"
55
43
 
56
 
using namespace std;
57
 
 
58
44
#define MAX_VAR_NAME_LENGTH    256
59
45
#define MAX_COLUMNS            256
60
46
#define MAX_EMBEDDED_SERVER_ARGS 64
65
51
#define QUERY_REAP_FLAG  2
66
52
 
67
53
enum {
 
54
  OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
68
55
  OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
69
56
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
70
57
};
134
121
static struct st_test_file* file_stack_end;
135
122
 
136
123
 
137
 
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
 
124
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
138
125
 
139
126
static int embedded_server_arg_count=0;
140
127
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
150
137
 
151
138
static uint64_t progress_start= 0;
152
139
 
153
 
vector<struct st_command*> q_lines;
 
140
DYNAMIC_ARRAY q_lines;
154
141
 
155
142
typedef struct {
156
143
  int read_lines,current_line;
160
147
typedef struct
161
148
{
162
149
  char file[FN_REFLEN];
163
 
  uint32_t pos;
 
150
  ulong pos;
164
151
} master_pos_st;
165
152
 
166
153
master_pos_st master_pos;
228
215
  Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
229
216
  Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
230
217
  Q_START_TIMER, Q_END_TIMER,
231
 
  Q_CHARACTER_SET,
 
218
  Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
232
219
  Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
233
220
  Q_IF,
234
221
  Q_DISABLE_PARSING, Q_ENABLE_PARSING,
310
297
  "copy_file",
311
298
  "perl",
312
299
  "die",
313
 
 
 
300
              
314
301
  /* Don't execute any more commands, compare result */
315
302
  "exit",
316
303
  "skip",
369
356
};
370
357
 
371
358
TYPELIB command_typelib= {array_elements(command_names),"",
372
 
                          command_names, 0};
 
359
        command_names, 0};
373
360
 
374
 
string ds_res, ds_progress, ds_warning_messages;
 
361
DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
375
362
 
376
363
char builtin_echo[FN_REFLEN];
377
364
 
395
382
void eval_expr(VAR* v, const char *p, const char** p_end);
396
383
bool match_delimiter(int c, const char *delim, uint length);
397
384
void dump_result_to_reject_file(char *buf, int size);
398
 
void dump_result_to_log_file(const char *buf, int size);
 
385
void dump_result_to_log_file(char *buf, int size);
399
386
void dump_warning_messages(void);
400
387
void dump_progress(void);
401
388
 
402
 
void do_eval(string *query_eval, const char *query,
 
389
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
403
390
             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);
 
391
void str_to_file(const char *fname, char *str, int size);
 
392
void str_to_file2(const char *fname, char *str, int size, bool append);
406
393
 
407
394
/* For replace_column */
408
395
static char *replace_column[MAX_COLUMNS];
428
415
  free_replace_column();
429
416
}
430
417
 
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);
 
418
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
 
419
                               int len);
 
420
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
 
421
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
 
422
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input);
436
423
 
437
424
void handle_error(struct st_command*,
438
425
                  unsigned int err_errno, const char *err_error,
439
 
                  const char *err_sqlstate, string *ds);
 
426
                  const char *err_sqlstate, DYNAMIC_STRING *ds);
440
427
void handle_no_error(struct st_command*);
441
428
 
 
429
#ifdef EMBEDDED_LIBRARY
 
430
 
 
431
/* attributes of the query thread */
 
432
pthread_attr_t cn_thd_attrib;
 
433
 
 
434
/*
 
435
  send_one_query executes query in separate thread, which is
 
436
  necessary in embedded library to run 'send' in proper way.
 
437
  This implementation doesn't handle errors returned
 
438
  by drizzle_send_query. It's technically possible, though
 
439
  I don't see where it is needed.
 
440
*/
 
441
pthread_handler_t send_one_query(void *arg)
 
442
{
 
443
  struct st_connection *cn= (struct st_connection*)arg;
 
444
 
 
445
  drizzle_thread_init();
 
446
  VOID(drizzle_send_query(&cn->drizzle, cn->cur_query, cn->cur_query_len));
 
447
 
 
448
  drizzle_thread_end();
 
449
  pthread_mutex_lock(&cn->mutex);
 
450
  cn->query_done= 1;
 
451
  VOID(pthread_cond_signal(&cn->cond));
 
452
  pthread_mutex_unlock(&cn->mutex);
 
453
  pthread_exit(0);
 
454
  return 0;
 
455
}
 
456
 
 
457
static int do_send_query(struct st_connection *cn, const char *q, int q_len,
 
458
                         int flags)
 
459
{
 
460
  pthread_t tid;
 
461
 
 
462
  if (flags & QUERY_REAP_FLAG)
 
463
    return drizzle_send_query(&cn->drizzle, q, q_len);
 
464
 
 
465
  if (pthread_mutex_init(&cn->mutex, NULL) ||
 
466
      pthread_cond_init(&cn->cond, NULL))
 
467
    die("Error in the thread library");
 
468
 
 
469
  cn->cur_query= q;
 
470
  cn->cur_query_len= q_len;
 
471
  cn->query_done= 0;
 
472
  if (pthread_create(&tid, &cn_thd_attrib, send_one_query, (void*)cn))
 
473
    die("Cannot start new thread for query");
 
474
 
 
475
  return 0;
 
476
}
 
477
 
 
478
static void wait_query_thread_end(struct st_connection *con)
 
479
{
 
480
  if (!con->query_done)
 
481
  {
 
482
    pthread_mutex_lock(&con->mutex);
 
483
    while (!con->query_done)
 
484
      pthread_cond_wait(&con->cond, &con->mutex);
 
485
    pthread_mutex_unlock(&con->mutex);
 
486
  }
 
487
}
 
488
 
 
489
#else /*EMBEDDED_LIBRARY*/
442
490
 
443
491
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
444
492
 
445
 
void do_eval(string *query_eval, const char *query,
 
493
#endif /*EMBEDDED_LIBRARY*/
 
494
 
 
495
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
446
496
             const char *query_end, bool pass_through_escape_chars)
447
497
{
448
498
  const char *p;
457
507
    case '$':
458
508
      if (escaped)
459
509
      {
460
 
        escaped= 0;
461
 
        query_eval->append(p, 1);
 
510
  escaped= 0;
 
511
  dynstr_append_mem(query_eval, p, 1);
462
512
      }
463
513
      else
464
514
      {
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);
 
515
  if (!(v= var_get(p, &p, 0, 0)))
 
516
    die("Bad variable in eval");
 
517
  dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
468
518
      }
469
519
      break;
470
520
    case '\\':
471
521
      next_c= *(p+1);
472
522
      if (escaped)
473
523
      {
474
 
        escaped= 0;
475
 
        query_eval->append(p, 1);
 
524
  escaped= 0;
 
525
  dynstr_append_mem(query_eval, p, 1);
476
526
      }
477
527
      else if (next_c == '\\' || next_c == '$' || next_c == '"')
478
528
      {
479
529
        /* Set escaped only if next char is \, " or $ */
480
 
        escaped= 1;
 
530
  escaped= 1;
481
531
 
482
532
        if (pass_through_escape_chars)
483
533
        {
484
534
          /* The escape char should be added to the output string. */
485
 
          query_eval->append(p, 1);
 
535
          dynstr_append_mem(query_eval, p, 1);
486
536
        }
487
537
      }
488
538
      else
489
 
        query_eval->append(p, 1);
 
539
  dynstr_append_mem(query_eval, p, 1);
490
540
      break;
491
541
    default:
492
542
      escaped= 0;
493
 
      query_eval->append(p, 1);
 
543
      dynstr_append_mem(query_eval, p, 1);
494
544
      break;
495
545
    }
496
546
  }
499
549
 
500
550
 
501
551
/*
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
552
  Run query and dump the result to stdout in vertical format
547
553
 
548
554
  NOTE! This function should be safe to call when an error
688
694
  const char *argname;       /* Name of argument   */
689
695
  enum arg_type type;        /* Type of argument   */
690
696
  bool required;          /* Argument required  */
691
 
  string *ds;        /* Storage for argument */
 
697
  DYNAMIC_STRING *ds;        /* Storage for argument */
692
698
  const char *description;   /* Description of the argument */
693
699
};
694
700
 
718
724
        ptr++;
719
725
      if (ptr > start)
720
726
      {
 
727
        init_dynamic_string(arg->ds, 0, ptr-start, 32);
721
728
        do_eval(arg->ds, start, ptr, false);
722
729
      }
723
730
      else
724
731
      {
725
732
        /* Empty string */
726
 
        arg->ds->erase();
 
733
        init_dynamic_string(arg->ds, "", 0, 0);
727
734
      }
728
735
      command->last_argument= (char*)ptr;
729
736
 
735
742
      /* Rest of line */
736
743
    case ARG_REST:
737
744
      start= ptr;
 
745
      init_dynamic_string(arg->ds, 0, command->query_len, 256);
738
746
      do_eval(arg->ds, start, command->end, false);
739
747
      command->last_argument= command->end;
740
748
      break;
745
753
    }
746
754
 
747
755
    /* Check required arg */
748
 
    if (arg->ds->length() == 0 && arg->required)
 
756
    if (arg->ds->length == 0 && arg->required)
749
757
      die("Missing required argument '%s' to command '%.*s'", arg->argname,
750
758
          command->first_word_len, command->query);
751
759
 
804
812
    drizzle_close(&next_con->drizzle);
805
813
    if (next_con->util_drizzle)
806
814
      drizzle_close(next_con->util_drizzle);
807
 
    free(next_con->name);
 
815
    my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
808
816
  }
809
817
  return;
810
818
}
819
827
    {
820
828
      my_fclose(cur_file->file, MYF(0));
821
829
    }
822
 
    free((unsigned char*) cur_file->file_name);
 
830
    my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
823
831
    cur_file->file_name= 0;
824
832
  }
825
833
  return;
835
843
  close_files();
836
844
  hash_free(&var_hash);
837
845
 
838
 
  vector<struct st_command *>::iterator iter;
839
 
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
 
846
  for (i= 0 ; i < q_lines.elements ; i++)
840
847
  {
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);
 
848
    struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
 
849
    my_free((*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
 
850
    my_free((*q),MYF(0));
847
851
  }
848
 
 
849
852
  for (i= 0; i < 10; i++)
850
853
  {
851
854
    if (var_reg[i].alloced_len)
852
 
      free(var_reg[i].str_val);
 
855
      my_free(var_reg[i].str_val, MYF(MY_WME));
853
856
  }
854
857
  while (embedded_server_arg_count > 1)
855
 
    free(embedded_server_args[--embedded_server_arg_count]);
856
 
 
 
858
    my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
 
859
  delete_dynamic(&q_lines);
 
860
  dynstr_free(&ds_res);
 
861
  dynstr_free(&ds_progress);
 
862
  dynstr_free(&ds_warning_messages);
857
863
  free_all_replace();
858
 
  free(opt_pass);
 
864
  my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
859
865
  free_defaults(default_argv);
860
866
 
 
867
  /* Only call drizzle_server_end if drizzle_server_init has been called */
 
868
  if (server_initialized)
 
869
    drizzle_server_end();
 
870
 
861
871
  return;
862
872
}
863
873
 
877
887
      break;
878
888
    case 62:
879
889
      printf("skipped\n");
880
 
      break;
 
890
    break;
881
891
    default:
882
892
      printf("unknown exit code: %d\n", exit_code);
883
893
      assert(0);
920
930
  fflush(stderr);
921
931
 
922
932
  /* Show results from queries just before failure */
923
 
  if (ds_res.length() && opt_tail_lines)
 
933
  if (ds_res.length && opt_tail_lines)
924
934
  {
925
935
    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 )
 
936
    char* show_from= ds_res.str + ds_res.length - 1;
 
937
    while(show_from > ds_res.str && tail_lines > 0 )
928
938
    {
929
939
      show_from--;
930
940
      if (*show_from == '\n')
931
941
        tail_lines--;
932
942
    }
933
943
    fprintf(stderr, "\nThe result from queries just before the failure was:\n");
934
 
    if (show_from > ds_res.c_str())
 
944
    if (show_from > ds_res.str)
935
945
      fprintf(stderr, "< snip >");
936
946
    fprintf(stderr, "%s", show_from);
937
947
    fflush(stderr);
938
948
  }
939
949
 
940
950
  /* 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());
 
951
  if (result_file_name && ds_res.length)
 
952
    dump_result_to_log_file(ds_res.str, ds_res.length);
943
953
 
944
954
  /* Dump warning messages */
945
 
  if (result_file_name && ds_warning_messages.length())
 
955
  if (result_file_name && ds_warning_messages.length)
946
956
    dump_warning_messages();
947
957
 
948
958
  /*
1019
1029
 
1020
1030
 
1021
1031
  va_start(args, fmt);
1022
 
  ds_warning_messages.append("drizzletest: ");
 
1032
  dynstr_append(&ds_warning_messages, "drizzletest: ");
1023
1033
  if (start_lineno != 0)
1024
1034
  {
1025
 
    ds_warning_messages.append("Warning detected ");
 
1035
    dynstr_append(&ds_warning_messages, "Warning detected ");
1026
1036
    if (cur_file && cur_file != file_stack)
1027
1037
    {
1028
1038
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1029
 
                    cur_file->file_name);
1030
 
      ds_warning_messages.append(buff, len);
 
1039
                       cur_file->file_name);
 
1040
      dynstr_append_mem(&ds_warning_messages,
 
1041
                        buff, len);
1031
1042
    }
1032
1043
    len= snprintf(buff, sizeof(buff), "at line %d: ",
1033
 
                  start_lineno);
1034
 
    ds_warning_messages.append(buff, len);
 
1044
                     start_lineno);
 
1045
    dynstr_append_mem(&ds_warning_messages,
 
1046
                      buff, len);
1035
1047
  }
1036
1048
 
1037
1049
  len= vsnprintf(buff, sizeof(buff), fmt, args);
1038
 
  ds_warning_messages.append(buff, len);
 
1050
  dynstr_append_mem(&ds_warning_messages, buff, len);
1039
1051
 
1040
 
  ds_warning_messages.append("\n");
 
1052
  dynstr_append(&ds_warning_messages, "\n");
1041
1053
  va_end(args);
1042
1054
 
1043
1055
  return;
1055
1067
  len= vsnprintf(buff, sizeof(buff)-1, fmt, args);
1056
1068
  va_end(args);
1057
1069
 
1058
 
  ds_res.append(buff, len);
1059
 
  ds_res.append("\n");
 
1070
  dynstr_append_mem(&ds_res, buff, len);
 
1071
  dynstr_append(&ds_res, "\n");
1060
1072
 
1061
1073
  return;
1062
1074
}
1072
1084
 
1073
1085
*/
1074
1086
 
1075
 
static void cat_file(string* ds, const char* filename)
 
1087
static void cat_file(DYNAMIC_STRING* ds, const char* filename)
1076
1088
{
1077
1089
  int fd;
1078
1090
  uint len;
1080
1092
 
1081
1093
  if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
1082
1094
    die("Failed to open file '%s'", filename);
1083
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1095
  while((len= my_read(fd, (uchar*)&buff,
1084
1096
                      sizeof(buff), MYF(0))) > 0)
1085
1097
  {
1086
1098
    char *p= buff, *start= buff;
1092
1104
        /* Add fake newline instead of cr and output the line */
1093
1105
        *p= '\n';
1094
1106
        p++; /* Step past the "fake" newline */
1095
 
        ds->append(start, p-start);
 
1107
        dynstr_append_mem(ds, start, p-start);
1096
1108
        p++; /* Step past the "fake" newline */
1097
1109
        start= p;
1098
1110
      }
1099
1111
      else
1100
1112
        p++;
1101
1113
    }
1102
 
    /* Output any chars that might be left */
1103
 
    ds->append(start, p-start);
 
1114
    /* Output any chars that migh be left */
 
1115
    dynstr_append_mem(ds, start, p-start);
1104
1116
  }
1105
1117
  my_close(fd, MYF(0));
1106
1118
}
1112
1124
  SYNOPSIS
1113
1125
  run_command
1114
1126
  cmd - command to execute(should be properly quoted
1115
 
  result - pointer to string where to store the result
 
1127
  ds_res- pointer to dynamic string where to store the result
1116
1128
 
1117
1129
*/
1118
1130
 
1119
 
static int run_command(const char * cmd, string * result)
 
1131
static int run_command(char* cmd,
 
1132
                       DYNAMIC_STRING *ds_res)
1120
1133
{
1121
 
  assert(result!=NULL);
1122
1134
  char buf[512]= {0};
1123
1135
  FILE *res_file;
1124
1136
  int error;
1128
1140
 
1129
1141
  while (fgets(buf, sizeof(buf), res_file))
1130
1142
  {
1131
 
    /* Save the output of this command in the supplied string */
1132
 
    result->append(buf);
 
1143
    if(ds_res)
 
1144
    {
 
1145
      /* Save the output of this command in the supplied string */
 
1146
      dynstr_append(ds_res, buf);
 
1147
    }
 
1148
    else
 
1149
    {
 
1150
      /* Print it directly on screen */
 
1151
      fprintf(stdout, "%s", buf);
 
1152
    }
1133
1153
  }
1134
1154
 
1135
1155
  error= pclose(res_file);
1143
1163
  SYNOPSIS
1144
1164
  run_tool
1145
1165
  tool_path - the name of the tool to run
1146
 
  result - pointer to dynamic string where to store the result
 
1166
  ds_res - pointer to dynamic string where to store the result
1147
1167
  ... - variable number of arguments that will be properly
1148
 
  quoted and appended after the tool's name
 
1168
        quoted and appended after the tool's name
1149
1169
 
1150
1170
*/
1151
1171
 
1152
 
static int run_tool(const char *tool_path, string * result, ...)
 
1172
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1153
1173
{
1154
1174
  int ret;
1155
1175
  const char* arg;
1156
1176
  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);
 
1177
  DYNAMIC_STRING ds_cmdline;
 
1178
 
 
1179
  if (init_dynamic_string(&ds_cmdline, "", FN_REFLEN, FN_REFLEN))
 
1180
    die("Out of memory");
 
1181
 
 
1182
  dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
 
1183
  dynstr_append(&ds_cmdline, " ");
 
1184
 
 
1185
  va_start(args, ds_res);
1164
1186
 
1165
1187
  while ((arg= va_arg(args, char *)))
1166
1188
  {
1167
1189
    /* Options should be os quoted */
1168
1190
    if (strncmp(arg, "--", 2) == 0)
1169
 
      append_os_quoted(&ds_cmdline, arg, NULL);
 
1191
      dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1170
1192
    else
1171
 
      ds_cmdline.append(arg);
1172
 
    ds_cmdline.append(" ");
 
1193
      dynstr_append(&ds_cmdline, arg);
 
1194
    dynstr_append(&ds_cmdline, " ");
1173
1195
  }
1174
1196
 
1175
1197
  va_end(args);
1176
1198
 
1177
 
  ret= run_command(ds_cmdline.c_str(), result);
 
1199
  ret= run_command(ds_cmdline.str, ds_res);
 
1200
  dynstr_free(&ds_cmdline);
1178
1201
  return(ret);
1179
1202
}
1180
1203
 
1192
1215
 
1193
1216
*/
1194
1217
 
1195
 
static void show_diff(string* ds,
 
1218
static void show_diff(DYNAMIC_STRING* ds,
1196
1219
                      const char* filename1, const char* filename2)
1197
1220
{
1198
1221
 
1199
 
  string ds_tmp;
 
1222
  DYNAMIC_STRING ds_tmp;
 
1223
 
 
1224
  if (init_dynamic_string(&ds_tmp, "", 256, 256))
 
1225
    die("Out of memory");
1200
1226
 
1201
1227
  /* First try with unified diff */
1202
1228
  if (run_tool("diff",
1207
1233
               "2>&1",
1208
1234
               NULL) > 1) /* Most "diff" tools return >1 if error */
1209
1235
  {
1210
 
    ds_tmp= "";
 
1236
    dynstr_set(&ds_tmp, "");
1211
1237
 
1212
1238
    /* Fallback to context diff with "diff -c" */
1213
1239
    if (run_tool("diff",
1222
1248
        Fallback to dump both files to result file and inform
1223
1249
        about installing "diff"
1224
1250
      */
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");
 
1251
      dynstr_set(&ds_tmp, "");
 
1252
 
 
1253
      dynstr_append(&ds_tmp,
 
1254
"\n"
 
1255
"The two files differ but it was not possible to execute 'diff' in\n"
 
1256
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
 
1257
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
 
1258
"To get a better report you should install 'diff' on your system, which you\n"
 
1259
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
 
1260
"\n");
 
1261
 
 
1262
      dynstr_append(&ds_tmp, " --- ");
 
1263
      dynstr_append(&ds_tmp, filename1);
 
1264
      dynstr_append(&ds_tmp, " >>>\n");
1239
1265
      cat_file(&ds_tmp, filename1);
1240
 
      ds_tmp.append("<<<\n --- ");
1241
 
      ds_tmp.append(filename1);
1242
 
      ds_tmp.append(" >>>\n");
 
1266
      dynstr_append(&ds_tmp, "<<<\n --- ");
 
1267
      dynstr_append(&ds_tmp, filename1);
 
1268
      dynstr_append(&ds_tmp, " >>>\n");
1243
1269
      cat_file(&ds_tmp, filename2);
1244
 
      ds_tmp.append("<<<<\n");
 
1270
      dynstr_append(&ds_tmp, "<<<<\n");
1245
1271
    }
1246
1272
  }
1247
1273
 
1248
1274
  if (ds)
1249
1275
  {
1250
1276
    /* Add the diff to output */
1251
 
    ds->append(ds_tmp.c_str(), ds_tmp.length());
 
1277
    dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1252
1278
  }
1253
1279
  else
1254
1280
  {
1255
1281
    /* Print diff directly to stdout */
1256
 
    fprintf(stderr, "%s\n", ds_tmp.c_str());
 
1282
    fprintf(stderr, "%s\n", ds_tmp.str);
1257
1283
  }
1258
1284
 
 
1285
  dynstr_free(&ds_tmp);
 
1286
 
1259
1287
}
1260
1288
 
1261
1289
 
1262
1290
enum compare_files_result_enum {
1263
 
  RESULT_OK= 0,
1264
 
  RESULT_CONTENT_MISMATCH= 1,
1265
 
  RESULT_LENGTH_MISMATCH= 2
 
1291
   RESULT_OK= 0,
 
1292
   RESULT_CONTENT_MISMATCH= 1,
 
1293
   RESULT_LENGTH_MISMATCH= 2
1266
1294
};
1267
1295
 
1268
1296
/*
1291
1319
    my_close(fd, MYF(0));
1292
1320
    die("Failed to open second file: '%s'", filename2);
1293
1321
  }
1294
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1322
  while((len= my_read(fd, (uchar*)&buff,
1295
1323
                      sizeof(buff), MYF(0))) > 0)
1296
1324
  {
1297
 
    if ((len2= my_read(fd2, (unsigned char*)&buff2,
 
1325
    if ((len2= my_read(fd2, (uchar*)&buff2,
1298
1326
                       sizeof(buff2), MYF(0))) < len)
1299
1327
    {
1300
1328
      /* File 2 was smaller */
1314
1342
      break;
1315
1343
    }
1316
1344
  }
1317
 
  if (!error && my_read(fd2, (unsigned char*)&buff2,
 
1345
  if (!error && my_read(fd2, (uchar*)&buff2,
1318
1346
                        sizeof(buff2), MYF(0)) > 0)
1319
1347
  {
1320
1348
    /* File 1 was smaller */
1360
1388
  Compare content of the string in ds to content of file fname
1361
1389
 
1362
1390
  SYNOPSIS
1363
 
  string_cmp
 
1391
  dyn_string_cmp
1364
1392
  ds - Dynamic string containing the string o be compared
1365
1393
  fname - Name of file to compare with
1366
1394
 
1368
1396
  See 'compare_files2'
1369
1397
*/
1370
1398
 
1371
 
static int string_cmp(string* ds, const char *fname)
 
1399
static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
1372
1400
{
1373
1401
  int error;
1374
1402
  File fd;
1375
1403
  char temp_file_path[FN_REFLEN];
1376
1404
 
1377
1405
  if ((fd= create_temp_file(temp_file_path, NULL,
1378
 
                            "tmp", O_CREAT | O_RDWR,
 
1406
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
1379
1407
                            MYF(MY_WME))) < 0)
1380
1408
    die("Failed to create temporary file for ds");
1381
1409
 
1382
1410
  /* Write ds to temporary file and set file pos to beginning*/
1383
 
  if (my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
 
1411
  if (my_write(fd, (uchar *) ds->str, ds->length,
1384
1412
               MYF(MY_FNABP | MY_WME)) ||
1385
1413
      my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1386
1414
  {
1412
1440
 
1413
1441
*/
1414
1442
 
1415
 
static void check_result(string* ds)
 
1443
static void check_result(DYNAMIC_STRING* ds)
1416
1444
{
1417
1445
  const char* mess= "Result content mismatch\n";
1418
1446
 
1422
1450
  if (access(result_file_name, F_OK) != 0)
1423
1451
    die("The specified result file does not exist: '%s'", result_file_name);
1424
1452
 
1425
 
  switch (string_cmp(ds, result_file_name)) {
 
1453
  switch (dyn_string_cmp(ds, result_file_name)) {
1426
1454
  case RESULT_OK:
1427
1455
    break; /* ok */
1428
1456
  case RESULT_LENGTH_MISMATCH:
1450
1478
      fn_format(reject_file, result_file_name, opt_logdir,
1451
1479
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1452
1480
    }
1453
 
    str_to_file(reject_file, ds->c_str(), ds->length());
 
1481
    str_to_file(reject_file, ds->str, ds->length);
1454
1482
 
1455
 
    ds->erase(); /* Don't create a .log file */
 
1483
    dynstr_set(ds, NULL); /* Don't create a .log file */
1456
1484
 
1457
1485
    show_diff(NULL, result_file_name, reject_file);
1458
1486
    die(mess);
1481
1509
 
1482
1510
*/
1483
1511
 
1484
 
static void check_require(string* ds, const char *fname)
 
1512
static void check_require(DYNAMIC_STRING* ds, const char *fname)
1485
1513
{
1486
1514
 
1487
1515
 
1488
 
  if (string_cmp(ds, fname))
 
1516
  if (dyn_string_cmp(ds, fname))
1489
1517
  {
1490
1518
    char reason[FN_REFLEN];
1491
1519
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1496
1524
 
1497
1525
 
1498
1526
/*
1499
 
  Remove surrounding chars from string
 
1527
   Remove surrounding chars from string
1500
1528
 
1501
 
  Return 1 if first character is found but not last
 
1529
   Return 1 if first character is found but not last
1502
1530
*/
1503
1531
static int strip_surrounding(char* str, char c1, char c2)
1504
1532
{
1513
1541
    *ptr= ' ';
1514
1542
 
1515
1543
    /* Last non space charecter should be c2 */
1516
 
    ptr= strchr(str, '\0')-1;
 
1544
    ptr= strend(str)-1;
1517
1545
    while(*ptr && my_isspace(charset_info, *ptr))
1518
1546
      ptr--;
1519
1547
    if (*ptr == c2)
1534
1562
static void strip_parentheses(struct st_command *command)
1535
1563
{
1536
1564
  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, '(', ')');
 
1565
      die("%.*s - argument list started with '%c' must be ended with '%c'",
 
1566
          command->first_word_len, command->query, '(', ')');
1539
1567
}
1540
1568
 
1541
1569
 
1542
 
static unsigned char *get_var_key(const unsigned char* var, size_t *len,
 
1570
static uchar *get_var_key(const uchar* var, size_t *len,
1543
1571
                          bool __attribute__((unused)) t)
1544
1572
{
1545
1573
  register char* key;
1546
1574
  key = ((VAR*)var)->name;
1547
1575
  *len = ((VAR*)var)->name_len;
1548
 
  return (unsigned char*)key;
 
1576
  return (uchar*)key;
1549
1577
}
1550
1578
 
1551
1579
 
1587
1615
 
1588
1616
void var_free(void *v)
1589
1617
{
1590
 
  free(((VAR*) v)->str_val);
1591
 
  free(((VAR*) v)->env_s);
 
1618
  my_free(((VAR*) v)->str_val, MYF(MY_WME));
 
1619
  my_free(((VAR*) v)->env_s, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
1592
1620
  if (((VAR*)v)->alloced)
1593
 
    free(v);
 
1621
    my_free(v, MYF(MY_WME));
1594
1622
}
1595
1623
 
1596
1624
 
1602
1630
    tmp = def_val;
1603
1631
 
1604
1632
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1605
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1633
  my_hash_insert(&var_hash, (uchar*)v);
1606
1634
  return v;
1607
1635
}
1608
1636
 
1609
1637
 
1610
1638
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1611
 
             bool ignore_not_existing)
 
1639
       bool ignore_not_existing)
1612
1640
{
1613
1641
  int digit;
1614
1642
  VAR *v;
1626
1654
    if (var_name == save_var_name)
1627
1655
    {
1628
1656
      if (ignore_not_existing)
1629
 
        return(0);
 
1657
  return(0);
1630
1658
      die("Empty variable");
1631
1659
    }
1632
1660
    length= (uint) (var_name - save_var_name);
1633
1661
    if (length >= MAX_VAR_NAME_LENGTH)
1634
1662
      die("Too long variable name: %s", save_var_name);
1635
1663
 
1636
 
    if (!(v = (VAR*) hash_search(&var_hash, (const unsigned char*) save_var_name,
1637
 
                                 length)))
 
1664
    if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
 
1665
                                            length)))
1638
1666
    {
1639
1667
      char buff[MAX_VAR_NAME_LENGTH+1];
1640
1668
      strmake(buff, save_var_name, length);
1665
1693
static VAR *var_obtain(const char *name, int len)
1666
1694
{
1667
1695
  VAR* v;
1668
 
  if ((v = (VAR*)hash_search(&var_hash, (const unsigned char *) name, len)))
 
1696
  if ((v = (VAR*)hash_search(&var_hash, (const uchar *) name, len)))
1669
1697
    return v;
1670
1698
  v = var_init(0, name, len, "", 0);
1671
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1699
  my_hash_insert(&var_hash, (uchar*)v);
1672
1700
  return v;
1673
1701
}
1674
1702
 
1710
1738
      v->str_val_len= strlen(v->str_val);
1711
1739
    }
1712
1740
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
1713
 
             v->name_len, v->name,
1714
 
             v->str_val_len, v->str_val);
 
1741
                v->name_len, v->name,
 
1742
                v->str_val_len, v->str_val);
1715
1743
    if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
1716
1744
      die("Out of memory");
1717
1745
    putenv(v->env_s);
1718
 
    free(old_env_s);
 
1746
    my_free(old_env_s, MYF(MY_ALLOW_ZERO_PTR));
1719
1747
  }
1720
1748
  return;
1721
1749
}
1782
1810
 
1783
1811
static void var_query_set(VAR *var, const char *query, const char** query_end)
1784
1812
{
1785
 
  const char *end = (char*)((query_end && *query_end) ?
1786
 
                            *query_end : query + strlen(query));
 
1813
  char *end = (char*)((query_end && *query_end) ?
 
1814
          *query_end : query + strlen(query));
1787
1815
  DRIZZLE_RES *res;
1788
1816
  DRIZZLE_ROW row;
1789
1817
  DRIZZLE *drizzle= &cur_con->drizzle;
1790
 
  string ds_query;
 
1818
  DYNAMIC_STRING ds_query;
1791
1819
 
1792
1820
 
1793
1821
  while (end > query && *end != '`')
1797
1825
  ++query;
1798
1826
 
1799
1827
  /* Eval the query, thus replacing all environment variables */
 
1828
  init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
1800
1829
  do_eval(&ds_query, query, end, false);
1801
1830
 
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));
 
1831
  if (drizzle_real_query(drizzle, ds_query.str, ds_query.length))
 
1832
    die("Error running query '%s': %d %s", ds_query.str,
 
1833
  drizzle_errno(drizzle), drizzle_error(drizzle));
1805
1834
  if (!(res= drizzle_store_result(drizzle)))
1806
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
 
1835
    die("Query '%s' didn't return a result set", ds_query.str);
 
1836
  dynstr_free(&ds_query);
1807
1837
 
1808
1838
  if ((row= drizzle_fetch_row(res)) && row[0])
1809
1839
  {
1811
1841
      Concatenate all fields in the first row with tab in between
1812
1842
      and assign that string to the $variable
1813
1843
    */
1814
 
    string result;
 
1844
    DYNAMIC_STRING result;
1815
1845
    uint32_t i;
1816
1846
    uint32_t *lengths;
1817
1847
 
 
1848
    init_dynamic_string(&result, "", 512, 512);
1818
1849
    lengths= drizzle_fetch_lengths(res);
1819
1850
    for (i= 0; i < drizzle_num_fields(res); i++)
1820
1851
    {
1821
1852
      if (row[i])
1822
1853
      {
1823
1854
        /* Add column to tab separated string */
1824
 
        result.append(row[i], lengths[i]);
 
1855
  dynstr_append_mem(&result, row[i], lengths[i]);
1825
1856
      }
1826
 
      result.append("\t", 1);
 
1857
      dynstr_append_mem(&result, "\t", 1);
1827
1858
    }
1828
 
    end= result.c_str() + result.length()-1;
1829
 
    eval_expr(var, result.c_str(), (const char**) &end);
 
1859
    end= result.str + result.length-1;
 
1860
    eval_expr(var, result.str, (const char**) &end);
 
1861
    dynstr_free(&result);
1830
1862
  }
1831
1863
  else
1832
1864
    eval_expr(var, "", 0);
1852
1884
 
1853
1885
  <query to run> -    The query that should be sent to the server
1854
1886
  <column name> -     Name of the column that holds the field be compared
1855
 
  against the expected value
 
1887
                      against the expected value
1856
1888
  <row no> -          Number of the row that holds the field to be
1857
 
  compared against the expected value
 
1889
                      compared against the expected value
1858
1890
 
1859
1891
*/
1860
1892
 
1865
1897
  DRIZZLE_RES* res;
1866
1898
  DRIZZLE *drizzle= &cur_con->drizzle;
1867
1899
 
1868
 
  string ds_query;
1869
 
  string ds_col;
1870
 
  string ds_row;
 
1900
  static DYNAMIC_STRING ds_query;
 
1901
  static DYNAMIC_STRING ds_col;
 
1902
  static DYNAMIC_STRING ds_row;
1871
1903
  const struct command_arg query_get_value_args[] = {
1872
1904
    {"query", ARG_STRING, true, &ds_query, "Query to run"},
1873
1905
    {"column name", ARG_STRING, true, &ds_col, "Name of column"},
1882
1914
                     ',');
1883
1915
 
1884
1916
  /* 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());
 
1917
  if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
 
1918
    die("Invalid row number: '%s'", ds_row.str);
 
1919
  dynstr_free(&ds_row);
1887
1920
 
1888
1921
  /* 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;
 
1922
  if (strip_surrounding(ds_query.str, '"', '"'))
 
1923
    die("Mismatched \"'s around query '%s'", ds_query.str);
1894
1924
 
1895
1925
  /* 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));
 
1926
  if (drizzle_real_query(drizzle, ds_query.str, ds_query.length))
 
1927
    die("Error running query '%s': %d %s", ds_query.str,
 
1928
  drizzle_errno(drizzle), drizzle_error(drizzle));
1899
1929
  if (!(res= drizzle_store_result(drizzle)))
1900
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
 
1930
    die("Query '%s' didn't return a result set", ds_query.str);
1901
1931
 
1902
1932
  {
1903
1933
    /* Find column number from the given column name */
1907
1937
 
1908
1938
    for (i= 0; i < num_fields; i++)
1909
1939
    {
1910
 
      if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
1911
 
          strlen(fields[i].name) == ds_col.length())
 
1940
      if (strcmp(fields[i].name, ds_col.str) == 0 &&
 
1941
          strlen(fields[i].name) == ds_col.length)
1912
1942
      {
1913
1943
        col_no= i;
1914
1944
        break;
1918
1948
    {
1919
1949
      drizzle_free_result(res);
1920
1950
      die("Could not find column '%s' in the result of '%s'",
1921
 
          ds_col.c_str(), ds_query.c_str());
 
1951
          ds_col.str, ds_query.str);
1922
1952
    }
1923
1953
  }
 
1954
  dynstr_free(&ds_col);
1924
1955
 
1925
1956
  {
1926
1957
    /* Get the value */
1944
1975
    }
1945
1976
    eval_expr(var, value, 0);
1946
1977
  }
 
1978
  dynstr_free(&ds_query);
1947
1979
  drizzle_free_result(res);
1948
1980
 
1949
1981
  return;
2014
2046
        MIN_VAR_ALLOC : new_val_len + 1;
2015
2047
      if (!(v->str_val =
2016
2048
            v->str_val ? (char *)my_realloc(v->str_val, v->alloced_len+1,
2017
 
                                            MYF(MY_WME)) :
 
2049
                                    MYF(MY_WME)) :
2018
2050
            (char *)my_malloc(v->alloced_len+1, MYF(MY_WME))))
2019
2051
        die("Out of memory");
2020
2052
    }
2034
2066
 
2035
2067
  if (!test_if_hard_path(name))
2036
2068
  {
2037
 
    strxmov(buff, opt_basedir, name, NULL);
 
2069
    strxmov(buff, opt_basedir, name, NullS);
2038
2070
    name=buff;
2039
2071
  }
2040
2072
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2042
2074
  if (cur_file == file_stack_end)
2043
2075
    die("Source directives are nesting too deep");
2044
2076
  cur_file++;
2045
 
  if (!(cur_file->file = my_fopen(buff, O_RDONLY, MYF(0))))
 
2077
  if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
2046
2078
  {
2047
2079
    cur_file--;
2048
2080
    die("Could not open '%s' for reading", buff);
2069
2101
 
2070
2102
static void do_source(struct st_command *command)
2071
2103
{
2072
 
  string ds_filename;
 
2104
  static DYNAMIC_STRING ds_filename;
2073
2105
  const struct command_arg source_args[] = {
2074
2106
    { "filename", ARG_STRING, true, &ds_filename, "File to source" }
2075
2107
  };
2087
2119
    ; /* Do nothing */
2088
2120
  else
2089
2121
  {
2090
 
    open_file(ds_filename.c_str());
 
2122
    open_file(ds_filename.str);
2091
2123
  }
2092
2124
 
 
2125
  dynstr_free(&ds_filename);
2093
2126
  return;
2094
2127
}
2095
2128
 
2096
2129
 
 
2130
static FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
 
2131
{
 
2132
  return popen(ds_cmd->str, mode);
 
2133
}
 
2134
 
 
2135
 
2097
2136
static void init_builtin_echo(void)
2098
2137
{
2099
2138
  builtin_echo[0]= 0;
2105
2144
  Replace a substring
2106
2145
 
2107
2146
  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
 
2147
    replace
 
2148
    ds_str      The string to search and perform the replace in
 
2149
    search_str  The string to search for
 
2150
    search_len  Length of the string to search for
 
2151
    replace_str The string to replace with
 
2152
    replace_len Length of the string to replace with
2114
2153
 
2115
2154
  RETURN
2116
 
  0 String replaced
2117
 
  1 Could not find search_str in str
 
2155
    0 String replaced
 
2156
    1 Could not find search_str in str
2118
2157
*/
2119
2158
 
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)
 
2159
static int replace(DYNAMIC_STRING *ds_str,
 
2160
                   const char *search_str, ulong search_len,
 
2161
                   const char *replace_str, ulong replace_len)
2123
2162
{
2124
 
  string ds_tmp;
2125
 
  const char *start= strstr(ds_str->c_str(), search_str);
 
2163
  DYNAMIC_STRING ds_tmp;
 
2164
  const char *start= strstr(ds_str->str, search_str);
2126
2165
  if (!start)
2127
2166
    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;
 
2167
  init_dynamic_string(&ds_tmp, "",
 
2168
                      ds_str->length + replace_len, 256);
 
2169
  dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
 
2170
  dynstr_append_mem(&ds_tmp, replace_str, replace_len);
 
2171
  dynstr_append(&ds_tmp, start + search_len);
 
2172
  dynstr_set(ds_str, ds_tmp.str);
 
2173
  dynstr_free(&ds_tmp);
2132
2174
  return 0;
2133
2175
}
2134
2176
 
2160
2202
  char buf[512];
2161
2203
  FILE *res_file;
2162
2204
  char *cmd= command->first_argument;
2163
 
  string ds_cmd;
 
2205
  DYNAMIC_STRING ds_cmd;
2164
2206
 
2165
2207
  /* Skip leading space */
2166
2208
  while (*cmd && my_isspace(charset_info, *cmd))
2169
2211
    die("Missing argument in exec");
2170
2212
  command->last_argument= command->end;
2171
2213
 
 
2214
  init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
2172
2215
  /* Eval the command, thus replacing all environment variables */
2173
2216
  do_eval(&ds_cmd, cmd, command->end, !is_windows);
2174
2217
 
2179
2222
    replace(&ds_cmd, "echo", 4, builtin_echo, strlen(builtin_echo));
2180
2223
  }
2181
2224
 
2182
 
  if (!(res_file= popen(ds_cmd.c_str(), "r")) && command->abort_on_error)
 
2225
  if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
2183
2226
  {
 
2227
    dynstr_free(&ds_cmd);
2184
2228
    die("popen(\"%s\", \"r\") failed", command->first_argument);
2185
2229
  }
2186
2230
 
2192
2236
    }
2193
2237
    else
2194
2238
    {
2195
 
      replace_append(&ds_res, buf);
 
2239
      replace_dynstr_append(&ds_res, buf);
2196
2240
    }
2197
2241
  }
2198
2242
  error= pclose(res_file);
2204
2248
    if (command->abort_on_error)
2205
2249
    {
2206
2250
      log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
2207
 
              ds_cmd.c_str(), error, status, errno);
 
2251
              ds_cmd.str, error, status, errno);
 
2252
      dynstr_free(&ds_cmd);
2208
2253
      die("command \"%s\" failed", command->first_argument);
2209
2254
    }
2210
2255
 
2218
2263
    }
2219
2264
    if (!ok)
2220
2265
    {
 
2266
      dynstr_free(&ds_cmd);
2221
2267
      die("command \"%s\" failed with wrong error: %d",
2222
2268
          command->first_argument, status);
2223
2269
    }
2227
2273
  {
2228
2274
    /* Error code we wanted was != 0, i.e. not an expected success */
2229
2275
    log_msg("exec of '%s failed, error: %d, errno: %d",
2230
 
            ds_cmd.c_str(), error, errno);
 
2276
            ds_cmd.str, error, errno);
 
2277
    dynstr_free(&ds_cmd);
2231
2278
    die("command \"%s\" succeeded - should have failed with errno %d...",
2232
2279
        command->first_argument, command->expected_errors.err[0].code.errnum);
2233
2280
  }
2234
2281
 
 
2282
  dynstr_free(&ds_cmd);
2235
2283
  return;
2236
2284
}
2237
2285
 
2285
2333
 
2286
2334
 
2287
2335
/*
 
2336
  Wrapper for 'system' function
 
2337
 
 
2338
  NOTE
 
2339
  If drizzletest is executed from cygwin shell, the command will be
 
2340
  executed in the "windows command interpreter" cmd.exe and we prepend "sh"
 
2341
  to make it be executed by cygwins "bash". Thus commands like "rm",
 
2342
  "mkdir" as well as shellscripts can executed by "system" in Windows.
 
2343
 
 
2344
*/
 
2345
 
 
2346
static int my_system(DYNAMIC_STRING* ds_cmd)
 
2347
{
 
2348
  return system(ds_cmd->str);
 
2349
}
 
2350
 
 
2351
 
 
2352
/*
2288
2353
  SYNOPSIS
2289
2354
  do_system
2290
2355
  command  called command
2299
2364
 
2300
2365
static void do_system(struct st_command *command)
2301
2366
{
2302
 
  string ds_cmd;
 
2367
  DYNAMIC_STRING ds_cmd;
2303
2368
 
2304
2369
 
2305
2370
  if (strlen(command->first_argument) == 0)
2306
2371
    die("Missing arguments to system, nothing to do!");
2307
2372
 
 
2373
  init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
 
2374
 
2308
2375
  /* Eval the system command, thus replacing all environment variables */
2309
2376
  do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2310
2377
 
2311
 
  if (system(ds_cmd.c_str()))
 
2378
  if (my_system(&ds_cmd))
2312
2379
  {
2313
2380
    if (command->abort_on_error)
2314
2381
      die("system command '%s' failed", command->first_argument);
2315
2382
 
2316
2383
    /* 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");
 
2384
    dynstr_append(&ds_res, "system command '");
 
2385
    replace_dynstr_append(&ds_res, command->first_argument);
 
2386
    dynstr_append(&ds_res, "' failed\n");
2320
2387
  }
2321
2388
 
2322
2389
  command->last_argument= command->end;
 
2390
  dynstr_free(&ds_cmd);
2323
2391
  return;
2324
2392
}
2325
2393
 
2337
2405
static void do_remove_file(struct st_command *command)
2338
2406
{
2339
2407
  int error;
2340
 
  string ds_filename;
 
2408
  static DYNAMIC_STRING ds_filename;
2341
2409
  const struct command_arg rm_args[] = {
2342
2410
    { "filename", ARG_STRING, true, &ds_filename, "File to delete" }
2343
2411
  };
2347
2415
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2348
2416
                     ' ');
2349
2417
 
2350
 
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2418
  error= my_delete(ds_filename.str, MYF(0)) != 0;
2351
2419
  handle_command_error(command, error);
 
2420
  dynstr_free(&ds_filename);
2352
2421
  return;
2353
2422
}
2354
2423
 
2368
2437
static void do_copy_file(struct st_command *command)
2369
2438
{
2370
2439
  int error;
2371
 
  string ds_from_file;
2372
 
  string ds_to_file;
 
2440
  static DYNAMIC_STRING ds_from_file;
 
2441
  static DYNAMIC_STRING ds_to_file;
2373
2442
  const struct command_arg copy_file_args[] = {
2374
2443
    { "from_file", ARG_STRING, true, &ds_from_file, "Filename to copy from" },
2375
2444
    { "to_file", ARG_STRING, true, &ds_to_file, "Filename to copy to" }
2381
2450
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2382
2451
                     ' ');
2383
2452
 
2384
 
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2453
  error= (my_copy(ds_from_file.str, ds_to_file.str,
2385
2454
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2386
2455
  handle_command_error(command, error);
 
2456
  dynstr_free(&ds_from_file);
 
2457
  dynstr_free(&ds_to_file);
2387
2458
  return;
2388
2459
}
2389
2460
 
2402
2473
static void do_chmod_file(struct st_command *command)
2403
2474
{
2404
2475
  long mode= 0;
2405
 
  string ds_mode;
2406
 
  string ds_file;
 
2476
  static DYNAMIC_STRING ds_mode;
 
2477
  static DYNAMIC_STRING ds_file;
2407
2478
  const struct command_arg chmod_file_args[] = {
2408
2479
    { "mode", ARG_STRING, true, &ds_mode, "Mode of file(octal) ex. 0660"},
2409
2480
    { "filename", ARG_STRING, true, &ds_file, "Filename of file to modify" }
2416
2487
                     ' ');
2417
2488
 
2418
2489
  /* Parse what mode to set */
2419
 
  if (ds_mode.length() != 4 ||
2420
 
      str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NULL)
 
2490
  if (ds_mode.length != 4 ||
 
2491
      str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
2421
2492
    die("You must write a 4 digit octal number for mode");
2422
2493
 
2423
 
  handle_command_error(command, chmod(ds_file.c_str(), mode));
 
2494
  handle_command_error(command, chmod(ds_file.str, mode));
 
2495
  dynstr_free(&ds_mode);
 
2496
  dynstr_free(&ds_file);
2424
2497
  return;
2425
2498
}
2426
2499
 
2438
2511
static void do_file_exist(struct st_command *command)
2439
2512
{
2440
2513
  int error;
2441
 
  string ds_filename;
 
2514
  static DYNAMIC_STRING ds_filename;
2442
2515
  const struct command_arg file_exist_args[] = {
2443
2516
    { "filename", ARG_STRING, true, &ds_filename, "File to check if it exist" }
2444
2517
  };
2449
2522
                     sizeof(file_exist_args)/sizeof(struct command_arg),
2450
2523
                     ' ');
2451
2524
 
2452
 
  error= (access(ds_filename.c_str(), F_OK) != 0);
 
2525
  error= (access(ds_filename.str, F_OK) != 0);
2453
2526
  handle_command_error(command, error);
 
2527
  dynstr_free(&ds_filename);
2454
2528
  return;
2455
2529
}
2456
2530
 
2468
2542
static void do_mkdir(struct st_command *command)
2469
2543
{
2470
2544
  int error;
2471
 
  string ds_dirname;
 
2545
  static DYNAMIC_STRING ds_dirname;
2472
2546
  const struct command_arg mkdir_args[] = {
2473
2547
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
2474
2548
  };
2478
2552
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2479
2553
                     ' ');
2480
2554
 
2481
 
  error= my_mkdir(ds_dirname.c_str(), 0777, MYF(0)) != 0;
 
2555
  error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
2482
2556
  handle_command_error(command, error);
 
2557
  dynstr_free(&ds_dirname);
2483
2558
  return;
2484
2559
}
2485
2560
 
2496
2571
static void do_rmdir(struct st_command *command)
2497
2572
{
2498
2573
  int error;
2499
 
  string ds_dirname;
 
2574
  static DYNAMIC_STRING ds_dirname;
2500
2575
  const struct command_arg rmdir_args[] = {
2501
2576
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to remove"}
2502
2577
  };
2506
2581
                     rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
2507
2582
                     ' ');
2508
2583
 
2509
 
  error= rmdir(ds_dirname.c_str()) != 0;
 
2584
  error= rmdir(ds_dirname.str) != 0;
2510
2585
  handle_command_error(command, error);
 
2586
  dynstr_free(&ds_dirname);
2511
2587
  return;
2512
2588
}
2513
2589
 
2536
2612
}
2537
2613
 
2538
2614
 
2539
 
static void read_until_delimiter(string *ds,
2540
 
                                 string *ds_delimiter)
 
2615
static void read_until_delimiter(DYNAMIC_STRING *ds,
 
2616
                                 DYNAMIC_STRING *ds_delimiter)
2541
2617
{
2542
2618
  char c;
2543
2619
 
2544
 
  if (ds_delimiter->length() > MAX_DELIMITER_LENGTH)
 
2620
  if (ds_delimiter->length > MAX_DELIMITER_LENGTH)
2545
2621
    die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
2546
2622
 
2547
2623
  /* Read from file until delimiter is found */
2568
2644
 
2569
2645
    if (feof(cur_file->file))
2570
2646
      die("End of file encountered before '%s' delimiter was found",
2571
 
          ds_delimiter->c_str());
 
2647
          ds_delimiter->str);
2572
2648
 
2573
 
    if (match_delimiter(c, ds_delimiter->c_str(), ds_delimiter->length()))
 
2649
    if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
2574
2650
      break;
2575
2651
 
2576
 
    ds->push_back(c);
 
2652
    dynstr_append_mem(ds, (const char*)&c, 1);
2577
2653
  }
2578
2654
  return;
2579
2655
}
2581
2657
 
2582
2658
static void do_write_file_command(struct st_command *command, bool append)
2583
2659
{
2584
 
  string ds_content;
2585
 
  string ds_filename;
2586
 
  string ds_delimiter;
 
2660
  static DYNAMIC_STRING ds_content;
 
2661
  static DYNAMIC_STRING ds_filename;
 
2662
  static DYNAMIC_STRING ds_delimiter;
2587
2663
  const struct command_arg write_file_args[] = {
2588
2664
    { "filename", ARG_STRING, true, &ds_filename, "File to write to" },
2589
2665
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
2597
2673
                     ' ');
2598
2674
 
2599
2675
  /* If no delimiter was provided, use EOF */
2600
 
  if (ds_delimiter.length() == 0)
2601
 
    ds_delimiter= "EOF";
 
2676
  if (ds_delimiter.length == 0)
 
2677
    dynstr_set(&ds_delimiter, "EOF");
2602
2678
 
2603
 
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
 
2679
  if (!append && access(ds_filename.str, F_OK) == 0)
2604
2680
  {
2605
2681
    /* The file should not be overwritten */
2606
 
    die("File already exist: '%s'", ds_filename.c_str());
 
2682
    die("File already exist: '%s'", ds_filename.str);
2607
2683
  }
2608
2684
 
 
2685
  init_dynamic_string(&ds_content, "", 1024, 1024);
2609
2686
  read_until_delimiter(&ds_content, &ds_delimiter);
2610
 
  str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2611
 
               ds_content.length(), append);
 
2687
  str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
 
2688
  dynstr_free(&ds_content);
 
2689
  dynstr_free(&ds_filename);
 
2690
  dynstr_free(&ds_delimiter);
2612
2691
  return;
2613
2692
}
2614
2693
 
2691
2770
 
2692
2771
static void do_cat_file(struct st_command *command)
2693
2772
{
2694
 
  static string ds_filename;
 
2773
  static DYNAMIC_STRING ds_filename;
2695
2774
  const struct command_arg cat_file_args[] = {
2696
2775
    { "filename", ARG_STRING, true, &ds_filename, "File to read from" }
2697
2776
  };
2703
2782
                     sizeof(cat_file_args)/sizeof(struct command_arg),
2704
2783
                     ' ');
2705
2784
 
2706
 
  cat_file(&ds_res, ds_filename.c_str());
 
2785
  cat_file(&ds_res, ds_filename.str);
2707
2786
 
 
2787
  dynstr_free(&ds_filename);
2708
2788
  return;
2709
2789
}
2710
2790
 
2724
2804
static void do_diff_files(struct st_command *command)
2725
2805
{
2726
2806
  int error= 0;
2727
 
  string ds_filename;
2728
 
  string ds_filename2;
 
2807
  static DYNAMIC_STRING ds_filename;
 
2808
  static DYNAMIC_STRING ds_filename2;
2729
2809
  const struct command_arg diff_file_args[] = {
2730
2810
    { "file1", ARG_STRING, true, &ds_filename, "First file to diff" },
2731
2811
    { "file2", ARG_STRING, true, &ds_filename2, "Second file to diff" }
2738
2818
                     sizeof(diff_file_args)/sizeof(struct command_arg),
2739
2819
                     ' ');
2740
2820
 
2741
 
  if ((error= compare_files(ds_filename.c_str(), ds_filename2.c_str())))
 
2821
  if ((error= compare_files(ds_filename.str, ds_filename2.str)))
2742
2822
  {
2743
2823
    /* Compare of the two files failed, append them to output
2744
2824
       so the failure can be analyzed
2745
2825
    */
2746
 
    show_diff(&ds_res, ds_filename.c_str(), ds_filename2.c_str());
 
2826
    show_diff(&ds_res, ds_filename.str, ds_filename2.str);
2747
2827
  }
2748
2828
 
 
2829
  dynstr_free(&ds_filename);
 
2830
  dynstr_free(&ds_filename2);
2749
2831
  handle_command_error(command, error);
2750
2832
  return;
2751
2833
}
2819
2901
{
2820
2902
  DRIZZLE *drizzle= &cur_con->drizzle;
2821
2903
  /* static keyword to make the NetWare compiler happy. */
2822
 
  string ds_user, ds_passwd, ds_db;
 
2904
  static DYNAMIC_STRING ds_user, ds_passwd, ds_db;
2823
2905
  const struct command_arg change_user_args[] = {
2824
2906
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
2825
2907
    { "password", ARG_STRING, false, &ds_passwd, "Password used when connecting" },
2833
2915
                     sizeof(change_user_args)/sizeof(struct command_arg),
2834
2916
                     ',');
2835
2917
 
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()))
 
2918
  if (!ds_user.length)
 
2919
    dynstr_set(&ds_user, drizzle->user);
 
2920
 
 
2921
  if (!ds_passwd.length)
 
2922
    dynstr_set(&ds_passwd, drizzle->passwd);
 
2923
 
 
2924
  if (!ds_db.length)
 
2925
    dynstr_set(&ds_db, drizzle->db);
 
2926
 
 
2927
  if (drizzle_change_user(drizzle, ds_user.str, ds_passwd.str, ds_db.str))
2847
2928
    die("change user failed: %s", drizzle_error(drizzle));
2848
2929
 
 
2930
  dynstr_free(&ds_user);
 
2931
  dynstr_free(&ds_passwd);
 
2932
  dynstr_free(&ds_db);
2849
2933
 
2850
2934
  return;
2851
2935
}
2877
2961
  FILE *res_file;
2878
2962
  char buf[FN_REFLEN];
2879
2963
  char temp_file_path[FN_REFLEN];
2880
 
  string ds_script;
2881
 
  string ds_delimiter;
 
2964
  static DYNAMIC_STRING ds_script;
 
2965
  static DYNAMIC_STRING ds_delimiter;
2882
2966
  const struct command_arg perl_args[] = {
2883
2967
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
2884
2968
  };
2891
2975
                     ' ');
2892
2976
 
2893
2977
  /* If no delimiter was provided, use EOF */
2894
 
  if (ds_delimiter.length() == 0)
2895
 
    ds_delimiter= "EOF";
 
2978
  if (ds_delimiter.length == 0)
 
2979
    dynstr_set(&ds_delimiter, "EOF");
2896
2980
 
 
2981
  init_dynamic_string(&ds_script, "", 1024, 1024);
2897
2982
  read_until_delimiter(&ds_script, &ds_delimiter);
2898
2983
 
2899
2984
  /* Create temporary file name */
2900
2985
  if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
2901
 
                            "tmp", O_CREAT | O_RDWR,
 
2986
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
2902
2987
                            MYF(MY_WME))) < 0)
2903
2988
    die("Failed to create temporary file for perl command");
2904
2989
  my_close(fd, MYF(0));
2905
2990
 
2906
 
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
 
2991
  str_to_file(temp_file_path, ds_script.str, ds_script.length);
2907
2992
 
2908
2993
  /* Format the "perl <filename>" command */
2909
2994
  snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
2916
3001
    if (disable_result_log)
2917
3002
      buf[strlen(buf)-1]=0;
2918
3003
    else
2919
 
      replace_append(&ds_res, buf);
 
3004
      replace_dynstr_append(&ds_res, buf);
2920
3005
  }
2921
3006
  error= pclose(res_file);
2922
3007
 
2924
3009
  my_delete(temp_file_path, MYF(0));
2925
3010
 
2926
3011
  handle_command_error(command, WEXITSTATUS(error));
 
3012
  dynstr_free(&ds_script);
 
3013
  dynstr_free(&ds_delimiter);
2927
3014
  return;
2928
3015
}
2929
3016
 
2931
3018
/*
2932
3019
  Print the content between echo and <delimiter> to result file.
2933
3020
  Evaluate all variables in the string before printing, allow
2934
 
  for variable names to be escaped using        \
 
3021
  for variable names to be escaped using \
2935
3022
 
2936
3023
  SYNOPSIS
2937
3024
  do_echo()
2954
3041
 
2955
3042
static int do_echo(struct st_command *command)
2956
3043
{
2957
 
  string ds_echo;
2958
 
 
2959
 
 
 
3044
  DYNAMIC_STRING ds_echo;
 
3045
 
 
3046
 
 
3047
  init_dynamic_string(&ds_echo, "", command->query_len, 256);
2960
3048
  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");
 
3049
  dynstr_append_mem(&ds_res, ds_echo.str, ds_echo.length);
 
3050
  dynstr_append_mem(&ds_res, "\n", 1);
 
3051
  dynstr_free(&ds_echo);
2963
3052
  command->last_argument= command->end;
2964
3053
  return(0);
2965
3054
}
2977
3066
    int done;
2978
3067
 
2979
3068
    if (drizzle_query(drizzle,"show status like 'Slave_running'") ||
2980
 
        !(res=drizzle_store_result(drizzle)))
 
3069
  !(res=drizzle_store_result(drizzle)))
2981
3070
      die("Query failed while probing slave for stop: %s",
2982
 
          drizzle_error(drizzle));
 
3071
    drizzle_error(drizzle));
2983
3072
    if (!(row=drizzle_fetch_row(res)) || !row[1])
2984
3073
    {
2985
3074
      drizzle_free_result(res);
3007
3096
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3008
3097
 
3009
3098
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3010
 
          master_pos.pos + offset);
 
3099
    master_pos.pos + offset);
3011
3100
 
3012
3101
wait_for_position:
3013
3102
 
3076
3165
 
3077
3166
  if (drizzle_query(drizzle, query= "show master status"))
3078
3167
    die("failed in 'show master status': %d %s",
3079
 
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
3168
  drizzle_errno(drizzle), drizzle_error(drizzle));
3080
3169
 
3081
3170
  if (!(res = drizzle_store_result(drizzle)))
3082
3171
    die("drizzle_store_result() retuned NULL for '%s'", query);
3083
3172
  if (!(row = drizzle_fetch_row(res)))
3084
3173
    die("empty result in show master status");
3085
 
  my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
 
3174
  strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
3086
3175
  master_pos.pos = strtoul(row[1], (char**) 0, 10);
3087
3176
  drizzle_free_result(res);
3088
3177
  return(0);
3112
3201
{
3113
3202
  char *p= command->first_argument;
3114
3203
  char *var_name, *var_name_end;
3115
 
  string let_rhs_expr;
3116
 
 
 
3204
  DYNAMIC_STRING let_rhs_expr;
 
3205
 
 
3206
 
 
3207
  init_dynamic_string(&let_rhs_expr, "", 512, 2048);
3117
3208
 
3118
3209
  /* Find <var_name> */
3119
3210
  if (!*p)
3138
3229
 
3139
3230
  command->last_argument= command->end;
3140
3231
  /* 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()));
 
3232
  var_set(var_name, var_name_end, let_rhs_expr.str,
 
3233
          (let_rhs_expr.str + let_rhs_expr.length));
 
3234
  dynstr_free(&let_rhs_expr);
3143
3235
  return;
3144
3236
}
3145
3237
 
3151
3243
  do_sleep()
3152
3244
  q         called command
3153
3245
  real_sleep   use the value from opt_sleep as number of seconds to sleep
3154
 
  if real_sleep is false
 
3246
               if real_sleep is false
3155
3247
 
3156
3248
  DESCRIPTION
3157
3249
  sleep <seconds>
3192
3284
    sleep_val= opt_sleep;
3193
3285
 
3194
3286
  if (sleep_val)
3195
 
    my_sleep((uint32_t) (sleep_val * 1000000L));
 
3287
    my_sleep((ulong) (sleep_val * 1000000L));
3196
3288
  command->last_argument= sleep_end;
3197
3289
  return 0;
3198
3290
}
3199
3291
 
3200
3292
 
3201
3293
static void do_get_file_name(struct st_command *command,
3202
 
                             char* dest, uint dest_max_len)
 
3294
                      char* dest, uint dest_max_len)
3203
3295
{
3204
3296
  char *p= command->first_argument, *name;
3205
3297
  if (!*p)
3300
3392
        if (my_isdigit(charset_info, *p) || my_isupper(charset_info, *p))
3301
3393
          *to_ptr++= *p++;
3302
3394
        else
3303
 
          die("The sqlstate may only consist of digits[0-9] "   \
 
3395
          die("The sqlstate may only consist of digits[0-9] " \
3304
3396
              "and _uppercase_ letters");
3305
3397
      }
3306
3398
 
3330
3422
      while (*p && p != end)
3331
3423
      {
3332
3424
        if (!my_isdigit(charset_info, *p))
3333
 
          die("Invalid argument to error: '%s' - "              \
 
3425
          die("Invalid argument to error: '%s' - "\
3334
3426
              "the errno may only consist of digits[0-9]",
3335
3427
              command->first_argument);
3336
3428
        p++;
3338
3430
 
3339
3431
      /* Convert the sting to int */
3340
3432
      if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
3341
 
        die("Invalid argument to error: '%s'", command->first_argument);
 
3433
  die("Invalid argument to error: '%s'", command->first_argument);
3342
3434
 
3343
3435
      to->code.errnum= (uint) val;
3344
3436
      to->type= ERR_ERRNO;
3397
3489
      /* We can't translate \0 -> ASCII 0 as replace can't handle ASCII 0 */
3398
3490
      switch (*++from) {
3399
3491
      case 'n':
3400
 
        *to++= '\n';
3401
 
        break;
 
3492
  *to++= '\n';
 
3493
  break;
3402
3494
      case 't':
3403
 
        *to++= '\t';
3404
 
        break;
 
3495
  *to++= '\t';
 
3496
  break;
3405
3497
      case 'r':
3406
 
        *to++ = '\r';
3407
 
        break;
 
3498
  *to++ = '\r';
 
3499
  break;
3408
3500
      case 'b':
3409
 
        *to++ = '\b';
3410
 
        break;
 
3501
  *to++ = '\b';
 
3502
  break;
3411
3503
      case 'Z':        /* ^Z must be escaped on Win32 */
3412
 
        *to++='\032';
3413
 
        break;
 
3504
  *to++='\032';
 
3505
  break;
3414
3506
      default:
3415
 
        *to++ = *from;
3416
 
        break;
 
3507
  *to++ = *from;
 
3508
  break;
3417
3509
      }
3418
3510
    }
3419
3511
    else if (c == sep)
3420
3512
    {
3421
3513
      if (c == ' ' || c != *++from)
3422
 
        break;        /* Found end of string */
 
3514
  break;        /* Found end of string */
3423
3515
      *to++=c;        /* Copy duplicated separator */
3424
3516
    }
3425
3517
    else
3509
3601
  {
3510
3602
    if (con->drizzle.net.vio)
3511
3603
    {
3512
 
      net_close(&(con->drizzle.net));
 
3604
      vio_delete(con->drizzle.net.vio);
 
3605
      con->drizzle.net.vio = 0;
3513
3606
    }
3514
3607
  }
3515
3608
 
3519
3612
    drizzle_close(con->util_drizzle);
3520
3613
  con->util_drizzle= 0;
3521
3614
 
3522
 
  free(con->name);
 
3615
  my_free(con->name, MYF(0));
3523
3616
 
3524
3617
  /*
3525
3618
    When the connection is closed set name to "-closed_connection-"
3558
3651
*/
3559
3652
 
3560
3653
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)
 
3654
                  const char *user, const char *pass, const char *db,
 
3655
                  int port)
3563
3656
{
3564
3657
  int failed_attempts= 0;
3565
 
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
 
3658
  static ulong connection_retry_sleep= 100000; /* Microseconds */
3566
3659
 
3567
3660
 
3568
3661
  while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3569
 
                         CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
 
3662
                            CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3570
3663
  {
3571
3664
    /*
3572
3665
      Connect failed
3624
3717
*/
3625
3718
 
3626
3719
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)
 
3720
                            DRIZZLE *con, const char* host,
 
3721
                            const char* user, const char* pass,
 
3722
                            const char* db, int port, const char* sock)
3630
3723
{
 
3724
  DYNAMIC_STRING *ds;
 
3725
 
 
3726
  ds= &ds_res;
3631
3727
 
3632
3728
  /* Only log if an error is expected */
3633
3729
  if (!command->abort_on_error &&
3636
3732
    /*
3637
3733
      Log the connect to result log
3638
3734
    */
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(",");
 
3735
    dynstr_append_mem(ds, "connect(", 8);
 
3736
    replace_dynstr_append(ds, host);
 
3737
    dynstr_append_mem(ds, ",", 1);
 
3738
    replace_dynstr_append(ds, user);
 
3739
    dynstr_append_mem(ds, ",", 1);
 
3740
    replace_dynstr_append(ds, pass);
 
3741
    dynstr_append_mem(ds, ",", 1);
3646
3742
    if (db)
3647
 
      replace_append(&ds_res, db);
3648
 
    ds_res.append(",");
3649
 
    replace_append_uint(&ds_res, port);
3650
 
    ds_res.append(",");
 
3743
      replace_dynstr_append(ds, db);
 
3744
    dynstr_append_mem(ds, ",", 1);
 
3745
    replace_dynstr_append_uint(ds, port);
 
3746
    dynstr_append_mem(ds, ",", 1);
3651
3747
    if (sock)
3652
 
      replace_append(&ds_res, sock);
3653
 
    ds_res.append(")");
3654
 
    ds_res.append(delimiter);
3655
 
    ds_res.append("\n");
 
3748
      replace_dynstr_append(ds, sock);
 
3749
    dynstr_append_mem(ds, ")", 1);
 
3750
    dynstr_append_mem(ds, delimiter, delimiter_length);
 
3751
    dynstr_append_mem(ds, "\n", 1);
3656
3752
  }
3657
3753
  if (!drizzle_connect(con, host, user, pass, db, port, 0,
3658
 
                       CLIENT_MULTI_STATEMENTS))
 
3754
                          CLIENT_MULTI_STATEMENTS))
3659
3755
  {
3660
3756
    var_set_errno(drizzle_errno(con));
3661
3757
    handle_error(command, drizzle_errno(con), drizzle_error(con),
3662
 
                 drizzle_sqlstate(con), &ds_res);
 
3758
     drizzle_sqlstate(con), ds);
3663
3759
    return 0; /* Not connected */
3664
3760
  }
3665
3761
 
3689
3785
  <port> - server port
3690
3786
  <sock> - server socket
3691
3787
  <opts> - options to use for the connection
3692
 
  * SSL - use SSL if available
3693
 
  * COMPRESS - use compression if available
 
3788
   * SSL - use SSL if available
 
3789
   * COMPRESS - use compression if available
3694
3790
 
3695
 
  */
 
3791
*/
3696
3792
 
3697
3793
static void do_connect(struct st_command *command)
3698
3794
{
3699
3795
  int con_port= opt_port;
3700
 
  const char *con_options;
 
3796
  char *con_options;
3701
3797
  bool con_ssl= 0, con_compress= 0;
3702
3798
  struct st_connection* con_slot;
3703
3799
 
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;
 
3800
  static DYNAMIC_STRING ds_connection_name;
 
3801
  static DYNAMIC_STRING ds_host;
 
3802
  static DYNAMIC_STRING ds_user;
 
3803
  static DYNAMIC_STRING ds_password;
 
3804
  static DYNAMIC_STRING ds_database;
 
3805
  static DYNAMIC_STRING ds_port;
 
3806
  static DYNAMIC_STRING ds_sock;
 
3807
  static DYNAMIC_STRING ds_options;
3712
3808
  const struct command_arg connect_args[] = {
3713
3809
    { "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3714
3810
    { "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3727
3823
                     ',');
3728
3824
 
3729
3825
  /* Port */
3730
 
  if (ds_port.length())
 
3826
  if (ds_port.length)
3731
3827
  {
3732
 
    con_port= atoi(ds_port.c_str());
 
3828
    con_port= atoi(ds_port.str);
3733
3829
    if (con_port == 0)
3734
 
      die("Illegal argument for port: '%s'", ds_port.c_str());
 
3830
      die("Illegal argument for port: '%s'", ds_port.str);
3735
3831
  }
3736
3832
 
3737
3833
  /* Sock */
3738
 
  if (!ds_sock.empty())
 
3834
  if (ds_sock.length)
3739
3835
  {
3740
3836
    /*
3741
3837
      If the socket is specified just as a name without path
3742
3838
      append tmpdir in front
3743
3839
    */
3744
 
    if (*ds_sock.c_str() != FN_LIBCHAR)
 
3840
    if (*ds_sock.str != FN_LIBCHAR)
3745
3841
    {
3746
3842
      char buff[FN_REFLEN];
3747
 
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3748
 
      ds_sock= buff;
 
3843
      fn_format(buff, ds_sock.str, TMPDIR, "", 0);
 
3844
      dynstr_set(&ds_sock, buff);
3749
3845
    }
3750
3846
  }
 
3847
  else
 
3848
  {
 
3849
    /* No socket specified, use default */
 
3850
    dynstr_set(&ds_sock, unix_sock);
 
3851
  }
3751
3852
 
3752
3853
  /* Options */
3753
 
  con_options= ds_options.c_str();
 
3854
  con_options= ds_options.str;
3754
3855
  while (*con_options)
3755
3856
  {
3756
 
    const char* end;
 
3857
    char* end;
3757
3858
    /* Step past any spaces in beginning of option*/
3758
3859
    while (*con_options && my_isspace(charset_info, *con_options))
3759
 
      con_options++;
 
3860
     con_options++;
3760
3861
    /* Find end of this option */
3761
3862
    end= con_options;
3762
3863
    while (*end && !my_isspace(charset_info, *end))
3772
3873
    con_options= end;
3773
3874
  }
3774
3875
 
3775
 
  if (find_connection_by_name(ds_connection_name.c_str()))
3776
 
    die("Connection %s already exists", ds_connection_name.c_str());
3777
 
 
 
3876
  if (find_connection_by_name(ds_connection_name.str))
 
3877
    die("Connection %s already exists", ds_connection_name.str);
 
3878
   
3778
3879
  if (next_con != connections_end)
3779
 
  {
3780
3880
    con_slot= next_con;
3781
 
  }
3782
3881
  else
3783
3882
  {
3784
3883
    if (!(con_slot= find_connection_by_name("-closed_connection-")))
3786
3885
          (int) (sizeof(connections)/sizeof(struct st_connection)));
3787
3886
  }
3788
3887
 
 
3888
#ifdef EMBEDDED_LIBRARY
 
3889
  con_slot->query_done= 1;
 
3890
#endif
3789
3891
  if (!drizzle_create(&con_slot->drizzle))
3790
3892
    die("Failed on drizzle_create()");
3791
3893
  if (opt_compress || con_compress)
3792
 
    drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NULL);
 
3894
    drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NullS);
3793
3895
  drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
3896
  drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_NAME,
 
3897
                charset_info->csname);
 
3898
  int opt_protocol= DRIZZLE_PROTOCOL_TCP;
 
3899
  drizzle_options(&con_slot->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
 
3900
  if (opt_charsets_dir)
 
3901
    drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_DIR,
 
3902
                  opt_charsets_dir);
3794
3903
 
3795
3904
  /* Use default db name */
3796
 
  if (ds_database.length() == 0)
3797
 
    ds_database= opt_db;
 
3905
  if (ds_database.length == 0)
 
3906
    dynstr_set(&ds_database, opt_db);
3798
3907
 
3799
3908
  /* 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= "";
 
3909
  if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
 
3910
    dynstr_set(&ds_database, "");
3802
3911
 
3803
3912
  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()))
 
3913
                              ds_host.str,ds_user.str,
 
3914
                              ds_password.str, ds_database.str,
 
3915
                              con_port, ds_sock.str))
3807
3916
  {
3808
 
    if (!(con_slot->name= strdup(ds_connection_name.c_str())))
 
3917
    if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3809
3918
      die("Out of memory");
3810
3919
    cur_con= con_slot;
3811
 
 
 
3920
   
3812
3921
    if (con_slot == next_con)
3813
3922
      next_con++; /* if we used the next_con slot, advance the pointer */
3814
3923
  }
3816
3925
  /* Update $drizzle_get_server_version to that of current connection */
3817
3926
  var_set_drizzle_get_server_version(&cur_con->drizzle);
3818
3927
 
 
3928
  dynstr_free(&ds_connection_name);
 
3929
  dynstr_free(&ds_host);
 
3930
  dynstr_free(&ds_user);
 
3931
  dynstr_free(&ds_password);
 
3932
  dynstr_free(&ds_database);
 
3933
  dynstr_free(&ds_port);
 
3934
  dynstr_free(&ds_sock);
 
3935
  dynstr_free(&ds_options);
3819
3936
  return;
3820
3937
}
3821
3938
 
3963
4080
    return 0;
3964
4081
 
3965
4082
  for (i= 1; i < length &&
3966
 
         (c= my_getc(cur_file->file)) == *(delim + i);
 
4083
   (c= my_getc(cur_file->file)) == *(delim + i);
3967
4084
       i++)
3968
4085
    tmp[i]= c;
3969
4086
 
4027
4144
  found_eof:
4028
4145
      if (cur_file->file != stdin)
4029
4146
      {
4030
 
        my_fclose(cur_file->file, MYF(0));
 
4147
  my_fclose(cur_file->file, MYF(0));
4031
4148
        cur_file->file= 0;
4032
4149
      }
4033
 
      free((unsigned char*) cur_file->file_name);
 
4150
      my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
4034
4151
      cur_file->file_name= 0;
4035
4152
      if (cur_file == file_stack)
4036
4153
      {
4062
4179
    case R_NORMAL:
4063
4180
      if (end_of_query(c))
4064
4181
      {
4065
 
        *p= 0;
4066
 
        return(0);
 
4182
  *p= 0;
 
4183
  return(0);
4067
4184
      }
4068
4185
      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))))
 
4186
                (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
 
4187
                                      (uchar*) buf, min(5, p - buf), 0) ||
 
4188
                 !my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
 
4189
                                      (uchar*) buf, min(2, p - buf), 0))))
4073
4190
      {
4074
4191
        /* Only if and while commands can be terminated by { */
4075
4192
        *p++= c;
4076
 
        *p= 0;
4077
 
        return(0);
 
4193
  *p= 0;
 
4194
  return(0);
4078
4195
      }
4079
4196
      else if (c == '\'' || c == '"' || c == '`')
4080
4197
      {
4081
4198
        last_quote= c;
4082
 
        state= R_Q;
 
4199
  state= R_Q;
4083
4200
      }
4084
4201
      break;
4085
4202
 
4087
4204
      if (c == '\n')
4088
4205
      {
4089
4206
        /* Comments are terminated by newline */
4090
 
        *p= 0;
4091
 
        return(0);
 
4207
  *p= 0;
 
4208
  return(0);
4092
4209
      }
4093
4210
      break;
4094
4211
 
4096
4213
      if (c == '#' || c == '-')
4097
4214
      {
4098
4215
        /* A # or - in the first position of the line - this is a comment */
4099
 
        state = R_COMMENT;
 
4216
  state = R_COMMENT;
4100
4217
      }
4101
4218
      else if (my_isspace(charset_info, c))
4102
4219
      {
4103
4220
        /* Skip all space at begining of line */
4104
 
        if (c == '\n')
 
4221
  if (c == '\n')
4105
4222
        {
4106
4223
          /* Query hasn't started yet */
4107
 
          start_lineno= cur_file->lineno;
 
4224
    start_lineno= cur_file->lineno;
4108
4225
        }
4109
 
        skip_char= 1;
 
4226
  skip_char= 1;
4110
4227
      }
4111
4228
      else if (end_of_query(c))
4112
4229
      {
4113
 
        *p= 0;
4114
 
        return(0);
 
4230
  *p= 0;
 
4231
  return(0);
4115
4232
      }
4116
4233
      else if (c == '}')
4117
4234
      {
4118
4235
        /* A "}" need to be by itself in the begining of a line to terminate */
4119
4236
        *p++= c;
4120
 
        *p= 0;
4121
 
        return(0);
 
4237
  *p= 0;
 
4238
  return(0);
4122
4239
      }
4123
4240
      else if (c == '\'' || c == '"' || c == '`')
4124
4241
      {
4125
4242
        last_quote= c;
4126
 
        state= R_Q;
 
4243
  state= R_Q;
4127
4244
      }
4128
4245
      else
4129
 
        state= R_NORMAL;
 
4246
  state= R_NORMAL;
4130
4247
      break;
4131
4248
 
4132
4249
    case R_Q:
4133
4250
      if (c == last_quote)
4134
 
        state= R_NORMAL;
 
4251
  state= R_NORMAL;
4135
4252
      else if (c == '\\')
4136
 
        state= R_SLASH_IN_Q;
 
4253
  state= R_SLASH_IN_Q;
4137
4254
      break;
4138
4255
 
4139
4256
    case R_SLASH_IN_Q:
4152
4269
      /* completed before we pass buf_end */
4153
4270
      if ((charlen > 1) && (p + charlen) <= buf_end)
4154
4271
      {
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
 
        }
 
4272
  int i;
 
4273
  char* mb_start = p;
 
4274
 
 
4275
  *p++ = c;
 
4276
 
 
4277
  for (i= 1; i < charlen; i++)
 
4278
  {
 
4279
    if (feof(cur_file->file))
 
4280
      goto found_eof;
 
4281
    c= my_getc(cur_file->file);
 
4282
    *p++ = c;
 
4283
  }
 
4284
  if (! my_ismbchar(charset_info, mb_start, p))
 
4285
  {
 
4286
    /* It was not a multiline char, push back the characters */
 
4287
    /* We leave first 'c', i.e. pretend it was a normal char */
 
4288
    while (p > mb_start)
 
4289
      my_ungetc(*--p);
 
4290
  }
4174
4291
      }
4175
4292
      else
4176
4293
#endif
4177
 
        *p++= c;
 
4294
  *p++= c;
4178
4295
    }
4179
4296
  }
4180
 
  die("The input buffer is too small for this query.x\n"        \
 
4297
  die("The input buffer is too small for this query.x\n" \
4181
4298
      "check your query or increase MAX_QUERY and recompile");
4182
4299
  return(0);
4183
4300
}
4198
4315
{
4199
4316
  int last_c_was_quote= 0;
4200
4317
  char *p= query, *to= query;
4201
 
  char *end= strchr(query, '\0');
 
4318
  char *end= strend(query);
4202
4319
  char last_c;
4203
4320
 
4204
4321
  while (p <= end)
4339
4456
  Create a command from a set of lines
4340
4457
 
4341
4458
  SYNOPSIS
4342
 
  read_command()
4343
 
  command_ptr pointer where to return the new query
 
4459
    read_command()
 
4460
    command_ptr pointer where to return the new query
4344
4461
 
4345
4462
  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.
 
4463
    Converts lines returned by read_line into a command, this involves
 
4464
    parsing the first word in the read line to find the command type.
4348
4465
 
4349
4466
  A -- comment may contain a valid query as the first word after the
4350
4467
  comment start. Thus it's always checked to see if that is the case.
4363
4480
 
4364
4481
  if (parser.current_line < parser.read_lines)
4365
4482
  {
4366
 
    *command_ptr= q_lines[parser.current_line];
 
4483
    get_dynamic(&q_lines, (uchar*) command_ptr, parser.current_line) ;
4367
4484
    return(0);
4368
4485
  }
4369
4486
  if (!(*command_ptr= command=
4370
4487
        (struct st_command*) my_malloc(sizeof(*command),
4371
 
                                       MYF(MY_WME|MY_ZEROFILL))))
4372
 
    die(NULL);
4373
 
  q_lines.push_back(command);
 
4488
                                       MYF(MY_WME|MY_ZEROFILL))) ||
 
4489
      insert_dynamic(&q_lines, (uchar*) &command))
 
4490
    die(NullS);
4374
4491
  command->type= Q_UNKNOWN;
4375
4492
 
4376
4493
  read_command_buf[0]= 0;
4410
4527
    p++;
4411
4528
  command->first_argument= p;
4412
4529
 
4413
 
  command->end= strchr(command->query, '\0');
 
4530
  command->end= strend(command->query);
4414
4531
  command->query_len= (command->end - command->query);
4415
4532
  parser.read_lines++;
4416
4533
  return(0);
4454
4571
  {"password", 'p', "Password to use when connecting to server.",
4455
4572
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4456
4573
  {"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) ").",
 
4574
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
 
4575
#if MYSQL_PORT_DEFAULT == 0
 
4576
   "/etc/services, "
 
4577
#endif
 
4578
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
4459
4579
   (char**) &opt_port,
4460
4580
   (char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4461
4581
  {"quiet", 's', "Suppress all normal output.", (char**) &silent,
4497
4617
static void print_version(void)
4498
4618
{
4499
4619
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4500
 
         drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
4620
   MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
4501
4621
}
4502
4622
 
4503
4623
static void usage(void)
4504
4624
{
4505
4625
  print_version();
4506
 
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
 
4626
  printf("DRIZZLE AB, by Sasha, Matt, Monty & Jani\n");
4507
4627
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4508
4628
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
4509
4629
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4524
4644
 
4525
4645
  if (!test_if_hard_path(name))
4526
4646
  {
4527
 
    strxmov(buff, opt_basedir, name, NULL);
 
4647
    strxmov(buff, opt_basedir, name, NullS);
4528
4648
    name=buff;
4529
4649
  }
4530
4650
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
4534
4654
    embedded_server_arg_count=1;
4535
4655
    embedded_server_args[0]= (char*) "";    /* Progname */
4536
4656
  }
4537
 
  if (!(file=my_fopen(buff, O_RDONLY, MYF(MY_WME))))
 
4657
  if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4538
4658
    die("Failed to open file '%s'", buff);
4539
4659
 
4540
4660
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4541
 
         (str=fgets(argument,sizeof(argument), file)))
 
4661
   (str=fgets(argument,sizeof(argument), file)))
4542
4662
  {
4543
 
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
 
4663
    *(strend(str)-1)=0;        /* Remove end newline */
4544
4664
    if (!(embedded_server_args[embedded_server_arg_count]=
4545
 
          (char*) my_strdup(str,MYF(MY_WME))))
 
4665
    (char*) my_strdup(str,MYF(MY_WME))))
4546
4666
    {
4547
4667
      my_fclose(file,MYF(0));
4548
4668
      die("Out of memory");
4560
4680
 
4561
4681
static bool
4562
4682
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
4563
 
               char *argument)
 
4683
         char *argument)
4564
4684
{
4565
4685
  switch(optid) {
4566
4686
  case 'r':
4571
4691
    char buff[FN_REFLEN];
4572
4692
    if (!test_if_hard_path(argument))
4573
4693
    {
4574
 
      strxmov(buff, opt_basedir, argument, NULL);
 
4694
      strxmov(buff, opt_basedir, argument, NullS);
4575
4695
      argument= buff;
4576
4696
    }
4577
4697
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4578
4698
    assert(cur_file == file_stack && cur_file->file == 0);
4579
4699
    if (!(cur_file->file=
4580
 
          my_fopen(buff, O_RDONLY, MYF(0))))
 
4700
          my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
4581
4701
      die("Could not open '%s' for reading: errno = %d", buff, errno);
4582
4702
    cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
4583
4703
    cur_file->lineno= 1;
4588
4708
    static char buff[FN_REFLEN];
4589
4709
    if (!test_if_hard_path(argument))
4590
4710
    {
4591
 
      strxmov(buff, opt_basedir, argument, NULL);
 
4711
      strxmov(buff, opt_basedir, argument, NullS);
4592
4712
      argument= buff;
4593
4713
    }
4594
4714
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4599
4719
  case 'p':
4600
4720
    if (argument)
4601
4721
    {
4602
 
      free(opt_pass);
 
4722
      my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
4603
4723
      opt_pass= my_strdup(argument, MYF(MY_FAE));
4604
4724
      while (*argument) *argument++= 'x';    /* Destroy argument */
4605
4725
      tty_password= 0;
4608
4728
      tty_password= 1;
4609
4729
    break;
4610
4730
  case 't':
4611
 
    my_stpncpy(TMPDIR, argument, sizeof(TMPDIR));
 
4731
    strnmov(TMPDIR, argument, sizeof(TMPDIR));
4612
4732
    break;
4613
4733
  case 'A':
4614
4734
    if (!embedded_server_arg_count)
4653
4773
  if (argc == 1)
4654
4774
    opt_db= *argv;
4655
4775
  if (tty_password)
4656
 
    opt_pass= get_tty_password(NULL);          /* purify tested */
 
4776
    opt_pass= get_tty_password(NullS);          /* purify tested */
4657
4777
  if (debug_info_flag)
4658
4778
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
4659
4779
  if (debug_check_flag)
4673
4793
  append - append to file instead of overwriting old file
4674
4794
*/
4675
4795
 
4676
 
void str_to_file2(const char *fname, const char *str, int size, bool append)
 
4796
void str_to_file2(const char *fname, char *str, int size, bool append)
4677
4797
{
4678
4798
  int fd;
4679
4799
  char buff[FN_REFLEN];
4680
4800
  int flags= O_WRONLY | O_CREAT;
4681
4801
  if (!test_if_hard_path(fname))
4682
4802
  {
4683
 
    strxmov(buff, opt_basedir, fname, NULL);
 
4803
    strxmov(buff, opt_basedir, fname, NullS);
4684
4804
    fname= buff;
4685
4805
  }
4686
4806
  fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4692
4812
    die("Could not open '%s' for writing: errno = %d", buff, errno);
4693
4813
  if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
4694
4814
    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)))
 
4815
  if (my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP)))
4696
4816
    die("write failed");
4697
4817
  my_close(fd, MYF(0));
4698
4818
}
4707
4827
  size - size of content witten to file
4708
4828
*/
4709
4829
 
4710
 
void str_to_file(const char *fname, const char *str, int size)
 
4830
void str_to_file(const char *fname, char *str, int size)
4711
4831
{
4712
4832
  str_to_file2(fname, str, size, false);
4713
4833
}
4714
4834
 
4715
4835
 
4716
 
void dump_result_to_log_file(const char *buf, int size)
 
4836
void dump_result_to_log_file(char *buf, int size)
4717
4837
{
4718
4838
  char log_file[FN_REFLEN];
4719
4839
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
4731
4851
                        opt_logdir, ".progress",
4732
4852
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4733
4853
                        MY_REPLACE_EXT),
4734
 
              ds_progress.c_str(), ds_progress.length());
 
4854
              ds_progress.str, ds_progress.length);
4735
4855
}
4736
4856
 
4737
4857
void dump_warning_messages(void)
4741
4861
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
4742
4862
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4743
4863
                        MY_REPLACE_EXT),
4744
 
              ds_warning_messages.c_str(), ds_warning_messages.length());
 
4864
              ds_warning_messages.str, ds_warning_messages.length);
4745
4865
}
4746
4866
 
4747
4867
 
4749
4869
  Append the result for one field to the dynamic string ds
4750
4870
*/
4751
4871
 
4752
 
static void append_field(string *ds, uint col_idx, const DRIZZLE_FIELD* field,
 
4872
static void append_field(DYNAMIC_STRING *ds, uint col_idx, const DRIZZLE_FIELD* field,
4753
4873
                         const char* val, uint64_t len, bool is_null)
4754
4874
{
4755
4875
  if (col_idx < max_replace_column && replace_column[col_idx])
4766
4886
  if (!display_result_vertically)
4767
4887
  {
4768
4888
    if (col_idx)
4769
 
      ds->append("\t");
4770
 
    replace_append_mem(ds, val, (int)len);
 
4889
      dynstr_append_mem(ds, "\t", 1);
 
4890
    replace_dynstr_append_mem(ds, val, (int)len);
4771
4891
  }
4772
4892
  else
4773
4893
  {
4774
 
    ds->append(field->name);
4775
 
    ds->append("\t");
4776
 
    replace_append_mem(ds, val, (int)len);
4777
 
    ds->append("\n");
 
4894
    dynstr_append(ds, field->name);
 
4895
    dynstr_append_mem(ds, "\t", 1);
 
4896
    replace_dynstr_append_mem(ds, val, (int)len);
 
4897
    dynstr_append_mem(ds, "\n", 1);
4778
4898
  }
4779
4899
}
4780
4900
 
4784
4904
  Values may be converted with 'replace_column'
4785
4905
*/
4786
4906
 
4787
 
static void append_result(string *ds, DRIZZLE_RES *res)
 
4907
static void append_result(DYNAMIC_STRING *ds, DRIZZLE_RES *res)
4788
4908
{
4789
4909
  DRIZZLE_ROW row;
4790
4910
  uint32_t num_fields= drizzle_num_fields(res);
4799
4919
      append_field(ds, i, &fields[i],
4800
4920
                   (const char*)row[i], lengths[i], !row[i]);
4801
4921
    if (!display_result_vertically)
4802
 
      ds->append("\n");
4803
 
 
 
4922
      dynstr_append_mem(ds, "\n", 1);
4804
4923
  }
4805
4924
}
4806
4925
 
4809
4928
  Append metadata for fields to output
4810
4929
*/
4811
4930
 
4812
 
static void append_metadata(string *ds,
 
4931
static void append_metadata(DYNAMIC_STRING *ds,
4813
4932
                            const DRIZZLE_FIELD *field,
4814
4933
                            uint num_fields)
4815
4934
{
4816
4935
  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");
 
4936
  dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
 
4937
                "Column_alias\tType\tLength\tMax length\tIs_null\t"
 
4938
                "Flags\tDecimals\tCharsetnr\n");
4820
4939
 
4821
4940
  for (field_end= field+num_fields ;
4822
4941
       field < field_end ;
4823
4942
       field++)
4824
4943
  {
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);
 
4944
    dynstr_append_mem(ds, field->catalog,
 
4945
                      field->catalog_length);
 
4946
    dynstr_append_mem(ds, "\t", 1);
 
4947
    dynstr_append_mem(ds, field->db, field->db_length);
 
4948
    dynstr_append_mem(ds, "\t", 1);
 
4949
    dynstr_append_mem(ds, field->org_table,
 
4950
                      field->org_table_length);
 
4951
    dynstr_append_mem(ds, "\t", 1);
 
4952
    dynstr_append_mem(ds, field->table,
 
4953
                      field->table_length);
 
4954
    dynstr_append_mem(ds, "\t", 1);
 
4955
    dynstr_append_mem(ds, field->org_name,
 
4956
                      field->org_name_length);
 
4957
    dynstr_append_mem(ds, "\t", 1);
 
4958
    dynstr_append_mem(ds, field->name, field->name_length);
 
4959
    dynstr_append_mem(ds, "\t", 1);
 
4960
    replace_dynstr_append_uint(ds, field->type);
 
4961
    dynstr_append_mem(ds, "\t", 1);
 
4962
    replace_dynstr_append_uint(ds, field->length);
 
4963
    dynstr_append_mem(ds, "\t", 1);
 
4964
    replace_dynstr_append_uint(ds, field->max_length);
 
4965
    dynstr_append_mem(ds, "\t", 1);
 
4966
    dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
 
4967
                                   "N" : "Y"), 1);
 
4968
    dynstr_append_mem(ds, "\t", 1);
 
4969
    replace_dynstr_append_uint(ds, field->flags);
 
4970
    dynstr_append_mem(ds, "\t", 1);
 
4971
    replace_dynstr_append_uint(ds, field->decimals);
 
4972
    dynstr_append_mem(ds, "\t", 1);
 
4973
    replace_dynstr_append_uint(ds, field->charsetnr);
 
4974
    dynstr_append_mem(ds, "\n", 1);
4856
4975
  }
4857
4976
}
4858
4977
 
4861
4980
  Append affected row count and other info to output
4862
4981
*/
4863
4982
 
4864
 
static void append_info(string *ds, uint64_t affected_rows,
 
4983
static void append_info(DYNAMIC_STRING *ds, uint64_t affected_rows,
4865
4984
                        const char *info)
4866
4985
{
4867
4986
  char buf[40], buff2[21];
4868
4987
  sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
4869
 
  ds->append(buf);
 
4988
  dynstr_append(ds, buf);
4870
4989
  if (info)
4871
4990
  {
4872
 
    ds->append("info: ");
4873
 
    ds->append(info);
4874
 
    ds->append("\n", 1);
 
4991
    dynstr_append(ds, "info: ");
 
4992
    dynstr_append(ds, info);
 
4993
    dynstr_append_mem(ds, "\n", 1);
4875
4994
  }
4876
4995
}
4877
4996
 
4880
4999
  Display the table headings with the names tab separated
4881
5000
*/
4882
5001
 
4883
 
static void append_table_headings(string *ds,
 
5002
static void append_table_headings(DYNAMIC_STRING *ds,
4884
5003
                                  const DRIZZLE_FIELD *field,
4885
5004
                                  uint num_fields)
4886
5005
{
4888
5007
  for (col_idx= 0; col_idx < num_fields; col_idx++)
4889
5008
  {
4890
5009
    if (col_idx)
4891
 
      ds->append("\t", 1);
4892
 
    replace_append(ds, field[col_idx].name);
 
5010
      dynstr_append_mem(ds, "\t", 1);
 
5011
    replace_dynstr_append(ds, field[col_idx].name);
4893
5012
  }
4894
 
  ds->append("\n", 1);
 
5013
  dynstr_append_mem(ds, "\n", 1);
4895
5014
}
4896
5015
 
4897
5016
/*
4901
5020
  Number of warnings appended to ds
4902
5021
*/
4903
5022
 
4904
 
static int append_warnings(string *ds, DRIZZLE *drizzle)
 
5023
static int append_warnings(DYNAMIC_STRING *ds, DRIZZLE *drizzle)
4905
5024
{
4906
5025
  uint count;
4907
5026
  DRIZZLE_RES *warn_res;
4922
5041
 
4923
5042
  if (!(warn_res= drizzle_store_result(drizzle)))
4924
5043
    die("Warning count is %u but didn't get any warnings",
4925
 
        count);
 
5044
  count);
4926
5045
 
4927
5046
  append_result(ds, warn_res);
 
5047
  drizzle_free_result(warn_res);
4928
5048
 
4929
5049
  return(count);
4930
5050
}
4934
5054
  Run query using DRIZZLE C API
4935
5055
 
4936
5056
  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
 
5057
    run_query_normal()
 
5058
    drizzle  DRIZZLE handle
 
5059
    command  current command pointer
 
5060
    flags  flags indicating if we should SEND and/or REAP
 
5061
    query  query string to execute
 
5062
    query_len  length query string to execute
 
5063
    ds    output buffer where to store result form query
4944
5064
*/
4945
5065
 
4946
5066
static void run_query_normal(struct st_connection *cn,
4947
5067
                             struct st_command *command,
4948
5068
                             int flags, char *query, int query_len,
4949
 
                             string *ds, string *ds_warnings)
 
5069
                             DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4950
5070
{
4951
5071
  DRIZZLE_RES *res= 0;
4952
5072
  DRIZZLE *drizzle= &cn->drizzle;
4955
5075
  if (flags & QUERY_SEND_FLAG)
4956
5076
  {
4957
5077
    /*
4958
 
     * Send the query
4959
 
     */
 
5078
      Send the query
 
5079
    */
4960
5080
    if (do_send_query(cn, query, query_len, flags))
4961
5081
    {
4962
5082
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4963
 
                   drizzle_sqlstate(drizzle), ds);
 
5083
       drizzle_sqlstate(drizzle), ds);
4964
5084
      goto end;
4965
5085
    }
4966
5086
  }
 
5087
#ifdef EMBEDDED_LIBRARY
 
5088
  /*
 
5089
    Here we handle 'reap' command, so we need to check if the
 
5090
    query's thread was finished and probably wait
 
5091
  */
 
5092
  else if (flags & QUERY_REAP_FLAG)
 
5093
    wait_query_thread_end(cn);
 
5094
#endif /*EMBEDDED_LIBRARY*/
4967
5095
  if (!(flags & QUERY_REAP_FLAG))
4968
5096
    return;
4969
5097
 
4976
5104
    if ((counter==0) && drizzle_read_query_result(drizzle))
4977
5105
    {
4978
5106
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4979
 
                   drizzle_sqlstate(drizzle), ds);
 
5107
       drizzle_sqlstate(drizzle), ds);
4980
5108
      goto end;
4981
5109
 
4982
5110
    }
4987
5115
    if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
4988
5116
    {
4989
5117
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4990
 
                   drizzle_sqlstate(drizzle), ds);
 
5118
       drizzle_sqlstate(drizzle), ds);
4991
5119
      goto end;
4992
5120
    }
4993
5121
 
5023
5151
      */
5024
5152
      if (!disable_warnings && !drizzle_more_results(drizzle))
5025
5153
      {
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
 
        }
 
5154
  if (append_warnings(ds_warnings, drizzle) || ds_warnings->length)
 
5155
  {
 
5156
    dynstr_append_mem(ds, "Warnings:\n", 10);
 
5157
    dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
 
5158
  }
5031
5159
      }
5032
5160
 
5033
5161
      if (!disable_info)
5034
 
        append_info(ds, affected_rows, drizzle_info(drizzle));
 
5162
  append_info(ds, affected_rows, drizzle_info(drizzle));
5035
5163
    }
5036
5164
 
5037
5165
    if (res)
5045
5173
  {
5046
5174
    /* We got an error from drizzle_next_result, maybe expected */
5047
5175
    handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5048
 
                 drizzle_sqlstate(drizzle), ds);
 
5176
     drizzle_sqlstate(drizzle), ds);
5049
5177
    goto end;
5050
5178
  }
5051
5179
  assert(err == -1); /* Successful and there are no more results */
5077
5205
  ds    - dynamic string which is used for output buffer
5078
5206
 
5079
5207
  NOTE
5080
 
  If there is an unexpected error this function will abort drizzletest
5081
 
  immediately.
 
5208
    If there is an unexpected error this function will abort drizzletest
 
5209
    immediately.
5082
5210
*/
5083
5211
 
5084
5212
void handle_error(struct st_command *command,
5085
5213
                  unsigned int err_errno, const char *err_error,
5086
 
                  const char *err_sqlstate, string *ds)
 
5214
                  const char *err_sqlstate, DYNAMIC_STRING *ds)
5087
5215
{
5088
5216
  uint i;
5089
5217
 
5090
5218
 
 
5219
 
5091
5220
  if (command->require_file[0])
5092
5221
  {
5093
5222
    /*
5121
5250
        if (command->expected_errors.count == 1)
5122
5251
        {
5123
5252
          /* 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);
 
5253
          dynstr_append_mem(ds, "ERROR ", 6);
 
5254
          replace_dynstr_append(ds, err_sqlstate);
 
5255
          dynstr_append_mem(ds, ": ", 2);
 
5256
          replace_dynstr_append(ds, err_error);
 
5257
          dynstr_append_mem(ds,"\n",1);
5129
5258
        }
5130
5259
        /* Don't log error if we may not get an error */
5131
5260
        else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5132
5261
                 (command->expected_errors.err[0].type == ERR_ERRNO &&
5133
5262
                  command->expected_errors.err[0].code.errnum != 0))
5134
 
          ds->append("Got one of the listed errors\n");
 
5263
          dynstr_append(ds,"Got one of the listed errors\n");
5135
5264
      }
5136
5265
      /* OK */
5137
5266
      return;
5140
5269
 
5141
5270
  if (!disable_result_log)
5142
5271
  {
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);
 
5272
    dynstr_append_mem(ds, "ERROR ",6);
 
5273
    replace_dynstr_append(ds, err_sqlstate);
 
5274
    dynstr_append_mem(ds, ": ", 2);
 
5275
    replace_dynstr_append(ds, err_error);
 
5276
    dynstr_append_mem(ds, "\n", 1);
5148
5277
  }
5149
5278
 
5150
5279
  if (i)
5156
5285
    else
5157
5286
      die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
5158
5287
          command->query, err_sqlstate, err_error,
5159
 
          command->expected_errors.err[0].code.sqlstate);
 
5288
    command->expected_errors.err[0].code.sqlstate);
5160
5289
  }
5161
5290
 
5162
5291
  return;
5201
5330
  Run query
5202
5331
 
5203
5332
  SYNPOSIS
5204
 
  run_query()
5205
 
  drizzle  DRIZZLE handle
5206
 
  command  currrent command pointer
 
5333
    run_query()
 
5334
     drizzle  DRIZZLE handle
 
5335
     command  currrent command pointer
5207
5336
 
5208
5337
  flags control the phased/stages of query execution to be performed
5209
5338
  if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
5214
5343
                      struct st_command *command,
5215
5344
                      int flags)
5216
5345
{
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;
 
5346
  DYNAMIC_STRING *ds;
 
5347
  DYNAMIC_STRING *save_ds= NULL;
 
5348
  DYNAMIC_STRING ds_result;
 
5349
  DYNAMIC_STRING ds_sorted;
 
5350
  DYNAMIC_STRING ds_warnings;
 
5351
  DYNAMIC_STRING eval_query;
5223
5352
  char *query;
5224
5353
  int query_len;
5225
5354
 
5226
5355
 
 
5356
  init_dynamic_string(&ds_warnings, NULL, 0, 256);
 
5357
 
5227
5358
  /* Scan for warning before sending to server */
5228
5359
  scan_command_for_warnings(command);
5229
5360
 
5232
5363
  */
5233
5364
  if (command->type == Q_EVAL)
5234
5365
  {
 
5366
    init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
5235
5367
    do_eval(&eval_query, command->query, command->end, false);
5236
 
    query = strdup(eval_query.c_str());
5237
 
    query_len = eval_query.length();
 
5368
    query = eval_query.str;
 
5369
    query_len = eval_query.length;
5238
5370
  }
5239
5371
  else
5240
5372
  {
5250
5382
  */
5251
5383
  if (command->require_file[0])
5252
5384
  {
 
5385
    init_dynamic_string(&ds_result, "", 1024, 1024);
5253
5386
    ds= &ds_result;
5254
5387
  }
5255
5388
  else
5256
 
  {
5257
5389
    ds= &ds_res;
5258
 
  }
 
5390
 
5259
5391
  /*
5260
5392
    Log the query into the output buffer
5261
5393
  */
5262
5394
  if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5263
5395
  {
5264
 
    replace_append_mem(ds, query, query_len);
5265
 
    ds->append(delimiter, delimiter_length);
5266
 
    ds->append("\n");
 
5396
    replace_dynstr_append_mem(ds, query, query_len);
 
5397
    dynstr_append_mem(ds, delimiter, delimiter_length);
 
5398
    dynstr_append_mem(ds, "\n", 1);
5267
5399
  }
5268
5400
 
5269
5401
  if (display_result_sorted)
5270
5402
  {
5271
5403
    /*
5272
 
      Collect the query output in a separate string
5273
 
      that can be sorted before it's added to the
5274
 
      global result string
 
5404
       Collect the query output in a separate string
 
5405
       that can be sorted before it's added to the
 
5406
       global result string
5275
5407
    */
 
5408
    init_dynamic_string(&ds_sorted, "", 1024, 1024);
5276
5409
    save_ds= ds; /* Remember original ds */
5277
5410
    ds= &ds_sorted;
5278
5411
  }
5287
5420
  if (display_result_sorted)
5288
5421
  {
5289
5422
    /* Sort the result set and append it to result */
5290
 
    append_sorted(save_ds, &ds_sorted);
 
5423
    dynstr_append_sorted(save_ds, &ds_sorted);
5291
5424
    ds= save_ds;
 
5425
    dynstr_free(&ds_sorted);
5292
5426
  }
5293
5427
 
5294
5428
  if (command->require_file[0])
5300
5434
    check_require(ds, command->require_file);
5301
5435
  }
5302
5436
 
 
5437
  dynstr_free(&ds_warnings);
 
5438
  if (ds == &ds_result)
 
5439
    dynstr_free(&ds_result);
 
5440
  if (command->type == Q_EVAL)
 
5441
    dynstr_free(&eval_query);
5303
5442
  return;
5304
5443
}
5305
5444
 
5349
5488
    {
5350
5489
      /* -- comment that didn't contain a drizzletest command */
5351
5490
      command->type= Q_COMMENT;
5352
 
      warning_msg("Suspicious command '--%s' detected, was this intentional? " \
 
5491
      warning_msg("Suspicious command '--%s' detected, was this intentional? "\
5353
5492
                  "Use # instead of -- to avoid this warning",
5354
5493
                  command->query);
5355
5494
 
5403
5542
 
5404
5543
  /* Milliseconds since start */
5405
5544
  end= int64_t2str(timer, buf, 10);
5406
 
  ds_progress.append(buf, (int)(end-buf));
5407
 
  ds_progress.append("\t", 1);
 
5545
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5546
  dynstr_append_mem(&ds_progress, "\t", 1);
5408
5547
 
5409
5548
  /* Parser line number */
5410
5549
  end= int10_to_str(line, buf, 10);
5411
 
  ds_progress.append(buf, (int)(end-buf));
5412
 
  ds_progress.append("\t", 1);
 
5550
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5551
  dynstr_append_mem(&ds_progress, "\t", 1);
5413
5552
 
5414
5553
  /* Filename */
5415
 
  ds_progress.append(cur_file->file_name);
5416
 
  ds_progress.append(":", 1);
 
5554
  dynstr_append(&ds_progress, cur_file->file_name);
 
5555
  dynstr_append_mem(&ds_progress, ":", 1);
5417
5556
 
5418
5557
  /* Line in file */
5419
5558
  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);
 
5559
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
 
5560
 
 
5561
 
 
5562
  dynstr_append_mem(&ds_progress, "\n", 1);
5424
5563
 
5425
5564
}
5426
5565
 
5446
5585
    (sizeof(connections)/sizeof(struct st_connection)) - 1;
5447
5586
  next_con= connections + 1;
5448
5587
 
 
5588
#ifdef EMBEDDED_LIBRARY
 
5589
  /* set appropriate stack for the 'query' threads */
 
5590
  (void) pthread_attr_init(&cn_thd_attrib);
 
5591
  pthread_attr_setstacksize(&cn_thd_attrib, DEFAULT_THREAD_STACK);
 
5592
#endif /*EMBEDDED_LIBRARY*/
 
5593
 
5449
5594
  /* Init file stack */
5450
5595
  memset(file_stack, 0, sizeof(file_stack));
5451
5596
  file_stack_end=
5460
5605
  cur_block->ok= true; /* Outer block should always be executed */
5461
5606
  cur_block->cmd= cmd_none;
5462
5607
 
 
5608
  my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
 
5609
 
5463
5610
  if (hash_init(&var_hash, charset_info,
5464
5611
                1024, 0, 0, get_var_key, var_free, MYF(0)))
5465
5612
    die("Variable hash initialization failed");
5466
5613
 
5467
 
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
 
5614
  var_set_string("$MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
5468
5615
 
5469
5616
  memset(&master_pos, 0, sizeof(master_pos));
5470
5617
 
5473
5620
 
5474
5621
  init_builtin_echo();
5475
5622
 
5476
 
  ds_res.reserve(65536);
5477
 
  ds_progress.reserve(2048);
5478
 
  ds_warning_messages.reserve(2048);
5479
 
 
 
5623
  init_dynamic_string(&ds_res, "", 65536, 65536);
 
5624
  init_dynamic_string(&ds_progress, "", 0, 2048);
 
5625
  init_dynamic_string(&ds_warning_messages, "", 0, 2048);
5480
5626
  parse_args(argc, argv);
5481
5627
 
5482
5628
  server_initialized= 1;
5490
5636
  if (!( drizzle_create(&cur_con->drizzle)))
5491
5637
    die("Failed in drizzle_create()");
5492
5638
  if (opt_compress)
5493
 
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
 
5639
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NullS);
5494
5640
  drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
5641
  drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_NAME,
 
5642
                charset_info->csname);
 
5643
  int opt_protocol= DRIZZLE_PROTOCOL_TCP;
 
5644
  drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
 
5645
  if (opt_charsets_dir)
 
5646
    drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_DIR,
 
5647
                  opt_charsets_dir);
5495
5648
 
5496
5649
  if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5497
5650
    die("Out of memory");
5539
5692
      case Q_CONNECT:
5540
5693
        do_connect(command);
5541
5694
        break;
5542
 
      case Q_CONNECTION:
5543
 
        select_connection(command);
5544
 
        break;
 
5695
      case Q_CONNECTION: select_connection(command); break;
5545
5696
      case Q_DISCONNECT:
5546
5697
      case Q_DIRTY_CLOSE:
5547
 
        do_close_connection(command); break;
 
5698
  do_close_connection(command); break;
5548
5699
      case Q_ENABLE_QUERY_LOG:   disable_query_log=0; break;
5549
5700
      case Q_DISABLE_QUERY_LOG:  disable_query_log=1; break;
5550
5701
      case Q_ENABLE_ABORT_ON_ERROR:  abort_on_error=1; break;
5580
5731
      case Q_PERL: do_perl(command); break;
5581
5732
      case Q_DELIMITER:
5582
5733
        do_delimiter(command);
5583
 
        break;
 
5734
  break;
5584
5735
      case Q_DISPLAY_VERTICAL_RESULTS:
5585
5736
        display_result_vertically= true;
5586
5737
        break;
5587
5738
      case Q_DISPLAY_HORIZONTAL_RESULTS:
5588
 
        display_result_vertically= false;
 
5739
  display_result_vertically= false;
5589
5740
        break;
5590
5741
      case Q_SORTED_RESULT:
5591
5742
        /*
5592
5743
          Turn on sorting of result set, will be reset after next
5593
5744
          command
5594
5745
        */
5595
 
        display_result_sorted= true;
 
5746
  display_result_sorted= true;
5596
5747
        break;
5597
5748
      case Q_LET: do_let(command); break;
5598
5749
      case Q_EVAL_RESULT:
5600
5751
      case Q_EVAL:
5601
5752
      case Q_QUERY_VERTICAL:
5602
5753
      case Q_QUERY_HORIZONTAL:
5603
 
        if (command->query == command->query_buf)
 
5754
  if (command->query == command->query_buf)
5604
5755
        {
5605
5756
          /* Skip the first part of command, i.e query_xxx */
5606
 
          command->query= command->first_argument;
 
5757
    command->query= command->first_argument;
5607
5758
          command->first_word_len= 0;
5608
5759
        }
5609
 
        /* fall through */
 
5760
  /* fall through */
5610
5761
      case Q_QUERY:
5611
5762
      case Q_REAP:
5612
5763
      {
5613
 
        bool old_display_result_vertically= display_result_vertically;
 
5764
  bool old_display_result_vertically= display_result_vertically;
5614
5765
        /* Default is full query, both reap and send  */
5615
5766
        int flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
5616
5767
 
5628
5779
        /* Check for special property for this query */
5629
5780
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5630
5781
 
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++;
 
5782
  if (save_file[0])
 
5783
  {
 
5784
    strmake(command->require_file, save_file, sizeof(save_file) - 1);
 
5785
    save_file[0]= 0;
 
5786
  }
 
5787
  run_query(cur_con, command, flags);
 
5788
  command_executed++;
5638
5789
        command->last_argument= command->end;
5639
5790
 
5640
5791
        /* Restore settings */
5641
 
        display_result_vertically= old_display_result_vertically;
 
5792
  display_result_vertically= old_display_result_vertically;
5642
5793
 
5643
 
        break;
 
5794
  break;
5644
5795
      }
5645
5796
      case Q_SEND:
5646
5797
        if (!*command->first_argument)
5654
5805
        }
5655
5806
 
5656
5807
        /* Remove "send" if this is first iteration */
5657
 
        if (command->query == command->query_buf)
5658
 
          command->query= command->first_argument;
 
5808
  if (command->query == command->query_buf)
 
5809
    command->query= command->first_argument;
5659
5810
 
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
 
5811
  /*
 
5812
    run_query() can execute a query partially, depending on the flags.
 
5813
    QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5663
5814
          the query and read the result some time later when reap instruction
5664
 
          is given on this connection.
 
5815
    is given on this connection.
5665
5816
        */
5666
 
        run_query(cur_con, command, QUERY_SEND_FLAG);
5667
 
        command_executed++;
 
5817
  run_query(cur_con, command, QUERY_SEND_FLAG);
 
5818
  command_executed++;
5668
5819
        command->last_argument= command->end;
5669
 
        break;
 
5820
  break;
5670
5821
      case Q_REQUIRE:
5671
 
        do_get_file_name(command, save_file, sizeof(save_file));
5672
 
        break;
 
5822
  do_get_file_name(command, save_file, sizeof(save_file));
 
5823
  break;
5673
5824
      case Q_ERROR:
5674
5825
        do_get_errcodes(command);
5675
 
        break;
 
5826
  break;
5676
5827
      case Q_REPLACE:
5677
 
        do_get_replace(command);
5678
 
        break;
 
5828
  do_get_replace(command);
 
5829
  break;
5679
5830
      case Q_REPLACE_REGEX:
5680
5831
        do_get_replace_regex(command);
5681
5832
        break;
5682
5833
      case Q_REPLACE_COLUMN:
5683
 
        do_get_replace_column(command);
5684
 
        break;
 
5834
  do_get_replace_column(command);
 
5835
  break;
5685
5836
      case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5686
5837
      case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5687
5838
      case Q_SYNC_SLAVE_WITH_MASTER:
5688
5839
      {
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;
 
5840
  do_save_master_pos();
 
5841
  if (*command->first_argument)
 
5842
    select_connection(command);
 
5843
  else
 
5844
    select_connection_name("slave");
 
5845
  do_sync_with_master2(0);
 
5846
  break;
5696
5847
      }
5697
5848
      case Q_COMMENT:        /* Ignore row */
5698
5849
        command->last_argument= command->end;
5699
 
        break;
 
5850
  break;
5700
5851
      case Q_PING:
5701
 
        (void) drizzle_ping(&cur_con->drizzle);
5702
 
        break;
 
5852
  (void) drizzle_ping(&cur_con->drizzle);
 
5853
  break;
5703
5854
      case Q_EXEC:
5704
 
        do_exec(command);
5705
 
        command_executed++;
5706
 
        break;
 
5855
  do_exec(command);
 
5856
  command_executed++;
 
5857
  break;
5707
5858
      case Q_START_TIMER:
5708
 
        /* Overwrite possible earlier start of timer */
5709
 
        timer_start= timer_now();
5710
 
        break;
 
5859
  /* Overwrite possible earlier start of timer */
 
5860
  timer_start= timer_now();
 
5861
  break;
5711
5862
      case Q_END_TIMER:
5712
 
        /* End timer before ending drizzletest */
5713
 
        timer_output();
5714
 
        break;
 
5863
  /* End timer before ending drizzletest */
 
5864
  timer_output();
 
5865
  break;
5715
5866
      case Q_CHARACTER_SET:
5716
 
        do_set_charset(command);
5717
 
        break;
 
5867
  do_set_charset(command);
 
5868
  break;
5718
5869
      case Q_DISABLE_RECONNECT:
5719
5870
        set_reconnect(&cur_con->drizzle, 0);
5720
5871
        break;
5810
5961
    Time to compare result or save it to record file.
5811
5962
    The entire output from test is now kept in ds_res.
5812
5963
  */
5813
 
  if (ds_res.length())
 
5964
  if (ds_res.length)
5814
5965
  {
5815
5966
    if (result_file_name)
5816
5967
    {
5818
5969
 
5819
5970
      if (record)
5820
5971
      {
5821
 
        /* Recording - dump the output from test to result file */
5822
 
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
 
5972
  /* Recording - dump the output from test to result file */
 
5973
  str_to_file(result_file_name, ds_res.str, ds_res.length);
5823
5974
      }
5824
5975
      else
5825
5976
      {
5826
 
        /* Check that the output from test is equal to result file
5827
 
           - detect missing result file
5828
 
           - detect zero size result file
 
5977
  /* Check that the output from test is equal to result file
 
5978
     - detect missing result file
 
5979
     - detect zero size result file
5829
5980
        */
5830
 
        check_result(&ds_res);
 
5981
  check_result(&ds_res);
5831
5982
      }
5832
5983
    }
5833
5984
    else
5834
5985
    {
5835
5986
      /* No result_file_name specified to compare with, print to stdout */
5836
 
      printf("%s", ds_res.c_str());
 
5987
      printf("%s", ds_res.str);
5837
5988
    }
5838
5989
  }
5839
5990
  else
5858
6009
    dump_progress();
5859
6010
 
5860
6011
  /* Dump warning messages */
5861
 
  if (result_file_name && ds_warning_messages.length())
 
6012
  if (result_file_name && ds_warning_messages.length)
5862
6013
    dump_warning_messages();
5863
6014
 
5864
6015
  timer_output();
5940
6091
    if (!*from)
5941
6092
      die("Wrong number of arguments to replace_column in '%s'", command->query);
5942
6093
    to= get_string(&buff, &from, command);
5943
 
    free(replace_column[column_number-1]);
 
6094
    my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
5944
6095
    replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
5945
6096
    set_if_bigger(max_replace_column, column_number);
5946
6097
  }
5947
 
  free(start);
 
6098
  my_free(start, MYF(0));
5948
6099
  command->last_argument= command->end;
5949
6100
}
5950
6101
 
5956
6107
  {
5957
6108
    if (replace_column[i])
5958
6109
    {
5959
 
      free(replace_column[i]);
 
6110
      my_free(replace_column[i], 0);
5960
6111
      replace_column[i]= 0;
5961
6112
    }
5962
6113
  }
5973
6124
 
5974
6125
typedef struct st_pointer_array {    /* when using array-strings */
5975
6126
  TYPELIB typelib;        /* Pointer to strings */
5976
 
  unsigned char  *str;          /* Strings is here */
5977
 
  uint8_t *flag;          /* Flag about each var. */
 
6127
  uchar  *str;          /* Strings is here */
 
6128
  int7  *flag;          /* Flag about each var. */
5978
6129
  uint  array_allocs,max_count,length,max_length;
5979
6130
} POINTER_ARRAY;
5980
6131
 
5981
6132
struct st_replace;
5982
6133
struct st_replace *init_replace(char * *from, char * *to, uint count,
5983
 
                                char * word_end_chars);
 
6134
        char * word_end_chars);
5984
6135
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5985
 
void replace_strings_append(struct st_replace *rep, string* ds,
 
6136
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5986
6137
                            const char *from, int len);
5987
6138
void free_pointer_array(POINTER_ARRAY *pa);
5988
6139
 
6028
6179
      *pos++= i;
6029
6180
  *pos=0;          /* End pointer */
6030
6181
  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)))
 
6182
          (char**) to_array.typelib.type_names,
 
6183
          (uint) from_array.typelib.count,
 
6184
          word_end_chars)))
6034
6185
    die("Can't initialize replace from '%s'", command->query);
6035
6186
  free_pointer_array(&from_array);
6036
6187
  free_pointer_array(&to_array);
6037
 
  free(start);
 
6188
  my_free(start, MYF(0));
6038
6189
  command->last_argument= command->end;
6039
6190
  return;
6040
6191
}
6045
6196
 
6046
6197
  if (glob_replace)
6047
6198
  {
6048
 
    free(glob_replace);
 
6199
    my_free(glob_replace,MYF(0));
6049
6200
    glob_replace=0;
6050
6201
  }
6051
6202
  return;
6065
6216
} REPLACE_STRING;
6066
6217
 
6067
6218
 
6068
 
void replace_strings_append(REPLACE *rep, string* ds,
6069
 
                            const char *str, int len)
 
6219
void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
 
6220
                            const char *str,
 
6221
                            int len __attribute__((unused)))
6070
6222
{
6071
6223
  register REPLACE *rep_pos;
6072
6224
  register REPLACE_STRING *rep_str;
6079
6231
  {
6080
6232
    /* Loop through states */
6081
6233
    while (!rep_pos->found)
6082
 
      rep_pos= rep_pos->next[(unsigned char) *from++];
 
6234
      rep_pos= rep_pos->next[(uchar) *from++];
6083
6235
 
6084
6236
    /* Does this state contain a string to be replaced */
6085
6237
    if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6086
6238
    {
6087
6239
      /* No match found */
6088
 
      ds->append(start, from - start - 1);
 
6240
      dynstr_append_mem(ds, start, from - start - 1);
6089
6241
      return;
6090
6242
    }
6091
6243
 
6092
6244
    /* Append part of original string before replace string */
6093
 
    ds->append(start, (from - rep_str->to_offset) - start);
 
6245
    dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6094
6246
 
6095
6247
    /* Append replace string */
6096
 
    ds->append(rep_str->replace_string,
6097
 
               strlen(rep_str->replace_string));
 
6248
    dynstr_append_mem(ds, rep_str->replace_string,
 
6249
                      strlen(rep_str->replace_string));
6098
6250
 
6099
6251
    if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6100
6252
      return;
6245
6397
      reg.icase= 1;
6246
6398
 
6247
6399
    /* done parsing the statement, now place it in regex_arr */
6248
 
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6400
    if (insert_dynamic(&res->regex_arr,(uchar*) &reg))
6249
6401
      die("Out of memory");
6250
6402
  }
6251
6403
  res->odd_buf_len= res->even_buf_len= 8192;
6256
6408
  return res;
6257
6409
 
6258
6410
err:
6259
 
  free(res);
 
6411
  my_free(res,0);
6260
6412
  die("Error parsing replace_regex \"%s\"", expr);
6261
6413
  return 0;
6262
6414
}
6297
6449
    struct st_regex re;
6298
6450
    char* save_out_buf= out_buf;
6299
6451
 
6300
 
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6452
    get_dynamic(&r->regex_arr,(uchar*)&re,i);
6301
6453
 
6302
6454
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6303
6455
                     in_buf, re.icase))
6315
6467
      if (in_buf == val)
6316
6468
        in_buf= r->odd_buf;
6317
6469
 
6318
 
      std::swap(in_buf,out_buf);
 
6470
      swap_variables(char*,in_buf,out_buf);
6319
6471
 
6320
6472
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
6321
6473
        &r->odd_buf_len;
6348
6500
  if (glob_replace_regex)
6349
6501
  {
6350
6502
    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);
 
6503
    my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6504
    my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6505
    my_free(glob_replace_regex,MYF(0));
6354
6506
    glob_replace_regex=0;
6355
6507
  }
6356
6508
}
6402
6554
    return 1;
6403
6555
  }
6404
6556
  strcpy(new_buf, new_str);
6405
 
  *buf_p= new_buf;
 
6557
  buf_p= &new_buf;
6406
6558
 
6407
6559
  return 0;
6408
6560
}
6481
6633
/* Init a replace structure for further calls */
6482
6634
 
6483
6635
REPLACE *init_replace(char * *from, char * *to,uint count,
6484
 
                      char * word_end_chars)
 
6636
          char * word_end_chars)
6485
6637
{
6486
6638
  static const int SPACE_CHAR= 256;
6487
6639
  static const int START_OF_LINE= 257;
6515
6667
  }
6516
6668
  memset(is_word_end, 0, sizeof(is_word_end));
6517
6669
  for (i=0 ; word_end_chars[i] ; i++)
6518
 
    is_word_end[(unsigned char) word_end_chars[i]]=1;
 
6670
    is_word_end[(uchar) word_end_chars[i]]=1;
6519
6671
 
6520
6672
  if (init_sets(&sets,states))
6521
6673
    return(0);
6522
6674
  found_sets=0;
6523
6675
  if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
6524
 
                                          MYF(MY_WME))))
 
6676
            MYF(MY_WME))))
6525
6677
  {
6526
6678
    free_sets(&sets);
6527
6679
    return(0);
6528
6680
  }
6529
 
  make_new_set(&sets);      /* Set starting set */
 
6681
  VOID(make_new_set(&sets));      /* Set starting set */
6530
6682
  make_sets_invisible(&sets);      /* Hide previus sets */
6531
6683
  used_sets=-1;
6532
6684
  word_states=make_new_set(&sets);    /* Start of new word */
6534
6686
  if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6535
6687
  {
6536
6688
    free_sets(&sets);
6537
 
    free(found_set);
 
6689
    my_free(found_set,MYF(0));
6538
6690
    return(0);
6539
6691
  }
6540
6692
 
6546
6698
      internal_set_bit(start_states,states+1);
6547
6699
      if (!from[i][2])
6548
6700
      {
6549
 
        start_states->table_offset=i;
6550
 
        start_states->found_offset=1;
 
6701
  start_states->table_offset=i;
 
6702
  start_states->found_offset=1;
6551
6703
      }
6552
6704
    }
6553
6705
    else if (from[i][0] == '\\' && from[i][1] == '$')
6554
6706
    {
6555
6707
      internal_set_bit(start_states,states);
6556
6708
      internal_set_bit(word_states,states);
6557
 
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
 
6709
      if (!from[i][2] && start_states->table_offset == (uint) ~0)
6558
6710
      {
6559
 
        start_states->table_offset=i;
6560
 
        start_states->found_offset=0;
 
6711
  start_states->table_offset=i;
 
6712
  start_states->found_offset=0;
6561
6713
      }
6562
6714
    }
6563
6715
    else
6564
6716
    {
6565
6717
      internal_set_bit(word_states,states);
6566
6718
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6567
 
        internal_set_bit(start_states,states+1);
 
6719
  internal_set_bit(start_states,states+1);
6568
6720
      else
6569
 
        internal_set_bit(start_states,states);
 
6721
  internal_set_bit(start_states,states);
6570
6722
    }
6571
6723
    for (pos=from[i], len=0; *pos ; pos++)
6572
6724
    {
6573
6725
      if (*pos == '\\' && *(pos+1))
6574
6726
      {
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
 
        }
 
6727
  pos++;
 
6728
  switch (*pos) {
 
6729
  case 'b':
 
6730
    follow_ptr->chr = SPACE_CHAR;
 
6731
    break;
 
6732
  case '^':
 
6733
    follow_ptr->chr = START_OF_LINE;
 
6734
    break;
 
6735
  case '$':
 
6736
    follow_ptr->chr = END_OF_LINE;
 
6737
    break;
 
6738
  case 'r':
 
6739
    follow_ptr->chr = '\r';
 
6740
    break;
 
6741
  case 't':
 
6742
    follow_ptr->chr = '\t';
 
6743
    break;
 
6744
  case 'v':
 
6745
    follow_ptr->chr = '\v';
 
6746
    break;
 
6747
  default:
 
6748
    follow_ptr->chr = (uchar) *pos;
 
6749
    break;
 
6750
  }
6599
6751
      }
6600
6752
      else
6601
 
        follow_ptr->chr= (unsigned char) *pos;
 
6753
  follow_ptr->chr= (uchar) *pos;
6602
6754
      follow_ptr->table_offset=i;
6603
6755
      follow_ptr->len= ++len;
6604
6756
      follow_ptr++;
6618
6770
 
6619
6771
    /* If end of found-string not found or start-set with current set */
6620
6772
 
6621
 
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
 
6773
    for (i= (uint) ~0; (i=get_next_bit(set,i)) ;)
6622
6774
    {
6623
6775
      if (!follow[i].chr)
6624
6776
      {
6625
 
        if (! default_state)
6626
 
          default_state= find_found(found_set,set->table_offset,
6627
 
                                    set->found_offset+1);
 
6777
  if (! default_state)
 
6778
    default_state= find_found(found_set,set->table_offset,
 
6779
            set->found_offset+1);
6628
6780
      }
6629
6781
    }
6630
6782
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6633
6785
 
6634
6786
    /* Find all chars that follows current sets */
6635
6787
    memset(used_chars, 0, sizeof(used_chars));
6636
 
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
 
6788
    for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6637
6789
    {
6638
6790
      used_chars[follow[i].chr]=1;
6639
6791
      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;
 
6792
     follow[i].len > 1) || follow[i].chr == END_OF_LINE)
 
6793
  used_chars[0]=1;
6642
6794
    }
6643
6795
 
6644
6796
    /* Mark word_chars used if \b is in state */
6645
6797
    if (used_chars[SPACE_CHAR])
6646
6798
      for (pos= word_end_chars ; *pos ; pos++)
6647
 
        used_chars[(int) (unsigned char) *pos] = 1;
 
6799
  used_chars[(int) (uchar) *pos] = 1;
6648
6800
 
6649
6801
    /* Handle other used characters */
6650
6802
    for (chr= 0 ; chr < 256 ; chr++)
6651
6803
    {
6652
6804
      if (! used_chars[chr])
6653
 
        set->next[chr]= chr ? default_state : -1;
 
6805
  set->next[chr]= chr ? default_state : -1;
6654
6806
      else
6655
6807
      {
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;
 
6808
  new_set=make_new_set(&sets);
 
6809
  set=sets.set+set_nr;      /* if realloc */
 
6810
  new_set->table_offset=set->table_offset;
 
6811
  new_set->found_len=set->found_len;
 
6812
  new_set->found_offset=set->found_offset+1;
 
6813
  found_end=0;
6662
6814
 
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);
 
6815
  for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
 
6816
  {
 
6817
    if (!follow[i].chr || follow[i].chr == chr ||
 
6818
        (follow[i].chr == SPACE_CHAR &&
 
6819
         (is_word_end[chr] ||
 
6820
    (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
 
6821
        (follow[i].chr == END_OF_LINE && ! chr))
 
6822
    {
 
6823
      if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
 
6824
    follow[i].len > found_end)
 
6825
        found_end=follow[i].len;
 
6826
      if (chr && follow[i].chr)
 
6827
        internal_set_bit(new_set,i+1);    /* To next set */
 
6828
      else
 
6829
        internal_set_bit(new_set,i);
 
6830
    }
 
6831
  }
 
6832
  if (found_end)
 
6833
  {
 
6834
    new_set->found_len=0;      /* Set for testing if first */
 
6835
    bits_set=0;
 
6836
    for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
 
6837
    {
 
6838
      if ((follow[i].chr == SPACE_CHAR ||
 
6839
     follow[i].chr == END_OF_LINE) && ! chr)
 
6840
        bit_nr=i+1;
 
6841
      else
 
6842
        bit_nr=i;
 
6843
      if (follow[bit_nr-1].len < found_end ||
 
6844
    (new_set->found_len &&
 
6845
     (chr == 0 || !follow[bit_nr].chr)))
 
6846
        internal_clear_bit(new_set,i);
 
6847
      else
 
6848
      {
 
6849
        if (chr == 0 || !follow[bit_nr].chr)
 
6850
        {          /* best match  */
 
6851
    new_set->table_offset=follow[bit_nr].table_offset;
 
6852
    if (chr || (follow[i].chr == SPACE_CHAR ||
 
6853
          follow[i].chr == END_OF_LINE))
 
6854
      new_set->found_offset=found_end;  /* New match */
 
6855
    new_set->found_len=found_end;
 
6856
        }
 
6857
        bits_set++;
 
6858
      }
 
6859
    }
 
6860
    if (bits_set == 1)
 
6861
    {
 
6862
      set->next[chr] = find_found(found_set,
 
6863
          new_set->table_offset,
 
6864
          new_set->found_offset);
 
6865
      free_last_set(&sets);
 
6866
    }
 
6867
    else
 
6868
      set->next[chr] = find_set(&sets,new_set);
 
6869
  }
 
6870
  else
 
6871
    set->next[chr] = find_set(&sets,new_set);
6720
6872
      }
6721
6873
    }
6722
6874
  }
6724
6876
  /* Alloc replace structure for the replace-state-machine */
6725
6877
 
6726
6878
  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))))
 
6879
            sizeof(REPLACE_STRING)*(found_sets+1)+
 
6880
            sizeof(char *)*count+result_len,
 
6881
            MYF(MY_WME | MY_ZEROFILL))))
6730
6882
  {
6731
6883
    rep_str=(REPLACE_STRING*) (replace+sets.count);
6732
6884
    to_array= (char **) (rep_str+found_sets+1);
6734
6886
    for (i=0 ; i < count ; i++)
6735
6887
    {
6736
6888
      to_array[i]=to_pos;
6737
 
      to_pos=my_stpcpy(to_pos,to[i])+1;
 
6889
      to_pos=strmov(to_pos,to[i])+1;
6738
6890
    }
6739
6891
    rep_str[0].found=1;
6740
6892
    rep_str[0].replace_string=0;
6745
6897
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
6746
6898
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
6747
6899
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6748
 
        end_of_word(pos);
 
6900
  end_of_word(pos);
6749
6901
    }
6750
6902
    for (i=0 ; i < sets.count ; i++)
6751
6903
    {
6752
6904
      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));
 
6905
  if (sets.set[i].next[j] >= 0)
 
6906
    replace[i].next[j]=replace+sets.set[i].next[j];
 
6907
  else
 
6908
    replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6757
6909
    }
6758
6910
  }
6759
 
  free(follow);
 
6911
  my_free(follow,MYF(0));
6760
6912
  free_sets(&sets);
6761
 
  free(found_set);
 
6913
  my_free(found_set,MYF(0));
6762
6914
  return(replace);
6763
6915
}
6764
6916
 
6768
6920
  memset(sets, 0, sizeof(*sets));
6769
6921
  sets->size_of_bits=((states+7)/8);
6770
6922
  if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
6771
 
                                              MYF(MY_WME))))
 
6923
                MYF(MY_WME))))
6772
6924
    return 1;
6773
6925
  if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
6774
 
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
 
6926
             SET_MALLOC_HUNC,MYF(MY_WME))))
6775
6927
  {
6776
 
    free(sets->set);
 
6928
    my_free(sets->set,MYF(0));
6777
6929
    return 1;
6778
6930
  }
6779
6931
  return 0;
6800
6952
    memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
6801
6953
    set->found_offset=0;
6802
6954
    set->found_len=0;
6803
 
    set->table_offset= UINT32_MAX;
 
6955
    set->table_offset= (uint) ~0;
6804
6956
    set->size_of_bits=sets->size_of_bits;
6805
6957
    return set;
6806
6958
  }
6807
6959
  count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6808
 
  if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
 
6960
  if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6809
6961
                                  sizeof(REP_SET)*count,
6810
 
                                  MYF(MY_WME))))
 
6962
          MYF(MY_WME))))
6811
6963
    return 0;
6812
6964
  sets->set_buffer=set;
6813
6965
  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))))
 
6966
  if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
 
6967
              (sizeof(uint)*sets->size_of_bits)*count,
 
6968
              MYF(MY_WME))))
6817
6969
    return 0;
6818
6970
  sets->bit_buffer=bit_buffer;
6819
6971
  for (i=0 ; i < count ; i++)
6834
6986
 
6835
6987
void free_sets(REP_SETS *sets)
6836
6988
{
6837
 
  free(sets->set_buffer);
6838
 
  free(sets->bit_buffer);
 
6989
  my_free(sets->set_buffer,MYF(0));
 
6990
  my_free(sets->bit_buffer,MYF(0));
6839
6991
  return;
6840
6992
}
6841
6993
 
6863
7015
void copy_bits(REP_SET *to,REP_SET *from)
6864
7016
{
6865
7017
  memcpy(to->bits,from->bits,
6866
 
         (size_t) (sizeof(uint) * to->size_of_bits));
 
7018
   (size_t) (sizeof(uint) * to->size_of_bits));
6867
7019
}
6868
7020
 
6869
7021
int cmp_bits(REP_SET *set1,REP_SET *set2)
6925
7077
  int i;
6926
7078
  for (i=0 ; (uint) i < found_sets ; i++)
6927
7079
    if (found_set[i].table_offset == table_offset &&
6928
 
        found_set[i].found_offset == found_offset)
 
7080
  found_set[i].found_offset == found_offset)
6929
7081
      return -i-2;
6930
7082
  found_set[i].table_offset=table_offset;
6931
7083
  found_set[i].found_offset=found_offset;
6943
7095
 
6944
7096
uint end_of_word(char * pos)
6945
7097
{
6946
 
  char * end= strchr(pos, '\0');
 
7098
  char * end=strend(pos);
6947
7099
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
6948
7100
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
6949
7101
}
6958
7110
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6959
7111
{
6960
7112
  uint i,length,old_count;
6961
 
  unsigned char *new_pos;
 
7113
  uchar *new_pos;
6962
7114
  const char **new_array;
6963
7115
 
6964
7116
 
6965
7117
  if (! pa->typelib.count)
6966
7118
  {
6967
7119
    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))))
 
7120
    my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
 
7121
         (sizeof(char *)+sizeof(*pa->flag))*
 
7122
         (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6971
7123
      return(-1);
6972
 
    if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
6973
 
                                      MYF(MY_WME))))
 
7124
    if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
 
7125
             MYF(MY_WME))))
6974
7126
    {
6975
 
      free((char*) pa->typelib.type_names);
 
7127
      my_free((char*) pa->typelib.type_names,MYF(0));
6976
7128
      return (-1);
6977
7129
    }
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);
 
7130
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
 
7131
                 sizeof(*pa->flag));
 
7132
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6981
7133
    pa->length=0;
6982
7134
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6983
7135
    pa->array_allocs=1;
6985
7137
  length=(uint) strlen(name)+1;
6986
7138
  if (pa->length+length >= pa->max_length)
6987
7139
  {
6988
 
    if (!(new_pos= (unsigned char*) my_realloc((unsigned char*) pa->str,
6989
 
                                       (uint) (pa->max_length+PS_MALLOC),
6990
 
                                       MYF(MY_WME))))
 
7140
    if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
 
7141
              (uint) (pa->max_length+PS_MALLOC),
 
7142
              MYF(MY_WME))))
6991
7143
      return(1);
6992
7144
    if (new_pos != pa->str)
6993
7145
    {
6994
7146
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
6995
7147
      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*);
 
7148
  pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
 
7149
                char*);
6998
7150
      pa->str=new_pos;
6999
7151
    }
7000
7152
    pa->max_length+=PS_MALLOC;
7004
7156
    int len;
7005
7157
    pa->array_allocs++;
7006
7158
    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)),
 
7159
    if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
 
7160
                 (uint) len/
 
7161
                                               (sizeof(uchar*)+sizeof(*pa->flag))*
 
7162
                                               (sizeof(uchar*)+sizeof(*pa->flag)),
7011
7163
                                               MYF(MY_WME))))
7012
7164
      return(1);
7013
7165
    pa->typelib.type_names=new_array;
7014
7166
    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);
 
7167
    pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
 
7168
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7017
7169
    memcpy(pa->flag, pa->typelib.type_names+old_count,
7018
7170
           old_count*sizeof(*pa->flag));
7019
7171
  }
7020
7172
  pa->flag[pa->typelib.count]=0;      /* Reset flag */
7021
7173
  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);
 
7174
  pa->typelib.type_names[pa->typelib.count]= NullS;  /* Put end-mark */
 
7175
  VOID(strmov((char*) pa->str+pa->length,name));
7024
7176
  pa->length+=length;
7025
7177
  return(0);
7026
7178
} /* insert_pointer_name */
7033
7185
  if (pa->typelib.count)
7034
7186
  {
7035
7187
    pa->typelib.count=0;
7036
 
    free((char*) pa->typelib.type_names);
 
7188
    my_free((char*) pa->typelib.type_names,MYF(0));
7037
7189
    pa->typelib.type_names=0;
7038
 
    free(pa->str);
 
7190
    my_free(pa->str,MYF(0));
7039
7191
  }
7040
7192
} /* free_pointer_array */
7041
7193
 
7043
7195
/* Functions that uses replace and replace_regex */
7044
7196
 
7045
7197
/* Append the string to ds, with optional replace */
7046
 
void replace_append_mem(string *ds,
7047
 
                        const char *val, int len)
 
7198
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
 
7199
                               const char *val, int len)
7048
7200
{
7049
 
  char *v= strdup(val);
7050
 
 
7051
7201
  if (glob_replace_regex)
7052
7202
  {
7053
7203
    /* Regex replace */
7054
 
    if (!multi_reg_replace(glob_replace_regex, v))
 
7204
    if (!multi_reg_replace(glob_replace_regex, (char*)val))
7055
7205
    {
7056
 
      v= glob_replace_regex->buf;
7057
 
      len= strlen(v);
 
7206
      val= glob_replace_regex->buf;
 
7207
      len= strlen(val);
7058
7208
    }
7059
7209
  }
7060
7210
 
7061
7211
  if (glob_replace)
7062
7212
  {
7063
7213
    /* Normal replace */
7064
 
    replace_strings_append(glob_replace, ds, v, len);
 
7214
    replace_strings_append(glob_replace, ds, val, len);
7065
7215
  }
7066
7216
  else
7067
 
  {
7068
 
    ds->append(v, len);
7069
 
  }
 
7217
    dynstr_append_mem(ds, val, len);
7070
7218
}
7071
7219
 
7072
7220
 
7073
7221
/* Append zero-terminated string to ds, with optional replace */
7074
 
void replace_append(string *ds, const char *val)
 
7222
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7075
7223
{
7076
 
  replace_append_mem(ds, val, strlen(val));
 
7224
  replace_dynstr_append_mem(ds, val, strlen(val));
7077
7225
}
7078
7226
 
7079
7227
/* Append uint to ds, with optional replace */
7080
 
void replace_append_uint(string *ds, uint val)
 
7228
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7081
7229
{
7082
7230
  char buff[22]; /* This should be enough for any int */
7083
7231
  char *end= int64_t10_to_str(val, buff, 10);
7084
 
  replace_append_mem(ds, buff, end - buff);
7085
 
 
 
7232
  replace_dynstr_append_mem(ds, buff, end - buff);
7086
7233
}
7087
7234
 
7088
7235
 
7099
7246
 
7100
7247
*/
7101
7248
 
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())
 
7249
static int comp_lines(const char **a, const char **b)
 
7250
{
 
7251
  return (strcmp(*a,*b));
 
7252
}
 
7253
 
 
7254
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
 
7255
{
 
7256
  unsigned i;
 
7257
  char *start= ds_input->str;
 
7258
  DYNAMIC_ARRAY lines;
 
7259
 
 
7260
 
 
7261
  if (!*start)
7108
7262
    return;  /* No input */
7109
7263
 
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;
 
7264
  my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
 
7265
 
 
7266
  /* First line is result header, skip past it */
 
7267
  while (*start && *start != '\n')
 
7268
    start++;
 
7269
  start++; /* Skip past \n */
 
7270
  dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
7119
7271
 
7120
7272
  /* Insert line(s) in array */
7121
 
  do {
 
7273
  while (*start)
 
7274
  {
 
7275
    char* line_end= (char*)start;
7122
7276
 
7123
 
    eol_pos= ds_input->find_first_of('\n', start_pos);
7124
7277
    /* 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);
 
7278
    while (*line_end && *line_end != '\n')
 
7279
      line_end++;
 
7280
    *line_end= 0;
 
7281
 
 
7282
    /* Insert pointer to the line in array */
 
7283
    if (insert_dynamic(&lines, (uchar*) &start))
 
7284
      die("Out of memory inserting lines to sort");
 
7285
 
 
7286
    start= line_end+1;
 
7287
  }
 
7288
 
 
7289
  /* Sort array */
 
7290
  qsort(lines.buffer, lines.elements,
 
7291
        sizeof(char**), (qsort_cmp)comp_lines);
7129
7292
 
7130
7293
  /* Create new result */
7131
 
  while (!lines.empty()) {
7132
 
    ds->append(lines.top());
7133
 
    lines.pop();
 
7294
  for (i= 0; i < lines.elements ; i++)
 
7295
  {
 
7296
    const char **line= dynamic_element(&lines, i, const char**);
 
7297
    dynstr_append(ds, *line);
 
7298
    dynstr_append(ds, "\n");
7134
7299
  }
7135
7300
 
 
7301
  delete_dynamic(&lines);
7136
7302
  return;
7137
7303
}