~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

Merging stdize-code with main trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 */
 
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
 */
15
20
 
16
21
/*
17
22
  drizzletest
32
37
*/
33
38
 
34
39
#define MTEST_VERSION "3.3"
 
40
 
 
41
#include <queue>
 
42
#include <map>
 
43
#include <string>
 
44
 
35
45
#include <pcrecpp.h>
36
46
 
37
47
#include "client_priv.h"
41
51
 
42
52
#include "errname.h"
43
53
 
 
54
using namespace std;
 
55
 
44
56
#define MAX_VAR_NAME_LENGTH    256
45
57
#define MAX_COLUMNS            256
46
58
#define MAX_EMBEDDED_SERVER_ARGS 64
51
63
#define QUERY_REAP_FLAG  2
52
64
 
53
65
enum {
54
 
  OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
55
66
  OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
56
67
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
57
68
};
121
132
static struct st_test_file* file_stack_end;
122
133
 
123
134
 
124
 
static const CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
 
135
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
125
136
 
126
137
static int embedded_server_arg_count=0;
127
138
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
137
148
 
138
149
static uint64_t progress_start= 0;
139
150
 
140
 
DYNAMIC_ARRAY q_lines;
 
151
vector<struct st_command*> q_lines;
141
152
 
142
153
typedef struct {
143
154
  int read_lines,current_line;
297
308
  "copy_file",
298
309
  "perl",
299
310
  "die",
300
 
              
 
311
 
301
312
  /* Don't execute any more commands, compare result */
302
313
  "exit",
303
314
  "skip",
356
367
};
357
368
 
358
369
TYPELIB command_typelib= {array_elements(command_names),"",
359
 
        command_names, 0};
 
370
                          command_names, 0};
360
371
 
361
 
DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
 
372
string ds_res, ds_progress, ds_warning_messages;
362
373
 
363
374
char builtin_echo[FN_REFLEN];
364
375
 
382
393
void eval_expr(VAR* v, const char *p, const char** p_end);
383
394
bool match_delimiter(int c, const char *delim, uint length);
384
395
void dump_result_to_reject_file(char *buf, int size);
385
 
void dump_result_to_log_file(char *buf, int size);
 
396
void dump_result_to_log_file(const char *buf, int size);
386
397
void dump_warning_messages(void);
387
398
void dump_progress(void);
388
399
 
389
 
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
 
400
void do_eval(string *query_eval, const char *query,
390
401
             const char *query_end, bool pass_through_escape_chars);
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);
 
402
void str_to_file(const char *fname, const char *str, int size);
 
403
void str_to_file2(const char *fname, const char *str, int size, bool append);
393
404
 
394
405
/* For replace_column */
395
406
static char *replace_column[MAX_COLUMNS];
415
426
  free_replace_column();
416
427
}
417
428
 
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);
 
429
void replace_append_mem(string *ds, const char *val,
 
430
                        int len);
 
431
void replace_append(string *ds, const char *val);
 
432
void replace_append_uint(string *ds, uint val);
 
433
void append_sorted(string* ds, string* ds_input);
423
434
 
424
435
void handle_error(struct st_command*,
425
436
                  unsigned int err_errno, const char *err_error,
426
 
                  const char *err_sqlstate, DYNAMIC_STRING *ds);
 
437
                  const char *err_sqlstate, string *ds);
427
438
void handle_no_error(struct st_command*);
428
439
 
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*/
490
440
 
491
441
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
492
442
 
493
 
#endif /*EMBEDDED_LIBRARY*/
494
 
 
495
 
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
 
443
void do_eval(string *query_eval, const char *query,
496
444
             const char *query_end, bool pass_through_escape_chars)
497
445
{
498
446
  const char *p;
507
455
    case '$':
508
456
      if (escaped)
509
457
      {
510
 
  escaped= 0;
511
 
  dynstr_append_mem(query_eval, p, 1);
 
458
        escaped= 0;
 
459
        query_eval->append(p, 1);
512
460
      }
513
461
      else
514
462
      {
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);
 
463
        if (!(v= var_get(p, &p, 0, 0)))
 
464
          die("Bad variable in eval");
 
465
        query_eval->append(v->str_val, v->str_val_len);
518
466
      }
519
467
      break;
520
468
    case '\\':
521
469
      next_c= *(p+1);
522
470
      if (escaped)
523
471
      {
524
 
  escaped= 0;
525
 
  dynstr_append_mem(query_eval, p, 1);
 
472
        escaped= 0;
 
473
        query_eval->append(p, 1);
526
474
      }
527
475
      else if (next_c == '\\' || next_c == '$' || next_c == '"')
528
476
      {
529
477
        /* Set escaped only if next char is \, " or $ */
530
 
  escaped= 1;
 
478
        escaped= 1;
531
479
 
532
480
        if (pass_through_escape_chars)
533
481
        {
534
482
          /* The escape char should be added to the output string. */
535
 
          dynstr_append_mem(query_eval, p, 1);
 
483
          query_eval->append(p, 1);
536
484
        }
537
485
      }
538
486
      else
539
 
  dynstr_append_mem(query_eval, p, 1);
 
487
        query_eval->append(p, 1);
540
488
      break;
541
489
    default:
542
490
      escaped= 0;
543
 
      dynstr_append_mem(query_eval, p, 1);
 
491
      query_eval->append(p, 1);
544
492
      break;
545
493
    }
546
494
  }
549
497
 
550
498
 
551
499
/*
 
500
  Concatenates any number of strings, escapes any OS quote in the result then
 
501
  surround the whole affair in another set of quotes which is finally appended
 
502
  to specified string.  This function is especially useful when
 
503
  building strings to be executed with the system() function.
 
504
 
 
505
  @param str string which will have addtional strings appended.
 
506
  @param append string to be appended.
 
507
  @param ... Optional. Additional string(s) to be appended.
 
508
 
 
509
  @note The final argument in the list must be NullS even if no additional
 
510
  options are passed.
 
511
*/
 
512
 
 
513
void append_os_quoted(string *str, const char *append, ...)
 
514
{
 
515
  const char *quote_str= "\'";
 
516
  const uint  quote_len= 1;
 
517
 
 
518
  va_list dirty_text;
 
519
 
 
520
  str->append(quote_str, quote_len); /* Leading quote */
 
521
  va_start(dirty_text, append);
 
522
  while (append != NullS)
 
523
  {
 
524
    const char  *cur_pos= append;
 
525
    const char *next_pos= cur_pos;
 
526
 
 
527
    /* Search for quote in each string and replace with escaped quote */
 
528
    while((next_pos= strrchr(cur_pos, quote_str[0])) != NULL)
 
529
    {
 
530
      str->append(cur_pos, next_pos - cur_pos);
 
531
      str->append("\\", 1);
 
532
      str->append(quote_str, quote_len);
 
533
      cur_pos= next_pos + 1;
 
534
    }
 
535
    str->append(cur_pos, next_pos - cur_pos);
 
536
    append= va_arg(dirty_text, char *);
 
537
  }
 
538
  va_end(dirty_text);
 
539
  str->append(quote_str, quote_len); /* Trailing quote */
 
540
}
 
541
 
 
542
 
 
543
/*
552
544
  Run query and dump the result to stdout in vertical format
553
545
 
554
546
  NOTE! This function should be safe to call when an error
694
686
  const char *argname;       /* Name of argument   */
695
687
  enum arg_type type;        /* Type of argument   */
696
688
  bool required;          /* Argument required  */
697
 
  DYNAMIC_STRING *ds;        /* Storage for argument */
 
689
  string *ds;        /* Storage for argument */
698
690
  const char *description;   /* Description of the argument */
699
691
};
700
692
 
724
716
        ptr++;
725
717
      if (ptr > start)
726
718
      {
727
 
        init_dynamic_string(arg->ds, 0, ptr-start, 32);
728
719
        do_eval(arg->ds, start, ptr, false);
729
720
      }
730
721
      else
731
722
      {
732
723
        /* Empty string */
733
 
        init_dynamic_string(arg->ds, "", 0, 0);
 
724
        arg->ds->erase();
734
725
      }
735
726
      command->last_argument= (char*)ptr;
736
727
 
742
733
      /* Rest of line */
743
734
    case ARG_REST:
744
735
      start= ptr;
745
 
      init_dynamic_string(arg->ds, 0, command->query_len, 256);
746
736
      do_eval(arg->ds, start, command->end, false);
747
737
      command->last_argument= command->end;
748
738
      break;
753
743
    }
754
744
 
755
745
    /* Check required arg */
756
 
    if (arg->ds->length == 0 && arg->required)
 
746
    if (arg->ds->length() == 0 && arg->required)
757
747
      die("Missing required argument '%s' to command '%.*s'", arg->argname,
758
748
          command->first_word_len, command->query);
759
749
 
843
833
  close_files();
844
834
  hash_free(&var_hash);
845
835
 
846
 
  for (i= 0 ; i < q_lines.elements ; i++)
 
836
  vector<struct st_command *>::iterator iter;
 
837
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
847
838
  {
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));
 
839
    struct st_command * q_line= *(iter.base());
 
840
    if (q_line->query_buf != NULL)
 
841
    {
 
842
      free(q_line->query_buf);
 
843
    }
 
844
    free(q_line);
851
845
  }
 
846
 
852
847
  for (i= 0; i < 10; i++)
853
848
  {
854
849
    if (var_reg[i].alloced_len)
856
851
  }
857
852
  while (embedded_server_arg_count > 1)
858
853
    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);
 
854
 
863
855
  free_all_replace();
864
856
  my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
865
857
  free_defaults(default_argv);
887
879
      break;
888
880
    case 62:
889
881
      printf("skipped\n");
890
 
    break;
 
882
      break;
891
883
    default:
892
884
      printf("unknown exit code: %d\n", exit_code);
893
885
      assert(0);
930
922
  fflush(stderr);
931
923
 
932
924
  /* Show results from queries just before failure */
933
 
  if (ds_res.length && opt_tail_lines)
 
925
  if (ds_res.length() && opt_tail_lines)
934
926
  {
935
927
    int tail_lines= opt_tail_lines;
936
 
    char* show_from= ds_res.str + ds_res.length - 1;
937
 
    while(show_from > ds_res.str && tail_lines > 0 )
 
928
    const char* show_from= ds_res.c_str() + ds_res.length() - 1;
 
929
    while(show_from > ds_res.c_str() && tail_lines > 0 )
938
930
    {
939
931
      show_from--;
940
932
      if (*show_from == '\n')
941
933
        tail_lines--;
942
934
    }
943
935
    fprintf(stderr, "\nThe result from queries just before the failure was:\n");
944
 
    if (show_from > ds_res.str)
 
936
    if (show_from > ds_res.c_str())
945
937
      fprintf(stderr, "< snip >");
946
938
    fprintf(stderr, "%s", show_from);
947
939
    fflush(stderr);
948
940
  }
949
941
 
950
942
  /* Dump the result that has been accumulated so far to .log file */
951
 
  if (result_file_name && ds_res.length)
952
 
    dump_result_to_log_file(ds_res.str, ds_res.length);
 
943
  if (result_file_name && ds_res.length())
 
944
    dump_result_to_log_file(ds_res.c_str(), ds_res.length());
953
945
 
954
946
  /* Dump warning messages */
955
 
  if (result_file_name && ds_warning_messages.length)
 
947
  if (result_file_name && ds_warning_messages.length())
956
948
    dump_warning_messages();
957
949
 
958
950
  /*
1029
1021
 
1030
1022
 
1031
1023
  va_start(args, fmt);
1032
 
  dynstr_append(&ds_warning_messages, "drizzletest: ");
 
1024
  ds_warning_messages.append("drizzletest: ");
1033
1025
  if (start_lineno != 0)
1034
1026
  {
1035
 
    dynstr_append(&ds_warning_messages, "Warning detected ");
 
1027
    ds_warning_messages.append("Warning detected ");
1036
1028
    if (cur_file && cur_file != file_stack)
1037
1029
    {
1038
1030
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1039
 
                       cur_file->file_name);
1040
 
      dynstr_append_mem(&ds_warning_messages,
1041
 
                        buff, len);
 
1031
                    cur_file->file_name);
 
1032
      ds_warning_messages.append(buff, len);
1042
1033
    }
1043
1034
    len= snprintf(buff, sizeof(buff), "at line %d: ",
1044
 
                     start_lineno);
1045
 
    dynstr_append_mem(&ds_warning_messages,
1046
 
                      buff, len);
 
1035
                  start_lineno);
 
1036
    ds_warning_messages.append(buff, len);
1047
1037
  }
1048
1038
 
1049
1039
  len= vsnprintf(buff, sizeof(buff), fmt, args);
1050
 
  dynstr_append_mem(&ds_warning_messages, buff, len);
 
1040
  ds_warning_messages.append(buff, len);
1051
1041
 
1052
 
  dynstr_append(&ds_warning_messages, "\n");
 
1042
  ds_warning_messages.append("\n");
1053
1043
  va_end(args);
1054
1044
 
1055
1045
  return;
1067
1057
  len= vsnprintf(buff, sizeof(buff)-1, fmt, args);
1068
1058
  va_end(args);
1069
1059
 
1070
 
  dynstr_append_mem(&ds_res, buff, len);
1071
 
  dynstr_append(&ds_res, "\n");
 
1060
  ds_res.append(buff, len);
 
1061
  ds_res.append("\n");
1072
1062
 
1073
1063
  return;
1074
1064
}
1084
1074
 
1085
1075
*/
1086
1076
 
1087
 
static void cat_file(DYNAMIC_STRING* ds, const char* filename)
 
1077
static void cat_file(string* ds, const char* filename)
1088
1078
{
1089
1079
  int fd;
1090
1080
  uint len;
1104
1094
        /* Add fake newline instead of cr and output the line */
1105
1095
        *p= '\n';
1106
1096
        p++; /* Step past the "fake" newline */
1107
 
        dynstr_append_mem(ds, start, p-start);
 
1097
        ds->append(start, p-start);
1108
1098
        p++; /* Step past the "fake" newline */
1109
1099
        start= p;
1110
1100
      }
1111
1101
      else
1112
1102
        p++;
1113
1103
    }
1114
 
    /* Output any chars that migh be left */
1115
 
    dynstr_append_mem(ds, start, p-start);
 
1104
    /* Output any chars that might be left */
 
1105
    ds->append(start, p-start);
1116
1106
  }
1117
1107
  my_close(fd, MYF(0));
1118
1108
}
1124
1114
  SYNOPSIS
1125
1115
  run_command
1126
1116
  cmd - command to execute(should be properly quoted
1127
 
  ds_res- pointer to dynamic string where to store the result
 
1117
  result - pointer to string where to store the result
1128
1118
 
1129
1119
*/
1130
1120
 
1131
 
static int run_command(char* cmd,
1132
 
                       DYNAMIC_STRING *ds_res)
 
1121
static int run_command(const char * cmd, string * result)
1133
1122
{
 
1123
  assert(result!=NULL);
1134
1124
  char buf[512]= {0};
1135
1125
  FILE *res_file;
1136
1126
  int error;
1140
1130
 
1141
1131
  while (fgets(buf, sizeof(buf), res_file))
1142
1132
  {
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
    /* Save the output of this command in the supplied string */
 
1134
    result->append(buf);
1153
1135
  }
1154
1136
 
1155
1137
  error= pclose(res_file);
1163
1145
  SYNOPSIS
1164
1146
  run_tool
1165
1147
  tool_path - the name of the tool to run
1166
 
  ds_res - pointer to dynamic string where to store the result
 
1148
  result - pointer to dynamic string where to store the result
1167
1149
  ... - variable number of arguments that will be properly
1168
 
        quoted and appended after the tool's name
 
1150
  quoted and appended after the tool's name
1169
1151
 
1170
1152
*/
1171
1153
 
1172
 
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
 
1154
static int run_tool(const char *tool_path, string * result, ...)
1173
1155
{
1174
1156
  int ret;
1175
1157
  const char* arg;
1176
1158
  va_list args;
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);
 
1159
  string ds_cmdline;
 
1160
 
 
1161
 
 
1162
  append_os_quoted(&ds_cmdline, tool_path);
 
1163
  ds_cmdline.append(" ");
 
1164
 
 
1165
  va_start(args, result);
1186
1166
 
1187
1167
  while ((arg= va_arg(args, char *)))
1188
1168
  {
1189
1169
    /* Options should be os quoted */
1190
1170
    if (strncmp(arg, "--", 2) == 0)
1191
 
      dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
 
1171
      append_os_quoted(&ds_cmdline, arg, NullS);
1192
1172
    else
1193
 
      dynstr_append(&ds_cmdline, arg);
1194
 
    dynstr_append(&ds_cmdline, " ");
 
1173
      ds_cmdline.append(arg);
 
1174
    ds_cmdline.append(" ");
1195
1175
  }
1196
1176
 
1197
1177
  va_end(args);
1198
1178
 
1199
 
  ret= run_command(ds_cmdline.str, ds_res);
1200
 
  dynstr_free(&ds_cmdline);
 
1179
  ret= run_command(ds_cmdline.c_str(), result);
1201
1180
  return(ret);
1202
1181
}
1203
1182
 
1215
1194
 
1216
1195
*/
1217
1196
 
1218
 
static void show_diff(DYNAMIC_STRING* ds,
 
1197
static void show_diff(string* ds,
1219
1198
                      const char* filename1, const char* filename2)
1220
1199
{
1221
1200
 
1222
 
  DYNAMIC_STRING ds_tmp;
1223
 
 
1224
 
  if (init_dynamic_string(&ds_tmp, "", 256, 256))
1225
 
    die("Out of memory");
 
1201
  string ds_tmp;
1226
1202
 
1227
1203
  /* First try with unified diff */
1228
1204
  if (run_tool("diff",
1233
1209
               "2>&1",
1234
1210
               NULL) > 1) /* Most "diff" tools return >1 if error */
1235
1211
  {
1236
 
    dynstr_set(&ds_tmp, "");
 
1212
    ds_tmp= "";
1237
1213
 
1238
1214
    /* Fallback to context diff with "diff -c" */
1239
1215
    if (run_tool("diff",
1248
1224
        Fallback to dump both files to result file and inform
1249
1225
        about installing "diff"
1250
1226
      */
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");
 
1227
      ds_tmp= "";
 
1228
 
 
1229
      ds_tmp.append(
 
1230
                    "\n"
 
1231
                    "The two files differ but it was not possible to execute 'diff' in\n"
 
1232
                    "order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
 
1233
                    "Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
 
1234
                    "To get a better report you should install 'diff' on your system, which you\n"
 
1235
                    "for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
 
1236
                    "\n");
 
1237
 
 
1238
      ds_tmp.append(" --- ");
 
1239
      ds_tmp.append(filename1);
 
1240
      ds_tmp.append(" >>>\n");
1265
1241
      cat_file(&ds_tmp, filename1);
1266
 
      dynstr_append(&ds_tmp, "<<<\n --- ");
1267
 
      dynstr_append(&ds_tmp, filename1);
1268
 
      dynstr_append(&ds_tmp, " >>>\n");
 
1242
      ds_tmp.append("<<<\n --- ");
 
1243
      ds_tmp.append(filename1);
 
1244
      ds_tmp.append(" >>>\n");
1269
1245
      cat_file(&ds_tmp, filename2);
1270
 
      dynstr_append(&ds_tmp, "<<<<\n");
 
1246
      ds_tmp.append("<<<<\n");
1271
1247
    }
1272
1248
  }
1273
1249
 
1274
1250
  if (ds)
1275
1251
  {
1276
1252
    /* Add the diff to output */
1277
 
    dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
 
1253
    ds->append(ds_tmp.c_str(), ds_tmp.length());
1278
1254
  }
1279
1255
  else
1280
1256
  {
1281
1257
    /* Print diff directly to stdout */
1282
 
    fprintf(stderr, "%s\n", ds_tmp.str);
 
1258
    fprintf(stderr, "%s\n", ds_tmp.c_str());
1283
1259
  }
1284
1260
 
1285
 
  dynstr_free(&ds_tmp);
1286
 
 
1287
1261
}
1288
1262
 
1289
1263
 
1290
1264
enum compare_files_result_enum {
1291
 
   RESULT_OK= 0,
1292
 
   RESULT_CONTENT_MISMATCH= 1,
1293
 
   RESULT_LENGTH_MISMATCH= 2
 
1265
  RESULT_OK= 0,
 
1266
  RESULT_CONTENT_MISMATCH= 1,
 
1267
  RESULT_LENGTH_MISMATCH= 2
1294
1268
};
1295
1269
 
1296
1270
/*
1388
1362
  Compare content of the string in ds to content of file fname
1389
1363
 
1390
1364
  SYNOPSIS
1391
 
  dyn_string_cmp
 
1365
  string_cmp
1392
1366
  ds - Dynamic string containing the string o be compared
1393
1367
  fname - Name of file to compare with
1394
1368
 
1396
1370
  See 'compare_files2'
1397
1371
*/
1398
1372
 
1399
 
static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
 
1373
static int string_cmp(string* ds, const char *fname)
1400
1374
{
1401
1375
  int error;
1402
1376
  File fd;
1408
1382
    die("Failed to create temporary file for ds");
1409
1383
 
1410
1384
  /* Write ds to temporary file and set file pos to beginning*/
1411
 
  if (my_write(fd, (uchar *) ds->str, ds->length,
 
1385
  if (my_write(fd, (uchar *) ds->c_str(), ds->length(),
1412
1386
               MYF(MY_FNABP | MY_WME)) ||
1413
1387
      my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1414
1388
  {
1440
1414
 
1441
1415
*/
1442
1416
 
1443
 
static void check_result(DYNAMIC_STRING* ds)
 
1417
static void check_result(string* ds)
1444
1418
{
1445
1419
  const char* mess= "Result content mismatch\n";
1446
1420
 
1450
1424
  if (access(result_file_name, F_OK) != 0)
1451
1425
    die("The specified result file does not exist: '%s'", result_file_name);
1452
1426
 
1453
 
  switch (dyn_string_cmp(ds, result_file_name)) {
 
1427
  switch (string_cmp(ds, result_file_name)) {
1454
1428
  case RESULT_OK:
1455
1429
    break; /* ok */
1456
1430
  case RESULT_LENGTH_MISMATCH:
1478
1452
      fn_format(reject_file, result_file_name, opt_logdir,
1479
1453
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1480
1454
    }
1481
 
    str_to_file(reject_file, ds->str, ds->length);
 
1455
    str_to_file(reject_file, ds->c_str(), ds->length());
1482
1456
 
1483
 
    dynstr_set(ds, NULL); /* Don't create a .log file */
 
1457
    ds->erase(); /* Don't create a .log file */
1484
1458
 
1485
1459
    show_diff(NULL, result_file_name, reject_file);
1486
1460
    die(mess);
1509
1483
 
1510
1484
*/
1511
1485
 
1512
 
static void check_require(DYNAMIC_STRING* ds, const char *fname)
 
1486
static void check_require(string* ds, const char *fname)
1513
1487
{
1514
1488
 
1515
1489
 
1516
 
  if (dyn_string_cmp(ds, fname))
 
1490
  if (string_cmp(ds, fname))
1517
1491
  {
1518
1492
    char reason[FN_REFLEN];
1519
1493
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1524
1498
 
1525
1499
 
1526
1500
/*
1527
 
   Remove surrounding chars from string
 
1501
  Remove surrounding chars from string
1528
1502
 
1529
 
   Return 1 if first character is found but not last
 
1503
  Return 1 if first character is found but not last
1530
1504
*/
1531
1505
static int strip_surrounding(char* str, char c1, char c2)
1532
1506
{
1541
1515
    *ptr= ' ';
1542
1516
 
1543
1517
    /* Last non space charecter should be c2 */
1544
 
    ptr= strend(str)-1;
 
1518
    ptr= strchr(str, '\0')-1;
1545
1519
    while(*ptr && my_isspace(charset_info, *ptr))
1546
1520
      ptr--;
1547
1521
    if (*ptr == c2)
1562
1536
static void strip_parentheses(struct st_command *command)
1563
1537
{
1564
1538
  if (strip_surrounding(command->first_argument, '(', ')'))
1565
 
      die("%.*s - argument list started with '%c' must be ended with '%c'",
1566
 
          command->first_word_len, command->query, '(', ')');
 
1539
    die("%.*s - argument list started with '%c' must be ended with '%c'",
 
1540
        command->first_word_len, command->query, '(', ')');
1567
1541
}
1568
1542
 
1569
1543
 
1636
1610
 
1637
1611
 
1638
1612
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1639
 
       bool ignore_not_existing)
 
1613
             bool ignore_not_existing)
1640
1614
{
1641
1615
  int digit;
1642
1616
  VAR *v;
1654
1628
    if (var_name == save_var_name)
1655
1629
    {
1656
1630
      if (ignore_not_existing)
1657
 
  return(0);
 
1631
        return(0);
1658
1632
      die("Empty variable");
1659
1633
    }
1660
1634
    length= (uint) (var_name - save_var_name);
1662
1636
      die("Too long variable name: %s", save_var_name);
1663
1637
 
1664
1638
    if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
1665
 
                                            length)))
 
1639
                                 length)))
1666
1640
    {
1667
1641
      char buff[MAX_VAR_NAME_LENGTH+1];
1668
1642
      strmake(buff, save_var_name, length);
1738
1712
      v->str_val_len= strlen(v->str_val);
1739
1713
    }
1740
1714
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
1741
 
                v->name_len, v->name,
1742
 
                v->str_val_len, v->str_val);
 
1715
             v->name_len, v->name,
 
1716
             v->str_val_len, v->str_val);
1743
1717
    if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
1744
1718
      die("Out of memory");
1745
1719
    putenv(v->env_s);
1810
1784
 
1811
1785
static void var_query_set(VAR *var, const char *query, const char** query_end)
1812
1786
{
1813
 
  char *end = (char*)((query_end && *query_end) ?
1814
 
          *query_end : query + strlen(query));
 
1787
  const char *end = (char*)((query_end && *query_end) ?
 
1788
                            *query_end : query + strlen(query));
1815
1789
  DRIZZLE_RES *res;
1816
1790
  DRIZZLE_ROW row;
1817
1791
  DRIZZLE *drizzle= &cur_con->drizzle;
1818
 
  DYNAMIC_STRING ds_query;
 
1792
  string ds_query;
1819
1793
 
1820
1794
 
1821
1795
  while (end > query && *end != '`')
1825
1799
  ++query;
1826
1800
 
1827
1801
  /* Eval the query, thus replacing all environment variables */
1828
 
  init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
1829
1802
  do_eval(&ds_query, query, end, false);
1830
1803
 
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));
 
1804
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
 
1805
    die("Error running query '%s': %d %s", ds_query.c_str(),
 
1806
        drizzle_errno(drizzle), drizzle_error(drizzle));
1834
1807
  if (!(res= drizzle_store_result(drizzle)))
1835
 
    die("Query '%s' didn't return a result set", ds_query.str);
1836
 
  dynstr_free(&ds_query);
 
1808
    die("Query '%s' didn't return a result set", ds_query.c_str());
1837
1809
 
1838
1810
  if ((row= drizzle_fetch_row(res)) && row[0])
1839
1811
  {
1841
1813
      Concatenate all fields in the first row with tab in between
1842
1814
      and assign that string to the $variable
1843
1815
    */
1844
 
    DYNAMIC_STRING result;
 
1816
    string result;
1845
1817
    uint32_t i;
1846
1818
    uint32_t *lengths;
1847
1819
 
1848
 
    init_dynamic_string(&result, "", 512, 512);
1849
1820
    lengths= drizzle_fetch_lengths(res);
1850
1821
    for (i= 0; i < drizzle_num_fields(res); i++)
1851
1822
    {
1852
1823
      if (row[i])
1853
1824
      {
1854
1825
        /* Add column to tab separated string */
1855
 
  dynstr_append_mem(&result, row[i], lengths[i]);
 
1826
        result.append(row[i], lengths[i]);
1856
1827
      }
1857
 
      dynstr_append_mem(&result, "\t", 1);
 
1828
      result.append("\t", 1);
1858
1829
    }
1859
 
    end= result.str + result.length-1;
1860
 
    eval_expr(var, result.str, (const char**) &end);
1861
 
    dynstr_free(&result);
 
1830
    end= result.c_str() + result.length()-1;
 
1831
    eval_expr(var, result.c_str(), (const char**) &end);
1862
1832
  }
1863
1833
  else
1864
1834
    eval_expr(var, "", 0);
1884
1854
 
1885
1855
  <query to run> -    The query that should be sent to the server
1886
1856
  <column name> -     Name of the column that holds the field be compared
1887
 
                      against the expected value
 
1857
  against the expected value
1888
1858
  <row no> -          Number of the row that holds the field to be
1889
 
                      compared against the expected value
 
1859
  compared against the expected value
1890
1860
 
1891
1861
*/
1892
1862
 
1897
1867
  DRIZZLE_RES* res;
1898
1868
  DRIZZLE *drizzle= &cur_con->drizzle;
1899
1869
 
1900
 
  static DYNAMIC_STRING ds_query;
1901
 
  static DYNAMIC_STRING ds_col;
1902
 
  static DYNAMIC_STRING ds_row;
 
1870
  string ds_query;
 
1871
  string ds_col;
 
1872
  string ds_row;
1903
1873
  const struct command_arg query_get_value_args[] = {
1904
1874
    {"query", ARG_STRING, true, &ds_query, "Query to run"},
1905
1875
    {"column name", ARG_STRING, true, &ds_col, "Name of column"},
1914
1884
                     ',');
1915
1885
 
1916
1886
  /* Convert row number to int */
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
  if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
 
1888
    die("Invalid row number: '%s'", ds_row.c_str());
1920
1889
 
1921
1890
  /* Remove any surrounding "'s from the query - if there is any */
1922
 
  if (strip_surrounding(ds_query.str, '"', '"'))
1923
 
    die("Mismatched \"'s around query '%s'", ds_query.str);
 
1891
  // (Don't get me started on this)
 
1892
  char * unstripped_query= strdup(ds_query.c_str());
 
1893
  if (strip_surrounding(unstripped_query, '"', '"'))
 
1894
    die("Mismatched \"'s around query '%s'", ds_query.c_str());
 
1895
  ds_query= unstripped_query;
1924
1896
 
1925
1897
  /* Run the query */
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));
 
1898
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
 
1899
    die("Error running query '%s': %d %s", ds_query.c_str(),
 
1900
        drizzle_errno(drizzle), drizzle_error(drizzle));
1929
1901
  if (!(res= drizzle_store_result(drizzle)))
1930
 
    die("Query '%s' didn't return a result set", ds_query.str);
 
1902
    die("Query '%s' didn't return a result set", ds_query.c_str());
1931
1903
 
1932
1904
  {
1933
1905
    /* Find column number from the given column name */
1937
1909
 
1938
1910
    for (i= 0; i < num_fields; i++)
1939
1911
    {
1940
 
      if (strcmp(fields[i].name, ds_col.str) == 0 &&
1941
 
          strlen(fields[i].name) == ds_col.length)
 
1912
      if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
 
1913
          strlen(fields[i].name) == ds_col.length())
1942
1914
      {
1943
1915
        col_no= i;
1944
1916
        break;
1948
1920
    {
1949
1921
      drizzle_free_result(res);
1950
1922
      die("Could not find column '%s' in the result of '%s'",
1951
 
          ds_col.str, ds_query.str);
 
1923
          ds_col.c_str(), ds_query.c_str());
1952
1924
    }
1953
1925
  }
1954
 
  dynstr_free(&ds_col);
1955
1926
 
1956
1927
  {
1957
1928
    /* Get the value */
1975
1946
    }
1976
1947
    eval_expr(var, value, 0);
1977
1948
  }
1978
 
  dynstr_free(&ds_query);
1979
1949
  drizzle_free_result(res);
1980
1950
 
1981
1951
  return;
2046
2016
        MIN_VAR_ALLOC : new_val_len + 1;
2047
2017
      if (!(v->str_val =
2048
2018
            v->str_val ? (char *)my_realloc(v->str_val, v->alloced_len+1,
2049
 
                                    MYF(MY_WME)) :
 
2019
                                            MYF(MY_WME)) :
2050
2020
            (char *)my_malloc(v->alloced_len+1, MYF(MY_WME))))
2051
2021
        die("Out of memory");
2052
2022
    }
2101
2071
 
2102
2072
static void do_source(struct st_command *command)
2103
2073
{
2104
 
  static DYNAMIC_STRING ds_filename;
 
2074
  string ds_filename;
2105
2075
  const struct command_arg source_args[] = {
2106
2076
    { "filename", ARG_STRING, true, &ds_filename, "File to source" }
2107
2077
  };
2119
2089
    ; /* Do nothing */
2120
2090
  else
2121
2091
  {
2122
 
    open_file(ds_filename.str);
 
2092
    open_file(ds_filename.c_str());
2123
2093
  }
2124
2094
 
2125
 
  dynstr_free(&ds_filename);
2126
2095
  return;
2127
2096
}
2128
2097
 
2129
2098
 
2130
 
static FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
2131
 
{
2132
 
  return popen(ds_cmd->str, mode);
2133
 
}
2134
 
 
2135
 
 
2136
2099
static void init_builtin_echo(void)
2137
2100
{
2138
2101
  builtin_echo[0]= 0;
2144
2107
  Replace a substring
2145
2108
 
2146
2109
  SYNOPSIS
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
 
2110
  replace
 
2111
  ds_str      The string to search and perform the replace in
 
2112
  search_str  The string to search for
 
2113
  search_len  Length of the string to search for
 
2114
  replace_str The string to replace with
 
2115
  replace_len Length of the string to replace with
2153
2116
 
2154
2117
  RETURN
2155
 
    0 String replaced
2156
 
    1 Could not find search_str in str
 
2118
  0 String replaced
 
2119
  1 Could not find search_str in str
2157
2120
*/
2158
2121
 
2159
 
static int replace(DYNAMIC_STRING *ds_str,
 
2122
static int replace(string *ds_str,
2160
2123
                   const char *search_str, uint32_t search_len,
2161
2124
                   const char *replace_str, uint32_t replace_len)
2162
2125
{
2163
 
  DYNAMIC_STRING ds_tmp;
2164
 
  const char *start= strstr(ds_str->str, search_str);
 
2126
  string ds_tmp;
 
2127
  const char *start= strstr(ds_str->c_str(), search_str);
2165
2128
  if (!start)
2166
2129
    return 1;
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);
 
2130
  ds_tmp.append(ds_str->c_str(), start - ds_str->c_str());
 
2131
  ds_tmp.append(replace_str, replace_len);
 
2132
  ds_tmp.append(start + search_len);
 
2133
  *ds_str= ds_tmp;
2174
2134
  return 0;
2175
2135
}
2176
2136
 
2202
2162
  char buf[512];
2203
2163
  FILE *res_file;
2204
2164
  char *cmd= command->first_argument;
2205
 
  DYNAMIC_STRING ds_cmd;
 
2165
  string ds_cmd;
2206
2166
 
2207
2167
  /* Skip leading space */
2208
2168
  while (*cmd && my_isspace(charset_info, *cmd))
2211
2171
    die("Missing argument in exec");
2212
2172
  command->last_argument= command->end;
2213
2173
 
2214
 
  init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
2215
2174
  /* Eval the command, thus replacing all environment variables */
2216
2175
  do_eval(&ds_cmd, cmd, command->end, !is_windows);
2217
2176
 
2222
2181
    replace(&ds_cmd, "echo", 4, builtin_echo, strlen(builtin_echo));
2223
2182
  }
2224
2183
 
2225
 
  if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
 
2184
  if (!(res_file= popen(ds_cmd.c_str(), "r")) && command->abort_on_error)
2226
2185
  {
2227
 
    dynstr_free(&ds_cmd);
2228
2186
    die("popen(\"%s\", \"r\") failed", command->first_argument);
2229
2187
  }
2230
2188
 
2236
2194
    }
2237
2195
    else
2238
2196
    {
2239
 
      replace_dynstr_append(&ds_res, buf);
 
2197
      replace_append(&ds_res, buf);
2240
2198
    }
2241
2199
  }
2242
2200
  error= pclose(res_file);
2248
2206
    if (command->abort_on_error)
2249
2207
    {
2250
2208
      log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
2251
 
              ds_cmd.str, error, status, errno);
2252
 
      dynstr_free(&ds_cmd);
 
2209
              ds_cmd.c_str(), error, status, errno);
2253
2210
      die("command \"%s\" failed", command->first_argument);
2254
2211
    }
2255
2212
 
2263
2220
    }
2264
2221
    if (!ok)
2265
2222
    {
2266
 
      dynstr_free(&ds_cmd);
2267
2223
      die("command \"%s\" failed with wrong error: %d",
2268
2224
          command->first_argument, status);
2269
2225
    }
2273
2229
  {
2274
2230
    /* Error code we wanted was != 0, i.e. not an expected success */
2275
2231
    log_msg("exec of '%s failed, error: %d, errno: %d",
2276
 
            ds_cmd.str, error, errno);
2277
 
    dynstr_free(&ds_cmd);
 
2232
            ds_cmd.c_str(), error, errno);
2278
2233
    die("command \"%s\" succeeded - should have failed with errno %d...",
2279
2234
        command->first_argument, command->expected_errors.err[0].code.errnum);
2280
2235
  }
2281
2236
 
2282
 
  dynstr_free(&ds_cmd);
2283
2237
  return;
2284
2238
}
2285
2239
 
2333
2287
 
2334
2288
 
2335
2289
/*
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
 
/*
2353
2290
  SYNOPSIS
2354
2291
  do_system
2355
2292
  command  called command
2364
2301
 
2365
2302
static void do_system(struct st_command *command)
2366
2303
{
2367
 
  DYNAMIC_STRING ds_cmd;
 
2304
  string ds_cmd;
2368
2305
 
2369
2306
 
2370
2307
  if (strlen(command->first_argument) == 0)
2371
2308
    die("Missing arguments to system, nothing to do!");
2372
2309
 
2373
 
  init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
2374
 
 
2375
2310
  /* Eval the system command, thus replacing all environment variables */
2376
2311
  do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2377
2312
 
2378
 
  if (my_system(&ds_cmd))
 
2313
  if (system(ds_cmd.c_str()))
2379
2314
  {
2380
2315
    if (command->abort_on_error)
2381
2316
      die("system command '%s' failed", command->first_argument);
2382
2317
 
2383
2318
    /* If ! abort_on_error, log message and continue */
2384
 
    dynstr_append(&ds_res, "system command '");
2385
 
    replace_dynstr_append(&ds_res, command->first_argument);
2386
 
    dynstr_append(&ds_res, "' failed\n");
 
2319
    ds_res.append("system command '");
 
2320
    replace_append(&ds_res, command->first_argument);
 
2321
    ds_res.append("' failed\n");
2387
2322
  }
2388
2323
 
2389
2324
  command->last_argument= command->end;
2390
 
  dynstr_free(&ds_cmd);
2391
2325
  return;
2392
2326
}
2393
2327
 
2405
2339
static void do_remove_file(struct st_command *command)
2406
2340
{
2407
2341
  int error;
2408
 
  static DYNAMIC_STRING ds_filename;
 
2342
  string ds_filename;
2409
2343
  const struct command_arg rm_args[] = {
2410
2344
    { "filename", ARG_STRING, true, &ds_filename, "File to delete" }
2411
2345
  };
2415
2349
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2416
2350
                     ' ');
2417
2351
 
2418
 
  error= my_delete(ds_filename.str, MYF(0)) != 0;
 
2352
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
2419
2353
  handle_command_error(command, error);
2420
 
  dynstr_free(&ds_filename);
2421
2354
  return;
2422
2355
}
2423
2356
 
2437
2370
static void do_copy_file(struct st_command *command)
2438
2371
{
2439
2372
  int error;
2440
 
  static DYNAMIC_STRING ds_from_file;
2441
 
  static DYNAMIC_STRING ds_to_file;
 
2373
  string ds_from_file;
 
2374
  string ds_to_file;
2442
2375
  const struct command_arg copy_file_args[] = {
2443
2376
    { "from_file", ARG_STRING, true, &ds_from_file, "Filename to copy from" },
2444
2377
    { "to_file", ARG_STRING, true, &ds_to_file, "Filename to copy to" }
2450
2383
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2451
2384
                     ' ');
2452
2385
 
2453
 
  error= (my_copy(ds_from_file.str, ds_to_file.str,
 
2386
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2454
2387
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2455
2388
  handle_command_error(command, error);
2456
 
  dynstr_free(&ds_from_file);
2457
 
  dynstr_free(&ds_to_file);
2458
2389
  return;
2459
2390
}
2460
2391
 
2473
2404
static void do_chmod_file(struct st_command *command)
2474
2405
{
2475
2406
  long mode= 0;
2476
 
  static DYNAMIC_STRING ds_mode;
2477
 
  static DYNAMIC_STRING ds_file;
 
2407
  string ds_mode;
 
2408
  string ds_file;
2478
2409
  const struct command_arg chmod_file_args[] = {
2479
2410
    { "mode", ARG_STRING, true, &ds_mode, "Mode of file(octal) ex. 0660"},
2480
2411
    { "filename", ARG_STRING, true, &ds_file, "Filename of file to modify" }
2487
2418
                     ' ');
2488
2419
 
2489
2420
  /* Parse what mode to set */
2490
 
  if (ds_mode.length != 4 ||
2491
 
      str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
 
2421
  if (ds_mode.length() != 4 ||
 
2422
      str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NullS)
2492
2423
    die("You must write a 4 digit octal number for mode");
2493
2424
 
2494
 
  handle_command_error(command, chmod(ds_file.str, mode));
2495
 
  dynstr_free(&ds_mode);
2496
 
  dynstr_free(&ds_file);
 
2425
  handle_command_error(command, chmod(ds_file.c_str(), mode));
2497
2426
  return;
2498
2427
}
2499
2428
 
2511
2440
static void do_file_exist(struct st_command *command)
2512
2441
{
2513
2442
  int error;
2514
 
  static DYNAMIC_STRING ds_filename;
 
2443
  string ds_filename;
2515
2444
  const struct command_arg file_exist_args[] = {
2516
2445
    { "filename", ARG_STRING, true, &ds_filename, "File to check if it exist" }
2517
2446
  };
2522
2451
                     sizeof(file_exist_args)/sizeof(struct command_arg),
2523
2452
                     ' ');
2524
2453
 
2525
 
  error= (access(ds_filename.str, F_OK) != 0);
 
2454
  error= (access(ds_filename.c_str(), F_OK) != 0);
2526
2455
  handle_command_error(command, error);
2527
 
  dynstr_free(&ds_filename);
2528
2456
  return;
2529
2457
}
2530
2458
 
2542
2470
static void do_mkdir(struct st_command *command)
2543
2471
{
2544
2472
  int error;
2545
 
  static DYNAMIC_STRING ds_dirname;
 
2473
  string ds_dirname;
2546
2474
  const struct command_arg mkdir_args[] = {
2547
2475
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
2548
2476
  };
2552
2480
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2553
2481
                     ' ');
2554
2482
 
2555
 
  error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
 
2483
  error= my_mkdir(ds_dirname.c_str(), 0777, MYF(0)) != 0;
2556
2484
  handle_command_error(command, error);
2557
 
  dynstr_free(&ds_dirname);
2558
2485
  return;
2559
2486
}
2560
2487
 
2571
2498
static void do_rmdir(struct st_command *command)
2572
2499
{
2573
2500
  int error;
2574
 
  static DYNAMIC_STRING ds_dirname;
 
2501
  string ds_dirname;
2575
2502
  const struct command_arg rmdir_args[] = {
2576
2503
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to remove"}
2577
2504
  };
2581
2508
                     rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
2582
2509
                     ' ');
2583
2510
 
2584
 
  error= rmdir(ds_dirname.str) != 0;
 
2511
  error= rmdir(ds_dirname.c_str()) != 0;
2585
2512
  handle_command_error(command, error);
2586
 
  dynstr_free(&ds_dirname);
2587
2513
  return;
2588
2514
}
2589
2515
 
2612
2538
}
2613
2539
 
2614
2540
 
2615
 
static void read_until_delimiter(DYNAMIC_STRING *ds,
2616
 
                                 DYNAMIC_STRING *ds_delimiter)
 
2541
static void read_until_delimiter(string *ds,
 
2542
                                 string *ds_delimiter)
2617
2543
{
2618
2544
  char c;
2619
2545
 
2620
 
  if (ds_delimiter->length > MAX_DELIMITER_LENGTH)
 
2546
  if (ds_delimiter->length() > MAX_DELIMITER_LENGTH)
2621
2547
    die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
2622
2548
 
2623
2549
  /* Read from file until delimiter is found */
2644
2570
 
2645
2571
    if (feof(cur_file->file))
2646
2572
      die("End of file encountered before '%s' delimiter was found",
2647
 
          ds_delimiter->str);
 
2573
          ds_delimiter->c_str());
2648
2574
 
2649
 
    if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
 
2575
    if (match_delimiter(c, ds_delimiter->c_str(), ds_delimiter->length()))
2650
2576
      break;
2651
2577
 
2652
 
    dynstr_append_mem(ds, (const char*)&c, 1);
 
2578
    ds->push_back(c);
2653
2579
  }
2654
2580
  return;
2655
2581
}
2657
2583
 
2658
2584
static void do_write_file_command(struct st_command *command, bool append)
2659
2585
{
2660
 
  static DYNAMIC_STRING ds_content;
2661
 
  static DYNAMIC_STRING ds_filename;
2662
 
  static DYNAMIC_STRING ds_delimiter;
 
2586
  string ds_content;
 
2587
  string ds_filename;
 
2588
  string ds_delimiter;
2663
2589
  const struct command_arg write_file_args[] = {
2664
2590
    { "filename", ARG_STRING, true, &ds_filename, "File to write to" },
2665
2591
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
2673
2599
                     ' ');
2674
2600
 
2675
2601
  /* If no delimiter was provided, use EOF */
2676
 
  if (ds_delimiter.length == 0)
2677
 
    dynstr_set(&ds_delimiter, "EOF");
 
2602
  if (ds_delimiter.length() == 0)
 
2603
    ds_delimiter= "EOF";
2678
2604
 
2679
 
  if (!append && access(ds_filename.str, F_OK) == 0)
 
2605
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
2680
2606
  {
2681
2607
    /* The file should not be overwritten */
2682
 
    die("File already exist: '%s'", ds_filename.str);
 
2608
    die("File already exist: '%s'", ds_filename.c_str());
2683
2609
  }
2684
2610
 
2685
 
  init_dynamic_string(&ds_content, "", 1024, 1024);
2686
2611
  read_until_delimiter(&ds_content, &ds_delimiter);
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
  str_to_file2(ds_filename.c_str(), ds_content.c_str(),
 
2613
               ds_content.length(), append);
2691
2614
  return;
2692
2615
}
2693
2616
 
2770
2693
 
2771
2694
static void do_cat_file(struct st_command *command)
2772
2695
{
2773
 
  static DYNAMIC_STRING ds_filename;
 
2696
  static string ds_filename;
2774
2697
  const struct command_arg cat_file_args[] = {
2775
2698
    { "filename", ARG_STRING, true, &ds_filename, "File to read from" }
2776
2699
  };
2782
2705
                     sizeof(cat_file_args)/sizeof(struct command_arg),
2783
2706
                     ' ');
2784
2707
 
2785
 
  cat_file(&ds_res, ds_filename.str);
 
2708
  cat_file(&ds_res, ds_filename.c_str());
2786
2709
 
2787
 
  dynstr_free(&ds_filename);
2788
2710
  return;
2789
2711
}
2790
2712
 
2804
2726
static void do_diff_files(struct st_command *command)
2805
2727
{
2806
2728
  int error= 0;
2807
 
  static DYNAMIC_STRING ds_filename;
2808
 
  static DYNAMIC_STRING ds_filename2;
 
2729
  string ds_filename;
 
2730
  string ds_filename2;
2809
2731
  const struct command_arg diff_file_args[] = {
2810
2732
    { "file1", ARG_STRING, true, &ds_filename, "First file to diff" },
2811
2733
    { "file2", ARG_STRING, true, &ds_filename2, "Second file to diff" }
2818
2740
                     sizeof(diff_file_args)/sizeof(struct command_arg),
2819
2741
                     ' ');
2820
2742
 
2821
 
  if ((error= compare_files(ds_filename.str, ds_filename2.str)))
 
2743
  if ((error= compare_files(ds_filename.c_str(), ds_filename2.c_str())))
2822
2744
  {
2823
2745
    /* Compare of the two files failed, append them to output
2824
2746
       so the failure can be analyzed
2825
2747
    */
2826
 
    show_diff(&ds_res, ds_filename.str, ds_filename2.str);
 
2748
    show_diff(&ds_res, ds_filename.c_str(), ds_filename2.c_str());
2827
2749
  }
2828
2750
 
2829
 
  dynstr_free(&ds_filename);
2830
 
  dynstr_free(&ds_filename2);
2831
2751
  handle_command_error(command, error);
2832
2752
  return;
2833
2753
}
2901
2821
{
2902
2822
  DRIZZLE *drizzle= &cur_con->drizzle;
2903
2823
  /* static keyword to make the NetWare compiler happy. */
2904
 
  static DYNAMIC_STRING ds_user, ds_passwd, ds_db;
 
2824
  string ds_user, ds_passwd, ds_db;
2905
2825
  const struct command_arg change_user_args[] = {
2906
2826
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
2907
2827
    { "password", ARG_STRING, false, &ds_passwd, "Password used when connecting" },
2915
2835
                     sizeof(change_user_args)/sizeof(struct command_arg),
2916
2836
                     ',');
2917
2837
 
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))
 
2838
  if (!ds_user.length())
 
2839
    ds_user= drizzle->user;
 
2840
 
 
2841
  if (!ds_passwd.length())
 
2842
    ds_passwd= drizzle->passwd;
 
2843
 
 
2844
  if (!ds_db.length())
 
2845
    ds_db= drizzle->db;
 
2846
 
 
2847
  if (drizzle_change_user(drizzle, ds_user.c_str(),
 
2848
                          ds_passwd.c_str(), ds_db.c_str()))
2928
2849
    die("change user failed: %s", drizzle_error(drizzle));
2929
2850
 
2930
 
  dynstr_free(&ds_user);
2931
 
  dynstr_free(&ds_passwd);
2932
 
  dynstr_free(&ds_db);
2933
2851
 
2934
2852
  return;
2935
2853
}
2961
2879
  FILE *res_file;
2962
2880
  char buf[FN_REFLEN];
2963
2881
  char temp_file_path[FN_REFLEN];
2964
 
  static DYNAMIC_STRING ds_script;
2965
 
  static DYNAMIC_STRING ds_delimiter;
 
2882
  string ds_script;
 
2883
  string ds_delimiter;
2966
2884
  const struct command_arg perl_args[] = {
2967
2885
    { "delimiter", ARG_STRING, false, &ds_delimiter, "Delimiter to read until" }
2968
2886
  };
2975
2893
                     ' ');
2976
2894
 
2977
2895
  /* If no delimiter was provided, use EOF */
2978
 
  if (ds_delimiter.length == 0)
2979
 
    dynstr_set(&ds_delimiter, "EOF");
 
2896
  if (ds_delimiter.length() == 0)
 
2897
    ds_delimiter= "EOF";
2980
2898
 
2981
 
  init_dynamic_string(&ds_script, "", 1024, 1024);
2982
2899
  read_until_delimiter(&ds_script, &ds_delimiter);
2983
2900
 
2984
2901
  /* Create temporary file name */
2988
2905
    die("Failed to create temporary file for perl command");
2989
2906
  my_close(fd, MYF(0));
2990
2907
 
2991
 
  str_to_file(temp_file_path, ds_script.str, ds_script.length);
 
2908
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
2992
2909
 
2993
2910
  /* Format the "perl <filename>" command */
2994
2911
  snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
3001
2918
    if (disable_result_log)
3002
2919
      buf[strlen(buf)-1]=0;
3003
2920
    else
3004
 
      replace_dynstr_append(&ds_res, buf);
 
2921
      replace_append(&ds_res, buf);
3005
2922
  }
3006
2923
  error= pclose(res_file);
3007
2924
 
3009
2926
  my_delete(temp_file_path, MYF(0));
3010
2927
 
3011
2928
  handle_command_error(command, WEXITSTATUS(error));
3012
 
  dynstr_free(&ds_script);
3013
 
  dynstr_free(&ds_delimiter);
3014
2929
  return;
3015
2930
}
3016
2931
 
3018
2933
/*
3019
2934
  Print the content between echo and <delimiter> to result file.
3020
2935
  Evaluate all variables in the string before printing, allow
3021
 
  for variable names to be escaped using \
 
2936
  for variable names to be escaped using        \
3022
2937
 
3023
2938
  SYNOPSIS
3024
2939
  do_echo()
3041
2956
 
3042
2957
static int do_echo(struct st_command *command)
3043
2958
{
3044
 
  DYNAMIC_STRING ds_echo;
3045
 
 
3046
 
 
3047
 
  init_dynamic_string(&ds_echo, "", command->query_len, 256);
 
2959
  string ds_echo;
 
2960
 
 
2961
 
3048
2962
  do_eval(&ds_echo, command->first_argument, command->end, false);
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
  ds_res.append(ds_echo.c_str(), ds_echo.length());
 
2964
  ds_res.append("\n");
3052
2965
  command->last_argument= command->end;
3053
2966
  return(0);
3054
2967
}
3066
2979
    int done;
3067
2980
 
3068
2981
    if (drizzle_query(drizzle,"show status like 'Slave_running'") ||
3069
 
  !(res=drizzle_store_result(drizzle)))
 
2982
        !(res=drizzle_store_result(drizzle)))
3070
2983
      die("Query failed while probing slave for stop: %s",
3071
 
    drizzle_error(drizzle));
 
2984
          drizzle_error(drizzle));
3072
2985
    if (!(row=drizzle_fetch_row(res)) || !row[1])
3073
2986
    {
3074
2987
      drizzle_free_result(res);
3096
3009
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3097
3010
 
3098
3011
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3099
 
    master_pos.pos + offset);
 
3012
          master_pos.pos + offset);
3100
3013
 
3101
3014
wait_for_position:
3102
3015
 
3165
3078
 
3166
3079
  if (drizzle_query(drizzle, query= "show master status"))
3167
3080
    die("failed in 'show master status': %d %s",
3168
 
  drizzle_errno(drizzle), drizzle_error(drizzle));
 
3081
        drizzle_errno(drizzle), drizzle_error(drizzle));
3169
3082
 
3170
3083
  if (!(res = drizzle_store_result(drizzle)))
3171
3084
    die("drizzle_store_result() retuned NULL for '%s'", query);
3201
3114
{
3202
3115
  char *p= command->first_argument;
3203
3116
  char *var_name, *var_name_end;
3204
 
  DYNAMIC_STRING let_rhs_expr;
3205
 
 
3206
 
 
3207
 
  init_dynamic_string(&let_rhs_expr, "", 512, 2048);
 
3117
  string let_rhs_expr;
 
3118
 
3208
3119
 
3209
3120
  /* Find <var_name> */
3210
3121
  if (!*p)
3229
3140
 
3230
3141
  command->last_argument= command->end;
3231
3142
  /* Assign var_val to var_name */
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
  var_set(var_name, var_name_end, let_rhs_expr.c_str(),
 
3144
          (let_rhs_expr.c_str() + let_rhs_expr.length()));
3235
3145
  return;
3236
3146
}
3237
3147
 
3243
3153
  do_sleep()
3244
3154
  q         called command
3245
3155
  real_sleep   use the value from opt_sleep as number of seconds to sleep
3246
 
               if real_sleep is false
 
3156
  if real_sleep is false
3247
3157
 
3248
3158
  DESCRIPTION
3249
3159
  sleep <seconds>
3291
3201
 
3292
3202
 
3293
3203
static void do_get_file_name(struct st_command *command,
3294
 
                      char* dest, uint dest_max_len)
 
3204
                             char* dest, uint dest_max_len)
3295
3205
{
3296
3206
  char *p= command->first_argument, *name;
3297
3207
  if (!*p)
3392
3302
        if (my_isdigit(charset_info, *p) || my_isupper(charset_info, *p))
3393
3303
          *to_ptr++= *p++;
3394
3304
        else
3395
 
          die("The sqlstate may only consist of digits[0-9] " \
 
3305
          die("The sqlstate may only consist of digits[0-9] "   \
3396
3306
              "and _uppercase_ letters");
3397
3307
      }
3398
3308
 
3422
3332
      while (*p && p != end)
3423
3333
      {
3424
3334
        if (!my_isdigit(charset_info, *p))
3425
 
          die("Invalid argument to error: '%s' - "\
 
3335
          die("Invalid argument to error: '%s' - "              \
3426
3336
              "the errno may only consist of digits[0-9]",
3427
3337
              command->first_argument);
3428
3338
        p++;
3430
3340
 
3431
3341
      /* Convert the sting to int */
3432
3342
      if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
3433
 
  die("Invalid argument to error: '%s'", command->first_argument);
 
3343
        die("Invalid argument to error: '%s'", command->first_argument);
3434
3344
 
3435
3345
      to->code.errnum= (uint) val;
3436
3346
      to->type= ERR_ERRNO;
3489
3399
      /* We can't translate \0 -> ASCII 0 as replace can't handle ASCII 0 */
3490
3400
      switch (*++from) {
3491
3401
      case 'n':
3492
 
  *to++= '\n';
3493
 
  break;
 
3402
        *to++= '\n';
 
3403
        break;
3494
3404
      case 't':
3495
 
  *to++= '\t';
3496
 
  break;
 
3405
        *to++= '\t';
 
3406
        break;
3497
3407
      case 'r':
3498
 
  *to++ = '\r';
3499
 
  break;
 
3408
        *to++ = '\r';
 
3409
        break;
3500
3410
      case 'b':
3501
 
  *to++ = '\b';
3502
 
  break;
 
3411
        *to++ = '\b';
 
3412
        break;
3503
3413
      case 'Z':        /* ^Z must be escaped on Win32 */
3504
 
  *to++='\032';
3505
 
  break;
 
3414
        *to++='\032';
 
3415
        break;
3506
3416
      default:
3507
 
  *to++ = *from;
3508
 
  break;
 
3417
        *to++ = *from;
 
3418
        break;
3509
3419
      }
3510
3420
    }
3511
3421
    else if (c == sep)
3512
3422
    {
3513
3423
      if (c == ' ' || c != *++from)
3514
 
  break;        /* Found end of string */
 
3424
        break;        /* Found end of string */
3515
3425
      *to++=c;        /* Copy duplicated separator */
3516
3426
    }
3517
3427
    else
3651
3561
*/
3652
3562
 
3653
3563
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
3654
 
                  const char *user, const char *pass, const char *db,
3655
 
                  int port)
 
3564
                         const char *user, const char *pass, const char *db,
 
3565
                         int port)
3656
3566
{
3657
3567
  int failed_attempts= 0;
3658
3568
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3659
3569
 
3660
3570
 
3661
3571
  while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3662
 
                            CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
 
3572
                         CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3663
3573
  {
3664
3574
    /*
3665
3575
      Connect failed
3717
3627
*/
3718
3628
 
3719
3629
static int connect_n_handle_errors(struct st_command *command,
3720
 
                            DRIZZLE *con, const char* host,
3721
 
                            const char* user, const char* pass,
3722
 
                            const char* db, int port, const char* sock)
 
3630
                                   DRIZZLE *con, const char* host,
 
3631
                                   const char* user, const char* pass,
 
3632
                                   const char* db, int port, const char* sock)
3723
3633
{
3724
 
  DYNAMIC_STRING *ds;
3725
 
 
3726
 
  ds= &ds_res;
3727
3634
 
3728
3635
  /* Only log if an error is expected */
3729
3636
  if (!command->abort_on_error &&
3732
3639
    /*
3733
3640
      Log the connect to result log
3734
3641
    */
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);
 
3642
    ds_res.append("connect(");
 
3643
    replace_append(&ds_res, host);
 
3644
    ds_res.append(",");
 
3645
    replace_append(&ds_res, user);
 
3646
    ds_res.append(",");
 
3647
    replace_append(&ds_res, pass);
 
3648
    ds_res.append(",");
3742
3649
    if (db)
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);
 
3650
      replace_append(&ds_res, db);
 
3651
    ds_res.append(",");
 
3652
    replace_append_uint(&ds_res, port);
 
3653
    ds_res.append(",");
3747
3654
    if (sock)
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);
 
3655
      replace_append(&ds_res, sock);
 
3656
    ds_res.append(")");
 
3657
    ds_res.append(delimiter);
 
3658
    ds_res.append("\n");
3752
3659
  }
3753
3660
  if (!drizzle_connect(con, host, user, pass, db, port, 0,
3754
 
                          CLIENT_MULTI_STATEMENTS))
 
3661
                       CLIENT_MULTI_STATEMENTS))
3755
3662
  {
3756
3663
    var_set_errno(drizzle_errno(con));
3757
3664
    handle_error(command, drizzle_errno(con), drizzle_error(con),
3758
 
     drizzle_sqlstate(con), ds);
 
3665
                 drizzle_sqlstate(con), &ds_res);
3759
3666
    return 0; /* Not connected */
3760
3667
  }
3761
3668
 
3785
3692
  <port> - server port
3786
3693
  <sock> - server socket
3787
3694
  <opts> - options to use for the connection
3788
 
   * SSL - use SSL if available
3789
 
   * COMPRESS - use compression if available
 
3695
  * SSL - use SSL if available
 
3696
  * COMPRESS - use compression if available
3790
3697
 
3791
 
*/
 
3698
  */
3792
3699
 
3793
3700
static void do_connect(struct st_command *command)
3794
3701
{
3795
3702
  int con_port= opt_port;
3796
 
  char *con_options;
 
3703
  const char *con_options;
3797
3704
  bool con_ssl= 0, con_compress= 0;
3798
3705
  struct st_connection* con_slot;
3799
3706
 
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;
 
3707
  string ds_connection_name;
 
3708
  string ds_host;
 
3709
  string ds_user;
 
3710
  string ds_password;
 
3711
  string ds_database;
 
3712
  string ds_port;
 
3713
  string ds_sock;
 
3714
  string ds_options;
3808
3715
  const struct command_arg connect_args[] = {
3809
3716
    { "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3810
3717
    { "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3823
3730
                     ',');
3824
3731
 
3825
3732
  /* Port */
3826
 
  if (ds_port.length)
 
3733
  if (ds_port.length())
3827
3734
  {
3828
 
    con_port= atoi(ds_port.str);
 
3735
    con_port= atoi(ds_port.c_str());
3829
3736
    if (con_port == 0)
3830
 
      die("Illegal argument for port: '%s'", ds_port.str);
 
3737
      die("Illegal argument for port: '%s'", ds_port.c_str());
3831
3738
  }
3832
3739
 
3833
3740
  /* Sock */
3834
 
  if (ds_sock.length)
 
3741
  if (!ds_sock.empty())
3835
3742
  {
3836
3743
    /*
3837
3744
      If the socket is specified just as a name without path
3838
3745
      append tmpdir in front
3839
3746
    */
3840
 
    if (*ds_sock.str != FN_LIBCHAR)
 
3747
    if (*ds_sock.c_str() != FN_LIBCHAR)
3841
3748
    {
3842
3749
      char buff[FN_REFLEN];
3843
 
      fn_format(buff, ds_sock.str, TMPDIR, "", 0);
3844
 
      dynstr_set(&ds_sock, buff);
 
3750
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
 
3751
      ds_sock= buff;
3845
3752
    }
3846
3753
  }
3847
 
  else
3848
 
  {
3849
 
    /* No socket specified, use default */
3850
 
    dynstr_set(&ds_sock, unix_sock);
3851
 
  }
3852
3754
 
3853
3755
  /* Options */
3854
 
  con_options= ds_options.str;
 
3756
  con_options= ds_options.c_str();
3855
3757
  while (*con_options)
3856
3758
  {
3857
 
    char* end;
 
3759
    const char* end;
3858
3760
    /* Step past any spaces in beginning of option*/
3859
3761
    while (*con_options && my_isspace(charset_info, *con_options))
3860
 
     con_options++;
 
3762
      con_options++;
3861
3763
    /* Find end of this option */
3862
3764
    end= con_options;
3863
3765
    while (*end && !my_isspace(charset_info, *end))
3873
3775
    con_options= end;
3874
3776
  }
3875
3777
 
3876
 
  if (find_connection_by_name(ds_connection_name.str))
3877
 
    die("Connection %s already exists", ds_connection_name.str);
3878
 
   
 
3778
  if (find_connection_by_name(ds_connection_name.c_str()))
 
3779
    die("Connection %s already exists", ds_connection_name.c_str());
 
3780
 
3879
3781
  if (next_con != connections_end)
 
3782
  {
3880
3783
    con_slot= next_con;
 
3784
  }
3881
3785
  else
3882
3786
  {
3883
3787
    if (!(con_slot= find_connection_by_name("-closed_connection-")))
3885
3789
          (int) (sizeof(connections)/sizeof(struct st_connection)));
3886
3790
  }
3887
3791
 
3888
 
#ifdef EMBEDDED_LIBRARY
3889
 
  con_slot->query_done= 1;
3890
 
#endif
3891
3792
  if (!drizzle_create(&con_slot->drizzle))
3892
3793
    die("Failed on drizzle_create()");
3893
3794
  if (opt_compress || con_compress)
3894
3795
    drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NullS);
3895
3796
  drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
3896
3797
  drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_NAME,
3897
 
                charset_info->csname);
 
3798
                  charset_info->csname);
3898
3799
  int opt_protocol= DRIZZLE_PROTOCOL_TCP;
3899
3800
  drizzle_options(&con_slot->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
3900
3801
  if (opt_charsets_dir)
3901
3802
    drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_DIR,
3902
 
                  opt_charsets_dir);
 
3803
                    opt_charsets_dir);
3903
3804
 
3904
3805
  /* Use default db name */
3905
 
  if (ds_database.length == 0)
3906
 
    dynstr_set(&ds_database, opt_db);
 
3806
  if (ds_database.length() == 0)
 
3807
    ds_database= opt_db;
3907
3808
 
3908
3809
  /* Special database to allow one to connect without a database name */
3909
 
  if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
3910
 
    dynstr_set(&ds_database, "");
 
3810
  if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
 
3811
    ds_database= "";
3911
3812
 
3912
3813
  if (connect_n_handle_errors(command, &con_slot->drizzle,
3913
 
                              ds_host.str,ds_user.str,
3914
 
                              ds_password.str, ds_database.str,
3915
 
                              con_port, ds_sock.str))
 
3814
                              ds_host.c_str(),ds_user.c_str(),
 
3815
                              ds_password.c_str(), ds_database.c_str(),
 
3816
                              con_port, ds_sock.c_str()))
3916
3817
  {
3917
 
    if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
 
3818
    if (!(con_slot->name= strdup(ds_connection_name.c_str())))
3918
3819
      die("Out of memory");
3919
3820
    cur_con= con_slot;
3920
 
   
 
3821
 
3921
3822
    if (con_slot == next_con)
3922
3823
      next_con++; /* if we used the next_con slot, advance the pointer */
3923
3824
  }
3925
3826
  /* Update $drizzle_get_server_version to that of current connection */
3926
3827
  var_set_drizzle_get_server_version(&cur_con->drizzle);
3927
3828
 
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);
3936
3829
  return;
3937
3830
}
3938
3831
 
4080
3973
    return 0;
4081
3974
 
4082
3975
  for (i= 1; i < length &&
4083
 
   (c= my_getc(cur_file->file)) == *(delim + i);
 
3976
         (c= my_getc(cur_file->file)) == *(delim + i);
4084
3977
       i++)
4085
3978
    tmp[i]= c;
4086
3979
 
4144
4037
  found_eof:
4145
4038
      if (cur_file->file != stdin)
4146
4039
      {
4147
 
  my_fclose(cur_file->file, MYF(0));
 
4040
        my_fclose(cur_file->file, MYF(0));
4148
4041
        cur_file->file= 0;
4149
4042
      }
4150
4043
      my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
4179
4072
    case R_NORMAL:
4180
4073
      if (end_of_query(c))
4181
4074
      {
4182
 
  *p= 0;
4183
 
  return(0);
 
4075
        *p= 0;
 
4076
        return(0);
4184
4077
      }
4185
4078
      else if ((c == '{' &&
4186
4079
                (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
4190
4083
      {
4191
4084
        /* Only if and while commands can be terminated by { */
4192
4085
        *p++= c;
4193
 
  *p= 0;
4194
 
  return(0);
 
4086
        *p= 0;
 
4087
        return(0);
4195
4088
      }
4196
4089
      else if (c == '\'' || c == '"' || c == '`')
4197
4090
      {
4198
4091
        last_quote= c;
4199
 
  state= R_Q;
 
4092
        state= R_Q;
4200
4093
      }
4201
4094
      break;
4202
4095
 
4204
4097
      if (c == '\n')
4205
4098
      {
4206
4099
        /* Comments are terminated by newline */
4207
 
  *p= 0;
4208
 
  return(0);
 
4100
        *p= 0;
 
4101
        return(0);
4209
4102
      }
4210
4103
      break;
4211
4104
 
4213
4106
      if (c == '#' || c == '-')
4214
4107
      {
4215
4108
        /* A # or - in the first position of the line - this is a comment */
4216
 
  state = R_COMMENT;
 
4109
        state = R_COMMENT;
4217
4110
      }
4218
4111
      else if (my_isspace(charset_info, c))
4219
4112
      {
4220
4113
        /* Skip all space at begining of line */
4221
 
  if (c == '\n')
 
4114
        if (c == '\n')
4222
4115
        {
4223
4116
          /* Query hasn't started yet */
4224
 
    start_lineno= cur_file->lineno;
 
4117
          start_lineno= cur_file->lineno;
4225
4118
        }
4226
 
  skip_char= 1;
 
4119
        skip_char= 1;
4227
4120
      }
4228
4121
      else if (end_of_query(c))
4229
4122
      {
4230
 
  *p= 0;
4231
 
  return(0);
 
4123
        *p= 0;
 
4124
        return(0);
4232
4125
      }
4233
4126
      else if (c == '}')
4234
4127
      {
4235
4128
        /* A "}" need to be by itself in the begining of a line to terminate */
4236
4129
        *p++= c;
4237
 
  *p= 0;
4238
 
  return(0);
 
4130
        *p= 0;
 
4131
        return(0);
4239
4132
      }
4240
4133
      else if (c == '\'' || c == '"' || c == '`')
4241
4134
      {
4242
4135
        last_quote= c;
4243
 
  state= R_Q;
 
4136
        state= R_Q;
4244
4137
      }
4245
4138
      else
4246
 
  state= R_NORMAL;
 
4139
        state= R_NORMAL;
4247
4140
      break;
4248
4141
 
4249
4142
    case R_Q:
4250
4143
      if (c == last_quote)
4251
 
  state= R_NORMAL;
 
4144
        state= R_NORMAL;
4252
4145
      else if (c == '\\')
4253
 
  state= R_SLASH_IN_Q;
 
4146
        state= R_SLASH_IN_Q;
4254
4147
      break;
4255
4148
 
4256
4149
    case R_SLASH_IN_Q:
4269
4162
      /* completed before we pass buf_end */
4270
4163
      if ((charlen > 1) && (p + charlen) <= buf_end)
4271
4164
      {
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
 
  }
 
4165
        int i;
 
4166
        char* mb_start = p;
 
4167
 
 
4168
        *p++ = c;
 
4169
 
 
4170
        for (i= 1; i < charlen; i++)
 
4171
        {
 
4172
          if (feof(cur_file->file))
 
4173
            goto found_eof;
 
4174
          c= my_getc(cur_file->file);
 
4175
          *p++ = c;
 
4176
        }
 
4177
        if (! my_ismbchar(charset_info, mb_start, p))
 
4178
        {
 
4179
          /* It was not a multiline char, push back the characters */
 
4180
          /* We leave first 'c', i.e. pretend it was a normal char */
 
4181
          while (p > mb_start)
 
4182
            my_ungetc(*--p);
 
4183
        }
4291
4184
      }
4292
4185
      else
4293
4186
#endif
4294
 
  *p++= c;
 
4187
        *p++= c;
4295
4188
    }
4296
4189
  }
4297
 
  die("The input buffer is too small for this query.x\n" \
 
4190
  die("The input buffer is too small for this query.x\n"        \
4298
4191
      "check your query or increase MAX_QUERY and recompile");
4299
4192
  return(0);
4300
4193
}
4315
4208
{
4316
4209
  int last_c_was_quote= 0;
4317
4210
  char *p= query, *to= query;
4318
 
  char *end= strend(query);
 
4211
  char *end= strchr(query, '\0');
4319
4212
  char last_c;
4320
4213
 
4321
4214
  while (p <= end)
4456
4349
  Create a command from a set of lines
4457
4350
 
4458
4351
  SYNOPSIS
4459
 
    read_command()
4460
 
    command_ptr pointer where to return the new query
 
4352
  read_command()
 
4353
  command_ptr pointer where to return the new query
4461
4354
 
4462
4355
  DESCRIPTION
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.
 
4356
  Converts lines returned by read_line into a command, this involves
 
4357
  parsing the first word in the read line to find the command type.
4465
4358
 
4466
4359
  A -- comment may contain a valid query as the first word after the
4467
4360
  comment start. Thus it's always checked to see if that is the case.
4480
4373
 
4481
4374
  if (parser.current_line < parser.read_lines)
4482
4375
  {
4483
 
    get_dynamic(&q_lines, (uchar*) command_ptr, parser.current_line) ;
 
4376
    *command_ptr= q_lines[parser.current_line];
4484
4377
    return(0);
4485
4378
  }
4486
4379
  if (!(*command_ptr= command=
4487
4380
        (struct st_command*) my_malloc(sizeof(*command),
4488
 
                                       MYF(MY_WME|MY_ZEROFILL))) ||
4489
 
      insert_dynamic(&q_lines, (uchar*) &command))
 
4381
                                       MYF(MY_WME|MY_ZEROFILL))))
4490
4382
    die(NullS);
 
4383
  q_lines.push_back(command);
4491
4384
  command->type= Q_UNKNOWN;
4492
4385
 
4493
4386
  read_command_buf[0]= 0;
4527
4420
    p++;
4528
4421
  command->first_argument= p;
4529
4422
 
4530
 
  command->end= strend(command->query);
 
4423
  command->end= strchr(command->query, '\0');
4531
4424
  command->query_len= (command->end - command->query);
4532
4425
  parser.read_lines++;
4533
4426
  return(0);
4614
4507
static void print_version(void)
4615
4508
{
4616
4509
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4617
 
   drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
4510
         drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
4618
4511
}
4619
4512
 
4620
4513
static void usage(void)
4621
4514
{
4622
4515
  print_version();
4623
 
  printf("DRIZZLE AB, by Sasha, Matt, Monty & Jani\n");
 
4516
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4624
4517
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4625
4518
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
4626
4519
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4655
4548
    die("Failed to open file '%s'", buff);
4656
4549
 
4657
4550
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4658
 
   (str=fgets(argument,sizeof(argument), file)))
 
4551
         (str=fgets(argument,sizeof(argument), file)))
4659
4552
  {
4660
 
    *(strend(str)-1)=0;        /* Remove end newline */
 
4553
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
4661
4554
    if (!(embedded_server_args[embedded_server_arg_count]=
4662
 
    (char*) my_strdup(str,MYF(MY_WME))))
 
4555
          (char*) my_strdup(str,MYF(MY_WME))))
4663
4556
    {
4664
4557
      my_fclose(file,MYF(0));
4665
4558
      die("Out of memory");
4677
4570
 
4678
4571
static bool
4679
4572
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
4680
 
         char *argument)
 
4573
               char *argument)
4681
4574
{
4682
4575
  switch(optid) {
4683
4576
  case 'r':
4790
4683
  append - append to file instead of overwriting old file
4791
4684
*/
4792
4685
 
4793
 
void str_to_file2(const char *fname, char *str, int size, bool append)
 
4686
void str_to_file2(const char *fname, const char *str, int size, bool append)
4794
4687
{
4795
4688
  int fd;
4796
4689
  char buff[FN_REFLEN];
4824
4717
  size - size of content witten to file
4825
4718
*/
4826
4719
 
4827
 
void str_to_file(const char *fname, char *str, int size)
 
4720
void str_to_file(const char *fname, const char *str, int size)
4828
4721
{
4829
4722
  str_to_file2(fname, str, size, false);
4830
4723
}
4831
4724
 
4832
4725
 
4833
 
void dump_result_to_log_file(char *buf, int size)
 
4726
void dump_result_to_log_file(const char *buf, int size)
4834
4727
{
4835
4728
  char log_file[FN_REFLEN];
4836
4729
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
4848
4741
                        opt_logdir, ".progress",
4849
4742
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4850
4743
                        MY_REPLACE_EXT),
4851
 
              ds_progress.str, ds_progress.length);
 
4744
              ds_progress.c_str(), ds_progress.length());
4852
4745
}
4853
4746
 
4854
4747
void dump_warning_messages(void)
4858
4751
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
4859
4752
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4860
4753
                        MY_REPLACE_EXT),
4861
 
              ds_warning_messages.str, ds_warning_messages.length);
 
4754
              ds_warning_messages.c_str(), ds_warning_messages.length());
4862
4755
}
4863
4756
 
4864
4757
 
4866
4759
  Append the result for one field to the dynamic string ds
4867
4760
*/
4868
4761
 
4869
 
static void append_field(DYNAMIC_STRING *ds, uint col_idx, const DRIZZLE_FIELD* field,
 
4762
static void append_field(string *ds, uint col_idx, const DRIZZLE_FIELD* field,
4870
4763
                         const char* val, uint64_t len, bool is_null)
4871
4764
{
4872
4765
  if (col_idx < max_replace_column && replace_column[col_idx])
4883
4776
  if (!display_result_vertically)
4884
4777
  {
4885
4778
    if (col_idx)
4886
 
      dynstr_append_mem(ds, "\t", 1);
4887
 
    replace_dynstr_append_mem(ds, val, (int)len);
 
4779
      ds->append("\t");
 
4780
    replace_append_mem(ds, val, (int)len);
4888
4781
  }
4889
4782
  else
4890
4783
  {
4891
 
    dynstr_append(ds, field->name);
4892
 
    dynstr_append_mem(ds, "\t", 1);
4893
 
    replace_dynstr_append_mem(ds, val, (int)len);
4894
 
    dynstr_append_mem(ds, "\n", 1);
 
4784
    ds->append(field->name);
 
4785
    ds->append("\t");
 
4786
    replace_append_mem(ds, val, (int)len);
 
4787
    ds->append("\n");
4895
4788
  }
4896
4789
}
4897
4790
 
4901
4794
  Values may be converted with 'replace_column'
4902
4795
*/
4903
4796
 
4904
 
static void append_result(DYNAMIC_STRING *ds, DRIZZLE_RES *res)
 
4797
static void append_result(string *ds, DRIZZLE_RES *res)
4905
4798
{
4906
4799
  DRIZZLE_ROW row;
4907
4800
  uint32_t num_fields= drizzle_num_fields(res);
4916
4809
      append_field(ds, i, &fields[i],
4917
4810
                   (const char*)row[i], lengths[i], !row[i]);
4918
4811
    if (!display_result_vertically)
4919
 
      dynstr_append_mem(ds, "\n", 1);
 
4812
      ds->append("\n");
 
4813
 
4920
4814
  }
4921
4815
}
4922
4816
 
4925
4819
  Append metadata for fields to output
4926
4820
*/
4927
4821
 
4928
 
static void append_metadata(DYNAMIC_STRING *ds,
 
4822
static void append_metadata(string *ds,
4929
4823
                            const DRIZZLE_FIELD *field,
4930
4824
                            uint num_fields)
4931
4825
{
4932
4826
  const DRIZZLE_FIELD *field_end;
4933
 
  dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4934
 
                "Column_alias\tType\tLength\tMax length\tIs_null\t"
4935
 
                "Flags\tDecimals\tCharsetnr\n");
 
4827
  ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
 
4828
             "Column_alias\tType\tLength\tMax length\tIs_null\t"
 
4829
             "Flags\tDecimals\tCharsetnr\n");
4936
4830
 
4937
4831
  for (field_end= field+num_fields ;
4938
4832
       field < field_end ;
4939
4833
       field++)
4940
4834
  {
4941
 
    dynstr_append_mem(ds, field->catalog,
4942
 
                      field->catalog_length);
4943
 
    dynstr_append_mem(ds, "\t", 1);
4944
 
    dynstr_append_mem(ds, field->db, field->db_length);
4945
 
    dynstr_append_mem(ds, "\t", 1);
4946
 
    dynstr_append_mem(ds, field->org_table,
4947
 
                      field->org_table_length);
4948
 
    dynstr_append_mem(ds, "\t", 1);
4949
 
    dynstr_append_mem(ds, field->table,
4950
 
                      field->table_length);
4951
 
    dynstr_append_mem(ds, "\t", 1);
4952
 
    dynstr_append_mem(ds, field->org_name,
4953
 
                      field->org_name_length);
4954
 
    dynstr_append_mem(ds, "\t", 1);
4955
 
    dynstr_append_mem(ds, field->name, field->name_length);
4956
 
    dynstr_append_mem(ds, "\t", 1);
4957
 
    replace_dynstr_append_uint(ds, field->type);
4958
 
    dynstr_append_mem(ds, "\t", 1);
4959
 
    replace_dynstr_append_uint(ds, field->length);
4960
 
    dynstr_append_mem(ds, "\t", 1);
4961
 
    replace_dynstr_append_uint(ds, field->max_length);
4962
 
    dynstr_append_mem(ds, "\t", 1);
4963
 
    dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
4964
 
                                   "N" : "Y"), 1);
4965
 
    dynstr_append_mem(ds, "\t", 1);
4966
 
    replace_dynstr_append_uint(ds, field->flags);
4967
 
    dynstr_append_mem(ds, "\t", 1);
4968
 
    replace_dynstr_append_uint(ds, field->decimals);
4969
 
    dynstr_append_mem(ds, "\t", 1);
4970
 
    replace_dynstr_append_uint(ds, field->charsetnr);
4971
 
    dynstr_append_mem(ds, "\n", 1);
 
4835
    ds->append(field->catalog,
 
4836
               field->catalog_length);
 
4837
    ds->append("\t", 1);
 
4838
    ds->append(field->db, field->db_length);
 
4839
    ds->append("\t", 1);
 
4840
    ds->append(field->org_table,
 
4841
               field->org_table_length);
 
4842
    ds->append("\t", 1);
 
4843
    ds->append(field->table,
 
4844
               field->table_length);
 
4845
    ds->append("\t", 1);
 
4846
    ds->append(field->org_name,
 
4847
               field->org_name_length);
 
4848
    ds->append("\t", 1);
 
4849
    ds->append(field->name, field->name_length);
 
4850
    ds->append("\t", 1);
 
4851
    replace_append_uint(ds, field->type);
 
4852
    ds->append("\t", 1);
 
4853
    replace_append_uint(ds, field->length);
 
4854
    ds->append("\t", 1);
 
4855
    replace_append_uint(ds, field->max_length);
 
4856
    ds->append("\t", 1);
 
4857
    ds->append((char*) (IS_NOT_NULL(field->flags) ?
 
4858
                        "N" : "Y"), 1);
 
4859
    ds->append("\t", 1);
 
4860
    replace_append_uint(ds, field->flags);
 
4861
    ds->append("\t", 1);
 
4862
    replace_append_uint(ds, field->decimals);
 
4863
    ds->append("\t", 1);
 
4864
    replace_append_uint(ds, field->charsetnr);
 
4865
    ds->append("\n", 1);
4972
4866
  }
4973
4867
}
4974
4868
 
4977
4871
  Append affected row count and other info to output
4978
4872
*/
4979
4873
 
4980
 
static void append_info(DYNAMIC_STRING *ds, uint64_t affected_rows,
 
4874
static void append_info(string *ds, uint64_t affected_rows,
4981
4875
                        const char *info)
4982
4876
{
4983
4877
  char buf[40], buff2[21];
4984
4878
  sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
4985
 
  dynstr_append(ds, buf);
 
4879
  ds->append(buf);
4986
4880
  if (info)
4987
4881
  {
4988
 
    dynstr_append(ds, "info: ");
4989
 
    dynstr_append(ds, info);
4990
 
    dynstr_append_mem(ds, "\n", 1);
 
4882
    ds->append("info: ");
 
4883
    ds->append(info);
 
4884
    ds->append("\n", 1);
4991
4885
  }
4992
4886
}
4993
4887
 
4996
4890
  Display the table headings with the names tab separated
4997
4891
*/
4998
4892
 
4999
 
static void append_table_headings(DYNAMIC_STRING *ds,
 
4893
static void append_table_headings(string *ds,
5000
4894
                                  const DRIZZLE_FIELD *field,
5001
4895
                                  uint num_fields)
5002
4896
{
5004
4898
  for (col_idx= 0; col_idx < num_fields; col_idx++)
5005
4899
  {
5006
4900
    if (col_idx)
5007
 
      dynstr_append_mem(ds, "\t", 1);
5008
 
    replace_dynstr_append(ds, field[col_idx].name);
 
4901
      ds->append("\t", 1);
 
4902
    replace_append(ds, field[col_idx].name);
5009
4903
  }
5010
 
  dynstr_append_mem(ds, "\n", 1);
 
4904
  ds->append("\n", 1);
5011
4905
}
5012
4906
 
5013
4907
/*
5017
4911
  Number of warnings appended to ds
5018
4912
*/
5019
4913
 
5020
 
static int append_warnings(DYNAMIC_STRING *ds, DRIZZLE *drizzle)
 
4914
static int append_warnings(string *ds, DRIZZLE *drizzle)
5021
4915
{
5022
4916
  uint count;
5023
4917
  DRIZZLE_RES *warn_res;
5038
4932
 
5039
4933
  if (!(warn_res= drizzle_store_result(drizzle)))
5040
4934
    die("Warning count is %u but didn't get any warnings",
5041
 
  count);
 
4935
        count);
5042
4936
 
5043
4937
  append_result(ds, warn_res);
5044
 
  drizzle_free_result(warn_res);
5045
4938
 
5046
4939
  return(count);
5047
4940
}
5051
4944
  Run query using DRIZZLE C API
5052
4945
 
5053
4946
  SYNOPSIS
5054
 
    run_query_normal()
5055
 
    drizzle  DRIZZLE handle
5056
 
    command  current command pointer
5057
 
    flags  flags indicating if we should SEND and/or REAP
5058
 
    query  query string to execute
5059
 
    query_len  length query string to execute
5060
 
    ds    output buffer where to store result form query
 
4947
  run_query_normal()
 
4948
  drizzle  DRIZZLE handle
 
4949
  command  current command pointer
 
4950
  flags  flags indicating if we should SEND and/or REAP
 
4951
  query  query string to execute
 
4952
  query_len  length query string to execute
 
4953
  ds    output buffer where to store result form query
5061
4954
*/
5062
4955
 
5063
4956
static void run_query_normal(struct st_connection *cn,
5064
4957
                             struct st_command *command,
5065
4958
                             int flags, char *query, int query_len,
5066
 
                             DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
 
4959
                             string *ds, string *ds_warnings)
5067
4960
{
5068
4961
  DRIZZLE_RES *res= 0;
5069
4962
  DRIZZLE *drizzle= &cn->drizzle;
5072
4965
  if (flags & QUERY_SEND_FLAG)
5073
4966
  {
5074
4967
    /*
5075
 
      Send the query
5076
 
    */
 
4968
     * Send the query
 
4969
     */
5077
4970
    if (do_send_query(cn, query, query_len, flags))
5078
4971
    {
5079
4972
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5080
 
       drizzle_sqlstate(drizzle), ds);
 
4973
                   drizzle_sqlstate(drizzle), ds);
5081
4974
      goto end;
5082
4975
    }
5083
4976
  }
5084
 
#ifdef EMBEDDED_LIBRARY
5085
 
  /*
5086
 
    Here we handle 'reap' command, so we need to check if the
5087
 
    query's thread was finished and probably wait
5088
 
  */
5089
 
  else if (flags & QUERY_REAP_FLAG)
5090
 
    wait_query_thread_end(cn);
5091
 
#endif /*EMBEDDED_LIBRARY*/
5092
4977
  if (!(flags & QUERY_REAP_FLAG))
5093
4978
    return;
5094
4979
 
5101
4986
    if ((counter==0) && drizzle_read_query_result(drizzle))
5102
4987
    {
5103
4988
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5104
 
       drizzle_sqlstate(drizzle), ds);
 
4989
                   drizzle_sqlstate(drizzle), ds);
5105
4990
      goto end;
5106
4991
 
5107
4992
    }
5112
4997
    if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
5113
4998
    {
5114
4999
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5115
 
       drizzle_sqlstate(drizzle), ds);
 
5000
                   drizzle_sqlstate(drizzle), ds);
5116
5001
      goto end;
5117
5002
    }
5118
5003
 
5148
5033
      */
5149
5034
      if (!disable_warnings && !drizzle_more_results(drizzle))
5150
5035
      {
5151
 
  if (append_warnings(ds_warnings, drizzle) || ds_warnings->length)
5152
 
  {
5153
 
    dynstr_append_mem(ds, "Warnings:\n", 10);
5154
 
    dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
5155
 
  }
 
5036
        if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
 
5037
        {
 
5038
          ds->append("Warnings:\n", 10);
 
5039
          ds->append(ds_warnings->c_str(), ds_warnings->length());
 
5040
        }
5156
5041
      }
5157
5042
 
5158
5043
      if (!disable_info)
5159
 
  append_info(ds, affected_rows, drizzle_info(drizzle));
 
5044
        append_info(ds, affected_rows, drizzle_info(drizzle));
5160
5045
    }
5161
5046
 
5162
5047
    if (res)
5170
5055
  {
5171
5056
    /* We got an error from drizzle_next_result, maybe expected */
5172
5057
    handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5173
 
     drizzle_sqlstate(drizzle), ds);
 
5058
                 drizzle_sqlstate(drizzle), ds);
5174
5059
    goto end;
5175
5060
  }
5176
5061
  assert(err == -1); /* Successful and there are no more results */
5202
5087
  ds    - dynamic string which is used for output buffer
5203
5088
 
5204
5089
  NOTE
5205
 
    If there is an unexpected error this function will abort drizzletest
5206
 
    immediately.
 
5090
  If there is an unexpected error this function will abort drizzletest
 
5091
  immediately.
5207
5092
*/
5208
5093
 
5209
5094
void handle_error(struct st_command *command,
5210
5095
                  unsigned int err_errno, const char *err_error,
5211
 
                  const char *err_sqlstate, DYNAMIC_STRING *ds)
 
5096
                  const char *err_sqlstate, string *ds)
5212
5097
{
5213
5098
  uint i;
5214
5099
 
5215
5100
 
5216
 
 
5217
5101
  if (command->require_file[0])
5218
5102
  {
5219
5103
    /*
5247
5131
        if (command->expected_errors.count == 1)
5248
5132
        {
5249
5133
          /* Only log error if there is one possible error */
5250
 
          dynstr_append_mem(ds, "ERROR ", 6);
5251
 
          replace_dynstr_append(ds, err_sqlstate);
5252
 
          dynstr_append_mem(ds, ": ", 2);
5253
 
          replace_dynstr_append(ds, err_error);
5254
 
          dynstr_append_mem(ds,"\n",1);
 
5134
          ds->append("ERROR ", 6);
 
5135
          replace_append(ds, err_sqlstate);
 
5136
          ds->append(": ", 2);
 
5137
          replace_append(ds, err_error);
 
5138
          ds->append("\n",1);
5255
5139
        }
5256
5140
        /* Don't log error if we may not get an error */
5257
5141
        else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5258
5142
                 (command->expected_errors.err[0].type == ERR_ERRNO &&
5259
5143
                  command->expected_errors.err[0].code.errnum != 0))
5260
 
          dynstr_append(ds,"Got one of the listed errors\n");
 
5144
          ds->append("Got one of the listed errors\n");
5261
5145
      }
5262
5146
      /* OK */
5263
5147
      return;
5266
5150
 
5267
5151
  if (!disable_result_log)
5268
5152
  {
5269
 
    dynstr_append_mem(ds, "ERROR ",6);
5270
 
    replace_dynstr_append(ds, err_sqlstate);
5271
 
    dynstr_append_mem(ds, ": ", 2);
5272
 
    replace_dynstr_append(ds, err_error);
5273
 
    dynstr_append_mem(ds, "\n", 1);
 
5153
    ds->append("ERROR ",6);
 
5154
    replace_append(ds, err_sqlstate);
 
5155
    ds->append(": ", 2);
 
5156
    replace_append(ds, err_error);
 
5157
    ds->append("\n", 1);
5274
5158
  }
5275
5159
 
5276
5160
  if (i)
5282
5166
    else
5283
5167
      die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
5284
5168
          command->query, err_sqlstate, err_error,
5285
 
    command->expected_errors.err[0].code.sqlstate);
 
5169
          command->expected_errors.err[0].code.sqlstate);
5286
5170
  }
5287
5171
 
5288
5172
  return;
5327
5211
  Run query
5328
5212
 
5329
5213
  SYNPOSIS
5330
 
    run_query()
5331
 
     drizzle  DRIZZLE handle
5332
 
     command  currrent command pointer
 
5214
  run_query()
 
5215
  drizzle  DRIZZLE handle
 
5216
  command  currrent command pointer
5333
5217
 
5334
5218
  flags control the phased/stages of query execution to be performed
5335
5219
  if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
5340
5224
                      struct st_command *command,
5341
5225
                      int flags)
5342
5226
{
5343
 
  DYNAMIC_STRING *ds;
5344
 
  DYNAMIC_STRING *save_ds= NULL;
5345
 
  DYNAMIC_STRING ds_result;
5346
 
  DYNAMIC_STRING ds_sorted;
5347
 
  DYNAMIC_STRING ds_warnings;
5348
 
  DYNAMIC_STRING eval_query;
 
5227
  string *ds= NULL;
 
5228
  string *save_ds= NULL;
 
5229
  string ds_result;
 
5230
  string ds_sorted;
 
5231
  string ds_warnings;
 
5232
  string eval_query;
5349
5233
  char *query;
5350
5234
  int query_len;
5351
5235
 
5352
5236
 
5353
 
  init_dynamic_string(&ds_warnings, NULL, 0, 256);
5354
 
 
5355
5237
  /* Scan for warning before sending to server */
5356
5238
  scan_command_for_warnings(command);
5357
5239
 
5360
5242
  */
5361
5243
  if (command->type == Q_EVAL)
5362
5244
  {
5363
 
    init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
5364
5245
    do_eval(&eval_query, command->query, command->end, false);
5365
 
    query = eval_query.str;
5366
 
    query_len = eval_query.length;
 
5246
    query = strdup(eval_query.c_str());
 
5247
    query_len = eval_query.length();
5367
5248
  }
5368
5249
  else
5369
5250
  {
5379
5260
  */
5380
5261
  if (command->require_file[0])
5381
5262
  {
5382
 
    init_dynamic_string(&ds_result, "", 1024, 1024);
5383
5263
    ds= &ds_result;
5384
5264
  }
5385
5265
  else
 
5266
  {
5386
5267
    ds= &ds_res;
5387
 
 
 
5268
  }
5388
5269
  /*
5389
5270
    Log the query into the output buffer
5390
5271
  */
5391
5272
  if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5392
5273
  {
5393
 
    replace_dynstr_append_mem(ds, query, query_len);
5394
 
    dynstr_append_mem(ds, delimiter, delimiter_length);
5395
 
    dynstr_append_mem(ds, "\n", 1);
 
5274
    replace_append_mem(ds, query, query_len);
 
5275
    ds->append(delimiter, delimiter_length);
 
5276
    ds->append("\n");
5396
5277
  }
5397
5278
 
5398
5279
  if (display_result_sorted)
5399
5280
  {
5400
5281
    /*
5401
 
       Collect the query output in a separate string
5402
 
       that can be sorted before it's added to the
5403
 
       global result string
 
5282
      Collect the query output in a separate string
 
5283
      that can be sorted before it's added to the
 
5284
      global result string
5404
5285
    */
5405
 
    init_dynamic_string(&ds_sorted, "", 1024, 1024);
5406
5286
    save_ds= ds; /* Remember original ds */
5407
5287
    ds= &ds_sorted;
5408
5288
  }
5417
5297
  if (display_result_sorted)
5418
5298
  {
5419
5299
    /* Sort the result set and append it to result */
5420
 
    dynstr_append_sorted(save_ds, &ds_sorted);
 
5300
    append_sorted(save_ds, &ds_sorted);
5421
5301
    ds= save_ds;
5422
 
    dynstr_free(&ds_sorted);
5423
5302
  }
5424
5303
 
5425
5304
  if (command->require_file[0])
5431
5310
    check_require(ds, command->require_file);
5432
5311
  }
5433
5312
 
5434
 
  dynstr_free(&ds_warnings);
5435
 
  if (ds == &ds_result)
5436
 
    dynstr_free(&ds_result);
5437
 
  if (command->type == Q_EVAL)
5438
 
    dynstr_free(&eval_query);
5439
5313
  return;
5440
5314
}
5441
5315
 
5485
5359
    {
5486
5360
      /* -- comment that didn't contain a drizzletest command */
5487
5361
      command->type= Q_COMMENT;
5488
 
      warning_msg("Suspicious command '--%s' detected, was this intentional? "\
 
5362
      warning_msg("Suspicious command '--%s' detected, was this intentional? " \
5489
5363
                  "Use # instead of -- to avoid this warning",
5490
5364
                  command->query);
5491
5365
 
5539
5413
 
5540
5414
  /* Milliseconds since start */
5541
5415
  end= int64_t2str(timer, buf, 10);
5542
 
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5543
 
  dynstr_append_mem(&ds_progress, "\t", 1);
 
5416
  ds_progress.append(buf, (int)(end-buf));
 
5417
  ds_progress.append("\t", 1);
5544
5418
 
5545
5419
  /* Parser line number */
5546
5420
  end= int10_to_str(line, buf, 10);
5547
 
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5548
 
  dynstr_append_mem(&ds_progress, "\t", 1);
 
5421
  ds_progress.append(buf, (int)(end-buf));
 
5422
  ds_progress.append("\t", 1);
5549
5423
 
5550
5424
  /* Filename */
5551
 
  dynstr_append(&ds_progress, cur_file->file_name);
5552
 
  dynstr_append_mem(&ds_progress, ":", 1);
 
5425
  ds_progress.append(cur_file->file_name);
 
5426
  ds_progress.append(":", 1);
5553
5427
 
5554
5428
  /* Line in file */
5555
5429
  end= int10_to_str(cur_file->lineno, buf, 10);
5556
 
  dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5557
 
 
5558
 
 
5559
 
  dynstr_append_mem(&ds_progress, "\n", 1);
 
5430
  ds_progress.append(buf, (int)(end-buf));
 
5431
 
 
5432
 
 
5433
  ds_progress.append("\n", 1);
5560
5434
 
5561
5435
}
5562
5436
 
5582
5456
    (sizeof(connections)/sizeof(struct st_connection)) - 1;
5583
5457
  next_con= connections + 1;
5584
5458
 
5585
 
#ifdef EMBEDDED_LIBRARY
5586
 
  /* set appropriate stack for the 'query' threads */
5587
 
  (void) pthread_attr_init(&cn_thd_attrib);
5588
 
  pthread_attr_setstacksize(&cn_thd_attrib, DEFAULT_THREAD_STACK);
5589
 
#endif /*EMBEDDED_LIBRARY*/
5590
 
 
5591
5459
  /* Init file stack */
5592
5460
  memset(file_stack, 0, sizeof(file_stack));
5593
5461
  file_stack_end=
5602
5470
  cur_block->ok= true; /* Outer block should always be executed */
5603
5471
  cur_block->cmd= cmd_none;
5604
5472
 
5605
 
  my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
5606
 
 
5607
5473
  if (hash_init(&var_hash, charset_info,
5608
5474
                1024, 0, 0, get_var_key, var_free, MYF(0)))
5609
5475
    die("Variable hash initialization failed");
5617
5483
 
5618
5484
  init_builtin_echo();
5619
5485
 
5620
 
  init_dynamic_string(&ds_res, "", 65536, 65536);
5621
 
  init_dynamic_string(&ds_progress, "", 0, 2048);
5622
 
  init_dynamic_string(&ds_warning_messages, "", 0, 2048);
 
5486
  ds_res.reserve(65536);
 
5487
  ds_progress.reserve(2048);
 
5488
  ds_warning_messages.reserve(2048);
 
5489
 
5623
5490
  parse_args(argc, argv);
5624
5491
 
5625
5492
  server_initialized= 1;
5636
5503
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NullS);
5637
5504
  drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
5638
5505
  drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_NAME,
5639
 
                charset_info->csname);
 
5506
                  charset_info->csname);
5640
5507
  int opt_protocol= DRIZZLE_PROTOCOL_TCP;
5641
5508
  drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
5642
5509
  if (opt_charsets_dir)
5643
5510
    drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_DIR,
5644
 
                  opt_charsets_dir);
 
5511
                    opt_charsets_dir);
5645
5512
 
5646
5513
  if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5647
5514
    die("Out of memory");
5689
5556
      case Q_CONNECT:
5690
5557
        do_connect(command);
5691
5558
        break;
5692
 
      case Q_CONNECTION: select_connection(command); break;
 
5559
      case Q_CONNECTION:
 
5560
        select_connection(command);
 
5561
        break;
5693
5562
      case Q_DISCONNECT:
5694
5563
      case Q_DIRTY_CLOSE:
5695
 
  do_close_connection(command); break;
 
5564
        do_close_connection(command); break;
5696
5565
      case Q_ENABLE_QUERY_LOG:   disable_query_log=0; break;
5697
5566
      case Q_DISABLE_QUERY_LOG:  disable_query_log=1; break;
5698
5567
      case Q_ENABLE_ABORT_ON_ERROR:  abort_on_error=1; break;
5728
5597
      case Q_PERL: do_perl(command); break;
5729
5598
      case Q_DELIMITER:
5730
5599
        do_delimiter(command);
5731
 
  break;
 
5600
        break;
5732
5601
      case Q_DISPLAY_VERTICAL_RESULTS:
5733
5602
        display_result_vertically= true;
5734
5603
        break;
5735
5604
      case Q_DISPLAY_HORIZONTAL_RESULTS:
5736
 
  display_result_vertically= false;
 
5605
        display_result_vertically= false;
5737
5606
        break;
5738
5607
      case Q_SORTED_RESULT:
5739
5608
        /*
5740
5609
          Turn on sorting of result set, will be reset after next
5741
5610
          command
5742
5611
        */
5743
 
  display_result_sorted= true;
 
5612
        display_result_sorted= true;
5744
5613
        break;
5745
5614
      case Q_LET: do_let(command); break;
5746
5615
      case Q_EVAL_RESULT:
5748
5617
      case Q_EVAL:
5749
5618
      case Q_QUERY_VERTICAL:
5750
5619
      case Q_QUERY_HORIZONTAL:
5751
 
  if (command->query == command->query_buf)
 
5620
        if (command->query == command->query_buf)
5752
5621
        {
5753
5622
          /* Skip the first part of command, i.e query_xxx */
5754
 
    command->query= command->first_argument;
 
5623
          command->query= command->first_argument;
5755
5624
          command->first_word_len= 0;
5756
5625
        }
5757
 
  /* fall through */
 
5626
        /* fall through */
5758
5627
      case Q_QUERY:
5759
5628
      case Q_REAP:
5760
5629
      {
5761
 
  bool old_display_result_vertically= display_result_vertically;
 
5630
        bool old_display_result_vertically= display_result_vertically;
5762
5631
        /* Default is full query, both reap and send  */
5763
5632
        int flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
5764
5633
 
5776
5645
        /* Check for special property for this query */
5777
5646
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5778
5647
 
5779
 
  if (save_file[0])
5780
 
  {
5781
 
    strmake(command->require_file, save_file, sizeof(save_file) - 1);
5782
 
    save_file[0]= 0;
5783
 
  }
5784
 
  run_query(cur_con, command, flags);
5785
 
  command_executed++;
 
5648
        if (save_file[0])
 
5649
        {
 
5650
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
 
5651
          save_file[0]= 0;
 
5652
        }
 
5653
        run_query(cur_con, command, flags);
 
5654
        command_executed++;
5786
5655
        command->last_argument= command->end;
5787
5656
 
5788
5657
        /* Restore settings */
5789
 
  display_result_vertically= old_display_result_vertically;
 
5658
        display_result_vertically= old_display_result_vertically;
5790
5659
 
5791
 
  break;
 
5660
        break;
5792
5661
      }
5793
5662
      case Q_SEND:
5794
5663
        if (!*command->first_argument)
5802
5671
        }
5803
5672
 
5804
5673
        /* Remove "send" if this is first iteration */
5805
 
  if (command->query == command->query_buf)
5806
 
    command->query= command->first_argument;
 
5674
        if (command->query == command->query_buf)
 
5675
          command->query= command->first_argument;
5807
5676
 
5808
 
  /*
5809
 
    run_query() can execute a query partially, depending on the flags.
5810
 
    QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
 
5677
        /*
 
5678
          run_query() can execute a query partially, depending on the flags.
 
5679
          QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5811
5680
          the query and read the result some time later when reap instruction
5812
 
    is given on this connection.
 
5681
          is given on this connection.
5813
5682
        */
5814
 
  run_query(cur_con, command, QUERY_SEND_FLAG);
5815
 
  command_executed++;
 
5683
        run_query(cur_con, command, QUERY_SEND_FLAG);
 
5684
        command_executed++;
5816
5685
        command->last_argument= command->end;
5817
 
  break;
 
5686
        break;
5818
5687
      case Q_REQUIRE:
5819
 
  do_get_file_name(command, save_file, sizeof(save_file));
5820
 
  break;
 
5688
        do_get_file_name(command, save_file, sizeof(save_file));
 
5689
        break;
5821
5690
      case Q_ERROR:
5822
5691
        do_get_errcodes(command);
5823
 
  break;
 
5692
        break;
5824
5693
      case Q_REPLACE:
5825
 
  do_get_replace(command);
5826
 
  break;
 
5694
        do_get_replace(command);
 
5695
        break;
5827
5696
      case Q_REPLACE_REGEX:
5828
5697
        do_get_replace_regex(command);
5829
5698
        break;
5830
5699
      case Q_REPLACE_COLUMN:
5831
 
  do_get_replace_column(command);
5832
 
  break;
 
5700
        do_get_replace_column(command);
 
5701
        break;
5833
5702
      case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5834
5703
      case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5835
5704
      case Q_SYNC_SLAVE_WITH_MASTER:
5836
5705
      {
5837
 
  do_save_master_pos();
5838
 
  if (*command->first_argument)
5839
 
    select_connection(command);
5840
 
  else
5841
 
    select_connection_name("slave");
5842
 
  do_sync_with_master2(0);
5843
 
  break;
 
5706
        do_save_master_pos();
 
5707
        if (*command->first_argument)
 
5708
          select_connection(command);
 
5709
        else
 
5710
          select_connection_name("slave");
 
5711
        do_sync_with_master2(0);
 
5712
        break;
5844
5713
      }
5845
5714
      case Q_COMMENT:        /* Ignore row */
5846
5715
        command->last_argument= command->end;
5847
 
  break;
 
5716
        break;
5848
5717
      case Q_PING:
5849
 
  (void) drizzle_ping(&cur_con->drizzle);
5850
 
  break;
 
5718
        (void) drizzle_ping(&cur_con->drizzle);
 
5719
        break;
5851
5720
      case Q_EXEC:
5852
 
  do_exec(command);
5853
 
  command_executed++;
5854
 
  break;
 
5721
        do_exec(command);
 
5722
        command_executed++;
 
5723
        break;
5855
5724
      case Q_START_TIMER:
5856
 
  /* Overwrite possible earlier start of timer */
5857
 
  timer_start= timer_now();
5858
 
  break;
 
5725
        /* Overwrite possible earlier start of timer */
 
5726
        timer_start= timer_now();
 
5727
        break;
5859
5728
      case Q_END_TIMER:
5860
 
  /* End timer before ending drizzletest */
5861
 
  timer_output();
5862
 
  break;
 
5729
        /* End timer before ending drizzletest */
 
5730
        timer_output();
 
5731
        break;
5863
5732
      case Q_CHARACTER_SET:
5864
 
  do_set_charset(command);
5865
 
  break;
 
5733
        do_set_charset(command);
 
5734
        break;
5866
5735
      case Q_DISABLE_RECONNECT:
5867
5736
        set_reconnect(&cur_con->drizzle, 0);
5868
5737
        break;
5958
5827
    Time to compare result or save it to record file.
5959
5828
    The entire output from test is now kept in ds_res.
5960
5829
  */
5961
 
  if (ds_res.length)
 
5830
  if (ds_res.length())
5962
5831
  {
5963
5832
    if (result_file_name)
5964
5833
    {
5966
5835
 
5967
5836
      if (record)
5968
5837
      {
5969
 
  /* Recording - dump the output from test to result file */
5970
 
  str_to_file(result_file_name, ds_res.str, ds_res.length);
 
5838
        /* Recording - dump the output from test to result file */
 
5839
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
5971
5840
      }
5972
5841
      else
5973
5842
      {
5974
 
  /* Check that the output from test is equal to result file
5975
 
     - detect missing result file
5976
 
     - detect zero size result file
 
5843
        /* Check that the output from test is equal to result file
 
5844
           - detect missing result file
 
5845
           - detect zero size result file
5977
5846
        */
5978
 
  check_result(&ds_res);
 
5847
        check_result(&ds_res);
5979
5848
      }
5980
5849
    }
5981
5850
    else
5982
5851
    {
5983
5852
      /* No result_file_name specified to compare with, print to stdout */
5984
 
      printf("%s", ds_res.str);
 
5853
      printf("%s", ds_res.c_str());
5985
5854
    }
5986
5855
  }
5987
5856
  else
6006
5875
    dump_progress();
6007
5876
 
6008
5877
  /* Dump warning messages */
6009
 
  if (result_file_name && ds_warning_messages.length)
 
5878
  if (result_file_name && ds_warning_messages.length())
6010
5879
    dump_warning_messages();
6011
5880
 
6012
5881
  timer_output();
6128
5997
 
6129
5998
struct st_replace;
6130
5999
struct st_replace *init_replace(char * *from, char * *to, uint count,
6131
 
        char * word_end_chars);
 
6000
                                char * word_end_chars);
6132
6001
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6133
 
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
 
6002
void replace_strings_append(struct st_replace *rep, string* ds,
6134
6003
                            const char *from, int len);
6135
6004
void free_pointer_array(POINTER_ARRAY *pa);
6136
6005
 
6176
6045
      *pos++= i;
6177
6046
  *pos=0;          /* End pointer */
6178
6047
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
6179
 
          (char**) to_array.typelib.type_names,
6180
 
          (uint) from_array.typelib.count,
6181
 
          word_end_chars)))
 
6048
                                   (char**) to_array.typelib.type_names,
 
6049
                                   (uint) from_array.typelib.count,
 
6050
                                   word_end_chars)))
6182
6051
    die("Can't initialize replace from '%s'", command->query);
6183
6052
  free_pointer_array(&from_array);
6184
6053
  free_pointer_array(&to_array);
6213
6082
} REPLACE_STRING;
6214
6083
 
6215
6084
 
6216
 
void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
6217
 
                            const char *str,
6218
 
                            int len __attribute__((unused)))
 
6085
void replace_strings_append(REPLACE *rep, string* ds,
 
6086
                            const char *str, int len)
6219
6087
{
6220
6088
  register REPLACE *rep_pos;
6221
6089
  register REPLACE_STRING *rep_str;
6234
6102
    if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6235
6103
    {
6236
6104
      /* No match found */
6237
 
      dynstr_append_mem(ds, start, from - start - 1);
 
6105
      ds->append(start, from - start - 1);
6238
6106
      return;
6239
6107
    }
6240
6108
 
6241
6109
    /* Append part of original string before replace string */
6242
 
    dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
 
6110
    ds->append(start, (from - rep_str->to_offset) - start);
6243
6111
 
6244
6112
    /* Append replace string */
6245
 
    dynstr_append_mem(ds, rep_str->replace_string,
6246
 
                      strlen(rep_str->replace_string));
 
6113
    ds->append(rep_str->replace_string,
 
6114
               strlen(rep_str->replace_string));
6247
6115
 
6248
6116
    if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6249
6117
      return;
6630
6498
/* Init a replace structure for further calls */
6631
6499
 
6632
6500
REPLACE *init_replace(char * *from, char * *to,uint count,
6633
 
          char * word_end_chars)
 
6501
                      char * word_end_chars)
6634
6502
{
6635
6503
  static const int SPACE_CHAR= 256;
6636
6504
  static const int START_OF_LINE= 257;
6670
6538
    return(0);
6671
6539
  found_sets=0;
6672
6540
  if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
6673
 
            MYF(MY_WME))))
 
6541
                                          MYF(MY_WME))))
6674
6542
  {
6675
6543
    free_sets(&sets);
6676
6544
    return(0);
6695
6563
      internal_set_bit(start_states,states+1);
6696
6564
      if (!from[i][2])
6697
6565
      {
6698
 
  start_states->table_offset=i;
6699
 
  start_states->found_offset=1;
 
6566
        start_states->table_offset=i;
 
6567
        start_states->found_offset=1;
6700
6568
      }
6701
6569
    }
6702
6570
    else if (from[i][0] == '\\' && from[i][1] == '$')
6705
6573
      internal_set_bit(word_states,states);
6706
6574
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6707
6575
      {
6708
 
  start_states->table_offset=i;
6709
 
  start_states->found_offset=0;
 
6576
        start_states->table_offset=i;
 
6577
        start_states->found_offset=0;
6710
6578
      }
6711
6579
    }
6712
6580
    else
6713
6581
    {
6714
6582
      internal_set_bit(word_states,states);
6715
6583
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6716
 
  internal_set_bit(start_states,states+1);
 
6584
        internal_set_bit(start_states,states+1);
6717
6585
      else
6718
 
  internal_set_bit(start_states,states);
 
6586
        internal_set_bit(start_states,states);
6719
6587
    }
6720
6588
    for (pos=from[i], len=0; *pos ; pos++)
6721
6589
    {
6722
6590
      if (*pos == '\\' && *(pos+1))
6723
6591
      {
6724
 
  pos++;
6725
 
  switch (*pos) {
6726
 
  case 'b':
6727
 
    follow_ptr->chr = SPACE_CHAR;
6728
 
    break;
6729
 
  case '^':
6730
 
    follow_ptr->chr = START_OF_LINE;
6731
 
    break;
6732
 
  case '$':
6733
 
    follow_ptr->chr = END_OF_LINE;
6734
 
    break;
6735
 
  case 'r':
6736
 
    follow_ptr->chr = '\r';
6737
 
    break;
6738
 
  case 't':
6739
 
    follow_ptr->chr = '\t';
6740
 
    break;
6741
 
  case 'v':
6742
 
    follow_ptr->chr = '\v';
6743
 
    break;
6744
 
  default:
6745
 
    follow_ptr->chr = (uchar) *pos;
6746
 
    break;
6747
 
  }
 
6592
        pos++;
 
6593
        switch (*pos) {
 
6594
        case 'b':
 
6595
          follow_ptr->chr = SPACE_CHAR;
 
6596
          break;
 
6597
        case '^':
 
6598
          follow_ptr->chr = START_OF_LINE;
 
6599
          break;
 
6600
        case '$':
 
6601
          follow_ptr->chr = END_OF_LINE;
 
6602
          break;
 
6603
        case 'r':
 
6604
          follow_ptr->chr = '\r';
 
6605
          break;
 
6606
        case 't':
 
6607
          follow_ptr->chr = '\t';
 
6608
          break;
 
6609
        case 'v':
 
6610
          follow_ptr->chr = '\v';
 
6611
          break;
 
6612
        default:
 
6613
          follow_ptr->chr = (uchar) *pos;
 
6614
          break;
 
6615
        }
6748
6616
      }
6749
6617
      else
6750
 
  follow_ptr->chr= (uchar) *pos;
 
6618
        follow_ptr->chr= (uchar) *pos;
6751
6619
      follow_ptr->table_offset=i;
6752
6620
      follow_ptr->len= ++len;
6753
6621
      follow_ptr++;
6771
6639
    {
6772
6640
      if (!follow[i].chr)
6773
6641
      {
6774
 
  if (! default_state)
6775
 
    default_state= find_found(found_set,set->table_offset,
6776
 
            set->found_offset+1);
 
6642
        if (! default_state)
 
6643
          default_state= find_found(found_set,set->table_offset,
 
6644
                                    set->found_offset+1);
6777
6645
      }
6778
6646
    }
6779
6647
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6786
6654
    {
6787
6655
      used_chars[follow[i].chr]=1;
6788
6656
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6789
 
     follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6790
 
  used_chars[0]=1;
 
6657
           follow[i].len > 1) || follow[i].chr == END_OF_LINE)
 
6658
        used_chars[0]=1;
6791
6659
    }
6792
6660
 
6793
6661
    /* Mark word_chars used if \b is in state */
6794
6662
    if (used_chars[SPACE_CHAR])
6795
6663
      for (pos= word_end_chars ; *pos ; pos++)
6796
 
  used_chars[(int) (uchar) *pos] = 1;
 
6664
        used_chars[(int) (uchar) *pos] = 1;
6797
6665
 
6798
6666
    /* Handle other used characters */
6799
6667
    for (chr= 0 ; chr < 256 ; chr++)
6800
6668
    {
6801
6669
      if (! used_chars[chr])
6802
 
  set->next[chr]= chr ? default_state : -1;
 
6670
        set->next[chr]= chr ? default_state : -1;
6803
6671
      else
6804
6672
      {
6805
 
  new_set=make_new_set(&sets);
6806
 
  set=sets.set+set_nr;      /* if realloc */
6807
 
  new_set->table_offset=set->table_offset;
6808
 
  new_set->found_len=set->found_len;
6809
 
  new_set->found_offset=set->found_offset+1;
6810
 
  found_end=0;
 
6673
        new_set=make_new_set(&sets);
 
6674
        set=sets.set+set_nr;      /* if realloc */
 
6675
        new_set->table_offset=set->table_offset;
 
6676
        new_set->found_len=set->found_len;
 
6677
        new_set->found_offset=set->found_offset+1;
 
6678
        found_end=0;
6811
6679
 
6812
 
  for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6813
 
  {
6814
 
    if (!follow[i].chr || follow[i].chr == chr ||
6815
 
        (follow[i].chr == SPACE_CHAR &&
6816
 
         (is_word_end[chr] ||
6817
 
    (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6818
 
        (follow[i].chr == END_OF_LINE && ! chr))
6819
 
    {
6820
 
      if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6821
 
    follow[i].len > found_end)
6822
 
        found_end=follow[i].len;
6823
 
      if (chr && follow[i].chr)
6824
 
        internal_set_bit(new_set,i+1);    /* To next set */
6825
 
      else
6826
 
        internal_set_bit(new_set,i);
6827
 
    }
6828
 
  }
6829
 
  if (found_end)
6830
 
  {
6831
 
    new_set->found_len=0;      /* Set for testing if first */
6832
 
    bits_set=0;
6833
 
    for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6834
 
    {
6835
 
      if ((follow[i].chr == SPACE_CHAR ||
6836
 
     follow[i].chr == END_OF_LINE) && ! chr)
6837
 
        bit_nr=i+1;
6838
 
      else
6839
 
        bit_nr=i;
6840
 
      if (follow[bit_nr-1].len < found_end ||
6841
 
    (new_set->found_len &&
6842
 
     (chr == 0 || !follow[bit_nr].chr)))
6843
 
        internal_clear_bit(new_set,i);
6844
 
      else
6845
 
      {
6846
 
        if (chr == 0 || !follow[bit_nr].chr)
6847
 
        {          /* best match  */
6848
 
    new_set->table_offset=follow[bit_nr].table_offset;
6849
 
    if (chr || (follow[i].chr == SPACE_CHAR ||
6850
 
          follow[i].chr == END_OF_LINE))
6851
 
      new_set->found_offset=found_end;  /* New match */
6852
 
    new_set->found_len=found_end;
6853
 
        }
6854
 
        bits_set++;
6855
 
      }
6856
 
    }
6857
 
    if (bits_set == 1)
6858
 
    {
6859
 
      set->next[chr] = find_found(found_set,
6860
 
          new_set->table_offset,
6861
 
          new_set->found_offset);
6862
 
      free_last_set(&sets);
6863
 
    }
6864
 
    else
6865
 
      set->next[chr] = find_set(&sets,new_set);
6866
 
  }
6867
 
  else
6868
 
    set->next[chr] = find_set(&sets,new_set);
 
6680
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
 
6681
        {
 
6682
          if (!follow[i].chr || follow[i].chr == chr ||
 
6683
              (follow[i].chr == SPACE_CHAR &&
 
6684
               (is_word_end[chr] ||
 
6685
                (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
 
6686
              (follow[i].chr == END_OF_LINE && ! chr))
 
6687
          {
 
6688
            if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
 
6689
                follow[i].len > found_end)
 
6690
              found_end=follow[i].len;
 
6691
            if (chr && follow[i].chr)
 
6692
              internal_set_bit(new_set,i+1);    /* To next set */
 
6693
            else
 
6694
              internal_set_bit(new_set,i);
 
6695
          }
 
6696
        }
 
6697
        if (found_end)
 
6698
        {
 
6699
          new_set->found_len=0;      /* Set for testing if first */
 
6700
          bits_set=0;
 
6701
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
 
6702
          {
 
6703
            if ((follow[i].chr == SPACE_CHAR ||
 
6704
                 follow[i].chr == END_OF_LINE) && ! chr)
 
6705
              bit_nr=i+1;
 
6706
            else
 
6707
              bit_nr=i;
 
6708
            if (follow[bit_nr-1].len < found_end ||
 
6709
                (new_set->found_len &&
 
6710
                 (chr == 0 || !follow[bit_nr].chr)))
 
6711
              internal_clear_bit(new_set,i);
 
6712
            else
 
6713
            {
 
6714
              if (chr == 0 || !follow[bit_nr].chr)
 
6715
              {          /* best match  */
 
6716
                new_set->table_offset=follow[bit_nr].table_offset;
 
6717
                if (chr || (follow[i].chr == SPACE_CHAR ||
 
6718
                            follow[i].chr == END_OF_LINE))
 
6719
                  new_set->found_offset=found_end;  /* New match */
 
6720
                new_set->found_len=found_end;
 
6721
              }
 
6722
              bits_set++;
 
6723
            }
 
6724
          }
 
6725
          if (bits_set == 1)
 
6726
          {
 
6727
            set->next[chr] = find_found(found_set,
 
6728
                                        new_set->table_offset,
 
6729
                                        new_set->found_offset);
 
6730
            free_last_set(&sets);
 
6731
          }
 
6732
          else
 
6733
            set->next[chr] = find_set(&sets,new_set);
 
6734
        }
 
6735
        else
 
6736
          set->next[chr] = find_set(&sets,new_set);
6869
6737
      }
6870
6738
    }
6871
6739
  }
6873
6741
  /* Alloc replace structure for the replace-state-machine */
6874
6742
 
6875
6743
  if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+
6876
 
            sizeof(REPLACE_STRING)*(found_sets+1)+
6877
 
            sizeof(char *)*count+result_len,
6878
 
            MYF(MY_WME | MY_ZEROFILL))))
 
6744
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
 
6745
                                    sizeof(char *)*count+result_len,
 
6746
                                    MYF(MY_WME | MY_ZEROFILL))))
6879
6747
  {
6880
6748
    rep_str=(REPLACE_STRING*) (replace+sets.count);
6881
6749
    to_array= (char **) (rep_str+found_sets+1);
6894
6762
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
6895
6763
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
6896
6764
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6897
 
  end_of_word(pos);
 
6765
        end_of_word(pos);
6898
6766
    }
6899
6767
    for (i=0 ; i < sets.count ; i++)
6900
6768
    {
6901
6769
      for (j=0 ; j < 256 ; j++)
6902
 
  if (sets.set[i].next[j] >= 0)
6903
 
    replace[i].next[j]=replace+sets.set[i].next[j];
6904
 
  else
6905
 
    replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
 
6770
        if (sets.set[i].next[j] >= 0)
 
6771
          replace[i].next[j]=replace+sets.set[i].next[j];
 
6772
        else
 
6773
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6906
6774
    }
6907
6775
  }
6908
6776
  my_free(follow,MYF(0));
6917
6785
  memset(sets, 0, sizeof(*sets));
6918
6786
  sets->size_of_bits=((states+7)/8);
6919
6787
  if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
6920
 
                MYF(MY_WME))))
 
6788
                                              MYF(MY_WME))))
6921
6789
    return 1;
6922
6790
  if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
6923
 
             SET_MALLOC_HUNC,MYF(MY_WME))))
 
6791
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
6924
6792
  {
6925
6793
    my_free(sets->set,MYF(0));
6926
6794
    return 1;
6956
6824
  count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6957
6825
  if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6958
6826
                                  sizeof(REP_SET)*count,
6959
 
          MYF(MY_WME))))
 
6827
                                  MYF(MY_WME))))
6960
6828
    return 0;
6961
6829
  sets->set_buffer=set;
6962
6830
  sets->set=set+sets->invisible;
6963
6831
  if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
6964
 
              (sizeof(uint)*sets->size_of_bits)*count,
6965
 
              MYF(MY_WME))))
 
6832
                                      (sizeof(uint)*sets->size_of_bits)*count,
 
6833
                                      MYF(MY_WME))))
6966
6834
    return 0;
6967
6835
  sets->bit_buffer=bit_buffer;
6968
6836
  for (i=0 ; i < count ; i++)
7012
6880
void copy_bits(REP_SET *to,REP_SET *from)
7013
6881
{
7014
6882
  memcpy(to->bits,from->bits,
7015
 
   (size_t) (sizeof(uint) * to->size_of_bits));
 
6883
         (size_t) (sizeof(uint) * to->size_of_bits));
7016
6884
}
7017
6885
 
7018
6886
int cmp_bits(REP_SET *set1,REP_SET *set2)
7074
6942
  int i;
7075
6943
  for (i=0 ; (uint) i < found_sets ; i++)
7076
6944
    if (found_set[i].table_offset == table_offset &&
7077
 
  found_set[i].found_offset == found_offset)
 
6945
        found_set[i].found_offset == found_offset)
7078
6946
      return -i-2;
7079
6947
  found_set[i].table_offset=table_offset;
7080
6948
  found_set[i].found_offset=found_offset;
7092
6960
 
7093
6961
uint end_of_word(char * pos)
7094
6962
{
7095
 
  char * end=strend(pos);
 
6963
  char * end= strchr(pos, '\0');
7096
6964
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
7097
6965
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7098
6966
}
7114
6982
  if (! pa->typelib.count)
7115
6983
  {
7116
6984
    if (!(pa->typelib.type_names=(const char **)
7117
 
    my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7118
 
         (sizeof(char *)+sizeof(*pa->flag))*
7119
 
         (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
 
6985
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
 
6986
                     (sizeof(char *)+sizeof(*pa->flag))*
 
6987
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
7120
6988
      return(-1);
7121
6989
    if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
7122
 
             MYF(MY_WME))))
 
6990
                                      MYF(MY_WME))))
7123
6991
    {
7124
6992
      my_free((char*) pa->typelib.type_names,MYF(0));
7125
6993
      return (-1);
7126
6994
    }
7127
6995
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7128
 
                 sizeof(*pa->flag));
 
6996
                                               sizeof(*pa->flag));
7129
6997
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7130
6998
    pa->length=0;
7131
6999
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
7135
7003
  if (pa->length+length >= pa->max_length)
7136
7004
  {
7137
7005
    if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
7138
 
              (uint) (pa->max_length+PS_MALLOC),
7139
 
              MYF(MY_WME))))
 
7006
                                       (uint) (pa->max_length+PS_MALLOC),
 
7007
                                       MYF(MY_WME))))
7140
7008
      return(1);
7141
7009
    if (new_pos != pa->str)
7142
7010
    {
7143
7011
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
7144
7012
      for (i=0 ; i < pa->typelib.count ; i++)
7145
 
  pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
7146
 
                char*);
 
7013
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
 
7014
                                              char*);
7147
7015
      pa->str=new_pos;
7148
7016
    }
7149
7017
    pa->max_length+=PS_MALLOC;
7154
7022
    pa->array_allocs++;
7155
7023
    len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7156
7024
    if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
7157
 
                 (uint) len/
 
7025
                                               (uint) len/
7158
7026
                                               (sizeof(uchar*)+sizeof(*pa->flag))*
7159
7027
                                               (sizeof(uchar*)+sizeof(*pa->flag)),
7160
7028
                                               MYF(MY_WME))))
7192
7060
/* Functions that uses replace and replace_regex */
7193
7061
 
7194
7062
/* Append the string to ds, with optional replace */
7195
 
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
7196
 
                               const char *val, int len)
 
7063
void replace_append_mem(string *ds,
 
7064
                        const char *val, int len)
7197
7065
{
 
7066
  char *v= strdup(val);
 
7067
 
7198
7068
  if (glob_replace_regex)
7199
7069
  {
7200
7070
    /* Regex replace */
7201
 
    if (!multi_reg_replace(glob_replace_regex, (char*)val))
 
7071
    if (!multi_reg_replace(glob_replace_regex, v))
7202
7072
    {
7203
 
      val= glob_replace_regex->buf;
7204
 
      len= strlen(val);
 
7073
      v= glob_replace_regex->buf;
 
7074
      len= strlen(v);
7205
7075
    }
7206
7076
  }
7207
7077
 
7208
7078
  if (glob_replace)
7209
7079
  {
7210
7080
    /* Normal replace */
7211
 
    replace_strings_append(glob_replace, ds, val, len);
 
7081
    replace_strings_append(glob_replace, ds, v, len);
7212
7082
  }
7213
7083
  else
7214
 
    dynstr_append_mem(ds, val, len);
 
7084
  {
 
7085
    ds->append(v, len);
 
7086
  }
7215
7087
}
7216
7088
 
7217
7089
 
7218
7090
/* Append zero-terminated string to ds, with optional replace */
7219
 
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
 
7091
void replace_append(string *ds, const char *val)
7220
7092
{
7221
 
  replace_dynstr_append_mem(ds, val, strlen(val));
 
7093
  replace_append_mem(ds, val, strlen(val));
7222
7094
}
7223
7095
 
7224
7096
/* Append uint to ds, with optional replace */
7225
 
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
 
7097
void replace_append_uint(string *ds, uint val)
7226
7098
{
7227
7099
  char buff[22]; /* This should be enough for any int */
7228
7100
  char *end= int64_t10_to_str(val, buff, 10);
7229
 
  replace_dynstr_append_mem(ds, buff, end - buff);
 
7101
  replace_append_mem(ds, buff, end - buff);
 
7102
 
7230
7103
}
7231
7104
 
7232
7105
 
7243
7116
 
7244
7117
*/
7245
7118
 
7246
 
static int comp_lines(const char **a, const char **b)
7247
 
{
7248
 
  return (strcmp(*a,*b));
7249
 
}
7250
 
 
7251
 
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
7252
 
{
7253
 
  unsigned i;
7254
 
  char *start= ds_input->str;
7255
 
  DYNAMIC_ARRAY lines;
7256
 
 
7257
 
 
7258
 
  if (!*start)
 
7119
 
 
7120
void append_sorted(string* ds, string *ds_input)
 
7121
{
 
7122
  priority_queue<string> lines;
 
7123
 
 
7124
  if (ds_input->empty())
7259
7125
    return;  /* No input */
7260
7126
 
7261
 
  my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
7262
 
 
7263
 
  /* First line is result header, skip past it */
7264
 
  while (*start && *start != '\n')
7265
 
    start++;
7266
 
  start++; /* Skip past \n */
7267
 
  dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
 
7127
  unsigned long eol_pos= 0;
 
7128
 
 
7129
  eol_pos= ds_input->find_first_of('\n', 0);
 
7130
  if (eol_pos == string::npos)
 
7131
    return; // We should have at least one header here
 
7132
 
 
7133
  ds->append(ds_input->substr(0, eol_pos));
 
7134
 
 
7135
  unsigned long start_pos= eol_pos+1;
7268
7136
 
7269
7137
  /* Insert line(s) in array */
7270
 
  while (*start)
7271
 
  {
7272
 
    char* line_end= (char*)start;
 
7138
  do {
7273
7139
 
 
7140
    eol_pos= ds_input->find_first_of('\n', start_pos);
7274
7141
    /* Find end of line */
7275
 
    while (*line_end && *line_end != '\n')
7276
 
      line_end++;
7277
 
    *line_end= 0;
7278
 
 
7279
 
    /* Insert pointer to the line in array */
7280
 
    if (insert_dynamic(&lines, (uchar*) &start))
7281
 
      die("Out of memory inserting lines to sort");
7282
 
 
7283
 
    start= line_end+1;
7284
 
  }
7285
 
 
7286
 
  /* Sort array */
7287
 
  qsort(lines.buffer, lines.elements,
7288
 
        sizeof(char**), (qsort_cmp)comp_lines);
 
7142
    lines.push(ds_input->substr(start_pos, eol_pos-start_pos));
 
7143
    start_pos= eol_pos+1;
 
7144
 
 
7145
  } while ( eol_pos != string::npos);
7289
7146
 
7290
7147
  /* Create new result */
7291
 
  for (i= 0; i < lines.elements ; i++)
7292
 
  {
7293
 
    const char **line= dynamic_element(&lines, i, const char**);
7294
 
    dynstr_append(ds, *line);
7295
 
    dynstr_append(ds, "\n");
 
7148
  while (!lines.empty()) {
 
7149
    ds->append(lines.top());
 
7150
    lines.pop();
7296
7151
  }
7297
7152
 
7298
 
  delete_dynamic(&lines);
7299
7153
  return;
7300
7154
}