~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Brian Aker
  • Date: 2008-08-10 16:57:26 UTC
  • Revision ID: brian@tangent.org-20080810165726-mc1660l11a5vkv69
libdrizzle has ulong removed.

Show diffs side-by-side

added added

removed removed

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