~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Brian Aker
  • Date: 2008-10-29 13:46:43 UTC
  • Revision ID: brian@tangent.org-20081029134643-z6jcwjvyruhk2vlu
Updates for ignore file.

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