~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Moriyoshi Koizumi
  • Date: 2008-11-15 18:36:31 UTC
  • mto: (584.1.5 devel)
  • mto: This revision was merged to the branch mainline in revision 588.
  • Revision ID: mozo@mozo.jp-20081115183631-81d0clowyot42mk7
Incorporating changes proposed by mtaylor.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 * 
4
 
 *  Copyright (C) 2010 Vijay Samuel
 
3
 *
5
4
 *  Copyright (C) 2008 MySQL
6
5
 *
7
6
 *  This program is free software; you can redistribute it and/or modify
39
38
 
40
39
#define MTEST_VERSION "3.3"
41
40
 
 
41
#include <config.h>
42
42
#include "client_priv.h"
43
43
 
44
44
#include <queue>
45
45
#include <map>
46
46
#include <string>
47
 
#include <sstream>
48
 
#include <fstream>
49
 
#include <iostream>
50
47
#include <vector>
51
 
#include <algorithm>
52
 
#ifdef HAVE_SYS_WAIT_H
53
 
#include <sys/wait.h>
54
 
#endif
55
 
#include <cassert>
56
 
#include <sys/stat.h>
57
 
#include <sys/types.h>
58
 
#include <fcntl.h>
59
 
#include <boost/array.hpp>
60
 
#include <boost/foreach.hpp>
61
 
#include <boost/program_options.hpp>
62
 
#include <boost/smart_ptr.hpp>
63
 
 
64
 
#include PCRE_HEADER
65
 
 
 
48
 
 
49
#include <pcrecpp.h>
 
50
 
 
51
#include <mysys/hash.h>
66
52
#include <stdarg.h>
67
 
#include <boost/unordered_map.hpp>
68
 
 
69
 
/* Added this for string translation. */
70
 
#include <drizzled/gettext.h>
71
 
#include <drizzled/type/time.h>
72
 
#include <drizzled/charset.h>
73
 
#include <drizzled/typelib.h>
74
 
#include <drizzled/configmake.h>
75
 
 
76
 
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
77
 
 
78
 
#ifndef DRIZZLE_RETURN_SERVER_GONE
79
 
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
80
 
#endif
81
 
namespace po= boost::program_options;
 
53
 
 
54
#include "errname.h"
 
55
 
82
56
using namespace std;
83
 
using namespace drizzled;
84
 
 
85
 
extern "C"
86
 
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
87
 
 
88
 
int get_one_option(int optid, const struct option *, char *argument);
89
57
 
90
58
#define MAX_VAR_NAME_LENGTH    256
91
59
#define MAX_COLUMNS            256
 
60
#define MAX_EMBEDDED_SERVER_ARGS 64
92
61
#define MAX_DELIMITER_LENGTH 16
93
62
/* Flags controlling send and reap */
94
63
#define QUERY_SEND_FLAG  1
95
64
#define QUERY_REAP_FLAG  2
96
65
 
97
 
typedef boost::unordered_map<std::string, uint32_t> ErrorCodes;
98
 
ErrorCodes global_error_names;
99
 
 
100
66
enum {
101
67
  OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
102
 
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
103
 
  OPT_TESTDIR
 
68
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
104
69
};
105
70
 
106
71
static int record= 0, opt_sleep= -1;
107
 
static char *opt_pass= NULL;
108
 
const char *unix_sock= NULL;
109
 
static uint32_t opt_port= 0;
110
 
static uint32_t opt_max_connect_retries;
111
 
static bool silent= false, verbose= false;
112
 
static bool opt_mark_progress= false;
113
 
static bool parsing_disabled= false;
 
72
static char *opt_db= 0, *opt_pass= 0;
 
73
const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./";
 
74
const char *opt_logdir= "";
 
75
const char *opt_include= 0, *opt_charsets_dir;
 
76
static int opt_port= 0;
 
77
static int opt_max_connect_retries;
 
78
static bool opt_compress= 0, silent= 0, verbose= 0;
 
79
static bool debug_info_flag= 0, debug_check_flag= 0;
 
80
static bool tty_password= 0;
 
81
static bool opt_mark_progress= 0;
 
82
static bool parsing_disabled= 0;
114
83
static bool display_result_vertically= false,
115
84
  display_metadata= false, display_result_sorted= false;
116
 
static bool disable_query_log= false, disable_result_log= false;
117
 
static bool disable_warnings= false;
118
 
static bool disable_info= true;
119
 
static bool abort_on_error= true;
120
 
static bool server_initialized= false;
121
 
static bool is_windows= false;
122
 
static bool use_drizzle_protocol= false;
 
85
static bool disable_query_log= 0, disable_result_log= 0;
 
86
static bool disable_warnings= 0;
 
87
static bool disable_info= 1;
 
88
static bool abort_on_error= 1;
 
89
static bool server_initialized= 0;
 
90
static bool is_windows= 0;
 
91
static char **default_argv;
 
92
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
123
93
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
124
 
static void free_all_replace();
125
 
 
126
 
std::string opt_basedir,
127
 
  opt_charsets_dir,
128
 
  opt_db,
129
 
  opt_host,
130
 
  opt_include,
131
 
  opt_testdir,
132
 
  opt_logdir,
133
 
  password,
134
 
  opt_password,
135
 
  result_file_name,
136
 
  opt_user,
137
 
  opt_protocol;
138
 
 
139
 
static uint32_t start_lineno= 0; /* Start line of current command */
 
94
 
 
95
static uint start_lineno= 0; /* Start line of current command */
 
96
static uint my_end_arg= 0;
140
97
 
141
98
/* Number of lines of the result to include in failure report */
142
 
static uint32_t opt_tail_lines= 0;
 
99
static uint opt_tail_lines= 0;
143
100
 
144
101
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
145
 
static uint32_t delimiter_length= 1;
 
102
static uint delimiter_length= 1;
146
103
 
147
104
static char TMPDIR[FN_REFLEN];
148
105
 
168
125
{
169
126
  FILE* file;
170
127
  const char *file_name;
171
 
  uint32_t lineno; /* Current line in file */
 
128
  uint lineno; /* Current line in file */
172
129
};
173
130
 
174
 
static boost::array<st_test_file, 16> file_stack;
175
 
static st_test_file* cur_file;
 
131
static struct st_test_file file_stack[16];
 
132
static struct st_test_file* cur_file;
 
133
static struct st_test_file* file_stack_end;
 
134
 
176
135
 
177
136
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
178
137
 
 
138
static int embedded_server_arg_count=0;
 
139
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
 
140
 
179
141
/*
180
142
  Timer related variables
181
143
  See the timer_output() definition for details
182
144
*/
183
145
static char *timer_file = NULL;
184
146
static uint64_t timer_start;
185
 
static void timer_output();
186
 
static uint64_t timer_now();
 
147
static void timer_output(void);
 
148
static uint64_t timer_now(void);
187
149
 
188
150
static uint64_t progress_start= 0;
189
151
 
203
165
master_pos_st master_pos;
204
166
 
205
167
/* if set, all results are concated and compared against this file */
 
168
const char *result_file_name= 0;
206
169
 
207
 
class VAR
 
170
typedef struct st_var
208
171
{
209
 
public:
210
172
  char *name;
211
173
  int name_len;
212
174
  char *str_val;
216
178
  int int_dirty; /* do not update string if int is updated until first read */
217
179
  int alloced;
218
180
  char *env_s;
219
 
};
 
181
} VAR;
220
182
 
221
183
/*Perl/shell-like variable registers */
222
 
boost::array<VAR, 10> var_reg;
 
184
VAR var_reg[10];
223
185
 
224
 
typedef boost::unordered_map<string, VAR *> var_hash_t;
225
 
var_hash_t var_hash;
 
186
HASH var_hash;
226
187
 
227
188
struct st_connection
228
189
{
229
 
  drizzle_st *drizzle;
230
 
  drizzle_con_st con;
 
190
  DRIZZLE drizzle;
231
191
  /* Used when creating views and sp, to avoid implicit commit */
232
 
  drizzle_con_st *util_con;
 
192
  DRIZZLE *util_drizzle;
233
193
  char *name;
234
194
};
235
195
struct st_connection connections[128];
385
345
  enum match_err_type type;
386
346
  union
387
347
  {
388
 
    uint32_t errnum;
389
 
    char sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE+1];  /* \0 terminated string */
 
348
    uint errnum;
 
349
    char sqlstate[SQLSTATE_LENGTH+1];  /* \0 terminated string */
390
350
  } code;
391
351
};
392
352
 
393
353
struct st_expected_errors
394
354
{
395
355
  struct st_match_err err[10];
396
 
  uint32_t count;
 
356
  uint count;
397
357
};
398
 
 
399
 
static st_expected_errors saved_expected_errors;
400
 
 
401
 
class st_command
 
358
static struct st_expected_errors saved_expected_errors;
 
359
 
 
360
struct st_command
402
361
{
403
 
public:
404
362
  char *query, *query_buf,*first_argument,*last_argument,*end;
405
363
  int first_word_len, query_len;
406
364
  bool abort_on_error;
407
 
  st_expected_errors expected_errors;
408
 
  string require_file;
409
 
  enum_commands type;
410
 
 
411
 
  st_command()
412
 
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
413
 
      end(NULL), first_word_len(0), query_len(0), abort_on_error(false),
414
 
      require_file(""), type(Q_CONNECTION)
415
 
  {
416
 
    memset(&expected_errors, 0, sizeof(st_expected_errors));
417
 
  }
418
 
 
419
 
  ~st_command()
420
 
  {
421
 
    free(query_buf);
422
 
  }
 
365
  struct st_expected_errors expected_errors;
 
366
  char require_file[FN_REFLEN];
 
367
  enum enum_commands type;
423
368
};
424
369
 
425
370
TYPELIB command_typelib= {array_elements(command_names),"",
443
388
VAR* var_from_env(const char *, const char *);
444
389
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
445
390
              int val_len);
 
391
void var_free(void* v);
446
392
VAR* var_get(const char *var_name, const char** var_name_end,
447
393
             bool raw, bool ignore_not_existing);
448
394
void eval_expr(VAR* v, const char *p, const char** p_end);
449
 
bool match_delimiter(int c, const char *delim, uint32_t length);
 
395
bool match_delimiter(int c, const char *delim, uint length);
450
396
void dump_result_to_reject_file(char *buf, int size);
451
397
void dump_result_to_log_file(const char *buf, int size);
452
 
void dump_warning_messages();
453
 
void dump_progress();
 
398
void dump_warning_messages(void);
 
399
void dump_progress(void);
454
400
 
455
401
void do_eval(string *query_eval, const char *query,
456
402
             const char *query_end, bool pass_through_escape_chars);
459
405
 
460
406
/* For replace_column */
461
407
static char *replace_column[MAX_COLUMNS];
462
 
static uint32_t max_replace_column= 0;
 
408
static uint max_replace_column= 0;
463
409
void do_get_replace_column(struct st_command*);
464
 
void free_replace_column();
 
410
void free_replace_column(void);
465
411
 
466
412
/* For replace */
467
413
void do_get_replace(struct st_command *command);
468
 
void free_replace();
 
414
void free_replace(void);
469
415
 
470
416
/* For replace_regex */
471
417
void do_get_replace_regex(struct st_command *command);
 
418
void free_replace_regex(void);
 
419
 
 
420
 
 
421
void free_all_replace(void);
 
422
 
 
423
 
 
424
void free_all_replace(void){
 
425
  free_replace();
 
426
  free_replace_regex();
 
427
  free_replace_column();
 
428
}
472
429
 
473
430
void replace_append_mem(string *ds, const char *val,
474
431
                        int len);
475
432
void replace_append(string *ds, const char *val);
476
 
void replace_append_uint(string *ds, uint32_t val);
 
433
void replace_append_uint(string *ds, uint val);
477
434
void append_sorted(string* ds, string* ds_input);
478
435
 
479
436
void handle_error(struct st_command*,
482
439
void handle_no_error(struct st_command*);
483
440
 
484
441
 
 
442
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
 
443
 
485
444
void do_eval(string *query_eval, const char *query,
486
445
             const char *query_end, bool pass_through_escape_chars)
487
446
{
488
 
  char c, next_c;
489
 
  int escaped = 0;
 
447
  const char *p;
 
448
  register char c, next_c;
 
449
  register int escaped = 0;
490
450
  VAR *v;
491
451
 
492
 
  for (const char *p= query; (c= *p) && p < query_end; ++p)
 
452
 
 
453
  for (p= query; (c= *p) && p < query_end; ++p)
493
454
  {
494
455
    switch(c) {
495
456
    case '$':
550
511
  options are passed.
551
512
*/
552
513
 
553
 
static void append_os_quoted(string *str, const char *append, ...)
 
514
void append_os_quoted(string *str, const char *append, ...)
554
515
{
555
516
  const char *quote_str= "\'";
556
 
  const uint32_t  quote_len= 1;
 
517
  const uint  quote_len= 1;
557
518
 
558
519
  va_list dirty_text;
559
520
 
593
554
 
594
555
*/
595
556
 
596
 
static void show_query(drizzle_con_st *con, const char* query)
 
557
static void show_query(DRIZZLE *drizzle, const char* query)
597
558
{
598
 
  drizzle_result_st res;
599
 
  drizzle_return_t ret;
600
 
 
601
 
  if (!con)
 
559
  DRIZZLE_RES* res;
 
560
 
 
561
 
 
562
  if (!drizzle)
602
563
    return;
603
564
 
604
 
  if (drizzle_query_str(con, &res, query, &ret) == NULL ||
605
 
      ret != DRIZZLE_RETURN_OK)
 
565
  if (drizzle_query(drizzle, query))
606
566
  {
607
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
608
 
    {
609
 
      log_msg("Error running query '%s': %d %s",
610
 
              query, drizzle_result_error_code(&res),
611
 
              drizzle_result_error(&res));
612
 
      drizzle_result_free(&res);
613
 
    }
614
 
    else
615
 
    {
616
 
      log_msg("Error running query '%s': %d %s",
617
 
              query, ret, drizzle_con_error(con));
618
 
    }
 
567
    log_msg("Error running query '%s': %d %s",
 
568
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
619
569
    return;
620
570
  }
621
571
 
622
 
  if (drizzle_result_column_count(&res) == 0 ||
623
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
572
  if ((res= drizzle_store_result(drizzle)) == NULL)
624
573
  {
625
574
    /* No result set returned */
626
 
    drizzle_result_free(&res);
627
575
    return;
628
576
  }
629
577
 
630
578
  {
631
 
    drizzle_row_t row;
 
579
    DRIZZLE_ROW row;
632
580
    unsigned int i;
633
581
    unsigned int row_num= 0;
634
 
    unsigned int num_fields= drizzle_result_column_count(&res);
635
 
    drizzle_column_st *column;
 
582
    unsigned int num_fields= drizzle_num_fields(res);
 
583
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
636
584
 
637
585
    fprintf(stderr, "=== %s ===\n", query);
638
 
    while ((row= drizzle_row_next(&res)))
 
586
    while ((row= drizzle_fetch_row(res)))
639
587
    {
640
 
      size_t *lengths= drizzle_row_field_sizes(&res);
 
588
      uint32_t *lengths= drizzle_fetch_lengths(res);
641
589
      row_num++;
642
590
 
643
591
      fprintf(stderr, "---- %d. ----\n", row_num);
644
 
      drizzle_column_seek(&res, 0);
645
592
      for(i= 0; i < num_fields; i++)
646
593
      {
647
 
        column= drizzle_column_next(&res);
648
594
        fprintf(stderr, "%s\t%.*s\n",
649
 
                drizzle_column_name(column),
 
595
                fields[i].name,
650
596
                (int)lengths[i], row[i] ? row[i] : "NULL");
651
597
      }
652
598
    }
654
600
      fprintf(stderr, "=");
655
601
    fprintf(stderr, "\n\n");
656
602
  }
657
 
  drizzle_result_free(&res);
 
603
  drizzle_free_result(res);
658
604
 
659
605
  return;
660
606
}
673
619
 
674
620
*/
675
621
 
676
 
static void show_warnings_before_error(drizzle_con_st *con)
 
622
static void show_warnings_before_error(DRIZZLE *drizzle)
677
623
{
678
 
  drizzle_result_st res;
679
 
  drizzle_return_t ret;
 
624
  DRIZZLE_RES* res;
680
625
  const char* query= "SHOW WARNINGS";
681
626
 
682
 
  if (!con)
 
627
 
 
628
  if (!drizzle)
683
629
    return;
684
630
 
685
 
  if (drizzle_query_str(con, &res, query, &ret) == NULL ||
686
 
      ret != DRIZZLE_RETURN_OK)
 
631
  if (drizzle_query(drizzle, query))
687
632
  {
688
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
689
 
    {
690
 
      log_msg("Error running query '%s': %d %s",
691
 
              query, drizzle_result_error_code(&res),
692
 
              drizzle_result_error(&res));
693
 
      drizzle_result_free(&res);
694
 
    }
695
 
    else
696
 
    {
697
 
      log_msg("Error running query '%s': %d %s",
698
 
              query, ret, drizzle_con_error(con));
699
 
    }
 
633
    log_msg("Error running query '%s': %d %s",
 
634
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
700
635
    return;
701
636
  }
702
637
 
703
 
  if (drizzle_result_column_count(&res) == 0 ||
704
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
638
  if ((res= drizzle_store_result(drizzle)) == NULL)
705
639
  {
706
640
    /* No result set returned */
707
 
    drizzle_result_free(&res);
708
641
    return;
709
642
  }
710
643
 
711
 
  if (drizzle_result_row_count(&res) <= 1)
 
644
  if (drizzle_num_rows(res) <= 1)
712
645
  {
713
646
    /* Don't display the last row, it's "last error" */
714
647
  }
715
648
  else
716
649
  {
717
 
    drizzle_row_t row;
 
650
    DRIZZLE_ROW row;
718
651
    unsigned int row_num= 0;
719
 
    unsigned int num_fields= drizzle_result_column_count(&res);
 
652
    unsigned int num_fields= drizzle_num_fields(res);
720
653
 
721
654
    fprintf(stderr, "\nWarnings from just before the error:\n");
722
 
    while ((row= drizzle_row_next(&res)))
 
655
    while ((row= drizzle_fetch_row(res)))
723
656
    {
724
657
      uint32_t i;
725
 
      size_t *lengths= drizzle_row_field_sizes(&res);
 
658
      uint32_t *lengths= drizzle_fetch_lengths(res);
726
659
 
727
 
      if (++row_num >= drizzle_result_row_count(&res))
 
660
      if (++row_num >= drizzle_num_rows(res))
728
661
      {
729
662
        /* Don't display the last row, it's "last error" */
730
663
        break;
738
671
      fprintf(stderr, "\n");
739
672
    }
740
673
  }
741
 
  drizzle_result_free(&res);
 
674
  drizzle_free_result(res);
742
675
 
743
676
  return;
744
677
}
771
704
  for (i= 0; i < num_args; i++)
772
705
  {
773
706
    const struct command_arg *arg= &args[i];
774
 
    arg->ds->clear();
775
707
 
776
 
    bool known_arg_type= true;
777
708
    switch (arg->type) {
778
709
      /* A string */
779
710
    case ARG_STRING:
808
739
      break;
809
740
 
810
741
    default:
811
 
      known_arg_type= false;
 
742
      assert("Unknown argument type");
812
743
      break;
813
744
    }
814
 
    assert(known_arg_type);
815
745
 
816
746
    /* Check required arg */
817
747
    if (arg->ds->length() == 0 && arg->required)
832
762
}
833
763
 
834
764
 
835
 
static void handle_command_error(struct st_command *command, uint32_t error)
 
765
static void handle_command_error(struct st_command *command, uint error)
836
766
{
 
767
 
837
768
  if (error != 0)
838
769
  {
839
 
    uint32_t i;
 
770
    uint i;
840
771
 
841
772
    if (command->abort_on_error)
842
773
      die("command \"%.*s\" failed with error %d",
860
791
        command->first_word_len, command->query,
861
792
        command->expected_errors.err[0].code.errnum);
862
793
  }
 
794
  return;
863
795
}
864
796
 
865
797
 
866
 
static void close_connections()
 
798
static void close_connections(void)
867
799
{
 
800
 
868
801
  for (--next_con; next_con >= connections; --next_con)
869
802
  {
870
 
    if (next_con->drizzle != NULL)
871
 
    {
872
 
      drizzle_free(next_con->drizzle);
873
 
      next_con->drizzle= NULL;
874
 
    }
 
803
    drizzle_close(&next_con->drizzle);
 
804
    if (next_con->util_drizzle)
 
805
      drizzle_close(next_con->util_drizzle);
875
806
    free(next_con->name);
876
807
  }
 
808
  return;
877
809
}
878
810
 
879
811
 
880
 
static void close_files()
 
812
static void close_files(void)
881
813
{
882
 
  for (; cur_file >= file_stack.data(); cur_file--)
 
814
 
 
815
  for (; cur_file >= file_stack; cur_file--)
883
816
  {
884
817
    if (cur_file->file && cur_file->file != stdin)
885
 
      fclose(cur_file->file);
886
 
    free(const_cast<char*>(cur_file->file_name));
 
818
    {
 
819
      my_fclose(cur_file->file, MYF(0));
 
820
    }
 
821
    free((unsigned char*) cur_file->file_name);
887
822
    cur_file->file_name= 0;
888
823
  }
 
824
  return;
889
825
}
890
826
 
891
 
static void free_used_memory()
 
827
 
 
828
static void free_used_memory(void)
892
829
{
 
830
  uint i;
 
831
 
 
832
 
893
833
  close_connections();
894
834
  close_files();
895
 
  BOOST_FOREACH(var_hash_t::reference i, var_hash)
 
835
  hash_free(&var_hash);
 
836
 
 
837
  vector<struct st_command *>::iterator iter;
 
838
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
896
839
  {
897
 
    free(i.second->str_val);
898
 
    free(i.second->env_s);
899
 
    if (i.second->alloced)
900
 
      free(i.second);
 
840
    struct st_command * q_line= *iter;
 
841
    if (q_line->query_buf != NULL)
 
842
    {
 
843
      free(q_line->query_buf);
 
844
    }
 
845
    free(q_line);
901
846
  }
902
 
  var_hash.clear();
903
 
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
904
 
    delete i;
905
 
  for (size_t i= 0; i < var_reg.size(); i++)
 
847
 
 
848
  for (i= 0; i < 10; i++)
906
849
  {
907
850
    if (var_reg[i].alloced_len)
908
851
      free(var_reg[i].str_val);
909
852
  }
 
853
  while (embedded_server_arg_count > 1)
 
854
    free(embedded_server_args[--embedded_server_arg_count]);
 
855
 
910
856
  free_all_replace();
911
857
  free(opt_pass);
 
858
  free_defaults(default_argv);
 
859
 
 
860
  return;
912
861
}
913
862
 
914
863
 
915
864
static void cleanup_and_exit(int exit_code)
916
865
{
917
866
  free_used_memory();
918
 
  internal::my_end();
 
867
  my_end(my_end_arg);
919
868
 
920
869
  if (!silent) {
921
870
    switch (exit_code) {
933
882
      assert(0);
934
883
    }
935
884
  }
 
885
 
936
886
  exit(exit_code);
937
887
}
938
888
 
952
902
 
953
903
  /* Print the error message */
954
904
  fprintf(stderr, "drizzletest: ");
955
 
  if (cur_file && cur_file != file_stack.data())
 
905
  if (cur_file && cur_file != file_stack)
956
906
    fprintf(stderr, "In included file \"%s\": ",
957
907
            cur_file->file_name);
958
908
  if (start_lineno > 0)
987
937
  }
988
938
 
989
939
  /* Dump the result that has been accumulated so far to .log file */
990
 
  if (! result_file_name.empty() && ds_res.length())
 
940
  if (result_file_name && ds_res.length())
991
941
    dump_result_to_log_file(ds_res.c_str(), ds_res.length());
992
942
 
993
943
  /* Dump warning messages */
994
 
  if (! result_file_name.empty() && ds_warning_messages.length())
 
944
  if (result_file_name && ds_warning_messages.length())
995
945
    dump_warning_messages();
996
946
 
997
947
  /*
999
949
    been produced prior to the error
1000
950
  */
1001
951
  if (cur_con)
1002
 
    show_warnings_before_error(&cur_con->con);
 
952
    show_warnings_before_error(&cur_con->drizzle);
1003
953
 
1004
954
  cleanup_and_exit(1);
1005
955
}
1013
963
 
1014
964
  /* Print include filestack */
1015
965
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1016
 
          file_stack[0].file_name);
 
966
          file_stack->file_name);
1017
967
  fprintf(stderr, "Detected in file %s at line %d\n",
1018
968
          err_file->file_name, err_file->lineno);
1019
 
  while (err_file != file_stack.data())
 
969
  while (err_file != file_stack)
1020
970
  {
1021
971
    err_file--;
1022
972
    fprintf(stderr, "included from %s at line %d\n",
1047
997
 
1048
998
  va_start(args, fmt);
1049
999
  fprintf(stderr, "drizzletest: ");
1050
 
  if (cur_file && cur_file != file_stack.data())
 
1000
  if (cur_file && cur_file != file_stack)
1051
1001
    fprintf(stderr, "In included file \"%s\": ",
1052
1002
            cur_file->file_name);
1053
1003
  if (start_lineno != 0)
1055
1005
  vfprintf(stderr, fmt, args);
1056
1006
  fprintf(stderr, "\n");
1057
1007
  va_end(args);
 
1008
 
 
1009
  return;
1058
1010
}
1059
1011
 
1060
1012
 
1070
1022
  if (start_lineno != 0)
1071
1023
  {
1072
1024
    ds_warning_messages.append("Warning detected ");
1073
 
    if (cur_file && cur_file != file_stack.data())
 
1025
    if (cur_file && cur_file != file_stack)
1074
1026
    {
1075
1027
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1076
1028
                    cur_file->file_name);
1122
1074
static void cat_file(string* ds, const char* filename)
1123
1075
{
1124
1076
  int fd;
1125
 
  uint32_t len;
 
1077
  uint len;
1126
1078
  char buff[512];
1127
1079
 
1128
 
  if ((fd= internal::my_open(filename, O_RDONLY, MYF(0))) < 0)
 
1080
  if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
1129
1081
    die("Failed to open file '%s'", filename);
1130
 
  while((len= internal::my_read(fd, (unsigned char*)&buff,
 
1082
  while((len= my_read(fd, (unsigned char*)&buff,
1131
1083
                      sizeof(buff), MYF(0))) > 0)
1132
1084
  {
1133
1085
    char *p= buff, *start= buff;
1149
1101
    /* Output any chars that might be left */
1150
1102
    ds->append(start, p-start);
1151
1103
  }
1152
 
  internal::my_close(fd, MYF(0));
 
1104
  my_close(fd, MYF(0));
1153
1105
}
1154
1106
 
1155
1107
 
1254
1206
               "2>&1",
1255
1207
               NULL) > 1) /* Most "diff" tools return >1 if error */
1256
1208
  {
 
1209
    ds_tmp= "";
1257
1210
 
1258
1211
    /* Fallback to context diff with "diff -c" */
1259
1212
    if (run_tool("diff",
1268
1221
        Fallback to dump both files to result file and inform
1269
1222
        about installing "diff"
1270
1223
      */
1271
 
      ds_tmp.clear();
 
1224
      ds_tmp= "";
1272
1225
 
1273
1226
      ds_tmp.append(
1274
1227
                    "\n"
1325
1278
 
1326
1279
*/
1327
1280
 
1328
 
static int compare_files2(int fd, const char* filename2)
 
1281
static int compare_files2(File fd, const char* filename2)
1329
1282
{
1330
1283
  int error= RESULT_OK;
1331
 
  int fd2;
1332
 
  uint32_t len, len2;
 
1284
  File fd2;
 
1285
  uint len, len2;
1333
1286
  char buff[512], buff2[512];
1334
 
  const char *fname= filename2;
1335
 
  string tmpfile;
1336
1287
 
1337
 
  if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
 
1288
  if ((fd2= my_open(filename2, O_RDONLY, MYF(0))) < 0)
1338
1289
  {
1339
 
    internal::my_close(fd, MYF(0));
1340
 
    if (! opt_testdir.empty())
1341
 
    {
1342
 
      tmpfile= opt_testdir;
1343
 
      if (tmpfile[tmpfile.length()] != '/')
1344
 
        tmpfile.append("/");
1345
 
      tmpfile.append(filename2);
1346
 
      fname= tmpfile.c_str();
1347
 
    }
1348
 
    if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
1349
 
    {
1350
 
      internal::my_close(fd, MYF(0));
1351
 
    
1352
 
      die("Failed to open second file: '%s'", fname);
1353
 
    }
 
1290
    my_close(fd, MYF(0));
 
1291
    die("Failed to open second file: '%s'", filename2);
1354
1292
  }
1355
 
  while((len= internal::my_read(fd, (unsigned char*)&buff,
 
1293
  while((len= my_read(fd, (unsigned char*)&buff,
1356
1294
                      sizeof(buff), MYF(0))) > 0)
1357
1295
  {
1358
 
    if ((len2= internal::my_read(fd2, (unsigned char*)&buff2,
 
1296
    if ((len2= my_read(fd2, (unsigned char*)&buff2,
1359
1297
                       sizeof(buff2), MYF(0))) < len)
1360
1298
    {
1361
1299
      /* File 2 was smaller */
1375
1313
      break;
1376
1314
    }
1377
1315
  }
1378
 
  if (!error && internal::my_read(fd2, (unsigned char*)&buff2,
 
1316
  if (!error && my_read(fd2, (unsigned char*)&buff2,
1379
1317
                        sizeof(buff2), MYF(0)) > 0)
1380
1318
  {
1381
1319
    /* File 1 was smaller */
1382
1320
    error= RESULT_LENGTH_MISMATCH;
1383
1321
  }
1384
1322
 
1385
 
  internal::my_close(fd2, MYF(0));
 
1323
  my_close(fd2, MYF(0));
1386
1324
 
1387
1325
  return error;
1388
1326
}
1403
1341
 
1404
1342
static int compare_files(const char* filename1, const char* filename2)
1405
1343
{
1406
 
  int fd;
 
1344
  File fd;
1407
1345
  int error;
1408
1346
 
1409
 
  if ((fd= internal::my_open(filename1, O_RDONLY, MYF(0))) < 0)
 
1347
  if ((fd= my_open(filename1, O_RDONLY, MYF(0))) < 0)
1410
1348
    die("Failed to open first file: '%s'", filename1);
1411
1349
 
1412
1350
  error= compare_files2(fd, filename2);
1413
1351
 
1414
 
  internal::my_close(fd, MYF(0));
 
1352
  my_close(fd, MYF(0));
1415
1353
 
1416
1354
  return error;
1417
1355
}
1432
1370
static int string_cmp(string* ds, const char *fname)
1433
1371
{
1434
1372
  int error;
1435
 
  int fd;
 
1373
  File fd;
1436
1374
  char temp_file_path[FN_REFLEN];
1437
1375
 
1438
 
  if ((fd= internal::create_temp_file(temp_file_path, TMPDIR,
1439
 
                            "tmp", MYF(MY_WME))) < 0)
 
1376
  if ((fd= create_temp_file(temp_file_path, NULL,
 
1377
                            "tmp", O_CREAT | O_RDWR,
 
1378
                            MYF(MY_WME))) < 0)
1440
1379
    die("Failed to create temporary file for ds");
1441
1380
 
1442
1381
  /* Write ds to temporary file and set file pos to beginning*/
1443
 
  if (internal::my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
 
1382
  if (my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
1444
1383
               MYF(MY_FNABP | MY_WME)) ||
1445
 
      lseek(fd, 0, SEEK_SET) == MY_FILEPOS_ERROR)
 
1384
      my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1446
1385
  {
1447
 
    internal::my_close(fd, MYF(0));
 
1386
    my_close(fd, MYF(0));
1448
1387
    /* Remove the temporary file */
1449
 
    internal::my_delete(temp_file_path, MYF(0));
 
1388
    my_delete(temp_file_path, MYF(0));
1450
1389
    die("Failed to write file '%s'", temp_file_path);
1451
1390
  }
1452
1391
 
1453
1392
  error= compare_files2(fd, fname);
1454
1393
 
1455
 
  internal::my_close(fd, MYF(0));
 
1394
  my_close(fd, MYF(0));
1456
1395
  /* Remove the temporary file */
1457
 
  internal::my_delete(temp_file_path, MYF(0));
 
1396
  my_delete(temp_file_path, MYF(0));
1458
1397
 
1459
1398
  return(error);
1460
1399
}
1477
1416
  const char* mess= "Result content mismatch\n";
1478
1417
 
1479
1418
 
1480
 
  assert(result_file_name.c_str());
1481
 
 
1482
 
  if (access(result_file_name.c_str(), F_OK) != 0)
1483
 
    die("The specified result file does not exist: '%s'", result_file_name.c_str());
1484
 
 
1485
 
  switch (string_cmp(ds, result_file_name.c_str())) {
 
1419
  assert(result_file_name);
 
1420
 
 
1421
  if (access(result_file_name, F_OK) != 0)
 
1422
    die("The specified result file does not exist: '%s'", result_file_name);
 
1423
 
 
1424
  switch (string_cmp(ds, result_file_name)) {
1486
1425
  case RESULT_OK:
1487
1426
    break; /* ok */
1488
1427
  case RESULT_LENGTH_MISMATCH:
1496
1435
    */
1497
1436
    char reject_file[FN_REFLEN];
1498
1437
    size_t reject_length;
1499
 
    internal::dirname_part(reject_file, result_file_name.c_str(), &reject_length);
 
1438
    dirname_part(reject_file, result_file_name, &reject_length);
1500
1439
 
1501
1440
    if (access(reject_file, W_OK) == 0)
1502
1441
    {
1503
1442
      /* Result file directory is writable, save reject file there */
1504
 
      internal::fn_format(reject_file, result_file_name.c_str(), NULL,
 
1443
      fn_format(reject_file, result_file_name, NULL,
1505
1444
                ".reject", MY_REPLACE_EXT);
1506
1445
    }
1507
1446
    else
1508
1447
    {
1509
1448
      /* Put reject file in opt_logdir */
1510
 
      internal::fn_format(reject_file, result_file_name.c_str(), opt_logdir.c_str(),
 
1449
      fn_format(reject_file, result_file_name, opt_logdir,
1511
1450
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1512
1451
    }
1513
1452
    str_to_file(reject_file, ds->c_str(), ds->length());
1514
1453
 
1515
1454
    ds->erase(); /* Don't create a .log file */
1516
1455
 
1517
 
    show_diff(NULL, result_file_name.c_str(), reject_file);
 
1456
    show_diff(NULL, result_file_name, reject_file);
1518
1457
    die("%s",mess);
1519
1458
    break;
1520
1459
  }
1541
1480
 
1542
1481
*/
1543
1482
 
1544
 
static void check_require(string* ds, const string &fname)
 
1483
static void check_require(string* ds, const char *fname)
1545
1484
{
1546
1485
 
1547
1486
 
1548
 
  if (string_cmp(ds, fname.c_str()))
 
1487
  if (string_cmp(ds, fname))
1549
1488
  {
1550
1489
    char reason[FN_REFLEN];
1551
 
    internal::fn_format(reason, fname.c_str(), "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
 
1490
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1552
1491
    abort_not_supported_test("Test requires: '%s'", reason);
1553
1492
  }
1554
1493
  return;
1599
1538
}
1600
1539
 
1601
1540
 
 
1541
static unsigned char *get_var_key(const unsigned char* var, size_t *len,
 
1542
                          bool __attribute__((unused)) t)
 
1543
{
 
1544
  register char* key;
 
1545
  key = ((VAR*)var)->name;
 
1546
  *len = ((VAR*)var)->name_len;
 
1547
  return (unsigned char*)key;
 
1548
}
 
1549
 
1602
1550
 
1603
1551
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1604
1552
              int val_len)
1605
1553
{
 
1554
  int val_alloc_len;
 
1555
  VAR *tmp_var;
1606
1556
  if (!name_len && name)
1607
1557
    name_len = strlen(name);
1608
1558
  if (!val_len && val)
1609
1559
    val_len = strlen(val) ;
1610
 
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
 
1560
  val_alloc_len = val_len + 16; /* room to grow */
 
1561
  if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
 
1562
                                                  + name_len+1, MYF(MY_WME))))
 
1563
    die("Out of memory");
1611
1564
 
1612
 
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
 
1565
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1613
1566
  tmp_var->alloced = (v == 0);
1614
1567
 
1615
 
  int val_alloc_len = val_len + 16; /* room to grow */
1616
 
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
 
1568
  if (!(tmp_var->str_val = (char *)my_malloc(val_alloc_len+1, MYF(MY_WME))))
 
1569
    die("Out of memory");
1617
1570
 
1618
1571
  memcpy(tmp_var->name, name, name_len);
1619
1572
  if (val)
1624
1577
  tmp_var->name_len = name_len;
1625
1578
  tmp_var->str_val_len = val_len;
1626
1579
  tmp_var->alloced_len = val_alloc_len;
1627
 
  tmp_var->int_val = val ? atoi(val) : 0;
1628
 
  tmp_var->int_dirty = false;
 
1580
  tmp_var->int_val = (val) ? atoi(val) : 0;
 
1581
  tmp_var->int_dirty = 0;
1629
1582
  tmp_var->env_s = 0;
1630
1583
  return tmp_var;
1631
1584
}
1632
1585
 
 
1586
 
 
1587
void var_free(void *v)
 
1588
{
 
1589
  free(((VAR*) v)->str_val);
 
1590
  free(((VAR*) v)->env_s);
 
1591
  if (((VAR*)v)->alloced)
 
1592
    free(v);
 
1593
}
 
1594
 
 
1595
 
1633
1596
VAR* var_from_env(const char *name, const char *def_val)
1634
1597
{
1635
 
  const char *tmp= getenv(name);
1636
 
  if (!tmp)
 
1598
  const char *tmp;
 
1599
  VAR *v;
 
1600
  if (!(tmp = getenv(name)))
1637
1601
    tmp = def_val;
1638
 
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1602
 
 
1603
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1604
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1605
  return v;
1639
1606
}
1640
1607
 
 
1608
 
1641
1609
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1642
1610
             bool ignore_not_existing)
1643
1611
{
1644
1612
  int digit;
1645
1613
  VAR *v;
 
1614
 
1646
1615
  if (*var_name != '$')
1647
1616
    goto err;
1648
1617
  digit = *++var_name - '0';
1649
1618
  if (digit < 0 || digit >= 10)
1650
1619
  {
1651
1620
    const char *save_var_name = var_name, *end;
1652
 
    uint32_t length;
 
1621
    uint length;
1653
1622
    end = (var_name_end) ? *var_name_end : 0;
1654
1623
    while (my_isvar(charset_info,*var_name) && var_name != end)
1655
1624
      var_name++;
1659
1628
        return(0);
1660
1629
      die("Empty variable");
1661
1630
    }
1662
 
    length= (uint32_t) (var_name - save_var_name);
 
1631
    length= (uint) (var_name - save_var_name);
1663
1632
    if (length >= MAX_VAR_NAME_LENGTH)
1664
1633
      die("Too long variable name: %s", save_var_name);
1665
1634
 
1666
 
    string save_var_name_str(save_var_name, length);
1667
 
    var_hash_t::iterator iter= var_hash.find(save_var_name_str);
1668
 
    if (iter == var_hash.end())
 
1635
    if (!(v = (VAR*) hash_search(&var_hash, (const unsigned char*) save_var_name,
 
1636
                                 length)))
1669
1637
    {
1670
1638
      char buff[MAX_VAR_NAME_LENGTH+1];
1671
 
      strncpy(buff, save_var_name, length);
1672
 
      buff[length]= '\0';
 
1639
      strmake(buff, save_var_name, length);
1673
1640
      v= var_from_env(buff, "");
1674
1641
    }
1675
 
    else
1676
 
    {
1677
 
      v= iter->second;
1678
 
    }
1679
1642
    var_name--;  /* Point at last character */
1680
1643
  }
1681
1644
  else
1682
 
    v = &var_reg[digit];
 
1645
    v = var_reg + digit;
1683
1646
 
1684
1647
  if (!raw && v->int_dirty)
1685
1648
  {
1700
1663
 
1701
1664
static VAR *var_obtain(const char *name, int len)
1702
1665
{
1703
 
  string var_name(name, len);
1704
 
  var_hash_t::iterator iter= var_hash.find(var_name);
1705
 
  if (iter != var_hash.end())
1706
 
    return iter->second;
1707
 
  return var_hash[var_name] = var_init(0, name, len, "", 0);
 
1666
  VAR* v;
 
1667
  if ((v = (VAR*)hash_search(&var_hash, (const unsigned char *) name, len)))
 
1668
    return v;
 
1669
  v = var_init(0, name, len, "", 0);
 
1670
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1671
  return v;
1708
1672
}
1709
1673
 
1710
1674
 
1728
1692
  digit= *var_name - '0';
1729
1693
  if (!(digit < 10 && digit >= 0))
1730
1694
  {
1731
 
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
 
1695
    v= var_obtain(var_name, (uint) (var_name_end - var_name));
1732
1696
  }
1733
1697
  else
1734
 
    v= &var_reg[digit];
 
1698
    v= var_reg + digit;
1735
1699
 
1736
1700
  eval_expr(v, var_val, (const char**) &var_val_end);
1737
1701
 
1747
1711
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
1748
1712
             v->name_len, v->name,
1749
1713
             v->str_val_len, v->str_val);
1750
 
    if (!(v->env_s= strdup(buf)))
 
1714
    if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
1751
1715
      die("Out of memory");
1752
1716
    putenv(v->env_s);
1753
1717
    free(old_env_s);
1772
1736
 
1773
1737
/*
1774
1738
  Store an integer (typically the returncode of the last SQL)
1775
 
  statement in the drizzletest builtin variable $drizzleclient_errno
 
1739
  statement in the drizzletest builtin variable $drizzle_errno
1776
1740
*/
1777
1741
 
1778
1742
static void var_set_errno(int sql_errno)
1779
1743
{
1780
 
  var_set_int("$drizzleclient_errno", sql_errno);
 
1744
  var_set_int("$drizzle_errno", sql_errno);
1781
1745
}
1782
1746
 
1783
1747
 
1784
1748
/*
1785
 
  Update $drizzleclient_get_server_version variable with version
 
1749
  Update $drizzle_get_server_version variable with version
1786
1750
  of the currently connected server
1787
1751
*/
1788
1752
 
1789
 
static void var_set_drizzleclient_get_server_version(drizzle_con_st *con)
 
1753
static void var_set_drizzle_get_server_version(DRIZZLE *drizzle)
1790
1754
{
1791
 
  var_set_int("$drizzle_con_server_version", drizzle_con_server_version_number(con));
 
1755
  var_set_int("$drizzle_get_server_version", drizzle_get_server_version(drizzle));
1792
1756
}
1793
1757
 
1794
1758
 
1819
1783
{
1820
1784
  const char *end = (char*)((query_end && *query_end) ?
1821
1785
                            *query_end : query + strlen(query));
1822
 
  drizzle_result_st res;
1823
 
  drizzle_return_t ret;
1824
 
  drizzle_row_t row;
1825
 
  drizzle_con_st *con= &cur_con->con;
 
1786
  DRIZZLE_RES *res;
 
1787
  DRIZZLE_ROW row;
 
1788
  DRIZZLE *drizzle= &cur_con->drizzle;
1826
1789
  string ds_query;
1827
1790
 
1828
1791
 
1835
1798
  /* Eval the query, thus replacing all environment variables */
1836
1799
  do_eval(&ds_query, query, end, false);
1837
1800
 
1838
 
  if (drizzle_query(con, &res, ds_query.c_str(), ds_query.length(),
1839
 
                    &ret) == NULL ||
1840
 
      ret != DRIZZLE_RETURN_OK)
1841
 
  {
1842
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
1843
 
    {
1844
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
1845
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
1846
 
      drizzle_result_free(&res);
1847
 
    }
1848
 
    else
1849
 
    {
1850
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
1851
 
          drizzle_con_error(con));
1852
 
    }
1853
 
  }
1854
 
  if (drizzle_result_column_count(&res) == 0 ||
1855
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
1801
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
 
1802
    die("Error running query '%s': %d %s", ds_query.c_str(),
 
1803
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
1804
  if (!(res= drizzle_store_result(drizzle)))
1856
1805
    die("Query '%s' didn't return a result set", ds_query.c_str());
1857
1806
 
1858
 
  if ((row= drizzle_row_next(&res)) && row[0])
 
1807
  if ((row= drizzle_fetch_row(res)) && row[0])
1859
1808
  {
1860
1809
    /*
1861
1810
      Concatenate all fields in the first row with tab in between
1863
1812
    */
1864
1813
    string result;
1865
1814
    uint32_t i;
1866
 
    size_t *lengths;
 
1815
    uint32_t *lengths;
1867
1816
 
1868
 
    lengths= drizzle_row_field_sizes(&res);
1869
 
    for (i= 0; i < drizzle_result_column_count(&res); i++)
 
1817
    lengths= drizzle_fetch_lengths(res);
 
1818
    for (i= 0; i < drizzle_num_fields(res); i++)
1870
1819
    {
1871
1820
      if (row[i])
1872
1821
      {
1881
1830
  else
1882
1831
    eval_expr(var, "", 0);
1883
1832
 
1884
 
  drizzle_result_free(&res);
 
1833
  drizzle_free_result(res);
1885
1834
  return;
1886
1835
}
1887
1836
 
1912
1861
{
1913
1862
  long row_no;
1914
1863
  int col_no= -1;
1915
 
  drizzle_result_st res;
1916
 
  drizzle_return_t ret;
1917
 
  drizzle_con_st *con= &cur_con->con;
 
1864
  DRIZZLE_RES* res;
 
1865
  DRIZZLE *drizzle= &cur_con->drizzle;
1918
1866
 
1919
1867
  string ds_query;
1920
1868
  string ds_col;
1933
1881
                     ',');
1934
1882
 
1935
1883
  /* Convert row number to int */
1936
 
  row_no= atoi(ds_row.c_str());
1937
 
  
1938
 
  istringstream buff(ds_row);
1939
 
  if ((buff >> row_no).fail())
 
1884
  if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1940
1885
    die("Invalid row number: '%s'", ds_row.c_str());
1941
1886
 
1942
1887
  /* Remove any surrounding "'s from the query - if there is any */
1944
1889
  char * unstripped_query= strdup(ds_query.c_str());
1945
1890
  if (strip_surrounding(unstripped_query, '"', '"'))
1946
1891
    die("Mismatched \"'s around query '%s'", ds_query.c_str());
1947
 
  ds_query.clear();
1948
 
  ds_query.append(unstripped_query);
 
1892
  ds_query= unstripped_query;
1949
1893
 
1950
1894
  /* Run the query */
1951
 
  if (drizzle_query(con, &res, ds_query.c_str(), ds_query.length(),
1952
 
                    &ret) == NULL ||
1953
 
      ret != DRIZZLE_RETURN_OK)
1954
 
  {
1955
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
1956
 
    {
1957
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
1958
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
1959
 
      drizzle_result_free(&res);
1960
 
    }
1961
 
    else
1962
 
    {
1963
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
1964
 
          drizzle_con_error(con));
1965
 
    }
1966
 
  }
1967
 
  if (drizzle_result_column_count(&res) == 0 ||
1968
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
1895
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
 
1896
    die("Error running query '%s': %d %s", ds_query.c_str(),
 
1897
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
1898
  if (!(res= drizzle_store_result(drizzle)))
1969
1899
    die("Query '%s' didn't return a result set", ds_query.c_str());
1970
1900
 
1971
1901
  {
1972
1902
    /* Find column number from the given column name */
1973
 
    uint32_t i;
1974
 
    uint32_t num_fields= drizzle_result_column_count(&res);
1975
 
    drizzle_column_st *column;
 
1903
    uint i;
 
1904
    uint num_fields= drizzle_num_fields(res);
 
1905
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
1976
1906
 
1977
1907
    for (i= 0; i < num_fields; i++)
1978
1908
    {
1979
 
      column= drizzle_column_next(&res);
1980
 
      if (strcmp(drizzle_column_name(column), ds_col.c_str()) == 0 &&
1981
 
          strlen(drizzle_column_name(column)) == ds_col.length())
 
1909
      if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
 
1910
          strlen(fields[i].name) == ds_col.length())
1982
1911
      {
1983
1912
        col_no= i;
1984
1913
        break;
1986
1915
    }
1987
1916
    if (col_no == -1)
1988
1917
    {
1989
 
      drizzle_result_free(&res);
 
1918
      drizzle_free_result(res);
1990
1919
      die("Could not find column '%s' in the result of '%s'",
1991
1920
          ds_col.c_str(), ds_query.c_str());
1992
1921
    }
1994
1923
 
1995
1924
  {
1996
1925
    /* Get the value */
1997
 
    drizzle_row_t row;
 
1926
    DRIZZLE_ROW row;
1998
1927
    long rows= 0;
1999
1928
    const char* value= "No such row";
2000
1929
 
2001
 
    while ((row= drizzle_row_next(&res)))
 
1930
    while ((row= drizzle_fetch_row(res)))
2002
1931
    {
2003
1932
      if (++rows == row_no)
2004
1933
      {
2014
1943
    }
2015
1944
    eval_expr(var, value, 0);
2016
1945
  }
2017
 
  drizzle_result_free(&res);
 
1946
  drizzle_free_result(res);
 
1947
 
 
1948
  return;
2018
1949
}
2019
1950
 
2020
1951
 
2024
1955
  dest->int_dirty= src->int_dirty;
2025
1956
 
2026
1957
  /* Alloc/realloc data for str_val in dest */
2027
 
  if (dest->alloced_len < src->alloced_len)
2028
 
  {
2029
 
    char *tmpptr= (char *)realloc(dest->str_val, src->alloced_len);
2030
 
    if (tmpptr == NULL)
2031
 
      die("Out of memory");
2032
 
    dest->str_val= tmpptr;
2033
 
  }
 
1958
  if (dest->alloced_len < src->alloced_len &&
 
1959
      !(dest->str_val= dest->str_val
 
1960
        ? (char *)my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
 
1961
        : (char *)my_malloc(src->alloced_len, MYF(MY_WME))))
 
1962
    die("Out of memory");
2034
1963
  else
2035
1964
    dest->alloced_len= src->alloced_len;
2036
1965
 
2045
1974
{
2046
1975
  if (*p == '$')
2047
1976
  {
2048
 
    VAR *vp= var_get(p, p_end, 0, 0);
2049
 
    if (vp)
 
1977
    VAR *vp;
 
1978
    if ((vp= var_get(p, p_end, 0, 0)))
2050
1979
      var_copy(v, vp);
2051
1980
    return;
2052
1981
  }
2063
1992
    const size_t len= strlen(get_value_str);
2064
1993
    if (strncmp(p, get_value_str, len)==0)
2065
1994
    {
2066
 
      st_command command;
 
1995
      struct st_command command;
 
1996
      memset(&command, 0, sizeof(command));
2067
1997
      command.query= (char*)p;
2068
1998
      command.first_word_len= len;
2069
1999
      command.first_argument= command.query + len;
2081
2011
      static int MIN_VAR_ALLOC= 32;
2082
2012
      v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
2083
2013
        MIN_VAR_ALLOC : new_val_len + 1;
2084
 
      char *tmpptr= (char *)realloc(v->str_val, v->alloced_len+1);
2085
 
      if (tmpptr == NULL)
 
2014
      if (!(v->str_val =
 
2015
            v->str_val ? (char *)my_realloc(v->str_val, v->alloced_len+1,
 
2016
                                            MYF(MY_WME)) :
 
2017
            (char *)my_malloc(v->alloced_len+1, MYF(MY_WME))))
2086
2018
        die("Out of memory");
2087
 
      v->str_val= tmpptr;
2088
2019
    }
2089
2020
    v->str_val_len = new_val_len;
2090
2021
    memcpy(v->str_val, p, new_val_len);
2100
2031
{
2101
2032
  char buff[FN_REFLEN];
2102
2033
 
2103
 
  if (!internal::test_if_hard_path(name))
 
2034
  if (!test_if_hard_path(name))
2104
2035
  {
2105
 
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),name);
 
2036
    strxmov(buff, opt_basedir, name, NULL);
2106
2037
    name=buff;
2107
2038
  }
2108
 
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
 
2039
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2109
2040
 
 
2041
  if (cur_file == file_stack_end)
 
2042
    die("Source directives are nesting too deep");
2110
2043
  cur_file++;
2111
 
  if (cur_file == &*file_stack.end())
2112
 
    die("Source directives are nesting too deep");
2113
 
  if (!(cur_file->file= fopen(buff, "r")))
 
2044
  if (!(cur_file->file = my_fopen(buff, O_RDONLY, MYF(0))))
2114
2045
  {
2115
2046
    cur_file--;
2116
2047
    die("Could not open '%s' for reading", buff);
2117
2048
  }
2118
 
  if (!(cur_file->file_name= strdup(buff)))
2119
 
    die("Out of memory");
 
2049
  cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
2120
2050
  cur_file->lineno=1;
2121
2051
  return(0);
2122
2052
}
2156
2086
    ; /* Do nothing */
2157
2087
  else
2158
2088
  {
2159
 
    if (! opt_testdir.empty())
2160
 
    {
2161
 
      string testdir(opt_testdir);
2162
 
      if (testdir[testdir.length()] != '/')
2163
 
        testdir.append("/");
2164
 
      testdir.append(ds_filename);
2165
 
      ds_filename.swap(testdir);
2166
 
    }
2167
2089
    open_file(ds_filename.c_str());
2168
2090
  }
2169
2091
 
2171
2093
}
2172
2094
 
2173
2095
 
2174
 
static void init_builtin_echo()
 
2096
static void init_builtin_echo(void)
2175
2097
{
2176
2098
  builtin_echo[0]= 0;
 
2099
  return;
2177
2100
}
2178
2101
 
2179
2102
 
2274
2197
  error= pclose(res_file);
2275
2198
  if (error > 0)
2276
2199
  {
2277
 
    uint32_t status= WEXITSTATUS(error), i;
 
2200
    uint status= WEXITSTATUS(error), i;
2278
2201
    bool ok= 0;
2279
2202
 
2280
2203
    if (command->abort_on_error)
2423
2346
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2424
2347
                     ' ');
2425
2348
 
2426
 
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2349
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
2427
2350
  handle_command_error(command, error);
 
2351
  return;
2428
2352
}
2429
2353
 
2430
2354
 
2456
2380
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2457
2381
                     ' ');
2458
2382
 
2459
 
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2383
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2460
2384
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2461
2385
  handle_command_error(command, error);
 
2386
  return;
2462
2387
}
2463
2388
 
2464
2389
 
2490
2415
                     ' ');
2491
2416
 
2492
2417
  /* Parse what mode to set */
2493
 
  istringstream buff(ds_mode);
2494
2418
  if (ds_mode.length() != 4 ||
2495
 
      (buff >> oct >> mode).fail())
 
2419
      str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NULL)
2496
2420
    die("You must write a 4 digit octal number for mode");
2497
2421
 
2498
2422
  handle_command_error(command, chmod(ds_file.c_str(), mode));
 
2423
  return;
2499
2424
}
2500
2425
 
2501
2426
 
2525
2450
 
2526
2451
  error= (access(ds_filename.c_str(), F_OK) != 0);
2527
2452
  handle_command_error(command, error);
 
2453
  return;
2528
2454
}
2529
2455
 
2530
2456
 
2540
2466
 
2541
2467
static void do_mkdir(struct st_command *command)
2542
2468
{
 
2469
  int error;
2543
2470
  string ds_dirname;
2544
 
  int error;
2545
2471
  const struct command_arg mkdir_args[] = {
2546
2472
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
2547
2473
  };
2551
2477
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2552
2478
                     ' ');
2553
2479
 
2554
 
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
 
2480
  error= my_mkdir(ds_dirname.c_str(), 0777, MYF(0)) != 0;
2555
2481
  handle_command_error(command, error);
 
2482
  return;
2556
2483
}
2557
2484
 
2558
2485
/*
2580
2507
 
2581
2508
  error= rmdir(ds_dirname.c_str()) != 0;
2582
2509
  handle_command_error(command, error);
 
2510
  return;
2583
2511
}
2584
2512
 
2585
2513
 
2669
2597
 
2670
2598
  /* If no delimiter was provided, use EOF */
2671
2599
  if (ds_delimiter.length() == 0)
2672
 
    ds_delimiter.append("EOF");
 
2600
    ds_delimiter= "EOF";
2673
2601
 
2674
2602
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
2675
2603
  {
2818
2746
  }
2819
2747
 
2820
2748
  handle_command_error(command, error);
 
2749
  return;
2821
2750
}
2822
2751
 
2823
2752
 
2849
2778
{
2850
2779
  char *p= command->first_argument, *name;
2851
2780
  struct st_connection *con;
2852
 
  drizzle_result_st result;
2853
 
  drizzle_return_t ret;
2854
2781
 
2855
2782
  if (!*p)
2856
2783
    die("Missing connection name in send_quit");
2865
2792
  if (!(con= find_connection_by_name(name)))
2866
2793
    die("connection '%s' not found in connection pool", name);
2867
2794
 
2868
 
  if (drizzle_quit(&con->con,&result, &ret))
2869
 
    drizzle_result_free(&result);
 
2795
  simple_command(&con->drizzle,COM_QUIT,0,0,1);
 
2796
 
 
2797
  return;
2870
2798
}
2871
2799
 
2872
2800
 
2886
2814
 
2887
2815
*/
2888
2816
 
2889
 
static void do_change_user(struct st_command *)
 
2817
static void do_change_user(struct st_command *command)
2890
2818
{
2891
 
  assert(0);
 
2819
  DRIZZLE *drizzle= &cur_con->drizzle;
 
2820
  /* static keyword to make the NetWare compiler happy. */
 
2821
  string ds_user, ds_passwd, ds_db;
 
2822
  const struct command_arg change_user_args[] = {
 
2823
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
 
2824
    { "password", ARG_STRING, false, &ds_passwd, "Password used when connecting" },
 
2825
    { "database", ARG_STRING, false, &ds_db, "Database to select after connect" },
 
2826
  };
 
2827
 
 
2828
 
 
2829
 
 
2830
  check_command_args(command, command->first_argument,
 
2831
                     change_user_args,
 
2832
                     sizeof(change_user_args)/sizeof(struct command_arg),
 
2833
                     ',');
 
2834
 
 
2835
  if (!ds_user.length())
 
2836
    ds_user= drizzle->user;
 
2837
 
 
2838
  if (!ds_passwd.length())
 
2839
    ds_passwd= drizzle->passwd;
 
2840
 
 
2841
  if (!ds_db.length())
 
2842
    ds_db= drizzle->db;
 
2843
 
 
2844
  if (drizzle_change_user(drizzle, ds_user.c_str(),
 
2845
                          ds_passwd.c_str(), ds_db.c_str()))
 
2846
    die("change user failed: %s", drizzle_error(drizzle));
 
2847
 
 
2848
 
 
2849
  return;
2892
2850
}
2893
2851
 
 
2852
 
2894
2853
/*
2895
2854
  SYNOPSIS
2896
2855
  do_perl
2913
2872
static void do_perl(struct st_command *command)
2914
2873
{
2915
2874
  int error;
2916
 
  int fd;
 
2875
  File fd;
2917
2876
  FILE *res_file;
2918
2877
  char buf[FN_REFLEN];
2919
2878
  char temp_file_path[FN_REFLEN];
2932
2891
 
2933
2892
  /* If no delimiter was provided, use EOF */
2934
2893
  if (ds_delimiter.length() == 0)
2935
 
    ds_delimiter.append("EOF");
 
2894
    ds_delimiter= "EOF";
2936
2895
 
2937
2896
  read_until_delimiter(&ds_script, &ds_delimiter);
2938
2897
 
2939
2898
  /* Create temporary file name */
2940
 
  if ((fd= internal::create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
2941
 
                            "tmp", MYF(MY_WME))) < 0)
 
2899
  if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
 
2900
                            "tmp", O_CREAT | O_RDWR,
 
2901
                            MYF(MY_WME))) < 0)
2942
2902
    die("Failed to create temporary file for perl command");
2943
 
  internal::my_close(fd, MYF(0));
 
2903
  my_close(fd, MYF(0));
2944
2904
 
2945
2905
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
2946
2906
 
2960
2920
  error= pclose(res_file);
2961
2921
 
2962
2922
  /* Remove the temporary file */
2963
 
  internal::my_delete(temp_file_path, MYF(0));
 
2923
  my_delete(temp_file_path, MYF(0));
2964
2924
 
2965
2925
  handle_command_error(command, WEXITSTATUS(error));
 
2926
  return;
2966
2927
}
2967
2928
 
2968
2929
 
3004
2965
 
3005
2966
 
3006
2967
static void
3007
 
do_wait_for_slave_to_stop(struct st_command *)
 
2968
do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
3008
2969
{
3009
2970
  static int SLAVE_POLL_INTERVAL= 300000;
3010
 
  drizzle_con_st *con= &cur_con->con;
 
2971
  DRIZZLE *drizzle= &cur_con->drizzle;
3011
2972
  for (;;)
3012
2973
  {
3013
 
    drizzle_result_st res;
3014
 
    drizzle_return_t ret;
3015
 
    drizzle_row_t row;
 
2974
    DRIZZLE_RES *res= NULL;
 
2975
    DRIZZLE_ROW row;
3016
2976
    int done;
3017
2977
 
3018
 
    if (drizzle_query_str(con,&res,"show status like 'Slave_running'",
3019
 
                          &ret) == NULL || ret != DRIZZLE_RETURN_OK)
3020
 
    {
3021
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
3022
 
      {
3023
 
        die("Query failed while probing slave for stop: %s",
3024
 
            drizzle_result_error(&res));
3025
 
        drizzle_result_free(&res);
3026
 
      }
3027
 
      else
3028
 
      {
3029
 
        die("Query failed while probing slave for stop: %s",
3030
 
            drizzle_con_error(con));
3031
 
      }
3032
 
    }
3033
 
 
3034
 
    if (drizzle_result_column_count(&res) == 0 ||
3035
 
        drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3036
 
    {
 
2978
    if (drizzle_query(drizzle,"show status like 'Slave_running'") ||
 
2979
        !(res=drizzle_store_result(drizzle)))
3037
2980
      die("Query failed while probing slave for stop: %s",
3038
 
          drizzle_con_error(con));
3039
 
    }
3040
 
 
3041
 
    if (!(row=drizzle_row_next(&res)) || !row[1])
 
2981
          drizzle_error(drizzle));
 
2982
    if (!(row=drizzle_fetch_row(res)) || !row[1])
3042
2983
    {
3043
 
      drizzle_result_free(&res);
 
2984
      drizzle_free_result(res);
3044
2985
      die("Strange result from query while probing slave for stop");
3045
2986
    }
3046
2987
    done = !strcmp(row[1],"OFF");
3047
 
    drizzle_result_free(&res);
 
2988
    drizzle_free_result(res);
3048
2989
    if (done)
3049
2990
      break;
3050
 
    usleep(SLAVE_POLL_INTERVAL);
 
2991
    my_sleep(SLAVE_POLL_INTERVAL);
3051
2992
  }
3052
2993
  return;
3053
2994
}
3055
2996
 
3056
2997
static void do_sync_with_master2(long offset)
3057
2998
{
3058
 
  drizzle_result_st res;
3059
 
  drizzle_return_t ret;
3060
 
  drizzle_row_t row;
3061
 
  drizzle_con_st *con= &cur_con->con;
 
2999
  DRIZZLE_RES *res;
 
3000
  DRIZZLE_ROW row;
 
3001
  DRIZZLE *drizzle= &cur_con->drizzle;
3062
3002
  char query_buf[FN_REFLEN+128];
3063
3003
  int tries= 0;
3064
3004
 
3065
3005
  if (!master_pos.file[0])
3066
3006
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3067
3007
 
3068
 
  snprintf(query_buf, sizeof(query_buf), "select master_pos_wait('%s', %ld)", master_pos.file,
 
3008
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3069
3009
          master_pos.pos + offset);
3070
3010
 
3071
3011
wait_for_position:
3072
3012
 
3073
 
  if (drizzle_query_str(con, &res, query_buf, &ret) == NULL ||
3074
 
      ret != DRIZZLE_RETURN_OK)
3075
 
  {
3076
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3077
 
    {
3078
 
      die("failed in '%s': %d: %s", query_buf, drizzle_result_error_code(&res),
3079
 
           drizzle_result_error(&res));
3080
 
      drizzle_result_free(&res);
3081
 
    }
3082
 
    else
3083
 
      die("failed in '%s': %d: %s", query_buf, ret, drizzle_con_error(con));
3084
 
  }
3085
 
 
3086
 
  if (drizzle_result_column_count(&res) == 0 ||
3087
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3088
 
    die("drizzle_result_buffer() returned NULL for '%s'", query_buf);
3089
 
 
3090
 
  if (!(row= drizzle_row_next(&res)))
3091
 
  {
3092
 
    drizzle_result_free(&res);
 
3013
  if (drizzle_query(drizzle, query_buf))
 
3014
    die("failed in '%s': %d: %s", query_buf, drizzle_errno(drizzle),
 
3015
        drizzle_error(drizzle));
 
3016
 
 
3017
  if (!(res= drizzle_store_result(drizzle)))
 
3018
    die("drizzle_store_result() returned NULL for '%s'", query_buf);
 
3019
  if (!(row= drizzle_fetch_row(res)))
 
3020
  {
 
3021
    drizzle_free_result(res);
3093
3022
    die("empty result in %s", query_buf);
3094
3023
  }
3095
3024
  if (!row[0])
3098
3027
      It may be that the slave SQL thread has not started yet, though START
3099
3028
      SLAVE has been issued ?
3100
3029
    */
3101
 
    drizzle_result_free(&res);
 
3030
    drizzle_free_result(res);
3102
3031
    if (tries++ == 30)
3103
3032
    {
3104
 
      show_query(con, "SHOW MASTER STATUS");
3105
 
      show_query(con, "SHOW SLAVE STATUS");
 
3033
      show_query(drizzle, "SHOW MASTER STATUS");
 
3034
      show_query(drizzle, "SHOW SLAVE STATUS");
3106
3035
      die("could not sync with master ('%s' returned NULL)", query_buf);
3107
3036
    }
3108
3037
    sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
3109
3038
    goto wait_for_position;
3110
3039
  }
3111
 
  drizzle_result_free(&res);
 
3040
  drizzle_free_result(res);
3112
3041
  return;
3113
3042
}
3114
3043
 
3136
3065
  when ndb binlog is on, this call will wait until last updated epoch
3137
3066
  (locally in the drizzled) has been received into the binlog
3138
3067
*/
3139
 
static int do_save_master_pos()
 
3068
static int do_save_master_pos(void)
3140
3069
{
3141
 
  drizzle_result_st res;
3142
 
  drizzle_return_t ret;
3143
 
  drizzle_row_t row;
3144
 
  drizzle_con_st *con= &cur_con->con;
 
3070
  DRIZZLE_RES *res;
 
3071
  DRIZZLE_ROW row;
 
3072
  DRIZZLE *drizzle= &cur_con->drizzle;
3145
3073
  const char *query;
3146
3074
 
3147
3075
 
3148
 
  if (drizzle_query_str(con, &res, query= "show master status", &ret) == NULL ||
3149
 
      ret != DRIZZLE_RETURN_OK)
3150
 
  {
3151
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3152
 
    {
3153
 
      die("failed in '%s': %d: %s", query, drizzle_result_error_code(&res),
3154
 
           drizzle_result_error(&res));
3155
 
      drizzle_result_free(&res);
3156
 
    }
3157
 
    else
3158
 
      die("failed in '%s': %d: %s", query, ret, drizzle_con_error(con));
3159
 
  }
 
3076
  if (drizzle_query(drizzle, query= "show master status"))
 
3077
    die("failed in 'show master status': %d %s",
 
3078
        drizzle_errno(drizzle), drizzle_error(drizzle));
3160
3079
 
3161
 
  if (drizzle_result_column_count(&res) == 0 ||
3162
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3163
 
    die("drizzleclient_store_result() retuned NULL for '%s'", query);
3164
 
  if (!(row = drizzle_row_next(&res)))
 
3080
  if (!(res = drizzle_store_result(drizzle)))
 
3081
    die("drizzle_store_result() retuned NULL for '%s'", query);
 
3082
  if (!(row = drizzle_fetch_row(res)))
3165
3083
    die("empty result in show master status");
3166
 
  strncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
 
3084
  my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
3167
3085
  master_pos.pos = strtoul(row[1], (char**) 0, 10);
3168
 
  drizzle_result_free(&res);
 
3086
  drizzle_free_result(res);
3169
3087
  return(0);
3170
3088
}
3171
3089
 
3249
3167
 
3250
3168
static int do_sleep(struct st_command *command, bool real_sleep)
3251
3169
{
3252
 
  bool error= false;
 
3170
  int error= 0;
3253
3171
  char *p= command->first_argument;
3254
3172
  char *sleep_start, *sleep_end= command->end;
3255
 
  double sleep_val= 0;
 
3173
  double sleep_val;
3256
3174
 
3257
3175
  while (my_isspace(charset_info, *p))
3258
3176
    p++;
3259
3177
  if (!*p)
3260
3178
    die("Missing argument to %.*s", command->first_word_len, command->query);
3261
3179
  sleep_start= p;
3262
 
  /* Check that arg starts with a digit, not handled by internal::my_strtod */
 
3180
  /* Check that arg starts with a digit, not handled by my_strtod */
3263
3181
  if (!my_isdigit(charset_info, *sleep_start))
3264
3182
    die("Invalid argument to %.*s \"%s\"", command->first_word_len,
3265
3183
        command->query,command->first_argument);
3266
 
  string buff_str(sleep_start, sleep_end-sleep_start);
3267
 
  istringstream buff(buff_str);
3268
 
  error= (buff >> sleep_val).fail();
 
3184
  sleep_val= my_strtod(sleep_start, &sleep_end, &error);
3269
3185
  if (error)
3270
3186
    die("Invalid argument to %.*s \"%s\"", command->first_word_len,
3271
3187
        command->query, command->first_argument);
3275
3191
    sleep_val= opt_sleep;
3276
3192
 
3277
3193
  if (sleep_val)
3278
 
    usleep(sleep_val * 1000000);
 
3194
    my_sleep((uint32_t) (sleep_val * 1000000L));
3279
3195
  command->last_argument= sleep_end;
3280
3196
  return 0;
3281
3197
}
3282
3198
 
3283
3199
 
3284
 
static void do_get_file_name(st_command *command, string &dest)
 
3200
static void do_get_file_name(struct st_command *command,
 
3201
                             char* dest, uint dest_max_len)
3285
3202
{
3286
 
  char *p= command->first_argument;
 
3203
  char *p= command->first_argument, *name;
3287
3204
  if (!*p)
3288
3205
    die("Missing file name argument");
3289
 
  char *name= p;
 
3206
  name= p;
3290
3207
  while (*p && !my_isspace(charset_info,*p))
3291
3208
    p++;
3292
3209
  if (*p)
3293
3210
    *p++= 0;
3294
3211
  command->last_argument= p;
3295
 
  if (! opt_testdir.empty())
3296
 
  {
3297
 
    dest= opt_testdir;
3298
 
    if (dest[dest.length()] != '/')
3299
 
      dest.append("/");
3300
 
  }
3301
 
  dest.append(name);
 
3212
  strmake(dest, name, dest_max_len - 1);
3302
3213
}
3303
3214
 
3304
3215
 
3316
3227
  if(*p)
3317
3228
    *p++= 0;
3318
3229
  command->last_argument= p;
3319
 
  charset_info= get_charset_by_csname(charset_name, MY_CS_PRIMARY);
 
3230
  charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
3320
3231
  if (!charset_info)
3321
3232
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3322
3233
}
3323
3234
 
3324
 
static void fill_global_error_names()
 
3235
static uint get_errcode_from_name(char *error_name, char *error_end)
3325
3236
{
3326
 
  drizzle_result_st res;
3327
 
  drizzle_return_t ret;
3328
 
  drizzle_row_t row;
3329
 
  drizzle_con_st *con= &cur_con->con;
3330
 
 
3331
 
  global_error_names.clear();
3332
 
 
3333
 
  const std::string ds_query("select error_name, error_code "
3334
 
                             "from data_dictionary.errors");
3335
 
  if (drizzle_query_str(con, &res, ds_query.c_str(), &ret) == NULL ||
3336
 
      ret != DRIZZLE_RETURN_OK)
3337
 
  {
3338
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3339
 
    {
3340
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
3341
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
3342
 
      drizzle_result_free(&res);
3343
 
    }
3344
 
    else
3345
 
    {
3346
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
3347
 
          drizzle_con_error(con));
3348
 
    }
3349
 
  }
3350
 
  if (drizzle_result_column_count(&res) == 0 ||
3351
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3352
 
  {
3353
 
    drizzle_result_free(&res);
3354
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
3355
 
  }
3356
 
 
3357
 
  while ((row= drizzle_row_next(&res)) && row[0])
 
3237
  /* SQL error as string */
 
3238
  st_error *e= global_error_names;
 
3239
 
 
3240
  /* Loop through the array of known error names */
 
3241
  for (; e->name; e++)
3358
3242
  {
3359
3243
    /*
3360
 
      Concatenate all fields in the first row with tab in between
3361
 
      and assign that string to the $variable
 
3244
      If we get a match, we need to check the length of the name we
 
3245
      matched against in case it was longer than what we are checking
 
3246
      (as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
3362
3247
    */
3363
 
    size_t *lengths= drizzle_row_field_sizes(&res);
3364
 
    try
3365
 
    {
3366
 
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
3367
 
    }
3368
 
    catch (boost::bad_lexical_cast &ex)
3369
 
    {
3370
 
      drizzle_result_free(&res);
3371
 
      die("Invalid error_code from Drizzle: %s", ex.what());
3372
 
    }
3373
 
 
 
3248
    if (!strncmp(error_name, e->name, (int) (error_end - error_name)) &&
 
3249
        (uint) strlen(e->name) == (uint) (error_end - error_name))
 
3250
    {
 
3251
      return(e->code);
 
3252
    }
3374
3253
  }
3375
 
 
3376
 
  drizzle_result_free(&res);
3377
 
}
3378
 
 
3379
 
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3380
 
{
3381
 
  size_t err_name_len= error_end - error_name;
3382
 
  string error_name_s(error_name, err_name_len);
3383
 
 
3384
 
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3385
 
  if (it != global_error_names.end())
3386
 
    return it->second;
3387
 
 
3388
 
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3389
 
  return 0;
 
3254
  if (!e->name)
 
3255
    die("Unknown SQL error name '%s'", error_name);
 
3256
  return(0);
3390
3257
}
3391
3258
 
3392
3259
static void do_get_errcodes(struct st_command *command)
3393
3260
{
3394
3261
  struct st_match_err *to= saved_expected_errors.err;
3395
3262
  char *p= command->first_argument;
3396
 
  uint32_t count= 0;
 
3263
  uint count= 0;
3397
3264
 
3398
3265
 
3399
3266
 
3419
3286
 
3420
3287
      /*
3421
3288
        SQLSTATE string
3422
 
        - Must be DRIZZLE_MAX_SQLSTATE_SIZE long
 
3289
        - Must be SQLSTATE_LENGTH long
3423
3290
        - May contain only digits[0-9] and _uppercase_ letters
3424
3291
      */
3425
3292
      p++; /* Step past the S */
3426
 
      if ((end - p) != DRIZZLE_MAX_SQLSTATE_SIZE)
3427
 
        die("The sqlstate must be exactly %d chars long", DRIZZLE_MAX_SQLSTATE_SIZE);
 
3293
      if ((end - p) != SQLSTATE_LENGTH)
 
3294
        die("The sqlstate must be exactly %d chars long", SQLSTATE_LENGTH);
3428
3295
 
3429
3296
      /* Check sqlstate string validity */
3430
3297
      while (*p && p < end)
3454
3321
    {
3455
3322
      die("The error name definition must start with an uppercase E");
3456
3323
    }
3457
 
    else if (*p == 'H')
 
3324
    else
3458
3325
    {
3459
 
      /* Error name string */
3460
 
 
3461
 
      to->code.errnum= get_errcode_from_name(p, end);
 
3326
      long val;
 
3327
      char *start= p;
 
3328
      /* Check that the string passed to str2int only contain digits */
 
3329
      while (*p && p != end)
 
3330
      {
 
3331
        if (!my_isdigit(charset_info, *p))
 
3332
          die("Invalid argument to error: '%s' - "              \
 
3333
              "the errno may only consist of digits[0-9]",
 
3334
              command->first_argument);
 
3335
        p++;
 
3336
      }
 
3337
 
 
3338
      /* Convert the sting to int */
 
3339
      if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
 
3340
        die("Invalid argument to error: '%s'", command->first_argument);
 
3341
 
 
3342
      to->code.errnum= (uint) val;
3462
3343
      to->type= ERR_ERRNO;
3463
3344
    }
3464
 
    else
3465
 
    {
3466
 
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3467
 
    }
3468
3345
    to++;
3469
3346
    count++;
3470
3347
 
3569
3446
}
3570
3447
 
3571
3448
 
3572
 
static void set_reconnect(drizzle_con_st *con, int val)
 
3449
static void set_reconnect(DRIZZLE *drizzle, int val)
3573
3450
{
3574
 
  (void) con;
3575
 
  (void) val;
3576
 
/* XXX
3577
3451
  bool reconnect= val;
3578
3452
 
3579
 
  drizzleclient_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
3580
 
*/
 
3453
  drizzle_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
 
3454
 
 
3455
  return;
3581
3456
}
3582
3457
 
3583
3458
 
3586
3461
  if (!(cur_con= find_connection_by_name(name)))
3587
3462
    die("connection '%s' not found in connection pool", name);
3588
3463
 
3589
 
  /* Update $drizzleclient_get_server_version to that of current connection */
3590
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
3464
  /* Update $drizzle_get_server_version to that of current connection */
 
3465
  var_set_drizzle_get_server_version(&cur_con->drizzle);
3591
3466
 
3592
3467
  return(0);
3593
3468
}
3629
3504
  if (!(con= find_connection_by_name(name)))
3630
3505
    die("connection '%s' not found in connection pool", name);
3631
3506
 
3632
 
  if (con->drizzle != NULL)
 
3507
  if (command->type == Q_DIRTY_CLOSE)
3633
3508
  {
3634
 
    drizzle_free(con->drizzle);
3635
 
    con->drizzle= NULL;
 
3509
    if (con->drizzle.net.vio)
 
3510
    {
 
3511
      net_close(&(con->drizzle.net));
 
3512
    }
3636
3513
  }
 
3514
 
 
3515
  drizzle_close(&con->drizzle);
 
3516
 
 
3517
  if (con->util_drizzle)
 
3518
    drizzle_close(con->util_drizzle);
 
3519
  con->util_drizzle= 0;
 
3520
 
3637
3521
  free(con->name);
3638
3522
 
3639
3523
  /*
3640
3524
    When the connection is closed set name to "-closed_connection-"
3641
3525
    to make it possible to reuse the connection name.
3642
3526
  */
3643
 
  if (!(con->name = strdup("-closed_connection-")))
 
3527
  if (!(con->name = my_strdup("-closed_connection-", MYF(MY_WME))))
3644
3528
    die("Out of memory");
3645
3529
 
3646
3530
  return;
3672
3556
 
3673
3557
*/
3674
3558
 
3675
 
static void safe_connect(drizzle_con_st *con, const char *name,
3676
 
                         const string host, const string user, const char *pass,
3677
 
                         const string db, uint32_t port)
 
3559
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
 
3560
                         const char *user, const char *pass, const char *db,
 
3561
                         int port)
3678
3562
{
3679
 
  uint32_t failed_attempts= 0;
 
3563
  int failed_attempts= 0;
3680
3564
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3681
 
  drizzle_return_t ret;
3682
 
 
3683
 
  drizzle_con_set_tcp(con, host.c_str(), port);
3684
 
  drizzle_con_set_auth(con, user.c_str(), pass);
3685
 
  drizzle_con_set_db(con, db.c_str());
3686
 
  while((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
 
3565
 
 
3566
 
 
3567
  while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
 
3568
                         CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3687
3569
  {
3688
3570
    /*
3689
3571
      Connect failed
3693
3575
      on protocol/connection type
3694
3576
    */
3695
3577
 
3696
 
    if ((ret == DRIZZLE_RETURN_GETADDRINFO ||
3697
 
         ret == DRIZZLE_RETURN_COULD_NOT_CONNECT) &&
 
3578
    if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
 
3579
         drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
3698
3580
        failed_attempts < opt_max_connect_retries)
3699
3581
    {
3700
3582
      verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3701
 
                  opt_max_connect_retries, ret, drizzle_con_error(con));
3702
 
      usleep(connection_retry_sleep);
 
3583
                  opt_max_connect_retries, drizzle_errno(drizzle),
 
3584
                  drizzle_error(drizzle));
 
3585
      my_sleep(connection_retry_sleep);
3703
3586
    }
3704
3587
    else
3705
3588
    {
3706
3589
      if (failed_attempts > 0)
3707
3590
        die("Could not open connection '%s' after %d attempts: %d %s", name,
3708
 
            failed_attempts, ret, drizzle_con_error(con));
 
3591
            failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
3709
3592
      else
3710
 
        die("Could not open connection '%s': %d %s", name, ret,
3711
 
            drizzle_con_error(con));
 
3593
        die("Could not open connection '%s': %d %s", name,
 
3594
            drizzle_errno(drizzle), drizzle_error(drizzle));
3712
3595
    }
3713
3596
    failed_attempts++;
3714
3597
  }
3740
3623
*/
3741
3624
 
3742
3625
static int connect_n_handle_errors(struct st_command *command,
3743
 
                                   drizzle_con_st *con, const char* host,
 
3626
                                   DRIZZLE *con, const char* host,
3744
3627
                                   const char* user, const char* pass,
3745
3628
                                   const char* db, int port, const char* sock)
3746
3629
{
3747
 
  drizzle_return_t ret;
3748
3630
 
3749
3631
  /* Only log if an error is expected */
3750
3632
  if (!command->abort_on_error &&
3771
3653
    ds_res.append(delimiter);
3772
3654
    ds_res.append("\n");
3773
3655
  }
3774
 
  drizzle_con_set_tcp(con, host, port);
3775
 
  drizzle_con_set_auth(con, user, pass);
3776
 
  drizzle_con_set_db(con, db);
3777
 
  if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
 
3656
  if (!drizzle_connect(con, host, user, pass, db, port, 0,
 
3657
                       CLIENT_MULTI_STATEMENTS))
3778
3658
  {
3779
 
    if (ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
3780
 
    {
3781
 
      var_set_errno(drizzle_con_error_code(con));
3782
 
      handle_error(command, drizzle_con_error_code(con), drizzle_con_error(con),
3783
 
                   drizzle_con_sqlstate(con), &ds_res);
3784
 
    }
3785
 
    else
3786
 
    {
3787
 
      var_set_errno(ret);
3788
 
      handle_error(command, ret, drizzle_con_error(con), "", &ds_res);
3789
 
    }
3790
 
 
 
3659
    var_set_errno(drizzle_errno(con));
 
3660
    handle_error(command, drizzle_errno(con), drizzle_error(con),
 
3661
                 drizzle_sqlstate(con), &ds_res);
3791
3662
    return 0; /* Not connected */
3792
3663
  }
3793
3664
 
3824
3695
 
3825
3696
static void do_connect(struct st_command *command)
3826
3697
{
3827
 
  uint32_t con_port= opt_port;
 
3698
  int con_port= opt_port;
3828
3699
  const char *con_options;
3829
 
  bool con_ssl= 0;
 
3700
  bool con_ssl= 0, con_compress= 0;
3830
3701
  struct st_connection* con_slot;
3831
3702
 
3832
3703
  string ds_connection_name;
3872
3743
    if (*ds_sock.c_str() != FN_LIBCHAR)
3873
3744
    {
3874
3745
      char buff[FN_REFLEN];
3875
 
      internal::fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3876
 
      ds_sock.clear();
3877
 
      ds_sock.append(buff);
 
3746
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
 
3747
      ds_sock= buff;
3878
3748
    }
3879
3749
  }
3880
3750
 
3892
3762
      end++;
3893
3763
    if (!strncmp(con_options, "SSL", 3))
3894
3764
      con_ssl= 1;
 
3765
    else if (!strncmp(con_options, "COMPRESS", 8))
 
3766
      con_compress= 1;
3895
3767
    else
3896
3768
      die("Illegal option to connect: %.*s",
3897
3769
          (int) (end - con_options), con_options);
3913
3785
          (int) (sizeof(connections)/sizeof(struct st_connection)));
3914
3786
  }
3915
3787
 
3916
 
  if ((con_slot->drizzle= drizzle_create(NULL)) == NULL)
 
3788
  if (!drizzle_create(&con_slot->drizzle))
3917
3789
    die("Failed on drizzle_create()");
3918
 
  if (!drizzle_con_create(con_slot->drizzle, &con_slot->con))
3919
 
    die("Failed on drizzle_con_create()");
3920
 
  drizzle_con_add_options(&con_slot->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
3790
  if (opt_compress || con_compress)
 
3791
    drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NULL);
 
3792
  drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
3921
3793
 
3922
3794
  /* Use default db name */
3923
3795
  if (ds_database.length() == 0)
3924
 
    ds_database.append(opt_db);
 
3796
    ds_database= opt_db;
3925
3797
 
3926
3798
  /* Special database to allow one to connect without a database name */
3927
3799
  if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
3928
 
    ds_database.clear();
 
3800
    ds_database= "";
3929
3801
 
3930
 
  if (connect_n_handle_errors(command, &con_slot->con,
 
3802
  if (connect_n_handle_errors(command, &con_slot->drizzle,
3931
3803
                              ds_host.c_str(),ds_user.c_str(),
3932
3804
                              ds_password.c_str(), ds_database.c_str(),
3933
3805
                              con_port, ds_sock.c_str()))
3940
3812
      next_con++; /* if we used the next_con slot, advance the pointer */
3941
3813
  }
3942
3814
 
3943
 
  /* Update $drizzleclient_get_server_version to that of current connection */
3944
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
3815
  /* Update $drizzle_get_server_version to that of current connection */
 
3816
  var_set_drizzle_get_server_version(&cur_con->drizzle);
3945
3817
 
3946
3818
  return;
3947
3819
}
4004
3876
{
4005
3877
  char *p= command->first_argument;
4006
3878
  const char *expr_start, *expr_end;
 
3879
  VAR v;
4007
3880
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4008
3881
  bool not_expr= false;
4009
3882
 
4046
3919
  if (*p && *p != '{')
4047
3920
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4048
3921
 
4049
 
  VAR v;
4050
3922
  var_init(&v,0,0,0,0);
4051
3923
  eval_expr(&v, expr_start, &expr_end);
4052
3924
 
4058
3930
  if (not_expr)
4059
3931
    cur_block->ok = !cur_block->ok;
4060
3932
 
4061
 
  free(v.str_val);
4062
 
  free(v.env_s);
4063
 
 
 
3933
  var_free(&v);
4064
3934
  return;
4065
3935
}
4066
3936
 
4075
3945
  if (!(*p))
4076
3946
    die("Can't set empty delimiter");
4077
3947
 
4078
 
  strncpy(delimiter, p, sizeof(delimiter) - 1);
 
3948
  strmake(delimiter, p, sizeof(delimiter) - 1);
4079
3949
  delimiter_length= strlen(delimiter);
4080
3950
 
4081
3951
  command->last_argument= p + delimiter_length;
4083
3953
}
4084
3954
 
4085
3955
 
4086
 
bool match_delimiter(int c, const char *delim, uint32_t length)
 
3956
bool match_delimiter(int c, const char *delim, uint length)
4087
3957
{
4088
 
  uint32_t i;
 
3958
  uint i;
4089
3959
  char tmp[MAX_DELIMITER_LENGTH];
4090
3960
 
4091
3961
  if (c != *delim)
4137
4007
 
4138
4008
*/
4139
4009
 
4140
 
 
4141
 
static int my_strnncoll_simple(const CHARSET_INFO * const  cs, const unsigned char *s, size_t slen,
4142
 
                               const unsigned char *t, size_t tlen,
4143
 
                               bool t_is_prefix)
4144
 
{
4145
 
  size_t len = ( slen > tlen ) ? tlen : slen;
4146
 
  unsigned char *map= cs->sort_order;
4147
 
  if (t_is_prefix && slen > tlen)
4148
 
    slen=tlen;
4149
 
  while (len--)
4150
 
  {
4151
 
    if (map[*s++] != map[*t++])
4152
 
      return ((int) map[s[-1]] - (int) map[t[-1]]);
4153
 
  }
4154
 
  /*
4155
 
    We can't use (slen - tlen) here as the result may be outside of the
4156
 
    precision of a signed int
4157
 
  */
4158
 
  return slen > tlen ? 1 : slen < tlen ? -1 : 0 ;
4159
 
}
4160
 
 
4161
4010
static int read_line(char *buf, int size)
4162
4011
{
4163
4012
  char c, last_quote= 0;
4177
4026
  found_eof:
4178
4027
      if (cur_file->file != stdin)
4179
4028
      {
4180
 
        fclose(cur_file->file);
 
4029
        my_fclose(cur_file->file, MYF(0));
4181
4030
        cur_file->file= 0;
4182
4031
      }
4183
4032
      free((unsigned char*) cur_file->file_name);
4184
4033
      cur_file->file_name= 0;
4185
 
      if (cur_file == file_stack.data())
 
4034
      if (cur_file == file_stack)
4186
4035
      {
4187
4036
        /* We're back at the first file, check if
4188
4037
           all { have matching }
4217
4066
      }
4218
4067
      else if ((c == '{' &&
4219
4068
                (!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
4220
 
                                      (unsigned char*) buf, min((ptrdiff_t)5, p - buf), 0) ||
 
4069
                                      (unsigned char*) buf, cmin((long)5, p - buf), 0) ||
4221
4070
                 !my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
4222
 
                                      (unsigned char*) buf, min((ptrdiff_t)2, p - buf), 0))))
 
4071
                                      (unsigned char*) buf, cmin((long)2, p - buf), 0))))
4223
4072
      {
4224
4073
        /* Only if and while commands can be terminated by { */
4225
4074
        *p++= c;
4296
4145
    {
4297
4146
      /* Could be a multibyte character */
4298
4147
      /* This code is based on the code in "sql_load.cc" */
 
4148
#ifdef USE_MB
4299
4149
      int charlen = my_mbcharlen(charset_info, c);
4300
4150
      /* We give up if multibyte character is started but not */
4301
4151
      /* completed before we pass buf_end */
4322
4172
        }
4323
4173
      }
4324
4174
      else
 
4175
#endif
4325
4176
        *p++= c;
4326
4177
    }
4327
4178
  }
4404
4255
        ptr[2] && ptr[2] == '-' &&
4405
4256
        ptr[3])
4406
4257
    {
4407
 
      uint32_t type;
 
4258
      uint type;
4408
4259
      char save;
4409
4260
      char *end, *start= (char*)ptr+3;
4410
4261
      /* Skip leading spaces */
4416
4267
        end++;
4417
4268
      save= *end;
4418
4269
      *end= 0;
4419
 
      type= command_typelib.find_type(start, 1+2);
 
4270
      type= find_type(start, &command_typelib, 1+2);
4420
4271
      if (type)
4421
4272
        warning_msg("Embedded drizzletest command '--%s' detected in "
4422
4273
                    "query '%s' was this intentional? ",
4481
4332
  return;
4482
4333
}
4483
4334
 
 
4335
 
 
4336
 
4484
4337
/*
4485
4338
  Create a command from a set of lines
4486
4339
 
4498
4351
  terminated by new line '\n' regardless how many "delimiter" it contain.
4499
4352
*/
4500
4353
 
4501
 
#define MAX_QUERY (768*1024*2) /* 256K -- a test in sp-big is >128K */
 
4354
#define MAX_QUERY (256*1024*2) /* 256K -- a test in sp-big is >128K */
4502
4355
static char read_command_buf[MAX_QUERY];
4503
4356
 
4504
4357
static int read_command(struct st_command** command_ptr)
4512
4365
    *command_ptr= q_lines[parser.current_line];
4513
4366
    return(0);
4514
4367
  }
4515
 
  if (!(*command_ptr= command= new st_command))
4516
 
    die("command construction failed");
 
4368
  if (!(*command_ptr= command=
 
4369
        (struct st_command*) my_malloc(sizeof(*command),
 
4370
                                       MYF(MY_WME|MY_ZEROFILL))))
 
4371
    die(NULL);
4517
4372
  q_lines.push_back(command);
4518
4373
  command->type= Q_UNKNOWN;
4519
4374
 
4540
4395
  while (*p && my_isspace(charset_info, *p))
4541
4396
    p++;
4542
4397
 
4543
 
  if (!(command->query_buf= command->query= strdup(p)))
 
4398
  if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME))))
4544
4399
    die("Out of memory");
4545
4400
 
4546
4401
  /* Calculate first word length(the command), terminated by space or ( */
4547
4402
  p= command->query;
4548
4403
  while (*p && !my_isspace(charset_info, *p) && *p != '(')
4549
4404
    p++;
4550
 
  command->first_word_len= (uint32_t) (p - command->query);
 
4405
  command->first_word_len= (uint) (p - command->query);
4551
4406
 
4552
4407
  /* Skip spaces between command and first argument */
4553
4408
  while (*p && my_isspace(charset_info, *p))
4560
4415
  return(0);
4561
4416
}
4562
4417
 
 
4418
 
 
4419
static struct my_option my_long_options[] =
 
4420
{
 
4421
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
 
4422
   0, 0, 0, 0, 0, 0},
 
4423
  {"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
 
4424
   (char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4425
  {"character-sets-dir", OPT_CHARSETS_DIR,
 
4426
   "Directory where character sets are.", (char**) &opt_charsets_dir,
 
4427
   (char**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4428
  {"compress", 'C', "Use the compressed server/client protocol.",
 
4429
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
4430
   0, 0, 0},
 
4431
  {"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
 
4432
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4433
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
 
4434
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
 
4435
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4436
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
 
4437
   (char**) &debug_info_flag, (char**) &debug_info_flag,
 
4438
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4439
  {"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
 
4440
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4441
  {"include", 'i', "Include SQL before each test case.", (char**) &opt_include,
 
4442
   (char**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4443
  {"logdir", OPT_LOG_DIR, "Directory for log files", (char**) &opt_logdir,
 
4444
   (char**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4445
  {"mark-progress", OPT_MARK_PROGRESS,
 
4446
   "Write linenumber and elapsed time to <testname>.progress ",
 
4447
   (char**) &opt_mark_progress, (char**) &opt_mark_progress, 0,
 
4448
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4449
  {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
 
4450
   "Max number of connection attempts when connecting to server",
 
4451
   (char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
 
4452
   GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
 
4453
  {"password", 'p', "Password to use when connecting to server.",
 
4454
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
4455
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
 
4456
   "order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
 
4457
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
 
4458
   (char**) &opt_port,
 
4459
   (char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4460
  {"quiet", 's', "Suppress all normal output.", (char**) &silent,
 
4461
   (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4462
  {"record", 'r', "Record output of test_file into result file.",
 
4463
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4464
  {"result-file", 'R', "Read/Store result from/in this file.",
 
4465
   (char**) &result_file_name, (char**) &result_file_name, 0,
 
4466
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4467
  {"server-arg", 'A', "Send option value to embedded server as a parameter.",
 
4468
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4469
  {"server-file", 'F', "Read embedded server arguments from file.",
 
4470
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4471
  {"silent", 's', "Suppress all normal output. Synonym for --quiet.",
 
4472
   (char**) &silent, (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4473
  {"sleep", 'T', "Sleep always this many seconds on sleep commands.",
 
4474
   (char**) &opt_sleep, (char**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
 
4475
   0, 0, 0},
 
4476
  {"tail-lines", OPT_TAIL_LINES,
 
4477
   "Number of lines of the resul to include in a failure report",
 
4478
   (char**) &opt_tail_lines, (char**) &opt_tail_lines, 0,
 
4479
   GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
 
4480
  {"test-file", 'x', "Read test from/in this file (default stdin).",
 
4481
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4482
  {"timer-file", 'm', "File where the timing in micro seconds is stored.",
 
4483
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4484
  {"tmpdir", 't', "Temporary directory where sockets are put.",
 
4485
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4486
  {"user", 'u', "User for login.", (char**) &opt_user, (char**) &opt_user, 0,
 
4487
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4488
  {"verbose", 'v', "Write more.", (char**) &verbose, (char**) &verbose, 0,
 
4489
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4490
  {"version", 'V', "Output version information and exit.",
 
4491
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4492
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
4493
};
 
4494
 
 
4495
 
 
4496
static void print_version(void)
 
4497
{
 
4498
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
 
4499
         drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
4500
}
 
4501
 
 
4502
static void usage(void)
 
4503
{
 
4504
  print_version();
 
4505
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
 
4506
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
 
4507
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
 
4508
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
 
4509
  my_print_help(my_long_options);
 
4510
  printf("  --no-defaults       Don't read default options from any options file.\n");
 
4511
  my_print_variables(my_long_options);
 
4512
}
 
4513
 
 
4514
/*
 
4515
  Read arguments for embedded server and put them into
 
4516
  embedded_server_args[]
 
4517
*/
 
4518
 
 
4519
static void read_embedded_server_arguments(const char *name)
 
4520
{
 
4521
  char argument[1024],buff[FN_REFLEN], *str=0;
 
4522
  FILE *file;
 
4523
 
 
4524
  if (!test_if_hard_path(name))
 
4525
  {
 
4526
    strxmov(buff, opt_basedir, name, NULL);
 
4527
    name=buff;
 
4528
  }
 
4529
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
 
4530
 
 
4531
  if (!embedded_server_arg_count)
 
4532
  {
 
4533
    embedded_server_arg_count=1;
 
4534
    embedded_server_args[0]= (char*) "";    /* Progname */
 
4535
  }
 
4536
  if (!(file=my_fopen(buff, O_RDONLY, MYF(MY_WME))))
 
4537
    die("Failed to open file '%s'", buff);
 
4538
 
 
4539
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
 
4540
         (str=fgets(argument,sizeof(argument), file)))
 
4541
  {
 
4542
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
 
4543
    if (!(embedded_server_args[embedded_server_arg_count]=
 
4544
          (char*) my_strdup(str,MYF(MY_WME))))
 
4545
    {
 
4546
      my_fclose(file,MYF(0));
 
4547
      die("Out of memory");
 
4548
 
 
4549
    }
 
4550
    embedded_server_arg_count++;
 
4551
  }
 
4552
  my_fclose(file,MYF(0));
 
4553
  if (str)
 
4554
    die("Too many arguments in option file: %s",name);
 
4555
 
 
4556
  return;
 
4557
}
 
4558
 
 
4559
 
 
4560
static bool
 
4561
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
 
4562
               char *argument)
 
4563
{
 
4564
  switch(optid) {
 
4565
  case 'r':
 
4566
    record = 1;
 
4567
    break;
 
4568
  case 'x':
 
4569
  {
 
4570
    char buff[FN_REFLEN];
 
4571
    if (!test_if_hard_path(argument))
 
4572
    {
 
4573
      strxmov(buff, opt_basedir, argument, NULL);
 
4574
      argument= buff;
 
4575
    }
 
4576
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4577
    assert(cur_file == file_stack && cur_file->file == 0);
 
4578
    if (!(cur_file->file=
 
4579
          my_fopen(buff, O_RDONLY, MYF(0))))
 
4580
      die("Could not open '%s' for reading: errno = %d", buff, errno);
 
4581
    cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
 
4582
    cur_file->lineno= 1;
 
4583
    break;
 
4584
  }
 
4585
  case 'm':
 
4586
  {
 
4587
    static char buff[FN_REFLEN];
 
4588
    if (!test_if_hard_path(argument))
 
4589
    {
 
4590
      strxmov(buff, opt_basedir, argument, NULL);
 
4591
      argument= buff;
 
4592
    }
 
4593
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4594
    timer_file= buff;
 
4595
    unlink(timer_file);       /* Ignore error, may not exist */
 
4596
    break;
 
4597
  }
 
4598
  case 'p':
 
4599
    if (argument)
 
4600
    {
 
4601
      free(opt_pass);
 
4602
      opt_pass= my_strdup(argument, MYF(MY_FAE));
 
4603
      while (*argument) *argument++= 'x';    /* Destroy argument */
 
4604
      tty_password= 0;
 
4605
    }
 
4606
    else
 
4607
      tty_password= 1;
 
4608
    break;
 
4609
  case 't':
 
4610
    my_stpncpy(TMPDIR, argument, sizeof(TMPDIR));
 
4611
    break;
 
4612
  case 'A':
 
4613
    if (!embedded_server_arg_count)
 
4614
    {
 
4615
      embedded_server_arg_count=1;
 
4616
      embedded_server_args[0]= (char*) "";
 
4617
    }
 
4618
    if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
 
4619
        !(embedded_server_args[embedded_server_arg_count++]=
 
4620
          my_strdup(argument, MYF(MY_FAE))))
 
4621
    {
 
4622
      die("Can't use server argument");
 
4623
    }
 
4624
    break;
 
4625
  case 'F':
 
4626
    read_embedded_server_arguments(argument);
 
4627
    break;
 
4628
  case 'V':
 
4629
    print_version();
 
4630
    exit(0);
 
4631
  case '?':
 
4632
    usage();
 
4633
    exit(0);
 
4634
  }
 
4635
  return 0;
 
4636
}
 
4637
 
 
4638
 
 
4639
static int parse_args(int argc, char **argv)
 
4640
{
 
4641
  load_defaults("drizzle",load_default_groups,&argc,&argv);
 
4642
  default_argv= argv;
 
4643
 
 
4644
  if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
 
4645
    exit(1);
 
4646
 
 
4647
  if (argc > 1)
 
4648
  {
 
4649
    usage();
 
4650
    exit(1);
 
4651
  }
 
4652
  if (argc == 1)
 
4653
    opt_db= *argv;
 
4654
  if (tty_password)
 
4655
    opt_pass= get_tty_password(NULL);          /* purify tested */
 
4656
  if (debug_info_flag)
 
4657
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
 
4658
  if (debug_check_flag)
 
4659
    my_end_arg= MY_CHECK_ERROR;
 
4660
 
 
4661
  return 0;
 
4662
}
 
4663
 
4563
4664
/*
4564
4665
  Write the content of str into file
4565
4666
 
4576
4677
  int fd;
4577
4678
  char buff[FN_REFLEN];
4578
4679
  int flags= O_WRONLY | O_CREAT;
4579
 
  if (!internal::test_if_hard_path(fname))
 
4680
  if (!test_if_hard_path(fname))
4580
4681
  {
4581
 
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),fname);
 
4682
    strxmov(buff, opt_basedir, fname, NULL);
4582
4683
    fname= buff;
4583
4684
  }
4584
 
  internal::fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
 
4685
  fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4585
4686
 
4586
4687
  if (!append)
4587
4688
    flags|= O_TRUNC;
4588
 
  if ((fd= internal::my_open(buff, flags,
 
4689
  if ((fd= my_open(buff, flags,
4589
4690
                   MYF(MY_WME | MY_FFNF))) < 0)
4590
4691
    die("Could not open '%s' for writing: errno = %d", buff, errno);
4591
 
  if (append && lseek(fd, 0, SEEK_END) == MY_FILEPOS_ERROR)
 
4692
  if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
4592
4693
    die("Could not find end of file '%s': errno = %d", buff, errno);
4593
 
  if (internal::my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
 
4694
  if (my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
4594
4695
    die("write failed");
4595
 
  internal::my_close(fd, MYF(0));
 
4696
  my_close(fd, MYF(0));
4596
4697
}
4597
4698
 
4598
4699
/*
4614
4715
void dump_result_to_log_file(const char *buf, int size)
4615
4716
{
4616
4717
  char log_file[FN_REFLEN];
4617
 
  str_to_file(internal::fn_format(log_file, result_file_name.c_str(), opt_logdir.c_str(), ".log",
4618
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4718
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
 
4719
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4619
4720
                        MY_REPLACE_EXT),
4620
4721
              buf, size);
4621
4722
  fprintf(stderr, "\nMore results from queries before failure can be found in %s\n",
4622
4723
          log_file);
4623
4724
}
4624
4725
 
4625
 
void dump_progress()
 
4726
void dump_progress(void)
4626
4727
{
4627
4728
  char progress_file[FN_REFLEN];
4628
 
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4629
 
                        opt_logdir.c_str(), ".progress",
4630
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4729
  str_to_file(fn_format(progress_file, result_file_name,
 
4730
                        opt_logdir, ".progress",
 
4731
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4631
4732
                        MY_REPLACE_EXT),
4632
4733
              ds_progress.c_str(), ds_progress.length());
4633
4734
}
4634
4735
 
4635
 
void dump_warning_messages()
 
4736
void dump_warning_messages(void)
4636
4737
{
4637
4738
  char warn_file[FN_REFLEN];
4638
4739
 
4639
 
  str_to_file(internal::fn_format(warn_file, result_file_name.c_str(), opt_logdir.c_str(), ".warnings",
4640
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4740
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
 
4741
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4641
4742
                        MY_REPLACE_EXT),
4642
4743
              ds_warning_messages.c_str(), ds_warning_messages.length());
4643
4744
}
4647
4748
  Append the result for one field to the dynamic string ds
4648
4749
*/
4649
4750
 
4650
 
static void append_field(string *ds, uint32_t col_idx, drizzle_column_st *column,
 
4751
static void append_field(string *ds, uint col_idx, const DRIZZLE_FIELD* field,
4651
4752
                         const char* val, uint64_t len, bool is_null)
4652
4753
{
4653
4754
  if (col_idx < max_replace_column && replace_column[col_idx])
4669
4770
  }
4670
4771
  else
4671
4772
  {
4672
 
    ds->append(drizzle_column_name(column));
 
4773
    ds->append(field->name);
4673
4774
    ds->append("\t");
4674
4775
    replace_append_mem(ds, val, (int)len);
4675
4776
    ds->append("\n");
4682
4783
  Values may be converted with 'replace_column'
4683
4784
*/
4684
4785
 
4685
 
static void append_result(string *ds, drizzle_result_st *res)
 
4786
static void append_result(string *ds, DRIZZLE_RES *res)
4686
4787
{
4687
 
  drizzle_row_t row;
4688
 
  uint32_t num_fields= drizzle_result_column_count(res);
4689
 
  drizzle_column_st *column;
4690
 
  size_t *lengths;
 
4788
  DRIZZLE_ROW row;
 
4789
  uint32_t num_fields= drizzle_num_fields(res);
 
4790
  const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
4791
  uint32_t *lengths;
4691
4792
 
4692
 
  while ((row = drizzle_row_next(res)))
 
4793
  while ((row = drizzle_fetch_row(res)))
4693
4794
  {
4694
4795
    uint32_t i;
4695
 
    lengths = drizzle_row_field_sizes(res);
4696
 
    drizzle_column_seek(res, 0);
 
4796
    lengths = drizzle_fetch_lengths(res);
4697
4797
    for (i = 0; i < num_fields; i++)
4698
 
    {
4699
 
      column= drizzle_column_next(res);
4700
 
      if (row[i] && (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY))
4701
 
      {
4702
 
        if (boost::lexical_cast<uint32_t>(row[i]))
4703
 
        {
4704
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4705
 
          {
4706
 
            append_field(ds, i, column, "YES", 3, false);
4707
 
          }
4708
 
          else
4709
 
          {
4710
 
            append_field(ds, i, column, "TRUE", 4, false);
4711
 
          }
4712
 
        }
4713
 
        else
4714
 
        {
4715
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4716
 
          {
4717
 
            append_field(ds, i, column, "NO", 2, false);
4718
 
          }
4719
 
          else
4720
 
          {
4721
 
            append_field(ds, i, column, "FALSE", 5, false);
4722
 
          }
4723
 
        }
4724
 
      }
4725
 
      else
4726
 
      {
4727
 
        append_field(ds, i, column,
4728
 
                     (const char*)row[i], lengths[i], !row[i]);
4729
 
      }
4730
 
    }
 
4798
      append_field(ds, i, &fields[i],
 
4799
                   (const char*)row[i], lengths[i], !row[i]);
4731
4800
    if (!display_result_vertically)
4732
4801
      ds->append("\n");
4733
4802
 
4739
4808
  Append metadata for fields to output
4740
4809
*/
4741
4810
 
4742
 
static void append_metadata(string *ds, drizzle_result_st *res)
 
4811
static void append_metadata(string *ds,
 
4812
                            const DRIZZLE_FIELD *field,
 
4813
                            uint num_fields)
4743
4814
{
4744
 
  drizzle_column_st *column;
 
4815
  const DRIZZLE_FIELD *field_end;
4745
4816
  ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4746
4817
             "Column_alias\tType\tLength\tMax length\tIs_null\t"
4747
4818
             "Flags\tDecimals\tCharsetnr\n");
4748
4819
 
4749
 
  drizzle_column_seek(res, 0);
4750
 
  while ((column= drizzle_column_next(res)))
 
4820
  for (field_end= field+num_fields ;
 
4821
       field < field_end ;
 
4822
       field++)
4751
4823
  {
4752
 
    ds->append(drizzle_column_catalog(column),
4753
 
               strlen(drizzle_column_catalog(column)));
4754
 
    ds->append("\t", 1);
4755
 
    ds->append(drizzle_column_db(column), strlen(drizzle_column_db(column)));
4756
 
    ds->append("\t", 1);
4757
 
    ds->append(drizzle_column_orig_table(column),
4758
 
               strlen(drizzle_column_orig_table(column)));
4759
 
    ds->append("\t", 1);
4760
 
    ds->append(drizzle_column_table(column),
4761
 
               strlen(drizzle_column_table(column)));
4762
 
    ds->append("\t", 1);
4763
 
    ds->append(drizzle_column_orig_name(column),
4764
 
               strlen(drizzle_column_orig_name(column)));
4765
 
    ds->append("\t", 1);
4766
 
    ds->append(drizzle_column_name(column),
4767
 
               strlen(drizzle_column_name(column)));
4768
 
    ds->append("\t", 1);
4769
 
    replace_append_uint(ds, drizzle_column_type_drizzle(column));
4770
 
    ds->append("\t", 1);
4771
 
    replace_append_uint(ds, drizzle_column_size(column));
4772
 
    ds->append("\t", 1);
4773
 
    if (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
4774
 
    {
4775
 
      replace_append_uint(ds, 1);
4776
 
    }
4777
 
    else
4778
 
    {
4779
 
      replace_append_uint(ds, drizzle_column_max_size(column));
4780
 
    }
4781
 
    ds->append("\t", 1);
4782
 
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4783
 
    ds->append("\t", 1);
4784
 
    replace_append_uint(ds, drizzle_column_flags(column));
4785
 
    ds->append("\t", 1);
4786
 
    replace_append_uint(ds, drizzle_column_decimals(column));
4787
 
    ds->append("\t", 1);
4788
 
    replace_append_uint(ds, drizzle_column_charset(column));
 
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);
4789
4854
    ds->append("\n", 1);
4790
4855
  }
4791
4856
}
4798
4863
static void append_info(string *ds, uint64_t affected_rows,
4799
4864
                        const char *info)
4800
4865
{
4801
 
  ostringstream buf;
4802
 
  buf << "affected rows: " << affected_rows << endl;
4803
 
  ds->append(buf.str());
4804
 
  if (info && strcmp(info, ""))
 
4866
  char buf[40], buff2[21];
 
4867
  sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
 
4868
  ds->append(buf);
 
4869
  if (info)
4805
4870
  {
4806
4871
    ds->append("info: ");
4807
4872
    ds->append(info);
4814
4879
  Display the table headings with the names tab separated
4815
4880
*/
4816
4881
 
4817
 
static void append_table_headings(string *ds, drizzle_result_st *res)
 
4882
static void append_table_headings(string *ds,
 
4883
                                  const DRIZZLE_FIELD *field,
 
4884
                                  uint num_fields)
4818
4885
{
4819
 
  uint32_t col_idx= 0;
4820
 
  drizzle_column_st *column;
4821
 
  drizzle_column_seek(res, 0);
4822
 
  while ((column= drizzle_column_next(res)))
 
4886
  uint col_idx;
 
4887
  for (col_idx= 0; col_idx < num_fields; col_idx++)
4823
4888
  {
4824
4889
    if (col_idx)
4825
4890
      ds->append("\t", 1);
4826
 
    replace_append(ds, drizzle_column_name(column));
4827
 
    col_idx++;
 
4891
    replace_append(ds, field[col_idx].name);
4828
4892
  }
4829
4893
  ds->append("\n", 1);
4830
4894
}
4836
4900
  Number of warnings appended to ds
4837
4901
*/
4838
4902
 
4839
 
static int append_warnings(string *ds, drizzle_con_st *con,
4840
 
                           drizzle_result_st *res)
 
4903
static int append_warnings(string *ds, DRIZZLE *drizzle)
4841
4904
{
4842
 
  uint32_t count;
4843
 
  drizzle_result_st warn_res;
4844
 
  drizzle_return_t ret;
4845
 
 
4846
 
 
4847
 
  if (!(count= drizzle_result_warning_count(res)))
 
4905
  uint count;
 
4906
  DRIZZLE_RES *warn_res;
 
4907
 
 
4908
 
 
4909
  if (!(count= drizzle_warning_count(drizzle)))
4848
4910
    return(0);
4849
4911
 
4850
 
  if (drizzle_query_str(con, &warn_res, "SHOW WARNINGS", &ret) == NULL ||
4851
 
      ret != DRIZZLE_RETURN_OK)
4852
 
  {
4853
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
4854
 
      die("Error running query \"SHOW WARNINGS\": %s", drizzle_result_error(&warn_res));
4855
 
    else
4856
 
      die("Error running query \"SHOW WARNINGS\": %s", drizzle_con_error(con));
4857
 
  }
4858
 
 
4859
 
  if (drizzle_result_column_count(&warn_res) == 0 ||
4860
 
      drizzle_result_buffer(&warn_res) != DRIZZLE_RETURN_OK)
4861
 
    die("Warning count is %u but didn't get any warnings", count);
4862
 
 
4863
 
  append_result(ds, &warn_res);
4864
 
  drizzle_result_free(&warn_res);
 
4912
  /*
 
4913
    If one day we will support execution of multi-statements
 
4914
    through PS API we should not issue SHOW WARNINGS until
 
4915
    we have not read all results...
 
4916
  */
 
4917
  assert(!drizzle_more_results(drizzle));
 
4918
 
 
4919
  if (drizzle_real_query(drizzle, "SHOW WARNINGS", 13))
 
4920
    die("Error running query \"SHOW WARNINGS\": %s", drizzle_error(drizzle));
 
4921
 
 
4922
  if (!(warn_res= drizzle_store_result(drizzle)))
 
4923
    die("Warning count is %u but didn't get any warnings",
 
4924
        count);
 
4925
 
 
4926
  append_result(ds, warn_res);
4865
4927
 
4866
4928
  return(count);
4867
4929
}
4885
4947
                             int flags, char *query, int query_len,
4886
4948
                             string *ds, string *ds_warnings)
4887
4949
{
4888
 
  drizzle_result_st res;
4889
 
  drizzle_return_t ret;
4890
 
  drizzle_con_st *con= &cn->con;
4891
 
  int err= 0;
4892
 
 
4893
 
  drizzle_con_add_options(con, DRIZZLE_CON_NO_RESULT_READ);
 
4950
  DRIZZLE_RES *res= 0;
 
4951
  DRIZZLE *drizzle= &cn->drizzle;
 
4952
  int err= 0, counter= 0;
4894
4953
 
4895
4954
  if (flags & QUERY_SEND_FLAG)
4896
4955
  {
4897
4956
    /*
4898
4957
     * Send the query
4899
4958
     */
4900
 
 
4901
 
    (void) drizzle_query(con, &res, query, query_len, &ret);
4902
 
    if (ret != DRIZZLE_RETURN_OK)
 
4959
    if (do_send_query(cn, query, query_len, flags))
4903
4960
    {
4904
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE ||
4905
 
          ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
4906
 
      {
4907
 
        err= drizzle_result_error_code(&res);
4908
 
        handle_error(command, err, drizzle_result_error(&res),
4909
 
                     drizzle_result_sqlstate(&res), ds);
4910
 
        if (ret == DRIZZLE_RETURN_ERROR_CODE)
4911
 
          drizzle_result_free(&res);
4912
 
      }
4913
 
      else
4914
 
      {
4915
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4916
 
        err= ret;
4917
 
      }
 
4961
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
4962
                   drizzle_sqlstate(drizzle), ds);
4918
4963
      goto end;
4919
4964
    }
4920
4965
  }
4921
4966
  if (!(flags & QUERY_REAP_FLAG))
4922
4967
    return;
4923
4968
 
 
4969
  do
4924
4970
  {
4925
4971
    /*
4926
 
     * Read the result packet
4927
 
     */
4928
 
    if (drizzle_result_read(con, &res, &ret) == NULL ||
4929
 
        ret != DRIZZLE_RETURN_OK)
 
4972
      When  on first result set, call drizzle_read_query_result to retrieve
 
4973
      answer to the query sent earlier
 
4974
    */
 
4975
    if ((counter==0) && drizzle_read_query_result(drizzle))
4930
4976
    {
4931
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
4932
 
      {
4933
 
        handle_error(command, drizzle_result_error_code(&res),
4934
 
                     drizzle_result_error(&res), drizzle_result_sqlstate(&res),
4935
 
                     ds);
4936
 
      }
4937
 
      else
4938
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4939
 
      drizzle_result_free(&res);
4940
 
      err= ret;
 
4977
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
4978
                   drizzle_sqlstate(drizzle), ds);
4941
4979
      goto end;
 
4980
 
4942
4981
    }
4943
4982
 
4944
4983
    /*
4945
4984
      Store the result of the query if it will return any fields
4946
4985
    */
4947
 
    if (drizzle_result_column_count(&res) &&
4948
 
        (ret= drizzle_result_buffer(&res)) != DRIZZLE_RETURN_OK)
 
4986
    if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
4949
4987
    {
4950
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
4951
 
      {
4952
 
        handle_error(command, drizzle_result_error_code(&res),
4953
 
                     drizzle_result_error(&res), drizzle_result_sqlstate(&res),
4954
 
                     ds);
4955
 
      }
4956
 
      else
4957
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4958
 
      drizzle_result_free(&res);
4959
 
      err= ret;
 
4988
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
4989
                   drizzle_sqlstate(drizzle), ds);
4960
4990
      goto end;
4961
4991
    }
4962
4992
 
4964
4994
    {
4965
4995
      uint64_t affected_rows= 0;    /* Ok to be undef if 'disable_info' is set */
4966
4996
 
4967
 
      if (drizzle_result_column_count(&res))
 
4997
      if (res)
4968
4998
      {
 
4999
        const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
5000
        uint num_fields= drizzle_num_fields(res);
 
5001
 
4969
5002
        if (display_metadata)
4970
 
          append_metadata(ds, &res);
 
5003
          append_metadata(ds, fields, num_fields);
4971
5004
 
4972
5005
        if (!display_result_vertically)
4973
 
          append_table_headings(ds, &res);
 
5006
          append_table_headings(ds, fields, num_fields);
4974
5007
 
4975
 
        append_result(ds, &res);
 
5008
        append_result(ds, res);
4976
5009
      }
4977
5010
 
4978
5011
      /*
4979
 
        Need to call drizzle_result_affected_rows() before the "new"
 
5012
        Need to call drizzle_affected_rows() before the "new"
4980
5013
        query to find the warnings
4981
5014
      */
4982
5015
      if (!disable_info)
4983
 
        affected_rows= drizzle_result_affected_rows(&res);
 
5016
        affected_rows= drizzle_affected_rows(drizzle);
4984
5017
 
4985
5018
      /*
4986
5019
        Add all warnings to the result. We can't do this if we are in
4987
5020
        the middle of processing results from multi-statement, because
4988
5021
        this will break protocol.
4989
5022
      */
4990
 
      if (!disable_warnings)
 
5023
      if (!disable_warnings && !drizzle_more_results(drizzle))
4991
5024
      {
4992
 
        drizzle_con_remove_options(con, DRIZZLE_CON_NO_RESULT_READ);
4993
 
        if (append_warnings(ds_warnings, con, &res) || ds_warnings->length())
 
5025
        if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
4994
5026
        {
4995
5027
          ds->append("Warnings:\n", 10);
4996
5028
          ds->append(ds_warnings->c_str(), ds_warnings->length());
4998
5030
      }
4999
5031
 
5000
5032
      if (!disable_info)
5001
 
        append_info(ds, affected_rows, drizzle_result_info(&res));
 
5033
        append_info(ds, affected_rows, drizzle_info(drizzle));
5002
5034
    }
5003
5035
 
5004
 
    drizzle_result_free(&res);
 
5036
    if (res)
 
5037
    {
 
5038
      drizzle_free_result(res);
 
5039
      res= 0;
 
5040
    }
 
5041
    counter++;
 
5042
  } while (!(err= drizzle_next_result(drizzle)));
 
5043
  if (err > 0)
 
5044
  {
 
5045
    /* We got an error from drizzle_next_result, maybe expected */
 
5046
    handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
5047
                 drizzle_sqlstate(drizzle), ds);
 
5048
    goto end;
5005
5049
  }
 
5050
  assert(err == -1); /* Successful and there are no more results */
5006
5051
 
5007
5052
  /* If we come here the query is both executed and read successfully */
5008
5053
  handle_no_error(command);
5010
5055
end:
5011
5056
 
5012
5057
  /*
5013
 
    We save the return code (drizzleclient_errno(drizzle)) from the last call sent
5014
 
    to the server into the drizzletest builtin variable $drizzleclient_errno. This
 
5058
    We save the return code (drizzle_errno(drizzle)) from the last call sent
 
5059
    to the server into the drizzletest builtin variable $drizzle_errno. This
5015
5060
    variable then can be used from the test case itself.
5016
5061
  */
5017
 
  drizzle_con_remove_options(con, DRIZZLE_CON_NO_RESULT_READ);
5018
 
  var_set_errno(err);
 
5062
  var_set_errno(drizzle_errno(drizzle));
5019
5063
  return;
5020
5064
}
5021
5065
 
5040
5084
                  unsigned int err_errno, const char *err_error,
5041
5085
                  const char *err_sqlstate, string *ds)
5042
5086
{
5043
 
  uint32_t i;
5044
 
 
5045
 
 
5046
 
  if (! command->require_file.empty())
 
5087
  uint i;
 
5088
 
 
5089
 
 
5090
  if (command->require_file[0])
5047
5091
  {
5048
5092
    /*
5049
5093
      The query after a "--require" failed. This is fine as long the server
5050
5094
      returned a valid reponse. Don't allow 2013 or 2006 to trigger an
5051
5095
      abort_not_supported_test
5052
5096
    */
5053
 
    if (err_errno == DRIZZLE_RETURN_SERVER_GONE)
 
5097
    if (err_errno == CR_SERVER_LOST ||
 
5098
        err_errno == CR_SERVER_GONE_ERROR)
5054
5099
      die("require query '%s' failed: %d: %s", command->query,
5055
5100
          err_errno, err_error);
5056
5101
 
5062
5107
  if (command->abort_on_error)
5063
5108
    die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
5064
5109
 
5065
 
  for (i= 0 ; (uint32_t) i < command->expected_errors.count ; i++)
 
5110
  for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
5066
5111
  {
5067
5112
    if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
5068
5113
         (command->expected_errors.err[i].code.errnum == err_errno)) ||
5069
5114
        ((command->expected_errors.err[i].type == ERR_SQLSTATE) &&
5070
5115
         (strncmp(command->expected_errors.err[i].code.sqlstate,
5071
 
                  err_sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE) == 0)))
 
5116
                  err_sqlstate, SQLSTATE_LENGTH) == 0)))
5072
5117
    {
5073
5118
      if (!disable_result_log)
5074
5119
      {
5202
5247
    Create a temporary dynamic string to contain the output from
5203
5248
    this query.
5204
5249
  */
5205
 
  if (! command->require_file.empty())
 
5250
  if (command->require_file[0])
5206
5251
  {
5207
5252
    ds= &ds_result;
5208
5253
  }
5245
5290
    ds= save_ds;
5246
5291
  }
5247
5292
 
5248
 
  if (! command->require_file.empty())
 
5293
  if (command->require_file[0])
5249
5294
  {
5250
5295
    /* A result file was specified for _this_ query
5251
5296
       and the output should be checked against an already
5263
5308
static void get_command_type(struct st_command* command)
5264
5309
{
5265
5310
  char save;
5266
 
  uint32_t type;
 
5311
  uint type;
5267
5312
 
5268
5313
 
5269
5314
  if (*command->query == '}')
5274
5319
 
5275
5320
  save= command->query[command->first_word_len];
5276
5321
  command->query[command->first_word_len]= 0;
5277
 
  type= command_typelib.find_type(command->query, 1+2);
 
5322
  type= find_type(command->query, &command_typelib, 1+2);
5278
5323
  command->query[command->first_word_len]= save;
5279
5324
  if (type > 0)
5280
5325
  {
5318
5363
        */
5319
5364
        save= command->query[command->first_word_len-1];
5320
5365
        command->query[command->first_word_len-1]= 0;
5321
 
        if (command_typelib.find_type(command->query, 1+2) > 0)
 
5366
        if (find_type(command->query, &command_typelib, 1+2) > 0)
5322
5367
          die("Extra delimiter \";\" found");
5323
5368
        command->query[command->first_word_len-1]= save;
5324
5369
 
5346
5391
 
5347
5392
*/
5348
5393
 
5349
 
static void mark_progress(struct st_command*, int line)
 
5394
static void mark_progress(struct st_command* command __attribute__((unused)),
 
5395
                          int line)
5350
5396
{
 
5397
  char buf[32], *end;
5351
5398
  uint64_t timer= timer_now();
5352
5399
  if (!progress_start)
5353
5400
    progress_start= timer;
5354
5401
  timer-= progress_start;
5355
5402
 
5356
 
  ostringstream buf;
5357
5403
  /* Milliseconds since start */
5358
 
  buf << timer << "\t";
 
5404
  end= int64_t2str(timer, buf, 10);
 
5405
  ds_progress.append(buf, (int)(end-buf));
 
5406
  ds_progress.append("\t", 1);
5359
5407
 
5360
5408
  /* Parser line number */
5361
 
  buf << line << "\t";
 
5409
  end= int10_to_str(line, buf, 10);
 
5410
  ds_progress.append(buf, (int)(end-buf));
 
5411
  ds_progress.append("\t", 1);
5362
5412
 
5363
5413
  /* Filename */
5364
 
  buf << cur_file->file_name << ":";
 
5414
  ds_progress.append(cur_file->file_name);
 
5415
  ds_progress.append(":", 1);
5365
5416
 
5366
5417
  /* Line in file */
5367
 
  buf << cur_file->lineno << endl;
5368
 
 
5369
 
  ds_progress.append(buf.str());
5370
 
 
5371
 
}
5372
 
 
5373
 
static void check_retries(uint32_t in_opt_max_connect_retries)
5374
 
{
5375
 
  if (in_opt_max_connect_retries > 10000 || opt_max_connect_retries<1)
5376
 
  {
5377
 
    cout << N_("Error: Invalid Value for opt_max_connect_retries"); 
5378
 
    exit(-1);
5379
 
  }
5380
 
  opt_max_connect_retries= in_opt_max_connect_retries;
5381
 
}
5382
 
 
5383
 
static void check_tail_lines(uint32_t in_opt_tail_lines)
5384
 
{
5385
 
  if (in_opt_tail_lines > 10000)
5386
 
  {
5387
 
    cout << N_("Error: Invalid Value for opt_tail_lines"); 
5388
 
    exit(-1);
5389
 
  }
5390
 
  opt_tail_lines= in_opt_tail_lines;
5391
 
}
5392
 
 
5393
 
static void check_sleep(int32_t in_opt_sleep)
5394
 
{
5395
 
  if (in_opt_sleep < -1)
5396
 
  {
5397
 
    cout << N_("Error: Invalid Value for opt_sleep"); 
5398
 
    exit(-1);
5399
 
  }
5400
 
  opt_sleep= in_opt_sleep;
5401
 
}
 
5418
  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);
 
5423
 
 
5424
}
 
5425
 
5402
5426
 
5403
5427
int main(int argc, char **argv)
5404
5428
{
5405
 
try
5406
 
{
5407
5429
  struct st_command *command;
5408
5430
  bool q_send_flag= 0, abort_flag= 0;
5409
 
  uint32_t command_executed= 0, last_command_executed= 0;
5410
 
  string save_file("");
 
5431
  uint command_executed= 0, last_command_executed= 0;
 
5432
  char save_file[FN_REFLEN];
5411
5433
  struct stat res_info;
 
5434
  MY_INIT(argv[0]);
5412
5435
 
 
5436
  save_file[0]= 0;
5413
5437
  TMPDIR[0]= 0;
5414
5438
 
5415
 
  internal::my_init();
5416
 
 
5417
 
  po::options_description commandline_options("Options used only in command line");
5418
 
  commandline_options.add_options()
5419
 
  ("help,?", "Display this help and exit.")
5420
 
  ("mark-progress", po::value<bool>(&opt_mark_progress)->default_value(false)->zero_tokens(),
5421
 
  "Write linenumber and elapsed time to <testname>.progress ")
5422
 
  ("sleep,T", po::value<int32_t>(&opt_sleep)->default_value(-1)->notifier(&check_sleep),
5423
 
  "Sleep always this many seconds on sleep commands.")
5424
 
  ("test-file,x", po::value<string>(),
5425
 
  "Read test from/in this file (default stdin).")
5426
 
  ("timer-file,f", po::value<string>(),
5427
 
  "File where the timing in micro seconds is stored.")
5428
 
  ("tmpdir,t", po::value<string>(),
5429
 
  "Temporary directory where sockets are put.")
5430
 
  ("verbose,v", po::value<bool>(&verbose)->default_value(false),
5431
 
  "Write more.")
5432
 
  ("version,V", "Output version information and exit.")
5433
 
  ("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
5434
 
  "Configuration file defaults are not used if no-defaults is set")
5435
 
  ;
5436
 
 
5437
 
  po::options_description test_options("Options specific to the drizzleimport");
5438
 
  test_options.add_options()
5439
 
  ("basedir,b", po::value<string>(&opt_basedir)->default_value(""),
5440
 
  "Basedir for tests.")
5441
 
  ("character-sets-dir", po::value<string>(&opt_charsets_dir)->default_value(""),
5442
 
  "Directory where character sets are.")
5443
 
  ("database,D", po::value<string>(&opt_db)->default_value(""),
5444
 
  "Database to use.")
5445
 
  ("include,i", po::value<string>(&opt_include)->default_value(""),
5446
 
  "Include SQL before each test case.")  
5447
 
  ("testdir", po::value<string>(&opt_testdir)->default_value(""),
5448
 
  "Path to use to search for test files")
5449
 
  ("logdir", po::value<string>(&opt_logdir)->default_value(""),
5450
 
  "Directory for log files")
5451
 
  ("max-connect-retries", po::value<uint32_t>(&opt_max_connect_retries)->default_value(500)->notifier(&check_retries),
5452
 
  "Max number of connection attempts when connecting to server")
5453
 
  ("quiet,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5454
 
  "Suppress all normal output.")
5455
 
  ("record,r", "Record output of test_file into result file.")
5456
 
  ("result-file,R", po::value<string>(&result_file_name)->default_value(""),
5457
 
  "Read/Store result from/in this file.")
5458
 
  ("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5459
 
  "Suppress all normal output. Synonym for --quiet.")
5460
 
  ("tail-lines", po::value<uint32_t>(&opt_tail_lines)->default_value(0)->notifier(&check_tail_lines),
5461
 
  "Number of lines of the resul to include in a failure report")
5462
 
  ;
5463
 
 
5464
 
  po::options_description client_options("Options specific to the client");
5465
 
  client_options.add_options()
5466
 
 
5467
 
  ("host,h", po::value<string>(&opt_host)->default_value("localhost"),
5468
 
  "Connect to host.")
5469
 
  ("password,P", po::value<string>(&password)->default_value("PASSWORD_SENTINEL"),
5470
 
  "Password to use when connecting to server.")
5471
 
  ("port,p", po::value<uint32_t>(&opt_port)->default_value(0),
5472
 
  "Port number to use for connection or 0 for default")
5473
 
  ("protocol", po::value<string>(&opt_protocol),
5474
 
  "The protocol of connection (mysql or drizzle).")
5475
 
  ("user,u", po::value<string>(&opt_user)->default_value(""),
5476
 
  "User for login.")
5477
 
  ;
5478
 
 
5479
 
  po::positional_options_description p;
5480
 
  p.add("database", 1);
5481
 
 
5482
 
  po::options_description long_options("Allowed Options");
5483
 
  long_options.add(commandline_options).add(test_options).add(client_options);
5484
 
 
5485
 
  std::string system_config_dir_test(SYSCONFDIR); 
5486
 
  system_config_dir_test.append("/drizzle/drizzletest.cnf");
5487
 
 
5488
 
  std::string system_config_dir_client(SYSCONFDIR); 
5489
 
  system_config_dir_client.append("/drizzle/client.cnf");
5490
 
 
5491
 
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
5492
 
 
5493
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
5494
 
  {
5495
 
    const char *homedir= getenv("HOME");
5496
 
    if (homedir != NULL)
5497
 
      user_config_dir.replace(0, 1, homedir);
5498
 
  }
5499
 
 
5500
 
  po::variables_map vm;
5501
 
 
5502
 
  // Disable allow_guessing
5503
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
5504
 
 
5505
 
  po::store(po::command_line_parser(argc, argv).options(long_options).
5506
 
            style(style).positional(p).extra_parser(parse_password_arg).run(),
5507
 
            vm);
5508
 
 
5509
 
  if (! vm["no-defaults"].as<bool>())
5510
 
  {
5511
 
    std::string user_config_dir_test(user_config_dir);
5512
 
    user_config_dir_test.append("/drizzle/drizzletest.cnf"); 
5513
 
 
5514
 
    std::string user_config_dir_client(user_config_dir);
5515
 
    user_config_dir_client.append("/drizzle/client.cnf");
5516
 
 
5517
 
    ifstream user_test_ifs(user_config_dir_test.c_str());
5518
 
    po::store(parse_config_file(user_test_ifs, test_options), vm);
5519
 
 
5520
 
    ifstream user_client_ifs(user_config_dir_client.c_str());
5521
 
    po::store(parse_config_file(user_client_ifs, client_options), vm);
5522
 
 
5523
 
    ifstream system_test_ifs(system_config_dir_test.c_str());
5524
 
    store(parse_config_file(system_test_ifs, test_options), vm);
5525
 
 
5526
 
    ifstream system_client_ifs(system_config_dir_client.c_str());
5527
 
    po::store(parse_config_file(system_client_ifs, client_options), vm);
5528
 
  }
5529
 
 
5530
 
  po::notify(vm);
5531
 
 
5532
5439
  /* Init expected errors */
5533
5440
  memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
5534
5441
 
5539
5446
  next_con= connections + 1;
5540
5447
 
5541
5448
  /* Init file stack */
5542
 
  memset(file_stack.data(), 0, sizeof(file_stack));
5543
 
  cur_file= file_stack.data();
 
5449
  memset(file_stack, 0, sizeof(file_stack));
 
5450
  file_stack_end=
 
5451
    file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
 
5452
  cur_file= file_stack;
5544
5453
 
5545
5454
  /* Init block stack */
5546
5455
  memset(block_stack, 0, sizeof(block_stack));
5550
5459
  cur_block->ok= true; /* Outer block should always be executed */
5551
5460
  cur_block->cmd= cmd_none;
5552
5461
 
5553
 
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_version());
 
5462
  if (hash_init(&var_hash, charset_info,
 
5463
                1024, 0, 0, get_var_key, var_free, MYF(0)))
 
5464
    die("Variable hash initialization failed");
 
5465
 
 
5466
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
5554
5467
 
5555
5468
  memset(&master_pos, 0, sizeof(master_pos));
5556
5469
 
5563
5476
  ds_progress.reserve(2048);
5564
5477
  ds_warning_messages.reserve(2048);
5565
5478
 
5566
 
 
5567
 
  if (vm.count("record"))
5568
 
  {
5569
 
    record = 1;
5570
 
  }
5571
 
 
5572
 
  if (vm.count("test-file"))
5573
 
  {
5574
 
    string tmp= vm["test-file"].as<string>();
5575
 
    char buff[FN_REFLEN];
5576
 
    if (!internal::test_if_hard_path(tmp.c_str()))
5577
 
    {
5578
 
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5579
 
      tmp= buff;
5580
 
    }
5581
 
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5582
 
    assert(cur_file == file_stack.data() && cur_file->file == 0);
5583
 
    if (!(cur_file->file= fopen(buff, "r")))
5584
 
    {
5585
 
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5586
 
      return EXIT_ARGUMENT_INVALID;
5587
 
    }
5588
 
    if (!(cur_file->file_name= strdup(buff)))
5589
 
    {
5590
 
      fprintf(stderr, _("Out of memory"));
5591
 
      return EXIT_OUT_OF_MEMORY;
5592
 
    }
5593
 
    cur_file->lineno= 1;
5594
 
  }
5595
 
 
5596
 
  if (vm.count("timer-file"))
5597
 
  {
5598
 
    string tmp= vm["timer-file"].as<string>().c_str();
5599
 
    static char buff[FN_REFLEN];
5600
 
    if (!internal::test_if_hard_path(tmp.c_str()))
5601
 
    {
5602
 
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5603
 
      tmp= buff;
5604
 
    }
5605
 
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5606
 
    timer_file= buff;
5607
 
    unlink(timer_file);       /* Ignore error, may not exist */
5608
 
  }
5609
 
 
5610
 
  if (vm.count("protocol"))
5611
 
  {
5612
 
    std::transform(opt_protocol.begin(), opt_protocol.end(),
5613
 
      opt_protocol.begin(), ::tolower);
5614
 
 
5615
 
    if (not opt_protocol.compare("mysql"))
5616
 
      use_drizzle_protocol=false;
5617
 
    else if (not opt_protocol.compare("drizzle"))
5618
 
      use_drizzle_protocol=true;
5619
 
    else
5620
 
    {
5621
 
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
5622
 
      exit(-1);
5623
 
    }
5624
 
  }
5625
 
 
5626
 
  if (vm.count("port"))
5627
 
  {
5628
 
    /* If the port number is > 65535 it is not a valid port
5629
 
       This also helps with potential data loss casting unsigned long to a
5630
 
       uint32_t. */
5631
 
    if (opt_port > 65535)
5632
 
    {
5633
 
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
5634
 
      exit(EXIT_ARGUMENT_INVALID);
5635
 
    }
5636
 
  }
5637
 
 
5638
 
  if( vm.count("password") )
5639
 
  {
5640
 
    if (!opt_password.empty())
5641
 
      opt_password.erase();
5642
 
    if (password == PASSWORD_SENTINEL)
5643
 
    {
5644
 
      opt_password= "";
5645
 
    }
5646
 
    else
5647
 
    {
5648
 
      opt_password= password;
5649
 
      tty_password= false;
5650
 
    }
5651
 
  }
5652
 
  else
5653
 
  {
5654
 
      tty_password= true;
5655
 
  }
5656
 
 
5657
 
  if (vm.count("tmpdir"))
5658
 
  {
5659
 
    strncpy(TMPDIR, vm["tmpdir"].as<string>().c_str(), sizeof(TMPDIR));
5660
 
  }
5661
 
 
5662
 
  if (vm.count("version"))
5663
 
  {
5664
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5665
 
    drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5666
 
    exit(0);
5667
 
  }
5668
 
  
5669
 
  if (vm.count("help"))
5670
 
  {
5671
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5672
 
    drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5673
 
    printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
5674
 
    printf("Drizzle version modified by Brian, Jay, Monty Taylor, PatG and Stewart\n");
5675
 
    printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
5676
 
    printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
5677
 
    printf("Usage: %s [OPTIONS] [database] < test_file\n", internal::my_progname);
5678
 
    exit(0);
5679
 
  }
5680
 
 
5681
 
  if (tty_password)
5682
 
  {
5683
 
    opt_pass= client_get_tty_password(NULL);          /* purify tested */
5684
 
  }
 
5479
  parse_args(argc, argv);
5685
5480
 
5686
5481
  server_initialized= 1;
5687
 
  if (cur_file == file_stack.data() && cur_file->file == 0)
 
5482
  if (cur_file == file_stack && cur_file->file == 0)
5688
5483
  {
5689
5484
    cur_file->file= stdin;
5690
 
    cur_file->file_name= strdup("<stdin>");
5691
 
    if (cur_file->file_name == NULL)
5692
 
      die("Out of memory");
 
5485
    cur_file->file_name= my_strdup("<stdin>", MYF(MY_WME));
5693
5486
    cur_file->lineno= 1;
5694
5487
  }
5695
5488
  cur_con= connections;
5696
 
  if ((cur_con->drizzle= drizzle_create(NULL)) == NULL)
 
5489
  if (!( drizzle_create(&cur_con->drizzle)))
5697
5490
    die("Failed in drizzle_create()");
5698
 
  if (!( drizzle_con_create(cur_con->drizzle, &cur_con->con)))
5699
 
    die("Failed in drizzle_con_create()");
5700
 
  drizzle_con_add_options(&cur_con->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
5491
  if (opt_compress)
 
5492
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
 
5493
  drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
5701
5494
 
5702
 
  if (!(cur_con->name = strdup("default")))
 
5495
  if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5703
5496
    die("Out of memory");
5704
 
  safe_connect(&cur_con->con, cur_con->name, opt_host, opt_user, opt_pass,
 
5497
 
 
5498
  safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
5705
5499
               opt_db, opt_port);
5706
5500
 
5707
 
  fill_global_error_names();
5708
 
 
5709
5501
  /* Use all time until exit if no explicit 'start_timer' */
5710
5502
  timer_start= timer_now();
5711
5503
 
5712
5504
  /*
5713
 
    Initialize $drizzleclient_errno with -1, so we can
 
5505
    Initialize $drizzle_errno with -1, so we can
5714
5506
    - distinguish it from valid values ( >= 0 ) and
5715
5507
    - detect if there was never a command sent to the server
5716
5508
  */
5717
5509
  var_set_errno(-1);
5718
5510
 
5719
 
  /* Update $drizzleclient_get_server_version to that of current connection */
5720
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
5511
  /* Update $drizzle_get_server_version to that of current connection */
 
5512
  var_set_drizzle_get_server_version(&cur_con->drizzle);
5721
5513
 
5722
 
  if (! opt_include.empty())
 
5514
  if (opt_include)
5723
5515
  {
5724
 
    open_file(opt_include.c_str());
 
5516
    open_file(opt_include);
5725
5517
  }
5726
5518
 
5727
5519
  while (!read_command(&command) && !abort_flag)
5835
5627
        /* Check for special property for this query */
5836
5628
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5837
5629
 
5838
 
        if (! save_file.empty())
 
5630
        if (save_file[0])
5839
5631
        {
5840
 
          command->require_file= save_file;
5841
 
          save_file.clear();
 
5632
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
 
5633
          save_file[0]= 0;
5842
5634
        }
5843
5635
        run_query(cur_con, command, flags);
5844
5636
        command_executed++;
5875
5667
        command->last_argument= command->end;
5876
5668
        break;
5877
5669
      case Q_REQUIRE:
5878
 
        do_get_file_name(command, save_file);
 
5670
        do_get_file_name(command, save_file, sizeof(save_file));
5879
5671
        break;
5880
5672
      case Q_ERROR:
5881
5673
        do_get_errcodes(command);
5905
5697
        command->last_argument= command->end;
5906
5698
        break;
5907
5699
      case Q_PING:
5908
 
        {
5909
 
          drizzle_result_st result;
5910
 
          drizzle_return_t ret;
5911
 
          (void) drizzle_ping(&cur_con->con, &result, &ret);
5912
 
          if (ret == DRIZZLE_RETURN_OK || ret == DRIZZLE_RETURN_ERROR_CODE)
5913
 
            drizzle_result_free(&result);
5914
 
        }
 
5700
        (void) drizzle_ping(&cur_con->drizzle);
5915
5701
        break;
5916
5702
      case Q_EXEC:
5917
5703
        do_exec(command);
5929
5715
        do_set_charset(command);
5930
5716
        break;
5931
5717
      case Q_DISABLE_RECONNECT:
5932
 
        set_reconnect(&cur_con->con, 0);
 
5718
        set_reconnect(&cur_con->drizzle, 0);
5933
5719
        break;
5934
5720
      case Q_ENABLE_RECONNECT:
5935
 
        set_reconnect(&cur_con->con, 1);
 
5721
        set_reconnect(&cur_con->drizzle, 1);
5936
5722
        break;
5937
5723
      case Q_DISABLE_PARSING:
5938
5724
        if (parsing_disabled == 0)
6025
5811
  */
6026
5812
  if (ds_res.length())
6027
5813
  {
6028
 
    if (! result_file_name.empty())
 
5814
    if (result_file_name)
6029
5815
    {
6030
5816
      /* A result file has been specified */
6031
5817
 
6032
5818
      if (record)
6033
5819
      {
6034
5820
        /* Recording - dump the output from test to result file */
6035
 
        str_to_file(result_file_name.c_str(), ds_res.c_str(), ds_res.length());
 
5821
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
6036
5822
      }
6037
5823
      else
6038
5824
      {
6055
5841
  }
6056
5842
 
6057
5843
  if (!command_executed &&
6058
 
      ! result_file_name.empty() && !stat(result_file_name.c_str(), &res_info))
 
5844
      result_file_name && !stat(result_file_name, &res_info))
6059
5845
  {
6060
5846
    /*
6061
5847
      my_stat() successful on result file. Check if we have not run a
6067
5853
    die("No queries executed but result file found!");
6068
5854
  }
6069
5855
 
6070
 
  if ( opt_mark_progress && ! result_file_name.empty() )
 
5856
  if ( opt_mark_progress && result_file_name )
6071
5857
    dump_progress();
6072
5858
 
6073
5859
  /* Dump warning messages */
6074
 
  if (! result_file_name.empty() && ds_warning_messages.length())
 
5860
  if (result_file_name && ds_warning_messages.length())
6075
5861
    dump_warning_messages();
6076
5862
 
6077
5863
  timer_output();
6078
5864
  /* Yes, if we got this far the test has suceeded! Sakila smiles */
6079
5865
  cleanup_and_exit(0);
6080
 
}
6081
 
 
6082
 
  catch(exception &err)
6083
 
  {
6084
 
    cerr<<err.what()<<endl;
6085
 
  }
6086
 
 
6087
5866
  return 0; /* Keep compiler happy too */
6088
5867
}
6089
5868
 
6109
5888
  the time between executing the two commands.
6110
5889
*/
6111
5890
 
6112
 
void timer_output()
 
5891
void timer_output(void)
6113
5892
{
6114
5893
  if (timer_file)
6115
5894
  {
6116
 
    ostringstream buf;
 
5895
    char buf[32], *end;
6117
5896
    uint64_t timer= timer_now() - timer_start;
6118
 
    buf << timer;
6119
 
    str_to_file(timer_file,buf.str().c_str(), buf.str().size() );
 
5897
    end= int64_t2str(timer, buf, 10);
 
5898
    str_to_file(timer_file,buf, (int) (end-buf));
6120
5899
    /* Timer has been written to the file, don't use it anymore */
6121
5900
    timer_file= 0;
6122
5901
  }
6123
5902
}
6124
5903
 
6125
5904
 
6126
 
uint64_t timer_now()
 
5905
uint64_t timer_now(void)
6127
5906
{
6128
 
#if defined(HAVE_GETHRTIME)
6129
 
  return gethrtime()/1000/1000;
6130
 
#else
6131
 
  uint64_t newtime;
6132
 
  struct timeval t;
6133
 
  /*
6134
 
    The following loop is here because gettimeofday may fail on some systems
6135
 
  */
6136
 
  while (gettimeofday(&t, NULL) != 0)
6137
 
  {}
6138
 
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
6139
 
  return newtime/1000;
6140
 
#endif  /* defined(HAVE_GETHRTIME) */
 
5907
  return my_micro_time() / 1000;
6141
5908
}
6142
5909
 
6143
5910
 
6160
5927
    die("Missing argument in %s", command->query);
6161
5928
 
6162
5929
  /* Allocate a buffer for results */
6163
 
  start= buff= (char *)malloc(strlen(from)+1);
 
5930
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6164
5931
  while (*from)
6165
5932
  {
6166
 
    uint32_t column_number;
 
5933
    char *to;
 
5934
    uint column_number;
6167
5935
 
6168
 
    char *to= get_string(&buff, &from, command);
 
5936
    to= get_string(&buff, &from, command);
6169
5937
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6170
5938
      die("Wrong column number to replace_column in '%s'", command->query);
6171
5939
    if (!*from)
6172
5940
      die("Wrong number of arguments to replace_column in '%s'", command->query);
6173
5941
    to= get_string(&buff, &from, command);
6174
5942
    free(replace_column[column_number-1]);
6175
 
    replace_column[column_number-1]= strdup(to);
6176
 
    if (replace_column[column_number-1] == NULL)
6177
 
      die("Out of memory");
 
5943
    replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
6178
5944
    set_if_bigger(max_replace_column, column_number);
6179
5945
  }
6180
5946
  free(start);
6184
5950
 
6185
5951
void free_replace_column()
6186
5952
{
6187
 
  for (uint32_t i= 0 ; i < max_replace_column; i++)
 
5953
  uint i;
 
5954
  for (i=0 ; i < max_replace_column ; i++)
6188
5955
  {
6189
 
    free(replace_column[i]);
6190
 
    replace_column[i]= 0;
 
5956
    if (replace_column[i])
 
5957
    {
 
5958
      free(replace_column[i]);
 
5959
      replace_column[i]= 0;
 
5960
    }
6191
5961
  }
6192
5962
  max_replace_column= 0;
6193
5963
}
6204
5974
  TYPELIB typelib;        /* Pointer to strings */
6205
5975
  unsigned char  *str;          /* Strings is here */
6206
5976
  uint8_t *flag;          /* Flag about each var. */
6207
 
  uint32_t  array_allocs,max_count,length,max_length;
 
5977
  uint  array_allocs,max_count,length,max_length;
6208
5978
} POINTER_ARRAY;
6209
5979
 
6210
5980
struct st_replace;
6211
 
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6212
 
                                char *word_end_chars);
 
5981
struct st_replace *init_replace(char * *from, char * *to, uint count,
 
5982
                                char * word_end_chars);
6213
5983
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6214
5984
void replace_strings_append(struct st_replace *rep, string* ds,
6215
5985
                            const char *from, int len);
 
5986
void free_pointer_array(POINTER_ARRAY *pa);
6216
5987
 
6217
 
st_replace *glob_replace= NULL;
6218
 
// boost::scoped_ptr<st_replace> glob_replace;
 
5988
struct st_replace *glob_replace;
6219
5989
 
6220
5990
/*
6221
5991
  Get arguments for replace. The syntax is:
6225
5995
  variable is replaced.
6226
5996
*/
6227
5997
 
6228
 
static void free_pointer_array(POINTER_ARRAY *pa)
6229
 
{
6230
 
  if (!pa->typelib.count)
6231
 
    return;
6232
 
  pa->typelib.count=0;
6233
 
  free((char*) pa->typelib.type_names);
6234
 
  pa->typelib.type_names=0;
6235
 
  free(pa->str);
6236
 
}
6237
 
 
6238
5998
void do_get_replace(struct st_command *command)
6239
5999
{
6240
 
  uint32_t i;
 
6000
  uint i;
6241
6001
  char *from= command->first_argument;
6242
6002
  char *buff, *start;
6243
6003
  char word_end_chars[256], *pos;
6250
6010
  memset(&from_array, 0, sizeof(from_array));
6251
6011
  if (!*from)
6252
6012
    die("Missing argument in %s", command->query);
6253
 
  start= buff= (char *)malloc(strlen(from)+1);
 
6013
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6254
6014
  while (*from)
6255
6015
  {
6256
6016
    char *to= buff;
6266
6026
    if (my_isspace(charset_info,i))
6267
6027
      *pos++= i;
6268
6028
  *pos=0;          /* End pointer */
6269
 
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
6270
 
                                   to_array.typelib.type_names,
6271
 
                                   from_array.typelib.count,
 
6029
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
 
6030
                                   (char**) to_array.typelib.type_names,
 
6031
                                   (uint) from_array.typelib.count,
6272
6032
                                   word_end_chars)))
6273
6033
    die("Can't initialize replace from '%s'", command->query);
6274
6034
  free_pointer_array(&from_array);
6281
6041
 
6282
6042
void free_replace()
6283
6043
{
6284
 
  free(glob_replace);
6285
 
  glob_replace=0;
 
6044
 
 
6045
  if (glob_replace)
 
6046
  {
 
6047
    free(glob_replace);
 
6048
    glob_replace=0;
 
6049
  }
 
6050
  return;
6286
6051
}
6287
6052
 
6288
6053
 
6294
6059
typedef struct st_replace_found {
6295
6060
  bool found;
6296
6061
  char *replace_string;
6297
 
  uint32_t to_offset;
 
6062
  uint to_offset;
6298
6063
  int from_offset;
6299
6064
} REPLACE_STRING;
6300
6065
 
6302
6067
void replace_strings_append(REPLACE *rep, string* ds,
6303
6068
                            const char *str, int len)
6304
6069
{
6305
 
  REPLACE *rep_pos;
6306
 
  REPLACE_STRING *rep_str;
 
6070
  register REPLACE *rep_pos;
 
6071
  register REPLACE_STRING *rep_str;
6307
6072
  const char *start, *from;
6308
6073
 
6309
6074
 
6352
6117
  char* pattern; /* Pattern to be replaced */
6353
6118
  char* replace; /* String or expression to replace the pattern with */
6354
6119
  int icase; /* true if the match is case insensitive */
6355
 
  int global; /* true if the match should be global -- 
6356
 
                 i.e. repeat the matching until the end of the string */
6357
6120
};
6358
6121
 
6359
 
class st_replace_regex
 
6122
struct st_replace_regex
6360
6123
{
6361
 
public:
6362
 
  st_replace_regex(char* expr);
6363
 
  int multi_reg_replace(char* val);
 
6124
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
6364
6125
 
6365
6126
  /*
6366
6127
    Temporary storage areas for substitutions. To reduce unnessary copying
6369
6130
    st_regex substition. At the end of substitutions  buf points to the
6370
6131
    one containing the final result.
6371
6132
  */
6372
 
  typedef vector<st_regex> regex_arr_t;
6373
 
 
6374
 
  char* buf_;
 
6133
  char* buf;
6375
6134
  char* even_buf;
6376
6135
  char* odd_buf;
6377
6136
  int even_buf_len;
6378
6137
  int odd_buf_len;
6379
 
  boost::array<char, 8 << 10> buf0_;
6380
 
  boost::array<char, 8 << 10> buf1_;
6381
 
  regex_arr_t regex_arr;
6382
6138
};
6383
6139
 
6384
 
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
 
6140
struct st_replace_regex *glob_replace_regex= 0;
6385
6141
 
6386
6142
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6387
 
                char *string, int icase, int global);
 
6143
                char *string, int icase);
6388
6144
 
6389
6145
 
6390
6146
 
6423
6179
  Returns: st_replace_regex struct with pairs of substitutions
6424
6180
*/
6425
6181
 
6426
 
st_replace_regex::st_replace_regex(char* expr)
 
6182
static struct st_replace_regex* init_replace_regex(char* expr)
6427
6183
{
6428
 
  uint32_t expr_len= strlen(expr);
 
6184
  struct st_replace_regex* res;
 
6185
  char* buf,*expr_end;
 
6186
  char* p;
 
6187
  char* buf_p;
 
6188
  uint expr_len= strlen(expr);
6429
6189
  char last_c = 0;
6430
 
  st_regex reg;
6431
 
 
6432
 
  char* buf= new char[expr_len];
6433
 
  char* expr_end= expr + expr_len;
6434
 
  char* p= expr;
6435
 
  char* buf_p= buf;
 
6190
  struct st_regex reg;
 
6191
 
 
6192
  /* my_malloc() will die on fail with MY_FAE */
 
6193
  res=(struct st_replace_regex*)my_malloc(
 
6194
                                          sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
 
6195
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
 
6196
 
 
6197
  buf= (char*)res + sizeof(*res);
 
6198
  expr_end= expr + expr_len;
 
6199
  p= expr;
 
6200
  buf_p= buf;
6436
6201
 
6437
6202
  /* for each regexp substitution statement */
6438
6203
  while (p < expr_end)
6448
6213
 
6449
6214
    if (p == expr_end || ++p == expr_end)
6450
6215
    {
6451
 
      if (!regex_arr.empty())
 
6216
      if (res->regex_arr.elements)
6452
6217
        break;
6453
6218
      else
6454
6219
        goto err;
6476
6241
 
6477
6242
    /* Check if we should do matching case insensitive */
6478
6243
    if (p < expr_end && *p == 'i')
6479
 
    {
6480
 
      p++;
6481
6244
      reg.icase= 1;
6482
 
    }
6483
6245
 
6484
 
    /* Check if we should do matching globally */
6485
 
    if (p < expr_end && *p == 'g')
6486
 
    {
6487
 
      p++;
6488
 
      reg.global= 1;
6489
 
    }
6490
 
    regex_arr.push_back(reg);
 
6246
    /* done parsing the statement, now place it in regex_arr */
 
6247
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6248
      die("Out of memory");
6491
6249
  }
6492
 
  odd_buf_len= even_buf_len= buf0_.size();
6493
 
  even_buf= buf0_.data();
6494
 
  odd_buf= buf1_.data();
6495
 
  buf_= even_buf;
 
6250
  res->odd_buf_len= res->even_buf_len= 8192;
 
6251
  res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
 
6252
  res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
 
6253
  res->buf= res->even_buf;
6496
6254
 
6497
 
  return;
 
6255
  return res;
6498
6256
 
6499
6257
err:
 
6258
  free(res);
6500
6259
  die("Error parsing replace_regex \"%s\"", expr);
 
6260
  return 0;
6501
6261
}
6502
6262
 
6503
6263
/*
6519
6279
  in one pass
6520
6280
*/
6521
6281
 
6522
 
int st_replace_regex::multi_reg_replace(char* val)
 
6282
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6523
6283
{
6524
 
  char* in_buf= val;
6525
 
  char* out_buf= even_buf;
6526
 
  int* buf_len_p= &even_buf_len;
6527
 
  buf_= 0;
 
6284
  uint i;
 
6285
  char* in_buf, *out_buf;
 
6286
  int* buf_len_p;
 
6287
 
 
6288
  in_buf= val;
 
6289
  out_buf= r->even_buf;
 
6290
  buf_len_p= &r->even_buf_len;
 
6291
  r->buf= 0;
6528
6292
 
6529
6293
  /* For each substitution, do the replace */
6530
 
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
 
6294
  for (i= 0; i < r->regex_arr.elements; i++)
6531
6295
  {
 
6296
    struct st_regex re;
6532
6297
    char* save_out_buf= out_buf;
6533
 
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6534
 
                     in_buf, i.icase, i.global))
 
6298
 
 
6299
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6300
 
 
6301
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
 
6302
                     in_buf, re.icase))
6535
6303
    {
6536
6304
      /* if the buffer has been reallocated, make adjustements */
6537
6305
      if (save_out_buf != out_buf)
6538
6306
      {
6539
 
        if (save_out_buf == even_buf)
6540
 
          even_buf= out_buf;
 
6307
        if (save_out_buf == r->even_buf)
 
6308
          r->even_buf= out_buf;
6541
6309
        else
6542
 
          odd_buf= out_buf;
 
6310
          r->odd_buf= out_buf;
6543
6311
      }
6544
 
      buf_= out_buf;
 
6312
 
 
6313
      r->buf= out_buf;
6545
6314
      if (in_buf == val)
6546
 
        in_buf= odd_buf;
6547
 
      std::swap(in_buf, out_buf);
6548
 
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
 
6315
        in_buf= r->odd_buf;
 
6316
 
 
6317
      std::swap(in_buf,out_buf);
 
6318
 
 
6319
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
 
6320
        &r->odd_buf_len;
6549
6321
    }
6550
6322
  }
6551
 
  return buf_ == 0;
 
6323
 
 
6324
  return (r->buf == 0);
6552
6325
}
6553
6326
 
6554
6327
/*
6563
6336
void do_get_replace_regex(struct st_command *command)
6564
6337
{
6565
6338
  char *expr= command->first_argument;
6566
 
  glob_replace_regex.reset(new st_replace_regex(expr));
 
6339
  free_replace_regex();
 
6340
  if (!(glob_replace_regex=init_replace_regex(expr)))
 
6341
    die("Could not init replace_regex");
6567
6342
  command->last_argument= command->end;
6568
6343
}
6569
6344
 
 
6345
void free_replace_regex()
 
6346
{
 
6347
  if (glob_replace_regex)
 
6348
  {
 
6349
    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);
 
6353
    glob_replace_regex=0;
 
6354
  }
 
6355
}
 
6356
 
 
6357
 
 
6358
 
6570
6359
/*
6571
6360
  Performs a regex substitution
6572
6361
 
6580
6369
  icase - flag, if set to 1 the match is case insensitive
6581
6370
*/
6582
6371
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
6583
 
                char *replace, char *in_string, int icase, int global)
 
6372
                char *replace, char *in_string, int icase)
6584
6373
{
6585
 
  const char *error= NULL;
6586
 
  int erroffset;
6587
 
  int ovector[3];
6588
 
  pcre *re= pcre_compile(pattern,
6589
 
                         icase ? PCRE_CASELESS | PCRE_MULTILINE : PCRE_MULTILINE,
6590
 
                         &error, &erroffset, NULL);
6591
 
  if (re == NULL)
6592
 
    return 1;
6593
 
 
6594
 
  if (! global)
6595
 
  {
6596
 
 
6597
 
    int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
6598
 
                      0, 0, ovector, 3);
6599
 
    if (rc < 0)
6600
 
    {
6601
 
      pcre_free(re);
6602
 
      return 1;
6603
 
    }
6604
 
 
6605
 
    char *substring_to_replace= in_string + ovector[0];
6606
 
    int substring_length= ovector[1] - ovector[0];
6607
 
    *buf_len_p= strlen(in_string) - substring_length + strlen(replace);
6608
 
    char * new_buf = (char *)malloc(*buf_len_p+1);
6609
 
    if (new_buf == NULL)
6610
 
    {
6611
 
      pcre_free(re);
6612
 
      return 1;
6613
 
    }
6614
 
 
6615
 
    memset(new_buf, 0, *buf_len_p+1);
6616
 
    strncpy(new_buf, in_string, substring_to_replace-in_string);
6617
 
    strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
6618
 
    strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
6619
 
            substring_to_replace + substring_length,
6620
 
            strlen(in_string)
6621
 
              - substring_length
6622
 
              - (substring_to_replace-in_string));
6623
 
    *buf_p= new_buf;
6624
 
 
6625
 
    pcre_free(re);
6626
 
    return 0;
6627
 
  }
6628
 
  else
6629
 
  {
6630
 
    /* Repeatedly replace the string with the matched regex */
6631
 
    string subject(in_string);
6632
 
    size_t replace_length= strlen(replace);
6633
 
    size_t length_of_replacement= strlen(replace);
6634
 
    size_t current_position= 0;
6635
 
    int rc= 0;
6636
 
 
6637
 
    while (true) 
6638
 
    {
6639
 
      rc= pcre_exec(re, NULL, subject.c_str(), subject.length(), 
6640
 
                    current_position, 0, ovector, 3);
6641
 
      if (rc < 0)
6642
 
      {
6643
 
        break;
6644
 
      }
6645
 
 
6646
 
      current_position= static_cast<size_t>(ovector[0]);
6647
 
      replace_length= static_cast<size_t>(ovector[1] - ovector[0]);
6648
 
      subject.replace(current_position, replace_length, replace, length_of_replacement);
6649
 
      current_position= current_position + length_of_replacement;
6650
 
    }
6651
 
 
6652
 
    char *new_buf = (char *) malloc(subject.length() + 1);
6653
 
    if (new_buf == NULL)
6654
 
    {
6655
 
      pcre_free(re);
6656
 
      return 1;
6657
 
    }
6658
 
    memset(new_buf, 0, subject.length() + 1);
6659
 
    strncpy(new_buf, subject.c_str(), subject.length());
6660
 
    *buf_len_p= subject.length() + 1;
6661
 
    *buf_p= new_buf;
6662
 
          
6663
 
    pcre_free(re);
6664
 
    return 0;
6665
 
  }
 
6374
  string string_to_match(in_string);
 
6375
  pcrecpp::RE_Options opt;
 
6376
 
 
6377
  if (icase)
 
6378
    opt.set_caseless(true);
 
6379
 
 
6380
  if (!pcrecpp::RE(pattern, opt).Replace(replace,&string_to_match)){
 
6381
    return 1;
 
6382
  }
 
6383
 
 
6384
  const char * new_str= string_to_match.c_str();
 
6385
  *buf_len_p= strlen(new_str);
 
6386
  char * new_buf = (char *)malloc(*buf_len_p+1);
 
6387
  if (new_buf == NULL)
 
6388
  {
 
6389
    return 1;
 
6390
  }
 
6391
  strcpy(new_buf, new_str);
 
6392
  *buf_p= new_buf;
 
6393
 
 
6394
  return 0;
6666
6395
}
6667
6396
 
6668
6397
 
6669
6398
#ifndef WORD_BIT
6670
 
#define WORD_BIT (8*sizeof(uint32_t))
 
6399
#define WORD_BIT (8*sizeof(uint))
6671
6400
#endif
6672
6401
 
6673
6402
#define SET_MALLOC_HUNC 64
6674
6403
#define LAST_CHAR_CODE 259
6675
6404
 
6676
 
class REP_SET
6677
 
{
6678
 
public:
6679
 
  void internal_set_bit(uint32_t bit);
6680
 
  void internal_clear_bit(uint32_t bit);
6681
 
  void or_bits(const REP_SET *from);
6682
 
  void copy_bits(const REP_SET *from);
6683
 
  int cmp_bits(const REP_SET *set2) const;
6684
 
  int get_next_bit(uint32_t lastpos) const;
6685
 
 
6686
 
  uint32_t  *bits;        /* Pointer to used sets */
 
6405
typedef struct st_rep_set {
 
6406
  uint  *bits;        /* Pointer to used sets */
6687
6407
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6688
 
  uint32_t  found_len;      /* Best match to date */
 
6408
  uint  found_len;      /* Best match to date */
6689
6409
  int  found_offset;
6690
 
  uint32_t  table_offset;
6691
 
  uint32_t  size_of_bits;      /* For convinience */
6692
 
};
6693
 
 
6694
 
class REP_SETS
6695
 
{
6696
 
public:
6697
 
  int find_set(const REP_SET *find);
6698
 
  void free_last_set();
6699
 
  void free_sets();
6700
 
  void make_sets_invisible();
6701
 
 
6702
 
  uint32_t    count;      /* Number of sets */
6703
 
  uint32_t    extra;      /* Extra sets in buffer */
6704
 
  uint32_t    invisible;    /* Sets not shown */
6705
 
  uint32_t    size_of_bits;
 
6410
  uint  table_offset;
 
6411
  uint  size_of_bits;      /* For convinience */
 
6412
} REP_SET;
 
6413
 
 
6414
typedef struct st_rep_sets {
 
6415
  uint    count;      /* Number of sets */
 
6416
  uint    extra;      /* Extra sets in buffer */
 
6417
  uint    invisible;    /* Sets not chown */
 
6418
  uint    size_of_bits;
6706
6419
  REP_SET  *set,*set_buffer;
6707
 
  uint32_t    *bit_buffer;
6708
 
};
 
6420
  uint    *bit_buffer;
 
6421
} REP_SETS;
6709
6422
 
6710
 
struct FOUND_SET 
6711
 
{
6712
 
  uint32_t table_offset;
 
6423
typedef struct st_found_set {
 
6424
  uint table_offset;
6713
6425
  int found_offset;
6714
 
};
 
6426
} FOUND_SET;
6715
6427
 
6716
 
struct FOLLOWS
6717
 
{
 
6428
typedef struct st_follow {
6718
6429
  int chr;
6719
 
  uint32_t table_offset;
6720
 
  uint32_t len;
6721
 
};
6722
 
 
6723
 
int init_sets(REP_SETS *sets, uint32_t states);
 
6430
  uint table_offset;
 
6431
  uint len;
 
6432
} FOLLOWS;
 
6433
 
 
6434
 
 
6435
int init_sets(REP_SETS *sets,uint states);
6724
6436
REP_SET *make_new_set(REP_SETS *sets);
6725
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6726
 
 
6727
 
static uint32_t found_sets= 0;
6728
 
 
6729
 
static uint32_t replace_len(const char *str)
 
6437
void make_sets_invisible(REP_SETS *sets);
 
6438
void free_last_set(REP_SETS *sets);
 
6439
void free_sets(REP_SETS *sets);
 
6440
void internal_set_bit(REP_SET *set, uint bit);
 
6441
void internal_clear_bit(REP_SET *set, uint bit);
 
6442
void or_bits(REP_SET *to,REP_SET *from);
 
6443
void copy_bits(REP_SET *to,REP_SET *from);
 
6444
int cmp_bits(REP_SET *set1,REP_SET *set2);
 
6445
int get_next_bit(REP_SET *set,uint lastpos);
 
6446
int find_set(REP_SETS *sets,REP_SET *find);
 
6447
int find_found(FOUND_SET *found_set,uint table_offset,
 
6448
               int found_offset);
 
6449
uint start_at_word(char * pos);
 
6450
uint end_of_word(char * pos);
 
6451
 
 
6452
static uint found_sets=0;
 
6453
 
 
6454
 
 
6455
static uint replace_len(char * str)
6730
6456
{
6731
 
  uint32_t len=0;
 
6457
  uint len=0;
6732
6458
  while (*str)
6733
6459
  {
6734
6460
    if (str[0] == '\\' && str[1])
6739
6465
  return len;
6740
6466
}
6741
6467
 
6742
 
/* Return 1 if regexp starts with \b or ends with \b*/
6743
 
 
6744
 
static bool start_at_word(const char *pos)
6745
 
{
6746
 
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
6747
 
}
6748
 
 
6749
 
static bool end_of_word(const char *pos)
6750
 
{
6751
 
  const char *end= strchr(pos, '\0');
6752
 
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6753
 
}
6754
 
 
6755
6468
/* Init a replace structure for further calls */
6756
6469
 
6757
 
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
 
6470
REPLACE *init_replace(char * *from, char * *to,uint count,
 
6471
                      char * word_end_chars)
6758
6472
{
6759
 
  const int SPACE_CHAR= 256;
6760
 
  const int START_OF_LINE= 257;
6761
 
  const int END_OF_LINE= 258;
 
6473
  static const int SPACE_CHAR= 256;
 
6474
  static const int START_OF_LINE= 257;
 
6475
  static const int END_OF_LINE= 258;
6762
6476
 
6763
 
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
 
6477
  uint i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6764
6478
  int used_sets,chr,default_state;
6765
6479
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6766
 
  char *to_pos, **to_array;
 
6480
  char * pos, *to_pos, **to_array;
 
6481
  REP_SETS sets;
 
6482
  REP_SET *set,*start_states,*word_states,*new_set;
 
6483
  FOLLOWS *follow,*follow_ptr;
 
6484
  REPLACE *replace;
 
6485
  FOUND_SET *found_set;
 
6486
  REPLACE_STRING *rep_str;
 
6487
 
6767
6488
 
6768
6489
  /* Count number of states */
6769
6490
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6775
6496
      return(0);
6776
6497
    }
6777
6498
    states+=len+1;
6778
 
    result_len+=(uint32_t) strlen(to[i])+1;
 
6499
    result_len+=(uint) strlen(to[i])+1;
6779
6500
    if (len > max_length)
6780
6501
      max_length=len;
6781
6502
  }
6783
6504
  for (i=0 ; word_end_chars[i] ; i++)
6784
6505
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6785
6506
 
6786
 
  REP_SETS sets;
6787
 
  REP_SET *set,*start_states,*word_states,*new_set;
6788
 
  REPLACE_STRING *rep_str;
6789
 
  if (init_sets(&sets, states))
6790
 
    return 0;
 
6507
  if (init_sets(&sets,states))
 
6508
    return(0);
6791
6509
  found_sets=0;
6792
 
  vector<FOUND_SET> found_set(max_length * count);
 
6510
  if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
 
6511
                                          MYF(MY_WME))))
 
6512
  {
 
6513
    free_sets(&sets);
 
6514
    return(0);
 
6515
  }
6793
6516
  make_new_set(&sets);      /* Set starting set */
6794
 
  sets.make_sets_invisible();      /* Hide previus sets */
 
6517
  make_sets_invisible(&sets);      /* Hide previus sets */
6795
6518
  used_sets=-1;
6796
6519
  word_states=make_new_set(&sets);    /* Start of new word */
6797
6520
  start_states=make_new_set(&sets);    /* This is first state */
6798
 
  vector<FOLLOWS> follow(states + 2);
6799
 
  FOLLOWS *follow_ptr= &follow[1];
 
6521
  if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
 
6522
  {
 
6523
    free_sets(&sets);
 
6524
    free(found_set);
 
6525
    return(0);
 
6526
  }
 
6527
 
6800
6528
  /* Init follow_ptr[] */
6801
 
  for (i=0, states=1; i < count; i++)
 
6529
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6802
6530
  {
6803
6531
    if (from[i][0] == '\\' && from[i][1] == '^')
6804
6532
    {
6805
 
      start_states->internal_set_bit(states + 1);
 
6533
      internal_set_bit(start_states,states+1);
6806
6534
      if (!from[i][2])
6807
6535
      {
6808
6536
        start_states->table_offset=i;
6811
6539
    }
6812
6540
    else if (from[i][0] == '\\' && from[i][1] == '$')
6813
6541
    {
6814
 
      start_states->internal_set_bit(states);
6815
 
      word_states->internal_set_bit(states);
 
6542
      internal_set_bit(start_states,states);
 
6543
      internal_set_bit(word_states,states);
6816
6544
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6817
6545
      {
6818
6546
        start_states->table_offset=i;
6821
6549
    }
6822
6550
    else
6823
6551
    {
6824
 
      word_states->internal_set_bit(states);
 
6552
      internal_set_bit(word_states,states);
6825
6553
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6826
 
        start_states->internal_set_bit(states + 1);
 
6554
        internal_set_bit(start_states,states+1);
6827
6555
      else
6828
 
        start_states->internal_set_bit(states);
 
6556
        internal_set_bit(start_states,states);
6829
6557
    }
6830
 
    const char *pos;
6831
 
    for (pos= from[i], len=0; *pos ; pos++)
 
6558
    for (pos=from[i], len=0; *pos ; pos++)
6832
6559
    {
6833
6560
      if (*pos == '\\' && *(pos+1))
6834
6561
      {
6867
6594
    follow_ptr->table_offset=i;
6868
6595
    follow_ptr->len=len;
6869
6596
    follow_ptr++;
6870
 
    states+=(uint32_t) len+1;
 
6597
    states+=(uint) len+1;
6871
6598
  }
6872
6599
 
6873
6600
 
6874
 
  for (set_nr=0; set_nr < sets.count ; set_nr++)
 
6601
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6875
6602
  {
6876
6603
    set=sets.set+set_nr;
6877
6604
    default_state= 0;        /* Start from beginning */
6878
6605
 
6879
6606
    /* If end of found-string not found or start-set with current set */
6880
6607
 
6881
 
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
 
6608
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6882
6609
    {
6883
 
      if (!follow[i].chr && !default_state)
6884
 
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
 
6610
      if (!follow[i].chr)
 
6611
      {
 
6612
        if (! default_state)
 
6613
          default_state= find_found(found_set,set->table_offset,
 
6614
                                    set->found_offset+1);
 
6615
      }
6885
6616
    }
6886
 
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
 
6617
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6887
6618
    if (!default_state)
6888
 
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
 
6619
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
6889
6620
 
6890
6621
    /* Find all chars that follows current sets */
6891
6622
    memset(used_chars, 0, sizeof(used_chars));
6892
 
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
 
6623
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6893
6624
    {
6894
6625
      used_chars[follow[i].chr]=1;
6895
6626
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6899
6630
 
6900
6631
    /* Mark word_chars used if \b is in state */
6901
6632
    if (used_chars[SPACE_CHAR])
6902
 
      for (const char *pos= word_end_chars ; *pos ; pos++)
 
6633
      for (pos= word_end_chars ; *pos ; pos++)
6903
6634
        used_chars[(int) (unsigned char) *pos] = 1;
6904
6635
 
6905
6636
    /* Handle other used characters */
6916
6647
        new_set->found_offset=set->found_offset+1;
6917
6648
        found_end=0;
6918
6649
 
6919
 
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
 
6650
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6920
6651
        {
6921
6652
          if (!follow[i].chr || follow[i].chr == chr ||
6922
6653
              (follow[i].chr == SPACE_CHAR &&
6928
6659
                follow[i].len > found_end)
6929
6660
              found_end=follow[i].len;
6930
6661
            if (chr && follow[i].chr)
6931
 
              new_set->internal_set_bit(i + 1);    /* To next set */
 
6662
              internal_set_bit(new_set,i+1);    /* To next set */
6932
6663
            else
6933
 
              new_set->internal_set_bit(i);
 
6664
              internal_set_bit(new_set,i);
6934
6665
          }
6935
6666
        }
6936
6667
        if (found_end)
6937
6668
        {
6938
6669
          new_set->found_len=0;      /* Set for testing if first */
6939
6670
          bits_set=0;
6940
 
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
 
6671
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6941
6672
          {
6942
6673
            if ((follow[i].chr == SPACE_CHAR ||
6943
6674
                 follow[i].chr == END_OF_LINE) && ! chr)
6947
6678
            if (follow[bit_nr-1].len < found_end ||
6948
6679
                (new_set->found_len &&
6949
6680
                 (chr == 0 || !follow[bit_nr].chr)))
6950
 
              new_set->internal_clear_bit(i);
 
6681
              internal_clear_bit(new_set,i);
6951
6682
            else
6952
6683
            {
6953
6684
              if (chr == 0 || !follow[bit_nr].chr)
6963
6694
          }
6964
6695
          if (bits_set == 1)
6965
6696
          {
6966
 
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6967
 
            sets.free_last_set();
 
6697
            set->next[chr] = find_found(found_set,
 
6698
                                        new_set->table_offset,
 
6699
                                        new_set->found_offset);
 
6700
            free_last_set(&sets);
6968
6701
          }
6969
6702
          else
6970
 
            set->next[chr] = sets.find_set(new_set);
 
6703
            set->next[chr] = find_set(&sets,new_set);
6971
6704
        }
6972
6705
        else
6973
 
          set->next[chr] = sets.find_set(new_set);
 
6706
          set->next[chr] = find_set(&sets,new_set);
6974
6707
      }
6975
6708
    }
6976
6709
  }
6977
6710
 
6978
6711
  /* Alloc replace structure for the replace-state-machine */
6979
6712
 
6980
 
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6981
 
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
6982
 
  if (replace)
 
6713
  if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+
 
6714
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
 
6715
                                    sizeof(char *)*count+result_len,
 
6716
                                    MYF(MY_WME | MY_ZEROFILL))))
6983
6717
  {
6984
 
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
6985
 
                       sizeof(REPLACE_STRING)*(found_sets+1)+
6986
 
                       sizeof(char *)*count+result_len);
6987
6718
    rep_str=(REPLACE_STRING*) (replace+sets.count);
6988
6719
    to_array= (char **) (rep_str+found_sets+1);
6989
6720
    to_pos=(char *) (to_array+count);
6990
6721
    for (i=0 ; i < count ; i++)
6991
6722
    {
6992
6723
      to_array[i]=to_pos;
6993
 
      to_pos=strcpy(to_pos,to[i])+strlen(to[i])+1;
 
6724
      to_pos=my_stpcpy(to_pos,to[i])+1;
6994
6725
    }
6995
6726
    rep_str[0].found=1;
6996
6727
    rep_str[0].replace_string=0;
6997
6728
    for (i=1 ; i <= found_sets ; i++)
6998
6729
    {
6999
 
      const char *pos= from[found_set[i-1].table_offset];
 
6730
      pos=from[found_set[i-1].table_offset];
7000
6731
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
7001
 
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
7002
 
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
7003
 
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
 
6732
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
 
6733
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
 
6734
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
 
6735
        end_of_word(pos);
7004
6736
    }
7005
6737
    for (i=0 ; i < sets.count ; i++)
7006
6738
    {
7011
6743
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7012
6744
    }
7013
6745
  }
7014
 
  sets.free_sets();
7015
 
  return replace;
 
6746
  free(follow);
 
6747
  free_sets(&sets);
 
6748
  free(found_set);
 
6749
  return(replace);
7016
6750
}
7017
6751
 
7018
6752
 
7019
 
int init_sets(REP_SETS *sets,uint32_t states)
 
6753
int init_sets(REP_SETS *sets,uint states)
7020
6754
{
7021
6755
  memset(sets, 0, sizeof(*sets));
7022
6756
  sets->size_of_bits=((states+7)/8);
7023
 
  if (!(sets->set_buffer=(REP_SET*) malloc(sizeof(REP_SET)*SET_MALLOC_HUNC)))
 
6757
  if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
 
6758
                                              MYF(MY_WME))))
7024
6759
    return 1;
7025
 
  if (!(sets->bit_buffer=(uint*) malloc(sizeof(uint32_t)*sets->size_of_bits*
7026
 
                                        SET_MALLOC_HUNC)))
 
6760
  if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
 
6761
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
7027
6762
  {
7028
6763
    free(sets->set);
7029
6764
    return 1;
7033
6768
 
7034
6769
/* Make help sets invisible for nicer codeing */
7035
6770
 
7036
 
void REP_SETS::make_sets_invisible()
 
6771
void make_sets_invisible(REP_SETS *sets)
7037
6772
{
7038
 
  invisible= count;
7039
 
  set += count;
7040
 
  count= 0;
 
6773
  sets->invisible=sets->count;
 
6774
  sets->set+=sets->count;
 
6775
  sets->count=0;
7041
6776
}
7042
6777
 
7043
6778
REP_SET *make_new_set(REP_SETS *sets)
7044
6779
{
7045
 
  uint32_t i,count,*bit_buffer;
 
6780
  uint i,count,*bit_buffer;
7046
6781
  REP_SET *set;
7047
6782
  if (sets->extra)
7048
6783
  {
7049
6784
    sets->extra--;
7050
6785
    set=sets->set+ sets->count++;
7051
 
    memset(set->bits, 0, sizeof(uint32_t)*sets->size_of_bits);
 
6786
    memset(set->bits, 0, sizeof(uint)*sets->size_of_bits);
7052
6787
    memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
7053
6788
    set->found_offset=0;
7054
6789
    set->found_len=0;
7057
6792
    return set;
7058
6793
  }
7059
6794
  count=sets->count+sets->invisible+SET_MALLOC_HUNC;
7060
 
  if (!(set=(REP_SET*) realloc((unsigned char*) sets->set_buffer,
7061
 
                                  sizeof(REP_SET)*count)))
 
6795
  if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
 
6796
                                  sizeof(REP_SET)*count,
 
6797
                                  MYF(MY_WME))))
7062
6798
    return 0;
7063
6799
  sets->set_buffer=set;
7064
6800
  sets->set=set+sets->invisible;
7065
 
  if (!(bit_buffer=(uint*) realloc((unsigned char*) sets->bit_buffer,
7066
 
                                   (sizeof(uint32_t)*sets->size_of_bits)*count)))
 
6801
  if (!(bit_buffer=(uint*) my_realloc((unsigned char*) sets->bit_buffer,
 
6802
                                      (sizeof(uint)*sets->size_of_bits)*count,
 
6803
                                      MYF(MY_WME))))
7067
6804
    return 0;
7068
6805
  sets->bit_buffer=bit_buffer;
7069
6806
  for (i=0 ; i < count ; i++)
7075
6812
  return make_new_set(sets);
7076
6813
}
7077
6814
 
7078
 
void REP_SETS::free_last_set()
7079
 
{
7080
 
  count--;
7081
 
  extra++;
7082
 
}
7083
 
 
7084
 
void REP_SETS::free_sets()
7085
 
{
7086
 
  free(set_buffer);
7087
 
  free(bit_buffer);
7088
 
}
7089
 
 
7090
 
void REP_SET::internal_set_bit(uint32_t bit)
7091
 
{
7092
 
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7093
 
}
7094
 
 
7095
 
void REP_SET::internal_clear_bit(uint32_t bit)
7096
 
{
7097
 
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7098
 
}
7099
 
 
7100
 
 
7101
 
void REP_SET::or_bits(const REP_SET *from)
7102
 
{
7103
 
  for (uint32_t i= 0 ; i < size_of_bits; i++)
7104
 
    bits[i]|=from->bits[i];
7105
 
}
7106
 
 
7107
 
void REP_SET::copy_bits(const REP_SET *from)
7108
 
{
7109
 
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
7110
 
}
7111
 
 
7112
 
int REP_SET::cmp_bits(const REP_SET *set2) const
7113
 
{
7114
 
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
7115
 
}
 
6815
void free_last_set(REP_SETS *sets)
 
6816
{
 
6817
  sets->count--;
 
6818
  sets->extra++;
 
6819
  return;
 
6820
}
 
6821
 
 
6822
void free_sets(REP_SETS *sets)
 
6823
{
 
6824
  free(sets->set_buffer);
 
6825
  free(sets->bit_buffer);
 
6826
  return;
 
6827
}
 
6828
 
 
6829
void internal_set_bit(REP_SET *set, uint bit)
 
6830
{
 
6831
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
 
6832
  return;
 
6833
}
 
6834
 
 
6835
void internal_clear_bit(REP_SET *set, uint bit)
 
6836
{
 
6837
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
 
6838
  return;
 
6839
}
 
6840
 
 
6841
 
 
6842
void or_bits(REP_SET *to,REP_SET *from)
 
6843
{
 
6844
  register uint i;
 
6845
  for (i=0 ; i < to->size_of_bits ; i++)
 
6846
    to->bits[i]|=from->bits[i];
 
6847
  return;
 
6848
}
 
6849
 
 
6850
void copy_bits(REP_SET *to,REP_SET *from)
 
6851
{
 
6852
  memcpy(to->bits,from->bits,
 
6853
         (size_t) (sizeof(uint) * to->size_of_bits));
 
6854
}
 
6855
 
 
6856
int cmp_bits(REP_SET *set1,REP_SET *set2)
 
6857
{
 
6858
  return memcmp(set1->bits,set2->bits, sizeof(uint) * set1->size_of_bits);
 
6859
}
 
6860
 
7116
6861
 
7117
6862
/* Get next set bit from set. */
7118
6863
 
7119
 
int REP_SET::get_next_bit(uint32_t lastpos) const
 
6864
int get_next_bit(REP_SET *set,uint lastpos)
7120
6865
{
7121
 
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
7122
 
  uint32_t *end= bits + size_of_bits;
7123
 
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7124
 
 
7125
 
  while (!bits0 && ++start < end)
7126
 
    bits0= start[0];
7127
 
  if (!bits0)
 
6866
  uint pos,*start,*end,bits;
 
6867
 
 
6868
  start=set->bits+ ((lastpos+1) / WORD_BIT);
 
6869
  end=set->bits + set->size_of_bits;
 
6870
  bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
 
6871
 
 
6872
  while (! bits && ++start < end)
 
6873
    bits=start[0];
 
6874
  if (!bits)
7128
6875
    return 0;
7129
 
  uint32_t pos= (start - bits) * WORD_BIT;
7130
 
  while (!(bits0 & 1))
 
6876
  pos=(uint) (start-set->bits)*WORD_BIT;
 
6877
  while (! (bits & 1))
7131
6878
  {
7132
 
    bits0 >>=1;
 
6879
    bits>>=1;
7133
6880
    pos++;
7134
6881
  }
7135
6882
  return pos;
7139
6886
   free given set, else put in given set in sets and return its
7140
6887
   position */
7141
6888
 
7142
 
int REP_SETS::find_set(const REP_SET *find)
 
6889
int find_set(REP_SETS *sets,REP_SET *find)
7143
6890
{
7144
 
  uint32_t i= 0;
7145
 
  for (; i < count - 1; i++)
 
6891
  uint i;
 
6892
  for (i=0 ; i < sets->count-1 ; i++)
7146
6893
  {
7147
 
    if (!set[i].cmp_bits(find))
 
6894
    if (!cmp_bits(sets->set+i,find))
7148
6895
    {
7149
 
      free_last_set();
 
6896
      free_last_set(sets);
7150
6897
      return i;
7151
6898
    }
7152
6899
  }
7160
6907
   set->next[] == -1 is reserved for end without replaces.
7161
6908
*/
7162
6909
 
7163
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
 
6910
int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
7164
6911
{
7165
 
  uint32_t i= 0;
7166
 
  for (; i < found_sets; i++)
7167
 
  {
 
6912
  int i;
 
6913
  for (i=0 ; (uint) i < found_sets ; i++)
7168
6914
    if (found_set[i].table_offset == table_offset &&
7169
6915
        found_set[i].found_offset == found_offset)
7170
 
      return - i - 2;
7171
 
  }
7172
 
  found_set[i].table_offset= table_offset;
7173
 
  found_set[i].found_offset= found_offset;
 
6916
      return -i-2;
 
6917
  found_set[i].table_offset=table_offset;
 
6918
  found_set[i].found_offset=found_offset;
7174
6919
  found_sets++;
7175
 
  return - i - 2; // return new postion
 
6920
  return -i-2;        /* return new postion */
 
6921
}
 
6922
 
 
6923
/* Return 1 if regexp starts with \b or ends with \b*/
 
6924
 
 
6925
uint start_at_word(char * pos)
 
6926
{
 
6927
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
 
6928
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
 
6929
}
 
6930
 
 
6931
uint end_of_word(char * pos)
 
6932
{
 
6933
  char * end= strchr(pos, '\0');
 
6934
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
 
6935
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7176
6936
}
7177
6937
 
7178
6938
/****************************************************************************
7184
6944
 
7185
6945
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
7186
6946
{
7187
 
  uint32_t i,length,old_count;
 
6947
  uint i,length,old_count;
7188
6948
  unsigned char *new_pos;
7189
6949
  const char **new_array;
7190
6950
 
7192
6952
  if (! pa->typelib.count)
7193
6953
  {
7194
6954
    if (!(pa->typelib.type_names=(const char **)
7195
 
          malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
 
6955
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7196
6956
                     (sizeof(char *)+sizeof(*pa->flag))*
7197
 
                     (sizeof(char *)+sizeof(*pa->flag))))))
 
6957
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
7198
6958
      return(-1);
7199
 
    if (!(pa->str= (unsigned char*) malloc(PS_MALLOC-MALLOC_OVERHEAD)))
 
6959
    if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
 
6960
                                      MYF(MY_WME))))
7200
6961
    {
7201
6962
      free((char*) pa->typelib.type_names);
7202
6963
      return (-1);
7208
6969
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
7209
6970
    pa->array_allocs=1;
7210
6971
  }
7211
 
  length=(uint32_t) strlen(name)+1;
 
6972
  length=(uint) strlen(name)+1;
7212
6973
  if (pa->length+length >= pa->max_length)
7213
6974
  {
7214
 
    if (!(new_pos= (unsigned char*)realloc((unsigned char*)pa->str,
7215
 
                                           (size_t)(pa->max_length+PS_MALLOC))))
 
6975
    if (!(new_pos= (unsigned char*) my_realloc((unsigned char*) pa->str,
 
6976
                                       (uint) (pa->max_length+PS_MALLOC),
 
6977
                                       MYF(MY_WME))))
7216
6978
      return(1);
7217
6979
    if (new_pos != pa->str)
7218
6980
    {
7219
 
      ptrdiff_t diff= PTR_BYTE_DIFF(new_pos,pa->str);
 
6981
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
7220
6982
      for (i=0 ; i < pa->typelib.count ; i++)
7221
6983
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
7222
6984
                                              char*);
7226
6988
  }
7227
6989
  if (pa->typelib.count >= pa->max_count-1)
7228
6990
  {
7229
 
    size_t len;
 
6991
    int len;
7230
6992
    pa->array_allocs++;
7231
6993
    len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7232
 
    if (!(new_array=
7233
 
         (const char **)realloc((unsigned char*) pa->typelib.type_names,
7234
 
                                 len/
7235
 
                                  (sizeof(unsigned char*)+sizeof(*pa->flag))*
7236
 
                                  (sizeof(unsigned char*)+sizeof(*pa->flag)))))
 
6994
    if (!(new_array=(const char **) my_realloc((unsigned char*) pa->typelib.type_names,
 
6995
                                               (uint) len/
 
6996
                                               (sizeof(unsigned char*)+sizeof(*pa->flag))*
 
6997
                                               (sizeof(unsigned char*)+sizeof(*pa->flag)),
 
6998
                                               MYF(MY_WME))))
7237
6999
      return(1);
7238
7000
    pa->typelib.type_names=new_array;
7239
7001
    old_count=pa->max_count;
7245
7007
  pa->flag[pa->typelib.count]=0;      /* Reset flag */
7246
7008
  pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
7247
7009
  pa->typelib.type_names[pa->typelib.count]= NULL;  /* Put end-mark */
7248
 
  strcpy((char*) pa->str+pa->length,name);
 
7010
  my_stpcpy((char*) pa->str+pa->length,name);
7249
7011
  pa->length+=length;
7250
7012
  return(0);
7251
7013
} /* insert_pointer_name */
7252
7014
 
7253
7015
 
 
7016
/* free pointer array */
 
7017
 
 
7018
void free_pointer_array(POINTER_ARRAY *pa)
 
7019
{
 
7020
  if (pa->typelib.count)
 
7021
  {
 
7022
    pa->typelib.count=0;
 
7023
    free((char*) pa->typelib.type_names);
 
7024
    pa->typelib.type_names=0;
 
7025
    free(pa->str);
 
7026
  }
 
7027
} /* free_pointer_array */
 
7028
 
 
7029
 
7254
7030
/* Functions that uses replace and replace_regex */
7255
7031
 
7256
7032
/* Append the string to ds, with optional replace */
7257
 
void replace_append_mem(string *ds, const char *val, int len)
 
7033
void replace_append_mem(string *ds,
 
7034
                        const char *val, int len)
7258
7035
{
7259
7036
  char *v= strdup(val);
7260
7037
 
7261
 
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
 
7038
  if (glob_replace_regex)
7262
7039
  {
7263
 
    v= glob_replace_regex->buf_;
7264
 
    len= strlen(v);
 
7040
    /* Regex replace */
 
7041
    if (!multi_reg_replace(glob_replace_regex, v))
 
7042
    {
 
7043
      v= glob_replace_regex->buf;
 
7044
      len= strlen(v);
 
7045
    }
7265
7046
  }
 
7047
 
7266
7048
  if (glob_replace)
7267
7049
  {
7268
7050
    /* Normal replace */
7269
7051
    replace_strings_append(glob_replace, ds, v, len);
7270
7052
  }
7271
7053
  else
 
7054
  {
7272
7055
    ds->append(v, len);
 
7056
  }
7273
7057
}
7274
7058
 
7275
7059
 
7279
7063
  replace_append_mem(ds, val, strlen(val));
7280
7064
}
7281
7065
 
7282
 
/* Append uint32_t to ds, with optional replace */
7283
 
void replace_append_uint(string *ds, uint32_t val)
 
7066
/* Append uint to ds, with optional replace */
 
7067
void replace_append_uint(string *ds, uint val)
7284
7068
{
7285
 
  ostringstream buff;
7286
 
  buff << val;
7287
 
  replace_append_mem(ds, buff.str().c_str(), buff.str().size());
 
7069
  char buff[22]; /* This should be enough for any int */
 
7070
  char *end= int64_t10_to_str(val, buff, 10);
 
7071
  replace_append_mem(ds, buff, end - buff);
7288
7072
 
7289
7073
}
7290
7074
 
7338
7122
 
7339
7123
  return;
7340
7124
}
7341
 
 
7342
 
static void free_all_replace()
7343
 
{
7344
 
  free_replace();
7345
 
  glob_replace_regex.reset();
7346
 
  free_replace_column();
7347
 
}