~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Monty Taylor
  • Date: 2008-09-16 00:00:48 UTC
  • mto: This revision was merged to the branch mainline in revision 391.
  • Revision ID: monty@inaugust.com-20080916000048-3rvrv3gv9l0ad3gs
Fixed copyright headers in drizzled/

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
 
42
 
#include "client_priv.h"
43
 
 
44
41
#include <queue>
45
42
#include <map>
46
43
#include <string>
47
 
#include <sstream>
48
 
#include <fstream>
49
 
#include <iostream>
50
 
#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/program_options.hpp>
60
 
 
61
 
#include PCRE_HEADER
62
 
 
 
44
 
 
45
#include <pcrecpp.h>
 
46
 
 
47
#include "client_priv.h"
 
48
#include <mysys/hash.h>
63
49
#include <stdarg.h>
64
 
#include <boost/unordered_map.hpp>
65
 
 
66
 
/* Added this for string translation. */
67
 
#include "drizzled/gettext.h"
68
 
#include "drizzled/type/time.h"
69
 
#include "drizzled/charset.h"
70
 
#include "drizzled/typelib.h"
71
 
#include <drizzled/configmake.h>
72
 
 
73
 
#ifndef DRIZZLE_RETURN_SERVER_GONE
74
 
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
75
 
#endif
76
 
namespace po= boost::program_options;
 
50
 
 
51
#include "errname.h"
 
52
 
77
53
using namespace std;
78
 
using namespace drizzled;
79
 
 
80
 
extern "C"
81
 
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
82
 
 
83
 
int get_one_option(int optid, const struct option *, char *argument);
84
54
 
85
55
#define MAX_VAR_NAME_LENGTH    256
86
56
#define MAX_COLUMNS            256
 
57
#define MAX_EMBEDDED_SERVER_ARGS 64
87
58
#define MAX_DELIMITER_LENGTH 16
 
59
 
88
60
/* Flags controlling send and reap */
89
61
#define QUERY_SEND_FLAG  1
90
62
#define QUERY_REAP_FLAG  2
91
63
 
92
 
typedef boost::unordered_map<std::string, uint32_t> ErrorCodes;
93
 
ErrorCodes global_error_names;
94
 
 
95
64
enum {
96
65
  OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
97
 
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
98
 
  OPT_TESTDIR
 
66
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
99
67
};
100
68
 
101
69
static int record= 0, opt_sleep= -1;
102
 
static char *opt_pass= NULL;
103
 
const char *unix_sock= NULL;
104
 
static uint32_t opt_port= 0;
105
 
static uint32_t opt_max_connect_retries;
106
 
static bool silent= false, verbose= false;
107
 
static bool opt_mark_progress= false;
108
 
static bool parsing_disabled= false;
 
70
static char *opt_db= 0, *opt_pass= 0;
 
71
const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./";
 
72
const char *opt_logdir= "";
 
73
const char *opt_include= 0, *opt_charsets_dir;
 
74
static int opt_port= 0;
 
75
static int opt_max_connect_retries;
 
76
static bool opt_compress= 0, silent= 0, verbose= 0;
 
77
static bool debug_info_flag= 0, debug_check_flag= 0;
 
78
static bool tty_password= 0;
 
79
static bool opt_mark_progress= 0;
 
80
static bool parsing_disabled= 0;
109
81
static bool display_result_vertically= false,
110
82
  display_metadata= false, display_result_sorted= false;
111
 
static bool disable_query_log= false, disable_result_log= false;
112
 
static bool disable_warnings= false;
113
 
static bool disable_info= true;
114
 
static bool abort_on_error= true;
115
 
static bool server_initialized= false;
116
 
static bool is_windows= false;
117
 
static bool use_drizzle_protocol= false;
 
83
static bool disable_query_log= 0, disable_result_log= 0;
 
84
static bool disable_warnings= 0;
 
85
static bool disable_info= 1;
 
86
static bool abort_on_error= 1;
 
87
static bool server_initialized= 0;
 
88
static bool is_windows= 0;
 
89
static char **default_argv;
 
90
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
118
91
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
119
92
 
120
 
std::string opt_basedir,
121
 
  opt_charsets_dir,
122
 
  opt_db,
123
 
  opt_host,
124
 
  opt_include,
125
 
  opt_testdir,
126
 
  opt_logdir,
127
 
  password,
128
 
  opt_password,
129
 
  result_file_name,
130
 
  opt_user,
131
 
  opt_protocol;
132
 
 
133
 
static uint32_t start_lineno= 0; /* Start line of current command */
 
93
static uint start_lineno= 0; /* Start line of current command */
 
94
static uint my_end_arg= 0;
134
95
 
135
96
/* Number of lines of the result to include in failure report */
136
 
static uint32_t opt_tail_lines= 0;
 
97
static uint opt_tail_lines= 0;
137
98
 
138
99
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
139
 
static uint32_t delimiter_length= 1;
 
100
static uint delimiter_length= 1;
140
101
 
141
102
static char TMPDIR[FN_REFLEN];
142
103
 
162
123
{
163
124
  FILE* file;
164
125
  const char *file_name;
165
 
  uint32_t lineno; /* Current line in file */
 
126
  uint lineno; /* Current line in file */
166
127
};
167
128
 
168
129
static struct st_test_file file_stack[16];
172
133
 
173
134
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
174
135
 
 
136
static int embedded_server_arg_count=0;
 
137
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
 
138
 
175
139
/*
176
140
  Timer related variables
177
141
  See the timer_output() definition for details
199
163
master_pos_st master_pos;
200
164
 
201
165
/* if set, all results are concated and compared against this file */
 
166
const char *result_file_name= 0;
202
167
 
203
168
typedef struct st_var
204
169
{
216
181
/*Perl/shell-like variable registers */
217
182
VAR var_reg[10];
218
183
 
219
 
 
220
 
boost::unordered_map<string, VAR *> var_hash;
 
184
HASH var_hash;
221
185
 
222
186
struct st_connection
223
187
{
224
 
  drizzle_st *drizzle;
225
 
  drizzle_con_st con;
 
188
  DRIZZLE drizzle;
226
189
  /* Used when creating views and sp, to avoid implicit commit */
227
 
  drizzle_con_st *util_con;
 
190
  DRIZZLE *util_drizzle;
228
191
  char *name;
229
192
};
230
193
struct st_connection connections[128];
262
225
  Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
263
226
  Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
264
227
  Q_START_TIMER, Q_END_TIMER,
265
 
  Q_CHARACTER_SET,
 
228
  Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
266
229
  Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
267
230
  Q_IF,
268
231
  Q_DISABLE_PARSING, Q_ENABLE_PARSING,
380
343
  enum match_err_type type;
381
344
  union
382
345
  {
383
 
    uint32_t errnum;
384
 
    char sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE+1];  /* \0 terminated string */
 
346
    uint errnum;
 
347
    char sqlstate[SQLSTATE_LENGTH+1];  /* \0 terminated string */
385
348
  } code;
386
349
};
387
350
 
388
351
struct st_expected_errors
389
352
{
390
353
  struct st_match_err err[10];
391
 
  uint32_t count;
 
354
  uint count;
392
355
};
393
356
static struct st_expected_errors saved_expected_errors;
394
357
 
397
360
  char *query, *query_buf,*first_argument,*last_argument,*end;
398
361
  int first_word_len, query_len;
399
362
  bool abort_on_error;
400
 
  st_expected_errors expected_errors;
401
 
  string require_file;
 
363
  struct st_expected_errors expected_errors;
 
364
  char require_file[FN_REFLEN];
402
365
  enum enum_commands type;
403
 
 
404
 
  st_command()
405
 
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
406
 
      end(NULL), first_word_len(0), query_len(0), abort_on_error(false),
407
 
      require_file(""), type(Q_CONNECTION)
408
 
  {
409
 
    memset(&expected_errors, 0, sizeof(st_expected_errors));
410
 
  }
411
 
 
412
 
  ~st_command()
413
 
  {
414
 
    if (query_buf != NULL)
415
 
    {
416
 
      free(query_buf);
417
 
    }
418
 
  }
419
366
};
420
367
 
421
368
TYPELIB command_typelib= {array_elements(command_names),"",
439
386
VAR* var_from_env(const char *, const char *);
440
387
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
441
388
              int val_len);
442
 
void var_free(pair<string, VAR*> v);
 
389
void var_free(void* v);
443
390
VAR* var_get(const char *var_name, const char** var_name_end,
444
391
             bool raw, bool ignore_not_existing);
445
392
void eval_expr(VAR* v, const char *p, const char** p_end);
446
 
bool match_delimiter(int c, const char *delim, uint32_t length);
 
393
bool match_delimiter(int c, const char *delim, uint length);
447
394
void dump_result_to_reject_file(char *buf, int size);
448
395
void dump_result_to_log_file(const char *buf, int size);
449
396
void dump_warning_messages(void);
456
403
 
457
404
/* For replace_column */
458
405
static char *replace_column[MAX_COLUMNS];
459
 
static uint32_t max_replace_column= 0;
 
406
static uint max_replace_column= 0;
460
407
void do_get_replace_column(struct st_command*);
461
408
void free_replace_column(void);
462
409
 
481
428
void replace_append_mem(string *ds, const char *val,
482
429
                        int len);
483
430
void replace_append(string *ds, const char *val);
484
 
void replace_append_uint(string *ds, uint32_t val);
 
431
void replace_append_uint(string *ds, uint val);
485
432
void append_sorted(string* ds, string* ds_input);
486
433
 
487
434
void handle_error(struct st_command*,
490
437
void handle_no_error(struct st_command*);
491
438
 
492
439
 
 
440
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
 
441
 
493
442
void do_eval(string *query_eval, const char *query,
494
443
             const char *query_end, bool pass_through_escape_chars)
495
444
{
556
505
  @param append string to be appended.
557
506
  @param ... Optional. Additional string(s) to be appended.
558
507
 
559
 
  @note The final argument in the list must be NULL even if no additional
 
508
  @note The final argument in the list must be NullS even if no additional
560
509
  options are passed.
561
510
*/
562
511
 
563
 
static void append_os_quoted(string *str, const char *append, ...)
 
512
void append_os_quoted(string *str, const char *append, ...)
564
513
{
565
514
  const char *quote_str= "\'";
566
 
  const uint32_t  quote_len= 1;
 
515
  const uint  quote_len= 1;
567
516
 
568
517
  va_list dirty_text;
569
518
 
570
519
  str->append(quote_str, quote_len); /* Leading quote */
571
520
  va_start(dirty_text, append);
572
 
  while (append != NULL)
 
521
  while (append != NullS)
573
522
  {
574
523
    const char  *cur_pos= append;
575
524
    const char *next_pos= cur_pos;
582
531
      str->append(quote_str, quote_len);
583
532
      cur_pos= next_pos + 1;
584
533
    }
585
 
    str->append(cur_pos);
 
534
    str->append(cur_pos, next_pos - cur_pos);
586
535
    append= va_arg(dirty_text, char *);
587
536
  }
588
537
  va_end(dirty_text);
603
552
 
604
553
*/
605
554
 
606
 
static void show_query(drizzle_con_st *con, const char* query)
 
555
static void show_query(DRIZZLE *drizzle, const char* query)
607
556
{
608
 
  drizzle_result_st res;
609
 
  drizzle_return_t ret;
610
 
 
611
 
  if (!con)
 
557
  DRIZZLE_RES* res;
 
558
 
 
559
 
 
560
  if (!drizzle)
612
561
    return;
613
562
 
614
 
  if (drizzle_query_str(con, &res, query, &ret) == NULL ||
615
 
      ret != DRIZZLE_RETURN_OK)
 
563
  if (drizzle_query(drizzle, query))
616
564
  {
617
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
618
 
    {
619
 
      log_msg("Error running query '%s': %d %s",
620
 
              query, drizzle_result_error_code(&res),
621
 
              drizzle_result_error(&res));
622
 
      drizzle_result_free(&res);
623
 
    }
624
 
    else
625
 
    {
626
 
      log_msg("Error running query '%s': %d %s",
627
 
              query, ret, drizzle_con_error(con));
628
 
    }
 
565
    log_msg("Error running query '%s': %d %s",
 
566
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
629
567
    return;
630
568
  }
631
569
 
632
 
  if (drizzle_result_column_count(&res) == 0 ||
633
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
570
  if ((res= drizzle_store_result(drizzle)) == NULL)
634
571
  {
635
572
    /* No result set returned */
636
 
    drizzle_result_free(&res);
637
573
    return;
638
574
  }
639
575
 
640
576
  {
641
 
    drizzle_row_t row;
 
577
    DRIZZLE_ROW row;
642
578
    unsigned int i;
643
579
    unsigned int row_num= 0;
644
 
    unsigned int num_fields= drizzle_result_column_count(&res);
645
 
    drizzle_column_st *column;
 
580
    unsigned int num_fields= drizzle_num_fields(res);
 
581
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
646
582
 
647
583
    fprintf(stderr, "=== %s ===\n", query);
648
 
    while ((row= drizzle_row_next(&res)))
 
584
    while ((row= drizzle_fetch_row(res)))
649
585
    {
650
 
      size_t *lengths= drizzle_row_field_sizes(&res);
 
586
      uint32_t *lengths= drizzle_fetch_lengths(res);
651
587
      row_num++;
652
588
 
653
589
      fprintf(stderr, "---- %d. ----\n", row_num);
654
 
      drizzle_column_seek(&res, 0);
655
590
      for(i= 0; i < num_fields; i++)
656
591
      {
657
 
        column= drizzle_column_next(&res);
658
592
        fprintf(stderr, "%s\t%.*s\n",
659
 
                drizzle_column_name(column),
 
593
                fields[i].name,
660
594
                (int)lengths[i], row[i] ? row[i] : "NULL");
661
595
      }
662
596
    }
664
598
      fprintf(stderr, "=");
665
599
    fprintf(stderr, "\n\n");
666
600
  }
667
 
  drizzle_result_free(&res);
 
601
  drizzle_free_result(res);
668
602
 
669
603
  return;
670
604
}
683
617
 
684
618
*/
685
619
 
686
 
static void show_warnings_before_error(drizzle_con_st *con)
 
620
static void show_warnings_before_error(DRIZZLE *drizzle)
687
621
{
688
 
  drizzle_result_st res;
689
 
  drizzle_return_t ret;
 
622
  DRIZZLE_RES* res;
690
623
  const char* query= "SHOW WARNINGS";
691
624
 
692
 
  if (!con)
 
625
 
 
626
  if (!drizzle)
693
627
    return;
694
628
 
695
 
  if (drizzle_query_str(con, &res, query, &ret) == NULL ||
696
 
      ret != DRIZZLE_RETURN_OK)
 
629
  if (drizzle_query(drizzle, query))
697
630
  {
698
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
699
 
    {
700
 
      log_msg("Error running query '%s': %d %s",
701
 
              query, drizzle_result_error_code(&res),
702
 
              drizzle_result_error(&res));
703
 
      drizzle_result_free(&res);
704
 
    }
705
 
    else
706
 
    {
707
 
      log_msg("Error running query '%s': %d %s",
708
 
              query, ret, drizzle_con_error(con));
709
 
    }
 
631
    log_msg("Error running query '%s': %d %s",
 
632
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
710
633
    return;
711
634
  }
712
635
 
713
 
  if (drizzle_result_column_count(&res) == 0 ||
714
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
636
  if ((res= drizzle_store_result(drizzle)) == NULL)
715
637
  {
716
638
    /* No result set returned */
717
 
    drizzle_result_free(&res);
718
639
    return;
719
640
  }
720
641
 
721
 
  if (drizzle_result_row_count(&res) <= 1)
 
642
  if (drizzle_num_rows(res) <= 1)
722
643
  {
723
644
    /* Don't display the last row, it's "last error" */
724
645
  }
725
646
  else
726
647
  {
727
 
    drizzle_row_t row;
 
648
    DRIZZLE_ROW row;
728
649
    unsigned int row_num= 0;
729
 
    unsigned int num_fields= drizzle_result_column_count(&res);
 
650
    unsigned int num_fields= drizzle_num_fields(res);
730
651
 
731
652
    fprintf(stderr, "\nWarnings from just before the error:\n");
732
 
    while ((row= drizzle_row_next(&res)))
 
653
    while ((row= drizzle_fetch_row(res)))
733
654
    {
734
655
      uint32_t i;
735
 
      size_t *lengths= drizzle_row_field_sizes(&res);
 
656
      uint32_t *lengths= drizzle_fetch_lengths(res);
736
657
 
737
 
      if (++row_num >= drizzle_result_row_count(&res))
 
658
      if (++row_num >= drizzle_num_rows(res))
738
659
      {
739
660
        /* Don't display the last row, it's "last error" */
740
661
        break;
748
669
      fprintf(stderr, "\n");
749
670
    }
750
671
  }
751
 
  drizzle_result_free(&res);
 
672
  drizzle_free_result(res);
752
673
 
753
674
  return;
754
675
}
781
702
  for (i= 0; i < num_args; i++)
782
703
  {
783
704
    const struct command_arg *arg= &args[i];
784
 
    arg->ds->clear();
785
705
 
786
 
    bool known_arg_type= true;
787
706
    switch (arg->type) {
788
707
      /* A string */
789
708
    case ARG_STRING:
818
737
      break;
819
738
 
820
739
    default:
821
 
      known_arg_type= false;
 
740
      assert("Unknown argument type");
822
741
      break;
823
742
    }
824
 
    assert(known_arg_type);
825
743
 
826
744
    /* Check required arg */
827
745
    if (arg->ds->length() == 0 && arg->required)
842
760
}
843
761
 
844
762
 
845
 
static void handle_command_error(struct st_command *command, uint32_t error)
 
763
static void handle_command_error(struct st_command *command, uint error)
846
764
{
 
765
 
847
766
  if (error != 0)
848
767
  {
849
 
    uint32_t i;
 
768
    uint i;
850
769
 
851
770
    if (command->abort_on_error)
852
771
      die("command \"%.*s\" failed with error %d",
870
789
        command->first_word_len, command->query,
871
790
        command->expected_errors.err[0].code.errnum);
872
791
  }
 
792
  return;
873
793
}
874
794
 
875
795
 
876
796
static void close_connections(void)
877
797
{
 
798
 
878
799
  for (--next_con; next_con >= connections; --next_con)
879
800
  {
880
 
    if (next_con->drizzle != NULL)
881
 
    {
882
 
      drizzle_free(next_con->drizzle);
883
 
      next_con->drizzle= NULL;
884
 
    }
885
 
    free(next_con->name);
 
801
    drizzle_close(&next_con->drizzle);
 
802
    if (next_con->util_drizzle)
 
803
      drizzle_close(next_con->util_drizzle);
 
804
    my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
886
805
  }
887
806
  return;
888
807
}
895
814
  {
896
815
    if (cur_file->file && cur_file->file != stdin)
897
816
    {
898
 
      fclose(cur_file->file);
 
817
      my_fclose(cur_file->file, MYF(0));
899
818
    }
900
 
    free((unsigned char*) cur_file->file_name);
 
819
    my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
901
820
    cur_file->file_name= 0;
902
821
  }
903
822
  return;
906
825
 
907
826
static void free_used_memory(void)
908
827
{
909
 
  uint32_t i;
 
828
  uint i;
910
829
 
911
830
 
912
831
  close_connections();
913
832
  close_files();
914
 
  for_each(var_hash.begin(), var_hash.end(), var_free);
915
 
  var_hash.clear();
 
833
  hash_free(&var_hash);
916
834
 
917
 
  vector<st_command *>::iterator iter;
 
835
  vector<struct st_command *>::iterator iter;
918
836
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
919
837
  {
920
 
    struct st_command * q_line= *iter;
921
 
    delete q_line;
 
838
    struct st_command * q_line= *(iter.base());
 
839
    if (q_line->query_buf != NULL)
 
840
    {
 
841
      free(q_line->query_buf);
 
842
    }
 
843
    free(q_line);
922
844
  }
923
845
 
924
846
  for (i= 0; i < 10; i++)
925
847
  {
926
848
    if (var_reg[i].alloced_len)
927
 
      free(var_reg[i].str_val);
 
849
      my_free(var_reg[i].str_val, MYF(MY_WME));
928
850
  }
 
851
  while (embedded_server_arg_count > 1)
 
852
    my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
929
853
 
930
854
  free_all_replace();
931
 
  free(opt_pass);
 
855
  my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
 
856
  free_defaults(default_argv);
 
857
 
 
858
  /* Only call drizzle_server_end if drizzle_server_init has been called */
 
859
  if (server_initialized)
 
860
    drizzle_server_end();
932
861
 
933
862
  return;
934
863
}
937
866
static void cleanup_and_exit(int exit_code)
938
867
{
939
868
  free_used_memory();
940
 
  internal::my_end();
 
869
  my_end(my_end_arg);
941
870
 
942
871
  if (!silent) {
943
872
    switch (exit_code) {
1010
939
  }
1011
940
 
1012
941
  /* Dump the result that has been accumulated so far to .log file */
1013
 
  if (! result_file_name.empty() && ds_res.length())
 
942
  if (result_file_name && ds_res.length())
1014
943
    dump_result_to_log_file(ds_res.c_str(), ds_res.length());
1015
944
 
1016
945
  /* Dump warning messages */
1017
 
  if (! result_file_name.empty() && ds_warning_messages.length())
 
946
  if (result_file_name && ds_warning_messages.length())
1018
947
    dump_warning_messages();
1019
948
 
1020
949
  /*
1022
951
    been produced prior to the error
1023
952
  */
1024
953
  if (cur_con)
1025
 
    show_warnings_before_error(&cur_con->con);
 
954
    show_warnings_before_error(&cur_con->drizzle);
1026
955
 
1027
956
  cleanup_and_exit(1);
1028
957
}
1147
1076
static void cat_file(string* ds, const char* filename)
1148
1077
{
1149
1078
  int fd;
1150
 
  uint32_t len;
 
1079
  uint len;
1151
1080
  char buff[512];
1152
1081
 
1153
 
  if ((fd= internal::my_open(filename, O_RDONLY, MYF(0))) < 0)
 
1082
  if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
1154
1083
    die("Failed to open file '%s'", filename);
1155
 
  while((len= internal::my_read(fd, (unsigned char*)&buff,
 
1084
  while((len= my_read(fd, (uchar*)&buff,
1156
1085
                      sizeof(buff), MYF(0))) > 0)
1157
1086
  {
1158
1087
    char *p= buff, *start= buff;
1174
1103
    /* Output any chars that might be left */
1175
1104
    ds->append(start, p-start);
1176
1105
  }
1177
 
  internal::my_close(fd, MYF(0));
 
1106
  my_close(fd, MYF(0));
1178
1107
}
1179
1108
 
1180
1109
 
1229
1158
  string ds_cmdline;
1230
1159
 
1231
1160
 
1232
 
  append_os_quoted(&ds_cmdline, tool_path, NULL);
 
1161
  append_os_quoted(&ds_cmdline, tool_path);
1233
1162
  ds_cmdline.append(" ");
1234
1163
 
1235
1164
  va_start(args, result);
1238
1167
  {
1239
1168
    /* Options should be os quoted */
1240
1169
    if (strncmp(arg, "--", 2) == 0)
1241
 
      append_os_quoted(&ds_cmdline, arg, NULL);
 
1170
      append_os_quoted(&ds_cmdline, arg, NullS);
1242
1171
    else
1243
1172
      ds_cmdline.append(arg);
1244
1173
    ds_cmdline.append(" ");
1279
1208
               "2>&1",
1280
1209
               NULL) > 1) /* Most "diff" tools return >1 if error */
1281
1210
  {
 
1211
    ds_tmp= "";
1282
1212
 
1283
1213
    /* Fallback to context diff with "diff -c" */
1284
1214
    if (run_tool("diff",
1293
1223
        Fallback to dump both files to result file and inform
1294
1224
        about installing "diff"
1295
1225
      */
1296
 
      ds_tmp.clear();
 
1226
      ds_tmp= "";
1297
1227
 
1298
1228
      ds_tmp.append(
1299
1229
                    "\n"
1350
1280
 
1351
1281
*/
1352
1282
 
1353
 
static int compare_files2(int fd, const char* filename2)
 
1283
static int compare_files2(File fd, const char* filename2)
1354
1284
{
1355
1285
  int error= RESULT_OK;
1356
 
  int fd2;
1357
 
  uint32_t len, len2;
 
1286
  File fd2;
 
1287
  uint len, len2;
1358
1288
  char buff[512], buff2[512];
1359
 
  const char *fname= filename2;
1360
 
  string tmpfile;
1361
1289
 
1362
 
  if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
 
1290
  if ((fd2= my_open(filename2, O_RDONLY, MYF(0))) < 0)
1363
1291
  {
1364
 
    internal::my_close(fd, MYF(0));
1365
 
    if (! opt_testdir.empty())
1366
 
    {
1367
 
      tmpfile= opt_testdir;
1368
 
      if (tmpfile[tmpfile.length()] != '/')
1369
 
        tmpfile.append("/");
1370
 
      tmpfile.append(filename2);
1371
 
      fname= tmpfile.c_str();
1372
 
    }
1373
 
    if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
1374
 
    {
1375
 
      internal::my_close(fd, MYF(0));
1376
 
    
1377
 
      die("Failed to open second file: '%s'", fname);
1378
 
    }
 
1292
    my_close(fd, MYF(0));
 
1293
    die("Failed to open second file: '%s'", filename2);
1379
1294
  }
1380
 
  while((len= internal::my_read(fd, (unsigned char*)&buff,
 
1295
  while((len= my_read(fd, (uchar*)&buff,
1381
1296
                      sizeof(buff), MYF(0))) > 0)
1382
1297
  {
1383
 
    if ((len2= internal::my_read(fd2, (unsigned char*)&buff2,
 
1298
    if ((len2= my_read(fd2, (uchar*)&buff2,
1384
1299
                       sizeof(buff2), MYF(0))) < len)
1385
1300
    {
1386
1301
      /* File 2 was smaller */
1400
1315
      break;
1401
1316
    }
1402
1317
  }
1403
 
  if (!error && internal::my_read(fd2, (unsigned char*)&buff2,
 
1318
  if (!error && my_read(fd2, (uchar*)&buff2,
1404
1319
                        sizeof(buff2), MYF(0)) > 0)
1405
1320
  {
1406
1321
    /* File 1 was smaller */
1407
1322
    error= RESULT_LENGTH_MISMATCH;
1408
1323
  }
1409
1324
 
1410
 
  internal::my_close(fd2, MYF(0));
 
1325
  my_close(fd2, MYF(0));
1411
1326
 
1412
1327
  return error;
1413
1328
}
1428
1343
 
1429
1344
static int compare_files(const char* filename1, const char* filename2)
1430
1345
{
1431
 
  int fd;
 
1346
  File fd;
1432
1347
  int error;
1433
1348
 
1434
 
  if ((fd= internal::my_open(filename1, O_RDONLY, MYF(0))) < 0)
 
1349
  if ((fd= my_open(filename1, O_RDONLY, MYF(0))) < 0)
1435
1350
    die("Failed to open first file: '%s'", filename1);
1436
1351
 
1437
1352
  error= compare_files2(fd, filename2);
1438
1353
 
1439
 
  internal::my_close(fd, MYF(0));
 
1354
  my_close(fd, MYF(0));
1440
1355
 
1441
1356
  return error;
1442
1357
}
1457
1372
static int string_cmp(string* ds, const char *fname)
1458
1373
{
1459
1374
  int error;
1460
 
  int fd;
 
1375
  File fd;
1461
1376
  char temp_file_path[FN_REFLEN];
1462
1377
 
1463
 
  if ((fd= internal::create_temp_file(temp_file_path, TMPDIR,
1464
 
                            "tmp", MYF(MY_WME))) < 0)
 
1378
  if ((fd= create_temp_file(temp_file_path, NULL,
 
1379
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
 
1380
                            MYF(MY_WME))) < 0)
1465
1381
    die("Failed to create temporary file for ds");
1466
1382
 
1467
1383
  /* Write ds to temporary file and set file pos to beginning*/
1468
 
  if (internal::my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
 
1384
  if (my_write(fd, (uchar *) ds->c_str(), ds->length(),
1469
1385
               MYF(MY_FNABP | MY_WME)) ||
1470
 
      lseek(fd, 0, SEEK_SET) == MY_FILEPOS_ERROR)
 
1386
      my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1471
1387
  {
1472
 
    internal::my_close(fd, MYF(0));
 
1388
    my_close(fd, MYF(0));
1473
1389
    /* Remove the temporary file */
1474
 
    internal::my_delete(temp_file_path, MYF(0));
 
1390
    my_delete(temp_file_path, MYF(0));
1475
1391
    die("Failed to write file '%s'", temp_file_path);
1476
1392
  }
1477
1393
 
1478
1394
  error= compare_files2(fd, fname);
1479
1395
 
1480
 
  internal::my_close(fd, MYF(0));
 
1396
  my_close(fd, MYF(0));
1481
1397
  /* Remove the temporary file */
1482
 
  internal::my_delete(temp_file_path, MYF(0));
 
1398
  my_delete(temp_file_path, MYF(0));
1483
1399
 
1484
1400
  return(error);
1485
1401
}
1502
1418
  const char* mess= "Result content mismatch\n";
1503
1419
 
1504
1420
 
1505
 
  assert(result_file_name.c_str());
1506
 
 
1507
 
  if (access(result_file_name.c_str(), F_OK) != 0)
1508
 
    die("The specified result file does not exist: '%s'", result_file_name.c_str());
1509
 
 
1510
 
  switch (string_cmp(ds, result_file_name.c_str())) {
 
1421
  assert(result_file_name);
 
1422
 
 
1423
  if (access(result_file_name, F_OK) != 0)
 
1424
    die("The specified result file does not exist: '%s'", result_file_name);
 
1425
 
 
1426
  switch (string_cmp(ds, result_file_name)) {
1511
1427
  case RESULT_OK:
1512
1428
    break; /* ok */
1513
1429
  case RESULT_LENGTH_MISMATCH:
1521
1437
    */
1522
1438
    char reject_file[FN_REFLEN];
1523
1439
    size_t reject_length;
1524
 
    internal::dirname_part(reject_file, result_file_name.c_str(), &reject_length);
 
1440
    dirname_part(reject_file, result_file_name, &reject_length);
1525
1441
 
1526
1442
    if (access(reject_file, W_OK) == 0)
1527
1443
    {
1528
1444
      /* Result file directory is writable, save reject file there */
1529
 
      internal::fn_format(reject_file, result_file_name.c_str(), NULL,
 
1445
      fn_format(reject_file, result_file_name, NULL,
1530
1446
                ".reject", MY_REPLACE_EXT);
1531
1447
    }
1532
1448
    else
1533
1449
    {
1534
1450
      /* Put reject file in opt_logdir */
1535
 
      internal::fn_format(reject_file, result_file_name.c_str(), opt_logdir.c_str(),
 
1451
      fn_format(reject_file, result_file_name, opt_logdir,
1536
1452
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1537
1453
    }
1538
1454
    str_to_file(reject_file, ds->c_str(), ds->length());
1539
1455
 
1540
1456
    ds->erase(); /* Don't create a .log file */
1541
1457
 
1542
 
    show_diff(NULL, result_file_name.c_str(), reject_file);
1543
 
    die("%s",mess);
 
1458
    show_diff(NULL, result_file_name, reject_file);
 
1459
    die(mess);
1544
1460
    break;
1545
1461
  }
1546
1462
  default: /* impossible */
1566
1482
 
1567
1483
*/
1568
1484
 
1569
 
static void check_require(string* ds, const string &fname)
 
1485
static void check_require(string* ds, const char *fname)
1570
1486
{
1571
1487
 
1572
1488
 
1573
 
  if (string_cmp(ds, fname.c_str()))
 
1489
  if (string_cmp(ds, fname))
1574
1490
  {
1575
1491
    char reason[FN_REFLEN];
1576
 
    internal::fn_format(reason, fname.c_str(), "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
 
1492
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1577
1493
    abort_not_supported_test("Test requires: '%s'", reason);
1578
1494
  }
1579
1495
  return;
1624
1540
}
1625
1541
 
1626
1542
 
 
1543
static uchar *get_var_key(const uchar* var, size_t *len,
 
1544
                          bool __attribute__((unused)) t)
 
1545
{
 
1546
  register char* key;
 
1547
  key = ((VAR*)var)->name;
 
1548
  *len = ((VAR*)var)->name_len;
 
1549
  return (uchar*)key;
 
1550
}
 
1551
 
1627
1552
 
1628
1553
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1629
1554
              int val_len)
1635
1560
  if (!val_len && val)
1636
1561
    val_len = strlen(val) ;
1637
1562
  val_alloc_len = val_len + 16; /* room to grow */
1638
 
  if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
1639
 
                                               + name_len+1)))
 
1563
  if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
 
1564
                                                  + name_len+1, MYF(MY_WME))))
1640
1565
    die("Out of memory");
1641
1566
 
1642
1567
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1643
1568
  tmp_var->alloced = (v == 0);
1644
1569
 
1645
 
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
 
1570
  if (!(tmp_var->str_val = (char *)my_malloc(val_alloc_len+1, MYF(MY_WME))))
1646
1571
    die("Out of memory");
1647
1572
 
1648
1573
  memcpy(tmp_var->name, name, name_len);
1661
1586
}
1662
1587
 
1663
1588
 
1664
 
void var_free(pair<string, VAR *> v)
 
1589
void var_free(void *v)
1665
1590
{
1666
 
  free(v.second->str_val);
1667
 
  free(v.second->env_s);
1668
 
  if (v.second->alloced)
1669
 
    free(v.second);
 
1591
  my_free(((VAR*) v)->str_val, MYF(MY_WME));
 
1592
  my_free(((VAR*) v)->env_s, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
 
1593
  if (((VAR*)v)->alloced)
 
1594
    my_free(v, MYF(MY_WME));
1670
1595
}
1671
1596
 
1672
1597
 
1678
1603
    tmp = def_val;
1679
1604
 
1680
1605
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1681
 
  string var_name(name);
1682
 
  var_hash.insert(make_pair(var_name, v));
 
1606
  my_hash_insert(&var_hash, (uchar*)v);
1683
1607
  return v;
1684
1608
}
1685
1609
 
1696
1620
  if (digit < 0 || digit >= 10)
1697
1621
  {
1698
1622
    const char *save_var_name = var_name, *end;
1699
 
    uint32_t length;
 
1623
    uint length;
1700
1624
    end = (var_name_end) ? *var_name_end : 0;
1701
1625
    while (my_isvar(charset_info,*var_name) && var_name != end)
1702
1626
      var_name++;
1706
1630
        return(0);
1707
1631
      die("Empty variable");
1708
1632
    }
1709
 
    length= (uint32_t) (var_name - save_var_name);
 
1633
    length= (uint) (var_name - save_var_name);
1710
1634
    if (length >= MAX_VAR_NAME_LENGTH)
1711
1635
      die("Too long variable name: %s", save_var_name);
1712
1636
 
1713
 
    string save_var_name_str(save_var_name, length);
1714
 
    boost::unordered_map<string, VAR*>::iterator iter=
1715
 
      var_hash.find(save_var_name_str);
1716
 
    if (iter == var_hash.end())
 
1637
    if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
 
1638
                                 length)))
1717
1639
    {
1718
1640
      char buff[MAX_VAR_NAME_LENGTH+1];
1719
 
      strncpy(buff, save_var_name, length);
1720
 
      buff[length]= '\0';
 
1641
      strmake(buff, save_var_name, length);
1721
1642
      v= var_from_env(buff, "");
1722
1643
    }
1723
 
    else
1724
 
    {
1725
 
      v= (*iter).second;
1726
 
    }
1727
1644
    var_name--;  /* Point at last character */
1728
1645
  }
1729
1646
  else
1748
1665
 
1749
1666
static VAR *var_obtain(const char *name, int len)
1750
1667
{
1751
 
  string var_name(name, len);
1752
 
  boost::unordered_map<string, VAR*>::iterator iter=
1753
 
    var_hash.find(var_name);
1754
 
  if (iter != var_hash.end())
1755
 
    return (*iter).second;
1756
 
  VAR *v = var_init(0, name, len, "", 0);
1757
 
  var_hash.insert(make_pair(var_name, v));
 
1668
  VAR* v;
 
1669
  if ((v = (VAR*)hash_search(&var_hash, (const uchar *) name, len)))
 
1670
    return v;
 
1671
  v = var_init(0, name, len, "", 0);
 
1672
  my_hash_insert(&var_hash, (uchar*)v);
1758
1673
  return v;
1759
1674
}
1760
1675
 
1779
1694
  digit= *var_name - '0';
1780
1695
  if (!(digit < 10 && digit >= 0))
1781
1696
  {
1782
 
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
 
1697
    v= var_obtain(var_name, (uint) (var_name_end - var_name));
1783
1698
  }
1784
1699
  else
1785
1700
    v= var_reg + digit;
1798
1713
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
1799
1714
             v->name_len, v->name,
1800
1715
             v->str_val_len, v->str_val);
1801
 
    if (!(v->env_s= strdup(buf)))
 
1716
    if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
1802
1717
      die("Out of memory");
1803
1718
    putenv(v->env_s);
1804
 
    free(old_env_s);
 
1719
    my_free(old_env_s, MYF(MY_ALLOW_ZERO_PTR));
1805
1720
  }
1806
1721
  return;
1807
1722
}
1823
1738
 
1824
1739
/*
1825
1740
  Store an integer (typically the returncode of the last SQL)
1826
 
  statement in the drizzletest builtin variable $drizzleclient_errno
 
1741
  statement in the drizzletest builtin variable $drizzle_errno
1827
1742
*/
1828
1743
 
1829
1744
static void var_set_errno(int sql_errno)
1830
1745
{
1831
 
  var_set_int("$drizzleclient_errno", sql_errno);
 
1746
  var_set_int("$drizzle_errno", sql_errno);
1832
1747
}
1833
1748
 
1834
1749
 
1835
1750
/*
1836
 
  Update $drizzleclient_get_server_version variable with version
 
1751
  Update $drizzle_get_server_version variable with version
1837
1752
  of the currently connected server
1838
1753
*/
1839
1754
 
1840
 
static void var_set_drizzleclient_get_server_version(drizzle_con_st *con)
 
1755
static void var_set_drizzle_get_server_version(DRIZZLE *drizzle)
1841
1756
{
1842
 
  var_set_int("$drizzle_con_server_version", drizzle_con_server_version_number(con));
 
1757
  var_set_int("$drizzle_get_server_version", drizzle_get_server_version(drizzle));
1843
1758
}
1844
1759
 
1845
1760
 
1870
1785
{
1871
1786
  const char *end = (char*)((query_end && *query_end) ?
1872
1787
                            *query_end : query + strlen(query));
1873
 
  drizzle_result_st res;
1874
 
  drizzle_return_t ret;
1875
 
  drizzle_row_t row;
1876
 
  drizzle_con_st *con= &cur_con->con;
 
1788
  DRIZZLE_RES *res;
 
1789
  DRIZZLE_ROW row;
 
1790
  DRIZZLE *drizzle= &cur_con->drizzle;
1877
1791
  string ds_query;
1878
1792
 
1879
1793
 
1886
1800
  /* Eval the query, thus replacing all environment variables */
1887
1801
  do_eval(&ds_query, query, end, false);
1888
1802
 
1889
 
  if (drizzle_query(con, &res, ds_query.c_str(), ds_query.length(),
1890
 
                    &ret) == NULL ||
1891
 
      ret != DRIZZLE_RETURN_OK)
1892
 
  {
1893
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
1894
 
    {
1895
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
1896
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
1897
 
      drizzle_result_free(&res);
1898
 
    }
1899
 
    else
1900
 
    {
1901
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
1902
 
          drizzle_con_error(con));
1903
 
    }
1904
 
  }
1905
 
  if (drizzle_result_column_count(&res) == 0 ||
1906
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
1803
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
 
1804
    die("Error running query '%s': %d %s", ds_query.c_str(),
 
1805
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
1806
  if (!(res= drizzle_store_result(drizzle)))
1907
1807
    die("Query '%s' didn't return a result set", ds_query.c_str());
1908
1808
 
1909
 
  if ((row= drizzle_row_next(&res)) && row[0])
 
1809
  if ((row= drizzle_fetch_row(res)) && row[0])
1910
1810
  {
1911
1811
    /*
1912
1812
      Concatenate all fields in the first row with tab in between
1914
1814
    */
1915
1815
    string result;
1916
1816
    uint32_t i;
1917
 
    size_t *lengths;
 
1817
    uint32_t *lengths;
1918
1818
 
1919
 
    lengths= drizzle_row_field_sizes(&res);
1920
 
    for (i= 0; i < drizzle_result_column_count(&res); i++)
 
1819
    lengths= drizzle_fetch_lengths(res);
 
1820
    for (i= 0; i < drizzle_num_fields(res); i++)
1921
1821
    {
1922
1822
      if (row[i])
1923
1823
      {
1932
1832
  else
1933
1833
    eval_expr(var, "", 0);
1934
1834
 
1935
 
  drizzle_result_free(&res);
 
1835
  drizzle_free_result(res);
1936
1836
  return;
1937
1837
}
1938
1838
 
1963
1863
{
1964
1864
  long row_no;
1965
1865
  int col_no= -1;
1966
 
  drizzle_result_st res;
1967
 
  drizzle_return_t ret;
1968
 
  drizzle_con_st *con= &cur_con->con;
 
1866
  DRIZZLE_RES* res;
 
1867
  DRIZZLE *drizzle= &cur_con->drizzle;
1969
1868
 
1970
1869
  string ds_query;
1971
1870
  string ds_col;
1984
1883
                     ',');
1985
1884
 
1986
1885
  /* Convert row number to int */
1987
 
  row_no= atoi(ds_row.c_str());
1988
 
  
1989
 
  istringstream buff(ds_row);
1990
 
  if ((buff >> row_no).fail())
 
1886
  if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1991
1887
    die("Invalid row number: '%s'", ds_row.c_str());
1992
1888
 
1993
1889
  /* Remove any surrounding "'s from the query - if there is any */
1995
1891
  char * unstripped_query= strdup(ds_query.c_str());
1996
1892
  if (strip_surrounding(unstripped_query, '"', '"'))
1997
1893
    die("Mismatched \"'s around query '%s'", ds_query.c_str());
1998
 
  ds_query.clear();
1999
 
  ds_query.append(unstripped_query);
 
1894
  ds_query= unstripped_query;
2000
1895
 
2001
1896
  /* Run the query */
2002
 
  if (drizzle_query(con, &res, ds_query.c_str(), ds_query.length(),
2003
 
                    &ret) == NULL ||
2004
 
      ret != DRIZZLE_RETURN_OK)
2005
 
  {
2006
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
2007
 
    {
2008
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
2009
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
2010
 
      drizzle_result_free(&res);
2011
 
    }
2012
 
    else
2013
 
    {
2014
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
2015
 
          drizzle_con_error(con));
2016
 
    }
2017
 
  }
2018
 
  if (drizzle_result_column_count(&res) == 0 ||
2019
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
1897
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
 
1898
    die("Error running query '%s': %d %s", ds_query.c_str(),
 
1899
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
1900
  if (!(res= drizzle_store_result(drizzle)))
2020
1901
    die("Query '%s' didn't return a result set", ds_query.c_str());
2021
1902
 
2022
1903
  {
2023
1904
    /* Find column number from the given column name */
2024
 
    uint32_t i;
2025
 
    uint32_t num_fields= drizzle_result_column_count(&res);
2026
 
    drizzle_column_st *column;
 
1905
    uint i;
 
1906
    uint num_fields= drizzle_num_fields(res);
 
1907
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
2027
1908
 
2028
1909
    for (i= 0; i < num_fields; i++)
2029
1910
    {
2030
 
      column= drizzle_column_next(&res);
2031
 
      if (strcmp(drizzle_column_name(column), ds_col.c_str()) == 0 &&
2032
 
          strlen(drizzle_column_name(column)) == ds_col.length())
 
1911
      if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
 
1912
          strlen(fields[i].name) == ds_col.length())
2033
1913
      {
2034
1914
        col_no= i;
2035
1915
        break;
2037
1917
    }
2038
1918
    if (col_no == -1)
2039
1919
    {
2040
 
      drizzle_result_free(&res);
 
1920
      drizzle_free_result(res);
2041
1921
      die("Could not find column '%s' in the result of '%s'",
2042
1922
          ds_col.c_str(), ds_query.c_str());
2043
1923
    }
2045
1925
 
2046
1926
  {
2047
1927
    /* Get the value */
2048
 
    drizzle_row_t row;
 
1928
    DRIZZLE_ROW row;
2049
1929
    long rows= 0;
2050
1930
    const char* value= "No such row";
2051
1931
 
2052
 
    while ((row= drizzle_row_next(&res)))
 
1932
    while ((row= drizzle_fetch_row(res)))
2053
1933
    {
2054
1934
      if (++rows == row_no)
2055
1935
      {
2065
1945
    }
2066
1946
    eval_expr(var, value, 0);
2067
1947
  }
2068
 
  drizzle_result_free(&res);
 
1948
  drizzle_free_result(res);
2069
1949
 
2070
1950
  return;
2071
1951
}
2077
1957
  dest->int_dirty= src->int_dirty;
2078
1958
 
2079
1959
  /* Alloc/realloc data for str_val in dest */
2080
 
  if (dest->alloced_len < src->alloced_len)
2081
 
  {
2082
 
    char *tmpptr= (char *)realloc(dest->str_val, src->alloced_len);
2083
 
    if (tmpptr == NULL)
2084
 
      die("Out of memory");
2085
 
    dest->str_val= tmpptr;
2086
 
  }
 
1960
  if (dest->alloced_len < src->alloced_len &&
 
1961
      !(dest->str_val= dest->str_val
 
1962
        ? (char *)my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
 
1963
        : (char *)my_malloc(src->alloced_len, MYF(MY_WME))))
 
1964
    die("Out of memory");
2087
1965
  else
2088
1966
    dest->alloced_len= src->alloced_len;
2089
1967
 
2116
1994
    const size_t len= strlen(get_value_str);
2117
1995
    if (strncmp(p, get_value_str, len)==0)
2118
1996
    {
2119
 
      st_command command;
 
1997
      struct st_command command;
 
1998
      memset(&command, 0, sizeof(command));
2120
1999
      command.query= (char*)p;
2121
2000
      command.first_word_len= len;
2122
2001
      command.first_argument= command.query + len;
2134
2013
      static int MIN_VAR_ALLOC= 32;
2135
2014
      v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
2136
2015
        MIN_VAR_ALLOC : new_val_len + 1;
2137
 
      char *tmpptr= (char *)realloc(v->str_val, v->alloced_len+1);
2138
 
      if (tmpptr == NULL)
 
2016
      if (!(v->str_val =
 
2017
            v->str_val ? (char *)my_realloc(v->str_val, v->alloced_len+1,
 
2018
                                            MYF(MY_WME)) :
 
2019
            (char *)my_malloc(v->alloced_len+1, MYF(MY_WME))))
2139
2020
        die("Out of memory");
2140
 
      v->str_val= tmpptr;
2141
2021
    }
2142
2022
    v->str_val_len = new_val_len;
2143
2023
    memcpy(v->str_val, p, new_val_len);
2153
2033
{
2154
2034
  char buff[FN_REFLEN];
2155
2035
 
2156
 
  if (!internal::test_if_hard_path(name))
 
2036
  if (!test_if_hard_path(name))
2157
2037
  {
2158
 
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),name);
 
2038
    strxmov(buff, opt_basedir, name, NullS);
2159
2039
    name=buff;
2160
2040
  }
2161
 
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
 
2041
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2162
2042
 
2163
2043
  if (cur_file == file_stack_end)
2164
2044
    die("Source directives are nesting too deep");
2165
2045
  cur_file++;
2166
 
  if (!(cur_file->file= fopen(buff, "r")))
 
2046
  if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
2167
2047
  {
2168
2048
    cur_file--;
2169
2049
    die("Could not open '%s' for reading", buff);
2170
2050
  }
2171
 
  if (!(cur_file->file_name= strdup(buff)))
2172
 
    die("Out of memory");
 
2051
  cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
2173
2052
  cur_file->lineno=1;
2174
2053
  return(0);
2175
2054
}
2209
2088
    ; /* Do nothing */
2210
2089
  else
2211
2090
  {
2212
 
    if (! opt_testdir.empty())
2213
 
    {
2214
 
      string testdir(opt_testdir);
2215
 
      if (testdir[testdir.length()] != '/')
2216
 
        testdir.append("/");
2217
 
      testdir.append(ds_filename);
2218
 
      ds_filename.swap(testdir);
2219
 
    }
2220
2091
    open_file(ds_filename.c_str());
2221
2092
  }
2222
2093
 
2328
2199
  error= pclose(res_file);
2329
2200
  if (error > 0)
2330
2201
  {
2331
 
    uint32_t status= WEXITSTATUS(error), i;
 
2202
    uint status= WEXITSTATUS(error), i;
2332
2203
    bool ok= 0;
2333
2204
 
2334
2205
    if (command->abort_on_error)
2477
2348
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2478
2349
                     ' ');
2479
2350
 
2480
 
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2351
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
2481
2352
  handle_command_error(command, error);
 
2353
  return;
2482
2354
}
2483
2355
 
2484
2356
 
2510
2382
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2511
2383
                     ' ');
2512
2384
 
2513
 
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2385
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2514
2386
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2515
2387
  handle_command_error(command, error);
 
2388
  return;
2516
2389
}
2517
2390
 
2518
2391
 
2544
2417
                     ' ');
2545
2418
 
2546
2419
  /* Parse what mode to set */
2547
 
  istringstream buff(ds_mode);
2548
2420
  if (ds_mode.length() != 4 ||
2549
 
      (buff >> oct >> mode).fail())
 
2421
      str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NullS)
2550
2422
    die("You must write a 4 digit octal number for mode");
2551
2423
 
2552
2424
  handle_command_error(command, chmod(ds_file.c_str(), mode));
 
2425
  return;
2553
2426
}
2554
2427
 
2555
2428
 
2579
2452
 
2580
2453
  error= (access(ds_filename.c_str(), F_OK) != 0);
2581
2454
  handle_command_error(command, error);
 
2455
  return;
2582
2456
}
2583
2457
 
2584
2458
 
2594
2468
 
2595
2469
static void do_mkdir(struct st_command *command)
2596
2470
{
 
2471
  int error;
2597
2472
  string ds_dirname;
2598
 
  int error;
2599
2473
  const struct command_arg mkdir_args[] = {
2600
2474
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
2601
2475
  };
2605
2479
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2606
2480
                     ' ');
2607
2481
 
2608
 
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
 
2482
  error= my_mkdir(ds_dirname.c_str(), 0777, MYF(0)) != 0;
2609
2483
  handle_command_error(command, error);
 
2484
  return;
2610
2485
}
2611
2486
 
2612
2487
/*
2634
2509
 
2635
2510
  error= rmdir(ds_dirname.c_str()) != 0;
2636
2511
  handle_command_error(command, error);
 
2512
  return;
2637
2513
}
2638
2514
 
2639
2515
 
2723
2599
 
2724
2600
  /* If no delimiter was provided, use EOF */
2725
2601
  if (ds_delimiter.length() == 0)
2726
 
    ds_delimiter.append("EOF");
 
2602
    ds_delimiter= "EOF";
2727
2603
 
2728
2604
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
2729
2605
  {
2872
2748
  }
2873
2749
 
2874
2750
  handle_command_error(command, error);
 
2751
  return;
2875
2752
}
2876
2753
 
2877
2754
 
2903
2780
{
2904
2781
  char *p= command->first_argument, *name;
2905
2782
  struct st_connection *con;
2906
 
  drizzle_result_st result;
2907
 
  drizzle_return_t ret;
2908
2783
 
2909
2784
  if (!*p)
2910
2785
    die("Missing connection name in send_quit");
2919
2794
  if (!(con= find_connection_by_name(name)))
2920
2795
    die("connection '%s' not found in connection pool", name);
2921
2796
 
2922
 
  if (drizzle_quit(&con->con,&result, &ret))
2923
 
    drizzle_result_free(&result);
 
2797
  simple_command(&con->drizzle,COM_QUIT,0,0,1);
 
2798
 
 
2799
  return;
2924
2800
}
2925
2801
 
2926
2802
 
2940
2816
 
2941
2817
*/
2942
2818
 
2943
 
static void do_change_user(struct st_command *)
 
2819
static void do_change_user(struct st_command *command)
2944
2820
{
2945
 
  assert(0);
 
2821
  DRIZZLE *drizzle= &cur_con->drizzle;
 
2822
  /* static keyword to make the NetWare compiler happy. */
 
2823
  string ds_user, ds_passwd, ds_db;
 
2824
  const struct command_arg change_user_args[] = {
 
2825
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
 
2826
    { "password", ARG_STRING, false, &ds_passwd, "Password used when connecting" },
 
2827
    { "database", ARG_STRING, false, &ds_db, "Database to select after connect" },
 
2828
  };
 
2829
 
 
2830
 
 
2831
 
 
2832
  check_command_args(command, command->first_argument,
 
2833
                     change_user_args,
 
2834
                     sizeof(change_user_args)/sizeof(struct command_arg),
 
2835
                     ',');
 
2836
 
 
2837
  if (!ds_user.length())
 
2838
    ds_user= drizzle->user;
 
2839
 
 
2840
  if (!ds_passwd.length())
 
2841
    ds_passwd= drizzle->passwd;
 
2842
 
 
2843
  if (!ds_db.length())
 
2844
    ds_db= drizzle->db;
 
2845
 
 
2846
  if (drizzle_change_user(drizzle, ds_user.c_str(),
 
2847
                          ds_passwd.c_str(), ds_db.c_str()))
 
2848
    die("change user failed: %s", drizzle_error(drizzle));
 
2849
 
 
2850
 
 
2851
  return;
2946
2852
}
2947
2853
 
 
2854
 
2948
2855
/*
2949
2856
  SYNOPSIS
2950
2857
  do_perl
2967
2874
static void do_perl(struct st_command *command)
2968
2875
{
2969
2876
  int error;
2970
 
  int fd;
 
2877
  File fd;
2971
2878
  FILE *res_file;
2972
2879
  char buf[FN_REFLEN];
2973
2880
  char temp_file_path[FN_REFLEN];
2986
2893
 
2987
2894
  /* If no delimiter was provided, use EOF */
2988
2895
  if (ds_delimiter.length() == 0)
2989
 
    ds_delimiter.append("EOF");
 
2896
    ds_delimiter= "EOF";
2990
2897
 
2991
2898
  read_until_delimiter(&ds_script, &ds_delimiter);
2992
2899
 
2993
2900
  /* Create temporary file name */
2994
 
  if ((fd= internal::create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
2995
 
                            "tmp", MYF(MY_WME))) < 0)
 
2901
  if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
 
2902
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
 
2903
                            MYF(MY_WME))) < 0)
2996
2904
    die("Failed to create temporary file for perl command");
2997
 
  internal::my_close(fd, MYF(0));
 
2905
  my_close(fd, MYF(0));
2998
2906
 
2999
2907
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
3000
2908
 
3014
2922
  error= pclose(res_file);
3015
2923
 
3016
2924
  /* Remove the temporary file */
3017
 
  internal::my_delete(temp_file_path, MYF(0));
 
2925
  my_delete(temp_file_path, MYF(0));
3018
2926
 
3019
2927
  handle_command_error(command, WEXITSTATUS(error));
 
2928
  return;
3020
2929
}
3021
2930
 
3022
2931
 
3058
2967
 
3059
2968
 
3060
2969
static void
3061
 
do_wait_for_slave_to_stop(struct st_command *)
 
2970
do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
3062
2971
{
3063
2972
  static int SLAVE_POLL_INTERVAL= 300000;
3064
 
  drizzle_con_st *con= &cur_con->con;
 
2973
  DRIZZLE *drizzle= &cur_con->drizzle;
3065
2974
  for (;;)
3066
2975
  {
3067
 
    drizzle_result_st res;
3068
 
    drizzle_return_t ret;
3069
 
    drizzle_row_t row;
 
2976
    DRIZZLE_RES *res= NULL;
 
2977
    DRIZZLE_ROW row;
3070
2978
    int done;
3071
2979
 
3072
 
    if (drizzle_query_str(con,&res,"show status like 'Slave_running'",
3073
 
                          &ret) == NULL || ret != DRIZZLE_RETURN_OK)
3074
 
    {
3075
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
3076
 
      {
3077
 
        die("Query failed while probing slave for stop: %s",
3078
 
            drizzle_result_error(&res));
3079
 
        drizzle_result_free(&res);
3080
 
      }
3081
 
      else
3082
 
      {
3083
 
        die("Query failed while probing slave for stop: %s",
3084
 
            drizzle_con_error(con));
3085
 
      }
3086
 
    }
3087
 
 
3088
 
    if (drizzle_result_column_count(&res) == 0 ||
3089
 
        drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3090
 
    {
 
2980
    if (drizzle_query(drizzle,"show status like 'Slave_running'") ||
 
2981
        !(res=drizzle_store_result(drizzle)))
3091
2982
      die("Query failed while probing slave for stop: %s",
3092
 
          drizzle_con_error(con));
3093
 
    }
3094
 
 
3095
 
    if (!(row=drizzle_row_next(&res)) || !row[1])
 
2983
          drizzle_error(drizzle));
 
2984
    if (!(row=drizzle_fetch_row(res)) || !row[1])
3096
2985
    {
3097
 
      drizzle_result_free(&res);
 
2986
      drizzle_free_result(res);
3098
2987
      die("Strange result from query while probing slave for stop");
3099
2988
    }
3100
2989
    done = !strcmp(row[1],"OFF");
3101
 
    drizzle_result_free(&res);
 
2990
    drizzle_free_result(res);
3102
2991
    if (done)
3103
2992
      break;
3104
 
    usleep(SLAVE_POLL_INTERVAL);
 
2993
    my_sleep(SLAVE_POLL_INTERVAL);
3105
2994
  }
3106
2995
  return;
3107
2996
}
3109
2998
 
3110
2999
static void do_sync_with_master2(long offset)
3111
3000
{
3112
 
  drizzle_result_st res;
3113
 
  drizzle_return_t ret;
3114
 
  drizzle_row_t row;
3115
 
  drizzle_con_st *con= &cur_con->con;
 
3001
  DRIZZLE_RES *res;
 
3002
  DRIZZLE_ROW row;
 
3003
  DRIZZLE *drizzle= &cur_con->drizzle;
3116
3004
  char query_buf[FN_REFLEN+128];
3117
3005
  int tries= 0;
3118
3006
 
3119
3007
  if (!master_pos.file[0])
3120
3008
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3121
3009
 
3122
 
  snprintf(query_buf, sizeof(query_buf), "select master_pos_wait('%s', %ld)", master_pos.file,
 
3010
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3123
3011
          master_pos.pos + offset);
3124
3012
 
3125
3013
wait_for_position:
3126
3014
 
3127
 
  if (drizzle_query_str(con, &res, query_buf, &ret) == NULL ||
3128
 
      ret != DRIZZLE_RETURN_OK)
3129
 
  {
3130
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3131
 
    {
3132
 
      die("failed in '%s': %d: %s", query_buf, drizzle_result_error_code(&res),
3133
 
           drizzle_result_error(&res));
3134
 
      drizzle_result_free(&res);
3135
 
    }
3136
 
    else
3137
 
      die("failed in '%s': %d: %s", query_buf, ret, drizzle_con_error(con));
3138
 
  }
3139
 
 
3140
 
  if (drizzle_result_column_count(&res) == 0 ||
3141
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3142
 
    die("drizzle_result_buffer() returned NULL for '%s'", query_buf);
3143
 
 
3144
 
  if (!(row= drizzle_row_next(&res)))
3145
 
  {
3146
 
    drizzle_result_free(&res);
 
3015
  if (drizzle_query(drizzle, query_buf))
 
3016
    die("failed in '%s': %d: %s", query_buf, drizzle_errno(drizzle),
 
3017
        drizzle_error(drizzle));
 
3018
 
 
3019
  if (!(res= drizzle_store_result(drizzle)))
 
3020
    die("drizzle_store_result() returned NULL for '%s'", query_buf);
 
3021
  if (!(row= drizzle_fetch_row(res)))
 
3022
  {
 
3023
    drizzle_free_result(res);
3147
3024
    die("empty result in %s", query_buf);
3148
3025
  }
3149
3026
  if (!row[0])
3152
3029
      It may be that the slave SQL thread has not started yet, though START
3153
3030
      SLAVE has been issued ?
3154
3031
    */
3155
 
    drizzle_result_free(&res);
 
3032
    drizzle_free_result(res);
3156
3033
    if (tries++ == 30)
3157
3034
    {
3158
 
      show_query(con, "SHOW MASTER STATUS");
3159
 
      show_query(con, "SHOW SLAVE STATUS");
 
3035
      show_query(drizzle, "SHOW MASTER STATUS");
 
3036
      show_query(drizzle, "SHOW SLAVE STATUS");
3160
3037
      die("could not sync with master ('%s' returned NULL)", query_buf);
3161
3038
    }
3162
3039
    sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
3163
3040
    goto wait_for_position;
3164
3041
  }
3165
 
  drizzle_result_free(&res);
 
3042
  drizzle_free_result(res);
3166
3043
  return;
3167
3044
}
3168
3045
 
3192
3069
*/
3193
3070
static int do_save_master_pos(void)
3194
3071
{
3195
 
  drizzle_result_st res;
3196
 
  drizzle_return_t ret;
3197
 
  drizzle_row_t row;
3198
 
  drizzle_con_st *con= &cur_con->con;
 
3072
  DRIZZLE_RES *res;
 
3073
  DRIZZLE_ROW row;
 
3074
  DRIZZLE *drizzle= &cur_con->drizzle;
3199
3075
  const char *query;
3200
3076
 
3201
3077
 
3202
 
  if (drizzle_query_str(con, &res, query= "show master status", &ret) == NULL ||
3203
 
      ret != DRIZZLE_RETURN_OK)
3204
 
  {
3205
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3206
 
    {
3207
 
      die("failed in '%s': %d: %s", query, drizzle_result_error_code(&res),
3208
 
           drizzle_result_error(&res));
3209
 
      drizzle_result_free(&res);
3210
 
    }
3211
 
    else
3212
 
      die("failed in '%s': %d: %s", query, ret, drizzle_con_error(con));
3213
 
  }
 
3078
  if (drizzle_query(drizzle, query= "show master status"))
 
3079
    die("failed in 'show master status': %d %s",
 
3080
        drizzle_errno(drizzle), drizzle_error(drizzle));
3214
3081
 
3215
 
  if (drizzle_result_column_count(&res) == 0 ||
3216
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3217
 
    die("drizzleclient_store_result() retuned NULL for '%s'", query);
3218
 
  if (!(row = drizzle_row_next(&res)))
 
3082
  if (!(res = drizzle_store_result(drizzle)))
 
3083
    die("drizzle_store_result() retuned NULL for '%s'", query);
 
3084
  if (!(row = drizzle_fetch_row(res)))
3219
3085
    die("empty result in show master status");
3220
 
  strncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
 
3086
  stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
3221
3087
  master_pos.pos = strtoul(row[1], (char**) 0, 10);
3222
 
  drizzle_result_free(&res);
 
3088
  drizzle_free_result(res);
3223
3089
  return(0);
3224
3090
}
3225
3091
 
3303
3169
 
3304
3170
static int do_sleep(struct st_command *command, bool real_sleep)
3305
3171
{
3306
 
  bool error= false;
 
3172
  int error= 0;
3307
3173
  char *p= command->first_argument;
3308
3174
  char *sleep_start, *sleep_end= command->end;
3309
 
  double sleep_val= 0;
 
3175
  double sleep_val;
3310
3176
 
3311
3177
  while (my_isspace(charset_info, *p))
3312
3178
    p++;
3313
3179
  if (!*p)
3314
3180
    die("Missing argument to %.*s", command->first_word_len, command->query);
3315
3181
  sleep_start= p;
3316
 
  /* Check that arg starts with a digit, not handled by internal::my_strtod */
 
3182
  /* Check that arg starts with a digit, not handled by my_strtod */
3317
3183
  if (!my_isdigit(charset_info, *sleep_start))
3318
3184
    die("Invalid argument to %.*s \"%s\"", command->first_word_len,
3319
3185
        command->query,command->first_argument);
3320
 
  string buff_str(sleep_start, sleep_end-sleep_start);
3321
 
  istringstream buff(buff_str);
3322
 
  error= (buff >> sleep_val).fail();
 
3186
  sleep_val= my_strtod(sleep_start, &sleep_end, &error);
3323
3187
  if (error)
3324
3188
    die("Invalid argument to %.*s \"%s\"", command->first_word_len,
3325
3189
        command->query, command->first_argument);
3329
3193
    sleep_val= opt_sleep;
3330
3194
 
3331
3195
  if (sleep_val)
3332
 
    usleep((uint32_t) (sleep_val * 1000000L));
 
3196
    my_sleep((uint32_t) (sleep_val * 1000000L));
3333
3197
  command->last_argument= sleep_end;
3334
3198
  return 0;
3335
3199
}
3336
3200
 
3337
3201
 
3338
 
static void do_get_file_name(struct st_command *command, string &dest)
 
3202
static void do_get_file_name(struct st_command *command,
 
3203
                             char* dest, uint dest_max_len)
3339
3204
{
3340
3205
  char *p= command->first_argument, *name;
3341
3206
  if (!*p)
3346
3211
  if (*p)
3347
3212
    *p++= 0;
3348
3213
  command->last_argument= p;
3349
 
  if (! opt_testdir.empty())
3350
 
  {
3351
 
    dest= opt_testdir;
3352
 
    if (dest[dest.length()] != '/')
3353
 
      dest.append("/");
3354
 
  }
3355
 
  dest.append(name);
 
3214
  strmake(dest, name, dest_max_len - 1);
3356
3215
}
3357
3216
 
3358
3217
 
3370
3229
  if(*p)
3371
3230
    *p++= 0;
3372
3231
  command->last_argument= p;
3373
 
  charset_info= get_charset_by_csname(charset_name, MY_CS_PRIMARY);
 
3232
  charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
3374
3233
  if (!charset_info)
3375
3234
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3376
3235
}
3377
3236
 
3378
 
static void fill_global_error_names()
 
3237
static uint get_errcode_from_name(char *error_name, char *error_end)
3379
3238
{
3380
 
  drizzle_result_st res;
3381
 
  drizzle_return_t ret;
3382
 
  drizzle_row_t row;
3383
 
  drizzle_con_st *con= &cur_con->con;
3384
 
 
3385
 
  global_error_names.clear();
3386
 
 
3387
 
  const std::string ds_query("select error_name, error_code "
3388
 
                             "from data_dictionary.errors");
3389
 
  if (drizzle_query_str(con, &res, ds_query.c_str(), &ret) == NULL ||
3390
 
      ret != DRIZZLE_RETURN_OK)
3391
 
  {
3392
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3393
 
    {
3394
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
3395
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
3396
 
      drizzle_result_free(&res);
3397
 
    }
3398
 
    else
3399
 
    {
3400
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
3401
 
          drizzle_con_error(con));
3402
 
    }
3403
 
  }
3404
 
  if (drizzle_result_column_count(&res) == 0 ||
3405
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3406
 
  {
3407
 
    drizzle_result_free(&res);
3408
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
3409
 
  }
3410
 
 
3411
 
  while ((row= drizzle_row_next(&res)) && row[0])
 
3239
  /* SQL error as string */
 
3240
  st_error *e= global_error_names;
 
3241
 
 
3242
  /* Loop through the array of known error names */
 
3243
  for (; e->name; e++)
3412
3244
  {
3413
3245
    /*
3414
 
      Concatenate all fields in the first row with tab in between
3415
 
      and assign that string to the $variable
 
3246
      If we get a match, we need to check the length of the name we
 
3247
      matched against in case it was longer than what we are checking
 
3248
      (as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
3416
3249
    */
3417
 
    size_t *lengths= drizzle_row_field_sizes(&res);
3418
 
    const std::string error_name(row[0], lengths[0]);
3419
 
    const std::string error_code(row[1], lengths[1]);
3420
 
 
3421
 
    try
3422
 
    {
3423
 
      global_error_names.insert(ErrorCodes::value_type(error_name,
3424
 
                                                       boost::lexical_cast<uint32_t>(error_code)));
3425
 
    }
3426
 
    catch (boost::bad_lexical_cast &ex)
3427
 
    {
3428
 
      drizzle_result_free(&res);
3429
 
      die("Invalid error_code from Drizzle: %s", ex.what());
3430
 
    }
3431
 
 
3432
 
  }
3433
 
 
3434
 
  drizzle_result_free(&res);
3435
 
}
3436
 
 
3437
 
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3438
 
{
3439
 
  size_t err_name_len= error_end - error_name;
3440
 
  string error_name_s(error_name, err_name_len);
3441
 
 
3442
 
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3443
 
  if (it != global_error_names.end())
3444
 
  {
3445
 
    return (*it).second;
3446
 
  }
3447
 
 
3448
 
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3449
 
  return 0;
 
3250
    if (!strncmp(error_name, e->name, (int) (error_end - error_name)) &&
 
3251
        (uint) strlen(e->name) == (uint) (error_end - error_name))
 
3252
    {
 
3253
      return(e->code);
 
3254
    }
 
3255
  }
 
3256
  if (!e->name)
 
3257
    die("Unknown SQL error name '%s'", error_name);
 
3258
  return(0);
3450
3259
}
3451
3260
 
3452
3261
static void do_get_errcodes(struct st_command *command)
3453
3262
{
3454
3263
  struct st_match_err *to= saved_expected_errors.err;
3455
3264
  char *p= command->first_argument;
3456
 
  uint32_t count= 0;
 
3265
  uint count= 0;
3457
3266
 
3458
3267
 
3459
3268
 
3479
3288
 
3480
3289
      /*
3481
3290
        SQLSTATE string
3482
 
        - Must be DRIZZLE_MAX_SQLSTATE_SIZE long
 
3291
        - Must be SQLSTATE_LENGTH long
3483
3292
        - May contain only digits[0-9] and _uppercase_ letters
3484
3293
      */
3485
3294
      p++; /* Step past the S */
3486
 
      if ((end - p) != DRIZZLE_MAX_SQLSTATE_SIZE)
3487
 
        die("The sqlstate must be exactly %d chars long", DRIZZLE_MAX_SQLSTATE_SIZE);
 
3295
      if ((end - p) != SQLSTATE_LENGTH)
 
3296
        die("The sqlstate must be exactly %d chars long", SQLSTATE_LENGTH);
3488
3297
 
3489
3298
      /* Check sqlstate string validity */
3490
3299
      while (*p && p < end)
3514
3323
    {
3515
3324
      die("The error name definition must start with an uppercase E");
3516
3325
    }
3517
 
    else if (*p == 'H')
 
3326
    else
3518
3327
    {
3519
 
      /* Error name string */
3520
 
 
3521
 
      to->code.errnum= get_errcode_from_name(p, end);
 
3328
      long val;
 
3329
      char *start= p;
 
3330
      /* Check that the string passed to str2int only contain digits */
 
3331
      while (*p && p != end)
 
3332
      {
 
3333
        if (!my_isdigit(charset_info, *p))
 
3334
          die("Invalid argument to error: '%s' - "              \
 
3335
              "the errno may only consist of digits[0-9]",
 
3336
              command->first_argument);
 
3337
        p++;
 
3338
      }
 
3339
 
 
3340
      /* Convert the sting to int */
 
3341
      if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
 
3342
        die("Invalid argument to error: '%s'", command->first_argument);
 
3343
 
 
3344
      to->code.errnum= (uint) val;
3522
3345
      to->type= ERR_ERRNO;
3523
3346
    }
3524
 
    else
3525
 
    {
3526
 
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3527
 
    }
3528
3347
    to++;
3529
3348
    count++;
3530
3349
 
3629
3448
}
3630
3449
 
3631
3450
 
3632
 
static void set_reconnect(drizzle_con_st *con, int val)
 
3451
static void set_reconnect(DRIZZLE *drizzle, int val)
3633
3452
{
3634
 
  (void) con;
3635
 
  (void) val;
3636
 
/* XXX
3637
3453
  bool reconnect= val;
3638
3454
 
3639
 
  drizzleclient_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
3640
 
*/
 
3455
  drizzle_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
 
3456
 
 
3457
  return;
3641
3458
}
3642
3459
 
3643
3460
 
3646
3463
  if (!(cur_con= find_connection_by_name(name)))
3647
3464
    die("connection '%s' not found in connection pool", name);
3648
3465
 
3649
 
  /* Update $drizzleclient_get_server_version to that of current connection */
3650
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
3466
  /* Update $drizzle_get_server_version to that of current connection */
 
3467
  var_set_drizzle_get_server_version(&cur_con->drizzle);
3651
3468
 
3652
3469
  return(0);
3653
3470
}
3689
3506
  if (!(con= find_connection_by_name(name)))
3690
3507
    die("connection '%s' not found in connection pool", name);
3691
3508
 
3692
 
  if (con->drizzle != NULL)
 
3509
  if (command->type == Q_DIRTY_CLOSE)
3693
3510
  {
3694
 
    drizzle_free(con->drizzle);
3695
 
    con->drizzle= NULL;
 
3511
    if (con->drizzle.net.vio)
 
3512
    {
 
3513
      net_close(&(con->drizzle.net));
 
3514
    }
3696
3515
  }
3697
 
  free(con->name);
 
3516
 
 
3517
  drizzle_close(&con->drizzle);
 
3518
 
 
3519
  if (con->util_drizzle)
 
3520
    drizzle_close(con->util_drizzle);
 
3521
  con->util_drizzle= 0;
 
3522
 
 
3523
  my_free(con->name, MYF(0));
3698
3524
 
3699
3525
  /*
3700
3526
    When the connection is closed set name to "-closed_connection-"
3701
3527
    to make it possible to reuse the connection name.
3702
3528
  */
3703
 
  if (!(con->name = strdup("-closed_connection-")))
 
3529
  if (!(con->name = my_strdup("-closed_connection-", MYF(MY_WME))))
3704
3530
    die("Out of memory");
3705
3531
 
3706
3532
  return;
3732
3558
 
3733
3559
*/
3734
3560
 
3735
 
static void safe_connect(drizzle_con_st *con, const char *name,
3736
 
                         const string host, const string user, const char *pass,
3737
 
                         const string db, uint32_t port)
 
3561
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
 
3562
                         const char *user, const char *pass, const char *db,
 
3563
                         int port)
3738
3564
{
3739
 
  uint32_t failed_attempts= 0;
 
3565
  int failed_attempts= 0;
3740
3566
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3741
 
  drizzle_return_t ret;
3742
 
 
3743
 
  drizzle_con_set_tcp(con, host.c_str(), port);
3744
 
  drizzle_con_set_auth(con, user.c_str(), pass);
3745
 
  drizzle_con_set_db(con, db.c_str());
3746
 
  while((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
 
3567
 
 
3568
 
 
3569
  while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
 
3570
                         CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3747
3571
  {
3748
3572
    /*
3749
3573
      Connect failed
3753
3577
      on protocol/connection type
3754
3578
    */
3755
3579
 
3756
 
    if ((ret == DRIZZLE_RETURN_GETADDRINFO ||
3757
 
         ret == DRIZZLE_RETURN_COULD_NOT_CONNECT) &&
 
3580
    if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
 
3581
         drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
3758
3582
        failed_attempts < opt_max_connect_retries)
3759
3583
    {
3760
3584
      verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3761
 
                  opt_max_connect_retries, ret, drizzle_con_error(con));
3762
 
      usleep(connection_retry_sleep);
 
3585
                  opt_max_connect_retries, drizzle_errno(drizzle),
 
3586
                  drizzle_error(drizzle));
 
3587
      my_sleep(connection_retry_sleep);
3763
3588
    }
3764
3589
    else
3765
3590
    {
3766
3591
      if (failed_attempts > 0)
3767
3592
        die("Could not open connection '%s' after %d attempts: %d %s", name,
3768
 
            failed_attempts, ret, drizzle_con_error(con));
 
3593
            failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
3769
3594
      else
3770
 
        die("Could not open connection '%s': %d %s", name, ret,
3771
 
            drizzle_con_error(con));
 
3595
        die("Could not open connection '%s': %d %s", name,
 
3596
            drizzle_errno(drizzle), drizzle_error(drizzle));
3772
3597
    }
3773
3598
    failed_attempts++;
3774
3599
  }
3800
3625
*/
3801
3626
 
3802
3627
static int connect_n_handle_errors(struct st_command *command,
3803
 
                                   drizzle_con_st *con, const char* host,
 
3628
                                   DRIZZLE *con, const char* host,
3804
3629
                                   const char* user, const char* pass,
3805
3630
                                   const char* db, int port, const char* sock)
3806
3631
{
3807
 
  drizzle_return_t ret;
3808
3632
 
3809
3633
  /* Only log if an error is expected */
3810
3634
  if (!command->abort_on_error &&
3831
3655
    ds_res.append(delimiter);
3832
3656
    ds_res.append("\n");
3833
3657
  }
3834
 
  drizzle_con_set_tcp(con, host, port);
3835
 
  drizzle_con_set_auth(con, user, pass);
3836
 
  drizzle_con_set_db(con, db);
3837
 
  if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
 
3658
  if (!drizzle_connect(con, host, user, pass, db, port, 0,
 
3659
                       CLIENT_MULTI_STATEMENTS))
3838
3660
  {
3839
 
    if (ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
3840
 
    {
3841
 
      var_set_errno(drizzle_con_error_code(con));
3842
 
      handle_error(command, drizzle_con_error_code(con), drizzle_con_error(con),
3843
 
                   drizzle_con_sqlstate(con), &ds_res);
3844
 
    }
3845
 
    else
3846
 
    {
3847
 
      var_set_errno(ret);
3848
 
      handle_error(command, ret, drizzle_con_error(con), "", &ds_res);
3849
 
    }
3850
 
 
 
3661
    var_set_errno(drizzle_errno(con));
 
3662
    handle_error(command, drizzle_errno(con), drizzle_error(con),
 
3663
                 drizzle_sqlstate(con), &ds_res);
3851
3664
    return 0; /* Not connected */
3852
3665
  }
3853
3666
 
3884
3697
 
3885
3698
static void do_connect(struct st_command *command)
3886
3699
{
3887
 
  uint32_t con_port= opt_port;
 
3700
  int con_port= opt_port;
3888
3701
  const char *con_options;
3889
 
  bool con_ssl= 0;
 
3702
  bool con_ssl= 0, con_compress= 0;
3890
3703
  struct st_connection* con_slot;
3891
3704
 
3892
3705
  string ds_connection_name;
3932
3745
    if (*ds_sock.c_str() != FN_LIBCHAR)
3933
3746
    {
3934
3747
      char buff[FN_REFLEN];
3935
 
      internal::fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3936
 
      ds_sock.clear();
3937
 
      ds_sock.append(buff);
 
3748
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
 
3749
      ds_sock= buff;
3938
3750
    }
3939
3751
  }
3940
3752
 
3952
3764
      end++;
3953
3765
    if (!strncmp(con_options, "SSL", 3))
3954
3766
      con_ssl= 1;
 
3767
    else if (!strncmp(con_options, "COMPRESS", 8))
 
3768
      con_compress= 1;
3955
3769
    else
3956
3770
      die("Illegal option to connect: %.*s",
3957
3771
          (int) (end - con_options), con_options);
3973
3787
          (int) (sizeof(connections)/sizeof(struct st_connection)));
3974
3788
  }
3975
3789
 
3976
 
  if ((con_slot->drizzle= drizzle_create(NULL)) == NULL)
 
3790
  if (!drizzle_create(&con_slot->drizzle))
3977
3791
    die("Failed on drizzle_create()");
3978
 
  if (!drizzle_con_create(con_slot->drizzle, &con_slot->con))
3979
 
    die("Failed on drizzle_con_create()");
3980
 
  drizzle_con_add_options(&con_slot->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
3792
  if (opt_compress || con_compress)
 
3793
    drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NullS);
 
3794
  drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
3981
3795
 
3982
3796
  /* Use default db name */
3983
3797
  if (ds_database.length() == 0)
3984
 
    ds_database.append(opt_db);
 
3798
    ds_database= opt_db;
3985
3799
 
3986
3800
  /* Special database to allow one to connect without a database name */
3987
3801
  if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
3988
 
    ds_database.clear();
 
3802
    ds_database= "";
3989
3803
 
3990
 
  if (connect_n_handle_errors(command, &con_slot->con,
 
3804
  if (connect_n_handle_errors(command, &con_slot->drizzle,
3991
3805
                              ds_host.c_str(),ds_user.c_str(),
3992
3806
                              ds_password.c_str(), ds_database.c_str(),
3993
3807
                              con_port, ds_sock.c_str()))
4000
3814
      next_con++; /* if we used the next_con slot, advance the pointer */
4001
3815
  }
4002
3816
 
4003
 
  /* Update $drizzleclient_get_server_version to that of current connection */
4004
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
3817
  /* Update $drizzle_get_server_version to that of current connection */
 
3818
  var_set_drizzle_get_server_version(&cur_con->drizzle);
4005
3819
 
4006
3820
  return;
4007
3821
}
4118
3932
  if (not_expr)
4119
3933
    cur_block->ok = !cur_block->ok;
4120
3934
 
4121
 
  free(v.str_val);
4122
 
  free(v.env_s);
4123
 
 
 
3935
  var_free(&v);
4124
3936
  return;
4125
3937
}
4126
3938
 
4135
3947
  if (!(*p))
4136
3948
    die("Can't set empty delimiter");
4137
3949
 
4138
 
  strncpy(delimiter, p, sizeof(delimiter) - 1);
 
3950
  strmake(delimiter, p, sizeof(delimiter) - 1);
4139
3951
  delimiter_length= strlen(delimiter);
4140
3952
 
4141
3953
  command->last_argument= p + delimiter_length;
4143
3955
}
4144
3956
 
4145
3957
 
4146
 
bool match_delimiter(int c, const char *delim, uint32_t length)
 
3958
bool match_delimiter(int c, const char *delim, uint length)
4147
3959
{
4148
 
  uint32_t i;
 
3960
  uint i;
4149
3961
  char tmp[MAX_DELIMITER_LENGTH];
4150
3962
 
4151
3963
  if (c != *delim)
4197
4009
 
4198
4010
*/
4199
4011
 
4200
 
 
4201
 
static int my_strnncoll_simple(const CHARSET_INFO * const  cs, const unsigned char *s, size_t slen,
4202
 
                               const unsigned char *t, size_t tlen,
4203
 
                               bool t_is_prefix)
4204
 
{
4205
 
  size_t len = ( slen > tlen ) ? tlen : slen;
4206
 
  unsigned char *map= cs->sort_order;
4207
 
  if (t_is_prefix && slen > tlen)
4208
 
    slen=tlen;
4209
 
  while (len--)
4210
 
  {
4211
 
    if (map[*s++] != map[*t++])
4212
 
      return ((int) map[s[-1]] - (int) map[t[-1]]);
4213
 
  }
4214
 
  /*
4215
 
    We can't use (slen - tlen) here as the result may be outside of the
4216
 
    precision of a signed int
4217
 
  */
4218
 
  return slen > tlen ? 1 : slen < tlen ? -1 : 0 ;
4219
 
}
4220
 
 
4221
4012
static int read_line(char *buf, int size)
4222
4013
{
4223
4014
  char c, last_quote= 0;
4237
4028
  found_eof:
4238
4029
      if (cur_file->file != stdin)
4239
4030
      {
4240
 
        fclose(cur_file->file);
 
4031
        my_fclose(cur_file->file, MYF(0));
4241
4032
        cur_file->file= 0;
4242
4033
      }
4243
 
      free((unsigned char*) cur_file->file_name);
 
4034
      my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
4244
4035
      cur_file->file_name= 0;
4245
4036
      if (cur_file == file_stack)
4246
4037
      {
4276
4067
        return(0);
4277
4068
      }
4278
4069
      else if ((c == '{' &&
4279
 
                (!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
4280
 
                                      (unsigned char*) buf, min((ptrdiff_t)5, p - buf), 0) ||
4281
 
                 !my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
4282
 
                                      (unsigned char*) buf, min((ptrdiff_t)2, p - buf), 0))))
 
4070
                (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
 
4071
                                      (uchar*) buf, min((long)5, p - buf), 0) ||
 
4072
                 !my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
 
4073
                                      (uchar*) buf, min((long)2, p - buf), 0))))
4283
4074
      {
4284
4075
        /* Only if and while commands can be terminated by { */
4285
4076
        *p++= c;
4356
4147
    {
4357
4148
      /* Could be a multibyte character */
4358
4149
      /* This code is based on the code in "sql_load.cc" */
 
4150
#ifdef USE_MB
4359
4151
      int charlen = my_mbcharlen(charset_info, c);
4360
4152
      /* We give up if multibyte character is started but not */
4361
4153
      /* completed before we pass buf_end */
4382
4174
        }
4383
4175
      }
4384
4176
      else
 
4177
#endif
4385
4178
        *p++= c;
4386
4179
    }
4387
4180
  }
4464
4257
        ptr[2] && ptr[2] == '-' &&
4465
4258
        ptr[3])
4466
4259
    {
4467
 
      uint32_t type;
 
4260
      uint type;
4468
4261
      char save;
4469
4262
      char *end, *start= (char*)ptr+3;
4470
4263
      /* Skip leading spaces */
4476
4269
        end++;
4477
4270
      save= *end;
4478
4271
      *end= 0;
4479
 
      type= command_typelib.find_type(start, 1+2);
 
4272
      type= find_type(start, &command_typelib, 1+2);
4480
4273
      if (type)
4481
4274
        warning_msg("Embedded drizzletest command '--%s' detected in "
4482
4275
                    "query '%s' was this intentional? ",
4541
4334
  return;
4542
4335
}
4543
4336
 
 
4337
 
 
4338
 
4544
4339
/*
4545
4340
  Create a command from a set of lines
4546
4341
 
4558
4353
  terminated by new line '\n' regardless how many "delimiter" it contain.
4559
4354
*/
4560
4355
 
4561
 
#define MAX_QUERY (768*1024*2) /* 256K -- a test in sp-big is >128K */
 
4356
#define MAX_QUERY (256*1024*2) /* 256K -- a test in sp-big is >128K */
4562
4357
static char read_command_buf[MAX_QUERY];
4563
4358
 
4564
4359
static int read_command(struct st_command** command_ptr)
4572
4367
    *command_ptr= q_lines[parser.current_line];
4573
4368
    return(0);
4574
4369
  }
4575
 
  if (!(*command_ptr= command= new st_command))
4576
 
    die("command construction failed");
 
4370
  if (!(*command_ptr= command=
 
4371
        (struct st_command*) my_malloc(sizeof(*command),
 
4372
                                       MYF(MY_WME|MY_ZEROFILL))))
 
4373
    die(NullS);
4577
4374
  q_lines.push_back(command);
4578
4375
  command->type= Q_UNKNOWN;
4579
4376
 
4600
4397
  while (*p && my_isspace(charset_info, *p))
4601
4398
    p++;
4602
4399
 
4603
 
  if (!(command->query_buf= command->query= strdup(p)))
 
4400
  if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME))))
4604
4401
    die("Out of memory");
4605
4402
 
4606
4403
  /* Calculate first word length(the command), terminated by space or ( */
4607
4404
  p= command->query;
4608
4405
  while (*p && !my_isspace(charset_info, *p) && *p != '(')
4609
4406
    p++;
4610
 
  command->first_word_len= (uint32_t) (p - command->query);
 
4407
  command->first_word_len= (uint) (p - command->query);
4611
4408
 
4612
4409
  /* Skip spaces between command and first argument */
4613
4410
  while (*p && my_isspace(charset_info, *p))
4620
4417
  return(0);
4621
4418
}
4622
4419
 
 
4420
 
 
4421
static struct my_option my_long_options[] =
 
4422
{
 
4423
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
 
4424
   0, 0, 0, 0, 0, 0},
 
4425
  {"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
 
4426
   (char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4427
  {"character-sets-dir", OPT_CHARSETS_DIR,
 
4428
   "Directory where character sets are.", (char**) &opt_charsets_dir,
 
4429
   (char**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4430
  {"compress", 'C', "Use the compressed server/client protocol.",
 
4431
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
4432
   0, 0, 0},
 
4433
  {"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
 
4434
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4435
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
 
4436
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
 
4437
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4438
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
 
4439
   (char**) &debug_info_flag, (char**) &debug_info_flag,
 
4440
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4441
  {"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
 
4442
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4443
  {"include", 'i', "Include SQL before each test case.", (char**) &opt_include,
 
4444
   (char**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4445
  {"logdir", OPT_LOG_DIR, "Directory for log files", (char**) &opt_logdir,
 
4446
   (char**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4447
  {"mark-progress", OPT_MARK_PROGRESS,
 
4448
   "Write linenumber and elapsed time to <testname>.progress ",
 
4449
   (char**) &opt_mark_progress, (char**) &opt_mark_progress, 0,
 
4450
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4451
  {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
 
4452
   "Max number of connection attempts when connecting to server",
 
4453
   (char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
 
4454
   GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
 
4455
  {"password", 'p', "Password to use when connecting to server.",
 
4456
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
4457
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
 
4458
   "order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
 
4459
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
 
4460
   (char**) &opt_port,
 
4461
   (char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4462
  {"quiet", 's', "Suppress all normal output.", (char**) &silent,
 
4463
   (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4464
  {"record", 'r', "Record output of test_file into result file.",
 
4465
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4466
  {"result-file", 'R', "Read/Store result from/in this file.",
 
4467
   (char**) &result_file_name, (char**) &result_file_name, 0,
 
4468
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4469
  {"server-arg", 'A', "Send option value to embedded server as a parameter.",
 
4470
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4471
  {"server-file", 'F', "Read embedded server arguments from file.",
 
4472
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4473
  {"silent", 's', "Suppress all normal output. Synonym for --quiet.",
 
4474
   (char**) &silent, (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4475
  {"sleep", 'T', "Sleep always this many seconds on sleep commands.",
 
4476
   (char**) &opt_sleep, (char**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
 
4477
   0, 0, 0},
 
4478
  {"tail-lines", OPT_TAIL_LINES,
 
4479
   "Number of lines of the resul to include in a failure report",
 
4480
   (char**) &opt_tail_lines, (char**) &opt_tail_lines, 0,
 
4481
   GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
 
4482
  {"test-file", 'x', "Read test from/in this file (default stdin).",
 
4483
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4484
  {"timer-file", 'm', "File where the timing in micro seconds is stored.",
 
4485
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4486
  {"tmpdir", 't', "Temporary directory where sockets are put.",
 
4487
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4488
  {"user", 'u', "User for login.", (char**) &opt_user, (char**) &opt_user, 0,
 
4489
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4490
  {"verbose", 'v', "Write more.", (char**) &verbose, (char**) &verbose, 0,
 
4491
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4492
  {"version", 'V', "Output version information and exit.",
 
4493
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4494
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
4495
};
 
4496
 
 
4497
 
 
4498
static void print_version(void)
 
4499
{
 
4500
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
 
4501
         drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
4502
}
 
4503
 
 
4504
static void usage(void)
 
4505
{
 
4506
  print_version();
 
4507
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
 
4508
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
 
4509
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
 
4510
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
 
4511
  my_print_help(my_long_options);
 
4512
  printf("  --no-defaults       Don't read default options from any options file.\n");
 
4513
  my_print_variables(my_long_options);
 
4514
}
 
4515
 
 
4516
/*
 
4517
  Read arguments for embedded server and put them into
 
4518
  embedded_server_args[]
 
4519
*/
 
4520
 
 
4521
static void read_embedded_server_arguments(const char *name)
 
4522
{
 
4523
  char argument[1024],buff[FN_REFLEN], *str=0;
 
4524
  FILE *file;
 
4525
 
 
4526
  if (!test_if_hard_path(name))
 
4527
  {
 
4528
    strxmov(buff, opt_basedir, name, NullS);
 
4529
    name=buff;
 
4530
  }
 
4531
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
 
4532
 
 
4533
  if (!embedded_server_arg_count)
 
4534
  {
 
4535
    embedded_server_arg_count=1;
 
4536
    embedded_server_args[0]= (char*) "";    /* Progname */
 
4537
  }
 
4538
  if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
 
4539
    die("Failed to open file '%s'", buff);
 
4540
 
 
4541
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
 
4542
         (str=fgets(argument,sizeof(argument), file)))
 
4543
  {
 
4544
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
 
4545
    if (!(embedded_server_args[embedded_server_arg_count]=
 
4546
          (char*) my_strdup(str,MYF(MY_WME))))
 
4547
    {
 
4548
      my_fclose(file,MYF(0));
 
4549
      die("Out of memory");
 
4550
 
 
4551
    }
 
4552
    embedded_server_arg_count++;
 
4553
  }
 
4554
  my_fclose(file,MYF(0));
 
4555
  if (str)
 
4556
    die("Too many arguments in option file: %s",name);
 
4557
 
 
4558
  return;
 
4559
}
 
4560
 
 
4561
 
 
4562
static bool
 
4563
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
 
4564
               char *argument)
 
4565
{
 
4566
  switch(optid) {
 
4567
  case 'r':
 
4568
    record = 1;
 
4569
    break;
 
4570
  case 'x':
 
4571
  {
 
4572
    char buff[FN_REFLEN];
 
4573
    if (!test_if_hard_path(argument))
 
4574
    {
 
4575
      strxmov(buff, opt_basedir, argument, NullS);
 
4576
      argument= buff;
 
4577
    }
 
4578
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4579
    assert(cur_file == file_stack && cur_file->file == 0);
 
4580
    if (!(cur_file->file=
 
4581
          my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
 
4582
      die("Could not open '%s' for reading: errno = %d", buff, errno);
 
4583
    cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
 
4584
    cur_file->lineno= 1;
 
4585
    break;
 
4586
  }
 
4587
  case 'm':
 
4588
  {
 
4589
    static char buff[FN_REFLEN];
 
4590
    if (!test_if_hard_path(argument))
 
4591
    {
 
4592
      strxmov(buff, opt_basedir, argument, NullS);
 
4593
      argument= buff;
 
4594
    }
 
4595
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4596
    timer_file= buff;
 
4597
    unlink(timer_file);       /* Ignore error, may not exist */
 
4598
    break;
 
4599
  }
 
4600
  case 'p':
 
4601
    if (argument)
 
4602
    {
 
4603
      my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
 
4604
      opt_pass= my_strdup(argument, MYF(MY_FAE));
 
4605
      while (*argument) *argument++= 'x';    /* Destroy argument */
 
4606
      tty_password= 0;
 
4607
    }
 
4608
    else
 
4609
      tty_password= 1;
 
4610
    break;
 
4611
  case 't':
 
4612
    stpncpy(TMPDIR, argument, sizeof(TMPDIR));
 
4613
    break;
 
4614
  case 'A':
 
4615
    if (!embedded_server_arg_count)
 
4616
    {
 
4617
      embedded_server_arg_count=1;
 
4618
      embedded_server_args[0]= (char*) "";
 
4619
    }
 
4620
    if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
 
4621
        !(embedded_server_args[embedded_server_arg_count++]=
 
4622
          my_strdup(argument, MYF(MY_FAE))))
 
4623
    {
 
4624
      die("Can't use server argument");
 
4625
    }
 
4626
    break;
 
4627
  case 'F':
 
4628
    read_embedded_server_arguments(argument);
 
4629
    break;
 
4630
  case 'V':
 
4631
    print_version();
 
4632
    exit(0);
 
4633
  case '?':
 
4634
    usage();
 
4635
    exit(0);
 
4636
  }
 
4637
  return 0;
 
4638
}
 
4639
 
 
4640
 
 
4641
static int parse_args(int argc, char **argv)
 
4642
{
 
4643
  load_defaults("my",load_default_groups,&argc,&argv);
 
4644
  default_argv= argv;
 
4645
 
 
4646
  if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
 
4647
    exit(1);
 
4648
 
 
4649
  if (argc > 1)
 
4650
  {
 
4651
    usage();
 
4652
    exit(1);
 
4653
  }
 
4654
  if (argc == 1)
 
4655
    opt_db= *argv;
 
4656
  if (tty_password)
 
4657
    opt_pass= get_tty_password(NullS);          /* purify tested */
 
4658
  if (debug_info_flag)
 
4659
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
 
4660
  if (debug_check_flag)
 
4661
    my_end_arg= MY_CHECK_ERROR;
 
4662
 
 
4663
  return 0;
 
4664
}
 
4665
 
4623
4666
/*
4624
4667
  Write the content of str into file
4625
4668
 
4636
4679
  int fd;
4637
4680
  char buff[FN_REFLEN];
4638
4681
  int flags= O_WRONLY | O_CREAT;
4639
 
  if (!internal::test_if_hard_path(fname))
 
4682
  if (!test_if_hard_path(fname))
4640
4683
  {
4641
 
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),fname);
 
4684
    strxmov(buff, opt_basedir, fname, NullS);
4642
4685
    fname= buff;
4643
4686
  }
4644
 
  internal::fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
 
4687
  fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4645
4688
 
4646
4689
  if (!append)
4647
4690
    flags|= O_TRUNC;
4648
 
  if ((fd= internal::my_open(buff, flags,
 
4691
  if ((fd= my_open(buff, flags,
4649
4692
                   MYF(MY_WME | MY_FFNF))) < 0)
4650
4693
    die("Could not open '%s' for writing: errno = %d", buff, errno);
4651
 
  if (append && lseek(fd, 0, SEEK_END) == MY_FILEPOS_ERROR)
 
4694
  if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
4652
4695
    die("Could not find end of file '%s': errno = %d", buff, errno);
4653
 
  if (internal::my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
 
4696
  if (my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP)))
4654
4697
    die("write failed");
4655
 
  internal::my_close(fd, MYF(0));
 
4698
  my_close(fd, MYF(0));
4656
4699
}
4657
4700
 
4658
4701
/*
4674
4717
void dump_result_to_log_file(const char *buf, int size)
4675
4718
{
4676
4719
  char log_file[FN_REFLEN];
4677
 
  str_to_file(internal::fn_format(log_file, result_file_name.c_str(), opt_logdir.c_str(), ".log",
4678
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4720
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
 
4721
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4679
4722
                        MY_REPLACE_EXT),
4680
4723
              buf, size);
4681
4724
  fprintf(stderr, "\nMore results from queries before failure can be found in %s\n",
4685
4728
void dump_progress(void)
4686
4729
{
4687
4730
  char progress_file[FN_REFLEN];
4688
 
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4689
 
                        opt_logdir.c_str(), ".progress",
4690
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4731
  str_to_file(fn_format(progress_file, result_file_name,
 
4732
                        opt_logdir, ".progress",
 
4733
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4691
4734
                        MY_REPLACE_EXT),
4692
4735
              ds_progress.c_str(), ds_progress.length());
4693
4736
}
4696
4739
{
4697
4740
  char warn_file[FN_REFLEN];
4698
4741
 
4699
 
  str_to_file(internal::fn_format(warn_file, result_file_name.c_str(), opt_logdir.c_str(), ".warnings",
4700
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4742
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
 
4743
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4701
4744
                        MY_REPLACE_EXT),
4702
4745
              ds_warning_messages.c_str(), ds_warning_messages.length());
4703
4746
}
4707
4750
  Append the result for one field to the dynamic string ds
4708
4751
*/
4709
4752
 
4710
 
static void append_field(string *ds, uint32_t col_idx, drizzle_column_st *column,
 
4753
static void append_field(string *ds, uint col_idx, const DRIZZLE_FIELD* field,
4711
4754
                         const char* val, uint64_t len, bool is_null)
4712
4755
{
4713
4756
  if (col_idx < max_replace_column && replace_column[col_idx])
4729
4772
  }
4730
4773
  else
4731
4774
  {
4732
 
    ds->append(drizzle_column_name(column));
 
4775
    ds->append(field->name);
4733
4776
    ds->append("\t");
4734
4777
    replace_append_mem(ds, val, (int)len);
4735
4778
    ds->append("\n");
4742
4785
  Values may be converted with 'replace_column'
4743
4786
*/
4744
4787
 
4745
 
static void append_result(string *ds, drizzle_result_st *res)
 
4788
static void append_result(string *ds, DRIZZLE_RES *res)
4746
4789
{
4747
 
  drizzle_row_t row;
4748
 
  uint32_t num_fields= drizzle_result_column_count(res);
4749
 
  drizzle_column_st *column;
4750
 
  size_t *lengths;
 
4790
  DRIZZLE_ROW row;
 
4791
  uint32_t num_fields= drizzle_num_fields(res);
 
4792
  const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
4793
  uint32_t *lengths;
4751
4794
 
4752
 
  while ((row = drizzle_row_next(res)))
 
4795
  while ((row = drizzle_fetch_row(res)))
4753
4796
  {
4754
4797
    uint32_t i;
4755
 
    lengths = drizzle_row_field_sizes(res);
4756
 
    drizzle_column_seek(res, 0);
 
4798
    lengths = drizzle_fetch_lengths(res);
4757
4799
    for (i = 0; i < num_fields; i++)
4758
 
    {
4759
 
      column= drizzle_column_next(res);
4760
 
      append_field(ds, i, column,
 
4800
      append_field(ds, i, &fields[i],
4761
4801
                   (const char*)row[i], lengths[i], !row[i]);
4762
 
    }
4763
4802
    if (!display_result_vertically)
4764
4803
      ds->append("\n");
4765
4804
 
4771
4810
  Append metadata for fields to output
4772
4811
*/
4773
4812
 
4774
 
static void append_metadata(string *ds, drizzle_result_st *res)
 
4813
static void append_metadata(string *ds,
 
4814
                            const DRIZZLE_FIELD *field,
 
4815
                            uint num_fields)
4775
4816
{
4776
 
  drizzle_column_st *column;
 
4817
  const DRIZZLE_FIELD *field_end;
4777
4818
  ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4778
4819
             "Column_alias\tType\tLength\tMax length\tIs_null\t"
4779
4820
             "Flags\tDecimals\tCharsetnr\n");
4780
4821
 
4781
 
  drizzle_column_seek(res, 0);
4782
 
  while ((column= drizzle_column_next(res)))
 
4822
  for (field_end= field+num_fields ;
 
4823
       field < field_end ;
 
4824
       field++)
4783
4825
  {
4784
 
    ds->append(drizzle_column_catalog(column),
4785
 
               strlen(drizzle_column_catalog(column)));
4786
 
    ds->append("\t", 1);
4787
 
    ds->append(drizzle_column_db(column), strlen(drizzle_column_db(column)));
4788
 
    ds->append("\t", 1);
4789
 
    ds->append(drizzle_column_orig_table(column),
4790
 
               strlen(drizzle_column_orig_table(column)));
4791
 
    ds->append("\t", 1);
4792
 
    ds->append(drizzle_column_table(column),
4793
 
               strlen(drizzle_column_table(column)));
4794
 
    ds->append("\t", 1);
4795
 
    ds->append(drizzle_column_orig_name(column),
4796
 
               strlen(drizzle_column_orig_name(column)));
4797
 
    ds->append("\t", 1);
4798
 
    ds->append(drizzle_column_name(column),
4799
 
               strlen(drizzle_column_name(column)));
4800
 
    ds->append("\t", 1);
4801
 
    replace_append_uint(ds, drizzle_column_type_drizzle(column));
4802
 
    ds->append("\t", 1);
4803
 
    replace_append_uint(ds, drizzle_column_size(column));
4804
 
    ds->append("\t", 1);
4805
 
    replace_append_uint(ds, drizzle_column_max_size(column));
4806
 
    ds->append("\t", 1);
4807
 
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4808
 
    ds->append("\t", 1);
4809
 
    replace_append_uint(ds, drizzle_column_flags(column));
4810
 
    ds->append("\t", 1);
4811
 
    replace_append_uint(ds, drizzle_column_decimals(column));
4812
 
    ds->append("\t", 1);
4813
 
    replace_append_uint(ds, drizzle_column_charset(column));
 
4826
    ds->append(field->catalog,
 
4827
               field->catalog_length);
 
4828
    ds->append("\t", 1);
 
4829
    ds->append(field->db, field->db_length);
 
4830
    ds->append("\t", 1);
 
4831
    ds->append(field->org_table,
 
4832
               field->org_table_length);
 
4833
    ds->append("\t", 1);
 
4834
    ds->append(field->table,
 
4835
               field->table_length);
 
4836
    ds->append("\t", 1);
 
4837
    ds->append(field->org_name,
 
4838
               field->org_name_length);
 
4839
    ds->append("\t", 1);
 
4840
    ds->append(field->name, field->name_length);
 
4841
    ds->append("\t", 1);
 
4842
    replace_append_uint(ds, field->type);
 
4843
    ds->append("\t", 1);
 
4844
    replace_append_uint(ds, field->length);
 
4845
    ds->append("\t", 1);
 
4846
    replace_append_uint(ds, field->max_length);
 
4847
    ds->append("\t", 1);
 
4848
    ds->append((char*) ((field->flags & NOT_NULL_FLAG) ?
 
4849
                        "N" : "Y"), 1);
 
4850
    ds->append("\t", 1);
 
4851
    replace_append_uint(ds, field->flags);
 
4852
    ds->append("\t", 1);
 
4853
    replace_append_uint(ds, field->decimals);
 
4854
    ds->append("\t", 1);
 
4855
    replace_append_uint(ds, field->charsetnr);
4814
4856
    ds->append("\n", 1);
4815
4857
  }
4816
4858
}
4823
4865
static void append_info(string *ds, uint64_t affected_rows,
4824
4866
                        const char *info)
4825
4867
{
4826
 
  ostringstream buf;
4827
 
  buf << "affected rows: " << affected_rows << endl;
4828
 
  ds->append(buf.str());
4829
 
  if (info && strcmp(info, ""))
 
4868
  char buf[40], buff2[21];
 
4869
  sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
 
4870
  ds->append(buf);
 
4871
  if (info)
4830
4872
  {
4831
4873
    ds->append("info: ");
4832
4874
    ds->append(info);
4839
4881
  Display the table headings with the names tab separated
4840
4882
*/
4841
4883
 
4842
 
static void append_table_headings(string *ds, drizzle_result_st *res)
 
4884
static void append_table_headings(string *ds,
 
4885
                                  const DRIZZLE_FIELD *field,
 
4886
                                  uint num_fields)
4843
4887
{
4844
 
  uint32_t col_idx= 0;
4845
 
  drizzle_column_st *column;
4846
 
  drizzle_column_seek(res, 0);
4847
 
  while ((column= drizzle_column_next(res)))
 
4888
  uint col_idx;
 
4889
  for (col_idx= 0; col_idx < num_fields; col_idx++)
4848
4890
  {
4849
4891
    if (col_idx)
4850
4892
      ds->append("\t", 1);
4851
 
    replace_append(ds, drizzle_column_name(column));
4852
 
    col_idx++;
 
4893
    replace_append(ds, field[col_idx].name);
4853
4894
  }
4854
4895
  ds->append("\n", 1);
4855
4896
}
4861
4902
  Number of warnings appended to ds
4862
4903
*/
4863
4904
 
4864
 
static int append_warnings(string *ds, drizzle_con_st *con,
4865
 
                           drizzle_result_st *res)
 
4905
static int append_warnings(string *ds, DRIZZLE *drizzle)
4866
4906
{
4867
 
  uint32_t count;
4868
 
  drizzle_result_st warn_res;
4869
 
  drizzle_return_t ret;
4870
 
 
4871
 
 
4872
 
  if (!(count= drizzle_result_warning_count(res)))
 
4907
  uint count;
 
4908
  DRIZZLE_RES *warn_res;
 
4909
 
 
4910
 
 
4911
  if (!(count= drizzle_warning_count(drizzle)))
4873
4912
    return(0);
4874
4913
 
4875
 
  if (drizzle_query_str(con, &warn_res, "SHOW WARNINGS", &ret) == NULL ||
4876
 
      ret != DRIZZLE_RETURN_OK)
4877
 
  {
4878
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
4879
 
      die("Error running query \"SHOW WARNINGS\": %s", drizzle_result_error(&warn_res));
4880
 
    else
4881
 
      die("Error running query \"SHOW WARNINGS\": %s", drizzle_con_error(con));
4882
 
  }
4883
 
 
4884
 
  if (drizzle_result_column_count(&warn_res) == 0 ||
4885
 
      drizzle_result_buffer(&warn_res) != DRIZZLE_RETURN_OK)
4886
 
    die("Warning count is %u but didn't get any warnings", count);
4887
 
 
4888
 
  append_result(ds, &warn_res);
4889
 
  drizzle_result_free(&warn_res);
 
4914
  /*
 
4915
    If one day we will support execution of multi-statements
 
4916
    through PS API we should not issue SHOW WARNINGS until
 
4917
    we have not read all results...
 
4918
  */
 
4919
  assert(!drizzle_more_results(drizzle));
 
4920
 
 
4921
  if (drizzle_real_query(drizzle, "SHOW WARNINGS", 13))
 
4922
    die("Error running query \"SHOW WARNINGS\": %s", drizzle_error(drizzle));
 
4923
 
 
4924
  if (!(warn_res= drizzle_store_result(drizzle)))
 
4925
    die("Warning count is %u but didn't get any warnings",
 
4926
        count);
 
4927
 
 
4928
  append_result(ds, warn_res);
4890
4929
 
4891
4930
  return(count);
4892
4931
}
4910
4949
                             int flags, char *query, int query_len,
4911
4950
                             string *ds, string *ds_warnings)
4912
4951
{
4913
 
  drizzle_result_st res;
4914
 
  drizzle_return_t ret;
4915
 
  drizzle_con_st *con= &cn->con;
4916
 
  int err= 0;
4917
 
 
4918
 
  drizzle_con_add_options(con, DRIZZLE_CON_NO_RESULT_READ);
 
4952
  DRIZZLE_RES *res= 0;
 
4953
  DRIZZLE *drizzle= &cn->drizzle;
 
4954
  int err= 0, counter= 0;
4919
4955
 
4920
4956
  if (flags & QUERY_SEND_FLAG)
4921
4957
  {
4922
4958
    /*
4923
4959
     * Send the query
4924
4960
     */
4925
 
 
4926
 
    (void) drizzle_query(con, &res, query, query_len, &ret);
4927
 
    if (ret != DRIZZLE_RETURN_OK)
 
4961
    if (do_send_query(cn, query, query_len, flags))
4928
4962
    {
4929
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE ||
4930
 
          ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
4931
 
      {
4932
 
        err= drizzle_result_error_code(&res);
4933
 
        handle_error(command, err, drizzle_result_error(&res),
4934
 
                     drizzle_result_sqlstate(&res), ds);
4935
 
        if (ret == DRIZZLE_RETURN_ERROR_CODE)
4936
 
          drizzle_result_free(&res);
4937
 
      }
4938
 
      else
4939
 
      {
4940
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4941
 
        err= ret;
4942
 
      }
 
4963
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
4964
                   drizzle_sqlstate(drizzle), ds);
4943
4965
      goto end;
4944
4966
    }
4945
4967
  }
4946
4968
  if (!(flags & QUERY_REAP_FLAG))
4947
4969
    return;
4948
4970
 
 
4971
  do
4949
4972
  {
4950
4973
    /*
4951
 
     * Read the result packet
4952
 
     */
4953
 
    if (drizzle_result_read(con, &res, &ret) == NULL ||
4954
 
        ret != DRIZZLE_RETURN_OK)
 
4974
      When  on first result set, call drizzle_read_query_result to retrieve
 
4975
      answer to the query sent earlier
 
4976
    */
 
4977
    if ((counter==0) && drizzle_read_query_result(drizzle))
4955
4978
    {
4956
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
4957
 
      {
4958
 
        handle_error(command, drizzle_result_error_code(&res),
4959
 
                     drizzle_result_error(&res), drizzle_result_sqlstate(&res),
4960
 
                     ds);
4961
 
      }
4962
 
      else
4963
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4964
 
      drizzle_result_free(&res);
4965
 
      err= ret;
 
4979
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
4980
                   drizzle_sqlstate(drizzle), ds);
4966
4981
      goto end;
 
4982
 
4967
4983
    }
4968
4984
 
4969
4985
    /*
4970
4986
      Store the result of the query if it will return any fields
4971
4987
    */
4972
 
    if (drizzle_result_column_count(&res) &&
4973
 
        (ret= drizzle_result_buffer(&res)) != DRIZZLE_RETURN_OK)
 
4988
    if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
4974
4989
    {
4975
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
4976
 
      {
4977
 
        handle_error(command, drizzle_result_error_code(&res),
4978
 
                     drizzle_result_error(&res), drizzle_result_sqlstate(&res),
4979
 
                     ds);
4980
 
      }
4981
 
      else
4982
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4983
 
      drizzle_result_free(&res);
4984
 
      err= ret;
 
4990
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
4991
                   drizzle_sqlstate(drizzle), ds);
4985
4992
      goto end;
4986
4993
    }
4987
4994
 
4989
4996
    {
4990
4997
      uint64_t affected_rows= 0;    /* Ok to be undef if 'disable_info' is set */
4991
4998
 
4992
 
      if (drizzle_result_column_count(&res))
 
4999
      if (res)
4993
5000
      {
 
5001
        const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
5002
        uint num_fields= drizzle_num_fields(res);
 
5003
 
4994
5004
        if (display_metadata)
4995
 
          append_metadata(ds, &res);
 
5005
          append_metadata(ds, fields, num_fields);
4996
5006
 
4997
5007
        if (!display_result_vertically)
4998
 
          append_table_headings(ds, &res);
 
5008
          append_table_headings(ds, fields, num_fields);
4999
5009
 
5000
 
        append_result(ds, &res);
 
5010
        append_result(ds, res);
5001
5011
      }
5002
5012
 
5003
5013
      /*
5004
 
        Need to call drizzle_result_affected_rows() before the "new"
 
5014
        Need to call drizzle_affected_rows() before the "new"
5005
5015
        query to find the warnings
5006
5016
      */
5007
5017
      if (!disable_info)
5008
 
        affected_rows= drizzle_result_affected_rows(&res);
 
5018
        affected_rows= drizzle_affected_rows(drizzle);
5009
5019
 
5010
5020
      /*
5011
5021
        Add all warnings to the result. We can't do this if we are in
5012
5022
        the middle of processing results from multi-statement, because
5013
5023
        this will break protocol.
5014
5024
      */
5015
 
      if (!disable_warnings)
 
5025
      if (!disable_warnings && !drizzle_more_results(drizzle))
5016
5026
      {
5017
 
        drizzle_con_remove_options(con, DRIZZLE_CON_NO_RESULT_READ);
5018
 
        if (append_warnings(ds_warnings, con, &res) || ds_warnings->length())
 
5027
        if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
5019
5028
        {
5020
5029
          ds->append("Warnings:\n", 10);
5021
5030
          ds->append(ds_warnings->c_str(), ds_warnings->length());
5023
5032
      }
5024
5033
 
5025
5034
      if (!disable_info)
5026
 
        append_info(ds, affected_rows, drizzle_result_info(&res));
 
5035
        append_info(ds, affected_rows, drizzle_info(drizzle));
5027
5036
    }
5028
5037
 
5029
 
    drizzle_result_free(&res);
 
5038
    if (res)
 
5039
    {
 
5040
      drizzle_free_result(res);
 
5041
      res= 0;
 
5042
    }
 
5043
    counter++;
 
5044
  } while (!(err= drizzle_next_result(drizzle)));
 
5045
  if (err > 0)
 
5046
  {
 
5047
    /* We got an error from drizzle_next_result, maybe expected */
 
5048
    handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
5049
                 drizzle_sqlstate(drizzle), ds);
 
5050
    goto end;
5030
5051
  }
 
5052
  assert(err == -1); /* Successful and there are no more results */
5031
5053
 
5032
5054
  /* If we come here the query is both executed and read successfully */
5033
5055
  handle_no_error(command);
5035
5057
end:
5036
5058
 
5037
5059
  /*
5038
 
    We save the return code (drizzleclient_errno(drizzle)) from the last call sent
5039
 
    to the server into the drizzletest builtin variable $drizzleclient_errno. This
 
5060
    We save the return code (drizzle_errno(drizzle)) from the last call sent
 
5061
    to the server into the drizzletest builtin variable $drizzle_errno. This
5040
5062
    variable then can be used from the test case itself.
5041
5063
  */
5042
 
  drizzle_con_remove_options(con, DRIZZLE_CON_NO_RESULT_READ);
5043
 
  var_set_errno(err);
 
5064
  var_set_errno(drizzle_errno(drizzle));
5044
5065
  return;
5045
5066
}
5046
5067
 
5065
5086
                  unsigned int err_errno, const char *err_error,
5066
5087
                  const char *err_sqlstate, string *ds)
5067
5088
{
5068
 
  uint32_t i;
5069
 
 
5070
 
 
5071
 
  if (! command->require_file.empty())
 
5089
  uint i;
 
5090
 
 
5091
 
 
5092
  if (command->require_file[0])
5072
5093
  {
5073
5094
    /*
5074
5095
      The query after a "--require" failed. This is fine as long the server
5075
5096
      returned a valid reponse. Don't allow 2013 or 2006 to trigger an
5076
5097
      abort_not_supported_test
5077
5098
    */
5078
 
    if (err_errno == DRIZZLE_RETURN_SERVER_GONE)
 
5099
    if (err_errno == CR_SERVER_LOST ||
 
5100
        err_errno == CR_SERVER_GONE_ERROR)
5079
5101
      die("require query '%s' failed: %d: %s", command->query,
5080
5102
          err_errno, err_error);
5081
5103
 
5087
5109
  if (command->abort_on_error)
5088
5110
    die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
5089
5111
 
5090
 
  for (i= 0 ; (uint32_t) i < command->expected_errors.count ; i++)
 
5112
  for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
5091
5113
  {
5092
5114
    if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
5093
5115
         (command->expected_errors.err[i].code.errnum == err_errno)) ||
5094
5116
        ((command->expected_errors.err[i].type == ERR_SQLSTATE) &&
5095
5117
         (strncmp(command->expected_errors.err[i].code.sqlstate,
5096
 
                  err_sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE) == 0)))
 
5118
                  err_sqlstate, SQLSTATE_LENGTH) == 0)))
5097
5119
    {
5098
5120
      if (!disable_result_log)
5099
5121
      {
5227
5249
    Create a temporary dynamic string to contain the output from
5228
5250
    this query.
5229
5251
  */
5230
 
  if (! command->require_file.empty())
 
5252
  if (command->require_file[0])
5231
5253
  {
5232
5254
    ds= &ds_result;
5233
5255
  }
5270
5292
    ds= save_ds;
5271
5293
  }
5272
5294
 
5273
 
  if (! command->require_file.empty())
 
5295
  if (command->require_file[0])
5274
5296
  {
5275
5297
    /* A result file was specified for _this_ query
5276
5298
       and the output should be checked against an already
5288
5310
static void get_command_type(struct st_command* command)
5289
5311
{
5290
5312
  char save;
5291
 
  uint32_t type;
 
5313
  uint type;
5292
5314
 
5293
5315
 
5294
5316
  if (*command->query == '}')
5299
5321
 
5300
5322
  save= command->query[command->first_word_len];
5301
5323
  command->query[command->first_word_len]= 0;
5302
 
  type= command_typelib.find_type(command->query, 1+2);
 
5324
  type= find_type(command->query, &command_typelib, 1+2);
5303
5325
  command->query[command->first_word_len]= save;
5304
5326
  if (type > 0)
5305
5327
  {
5343
5365
        */
5344
5366
        save= command->query[command->first_word_len-1];
5345
5367
        command->query[command->first_word_len-1]= 0;
5346
 
        if (command_typelib.find_type(command->query, 1+2) > 0)
 
5368
        if (find_type(command->query, &command_typelib, 1+2) > 0)
5347
5369
          die("Extra delimiter \";\" found");
5348
5370
        command->query[command->first_word_len-1]= save;
5349
5371
 
5371
5393
 
5372
5394
*/
5373
5395
 
5374
 
static void mark_progress(struct st_command*, int line)
 
5396
static void mark_progress(struct st_command* command __attribute__((unused)),
 
5397
                          int line)
5375
5398
{
 
5399
  char buf[32], *end;
5376
5400
  uint64_t timer= timer_now();
5377
5401
  if (!progress_start)
5378
5402
    progress_start= timer;
5379
5403
  timer-= progress_start;
5380
5404
 
5381
 
  ostringstream buf;
5382
5405
  /* Milliseconds since start */
5383
 
  buf << timer << "\t";
 
5406
  end= int64_t2str(timer, buf, 10);
 
5407
  ds_progress.append(buf, (int)(end-buf));
 
5408
  ds_progress.append("\t", 1);
5384
5409
 
5385
5410
  /* Parser line number */
5386
 
  buf << line << "\t";
 
5411
  end= int10_to_str(line, buf, 10);
 
5412
  ds_progress.append(buf, (int)(end-buf));
 
5413
  ds_progress.append("\t", 1);
5387
5414
 
5388
5415
  /* Filename */
5389
 
  buf << cur_file->file_name << ":";
 
5416
  ds_progress.append(cur_file->file_name);
 
5417
  ds_progress.append(":", 1);
5390
5418
 
5391
5419
  /* Line in file */
5392
 
  buf << cur_file->lineno << endl;
5393
 
 
5394
 
  ds_progress.append(buf.str());
5395
 
 
5396
 
}
5397
 
 
5398
 
static void check_retries(uint32_t in_opt_max_connect_retries)
5399
 
{
5400
 
  if (in_opt_max_connect_retries > 10000 || opt_max_connect_retries<1)
5401
 
  {
5402
 
    cout << N_("Error: Invalid Value for opt_max_connect_retries"); 
5403
 
    exit(-1);
5404
 
  }
5405
 
  opt_max_connect_retries= in_opt_max_connect_retries;
5406
 
}
5407
 
 
5408
 
static void check_tail_lines(uint32_t in_opt_tail_lines)
5409
 
{
5410
 
  if (in_opt_tail_lines > 10000)
5411
 
  {
5412
 
    cout << N_("Error: Invalid Value for opt_tail_lines"); 
5413
 
    exit(-1);
5414
 
  }
5415
 
  opt_tail_lines= in_opt_tail_lines;
5416
 
}
5417
 
 
5418
 
static void check_sleep(int32_t in_opt_sleep)
5419
 
{
5420
 
  if (in_opt_sleep < -1)
5421
 
  {
5422
 
    cout << N_("Error: Invalid Value for opt_sleep"); 
5423
 
    exit(-1);
5424
 
  }
5425
 
  opt_sleep= in_opt_sleep;
5426
 
}
 
5420
  end= int10_to_str(cur_file->lineno, buf, 10);
 
5421
  ds_progress.append(buf, (int)(end-buf));
 
5422
 
 
5423
 
 
5424
  ds_progress.append("\n", 1);
 
5425
 
 
5426
}
 
5427
 
5427
5428
 
5428
5429
int main(int argc, char **argv)
5429
5430
{
5430
 
try
5431
 
{
5432
5431
  struct st_command *command;
5433
5432
  bool q_send_flag= 0, abort_flag= 0;
5434
 
  uint32_t command_executed= 0, last_command_executed= 0;
5435
 
  string save_file("");
 
5433
  uint command_executed= 0, last_command_executed= 0;
 
5434
  char save_file[FN_REFLEN];
5436
5435
  struct stat res_info;
 
5436
  MY_INIT(argv[0]);
5437
5437
 
 
5438
  save_file[0]= 0;
5438
5439
  TMPDIR[0]= 0;
5439
5440
 
5440
 
  internal::my_init();
5441
 
 
5442
 
  po::options_description commandline_options("Options used only in command line");
5443
 
  commandline_options.add_options()
5444
 
  ("help,?", "Display this help and exit.")
5445
 
  ("mark-progress", po::value<bool>(&opt_mark_progress)->default_value(false)->zero_tokens(),
5446
 
  "Write linenumber and elapsed time to <testname>.progress ")
5447
 
  ("sleep,T", po::value<int32_t>(&opt_sleep)->default_value(-1)->notifier(&check_sleep),
5448
 
  "Sleep always this many seconds on sleep commands.")
5449
 
  ("test-file,x", po::value<string>(),
5450
 
  "Read test from/in this file (default stdin).")
5451
 
  ("timer-file,f", po::value<string>(),
5452
 
  "File where the timing in micro seconds is stored.")
5453
 
  ("tmpdir,t", po::value<string>(),
5454
 
  "Temporary directory where sockets are put.")
5455
 
  ("verbose,v", po::value<bool>(&verbose)->default_value(false),
5456
 
  "Write more.")
5457
 
  ("version,V", "Output version information and exit.")
5458
 
  ("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
5459
 
  "Configuration file defaults are not used if no-defaults is set")
5460
 
  ;
5461
 
 
5462
 
  po::options_description test_options("Options specific to the drizzleimport");
5463
 
  test_options.add_options()
5464
 
  ("basedir,b", po::value<string>(&opt_basedir)->default_value(""),
5465
 
  "Basedir for tests.")
5466
 
  ("character-sets-dir", po::value<string>(&opt_charsets_dir)->default_value(""),
5467
 
  "Directory where character sets are.")
5468
 
  ("database,D", po::value<string>(&opt_db)->default_value(""),
5469
 
  "Database to use.")
5470
 
  ("include,i", po::value<string>(&opt_include)->default_value(""),
5471
 
  "Include SQL before each test case.")  
5472
 
  ("testdir", po::value<string>(&opt_testdir)->default_value(""),
5473
 
  "Path to use to search for test files")
5474
 
  ("logdir", po::value<string>(&opt_logdir)->default_value(""),
5475
 
  "Directory for log files")
5476
 
  ("max-connect-retries", po::value<uint32_t>(&opt_max_connect_retries)->default_value(500)->notifier(&check_retries),
5477
 
  "Max number of connection attempts when connecting to server")
5478
 
  ("quiet,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5479
 
  "Suppress all normal output.")
5480
 
  ("record,r", "Record output of test_file into result file.")
5481
 
  ("result-file,R", po::value<string>(&result_file_name)->default_value(""),
5482
 
  "Read/Store result from/in this file.")
5483
 
  ("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5484
 
  "Suppress all normal output. Synonym for --quiet.")
5485
 
  ("tail-lines", po::value<uint32_t>(&opt_tail_lines)->default_value(0)->notifier(&check_tail_lines),
5486
 
  "Number of lines of the resul to include in a failure report")
5487
 
  ;
5488
 
 
5489
 
  po::options_description client_options("Options specific to the client");
5490
 
  client_options.add_options()
5491
 
 
5492
 
  ("host,h", po::value<string>(&opt_host)->default_value("localhost"),
5493
 
  "Connect to host.")
5494
 
  ("password,P", po::value<string>(&password)->default_value("PASSWORD_SENTINEL"),
5495
 
  "Password to use when connecting to server.")
5496
 
  ("port,p", po::value<uint32_t>(&opt_port)->default_value(0),
5497
 
  "Port number to use for connection or 0 for default")
5498
 
  ("protocol", po::value<string>(&opt_protocol),
5499
 
  "The protocol of connection (mysql or drizzle).")
5500
 
  ("user,u", po::value<string>(&opt_user)->default_value(""),
5501
 
  "User for login.")
5502
 
  ;
5503
 
 
5504
 
  po::positional_options_description p;
5505
 
  p.add("database", 1);
5506
 
 
5507
 
  po::options_description long_options("Allowed Options");
5508
 
  long_options.add(commandline_options).add(test_options).add(client_options);
5509
 
 
5510
 
  std::string system_config_dir_test(SYSCONFDIR); 
5511
 
  system_config_dir_test.append("/drizzle/drizzletest.cnf");
5512
 
 
5513
 
  std::string system_config_dir_client(SYSCONFDIR); 
5514
 
  system_config_dir_client.append("/drizzle/client.cnf");
5515
 
 
5516
 
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
5517
 
 
5518
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
5519
 
  {
5520
 
    char *homedir;
5521
 
    homedir= getenv("HOME");
5522
 
    if (homedir != NULL)
5523
 
      user_config_dir.replace(0, 1, homedir);
5524
 
  }
5525
 
 
5526
 
  po::variables_map vm;
5527
 
 
5528
 
  // Disable allow_guessing
5529
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
5530
 
 
5531
 
  po::store(po::command_line_parser(argc, argv).options(long_options).
5532
 
            style(style).positional(p).extra_parser(parse_password_arg).run(),
5533
 
            vm);
5534
 
 
5535
 
  if (! vm["no-defaults"].as<bool>())
5536
 
  {
5537
 
    std::string user_config_dir_test(user_config_dir);
5538
 
    user_config_dir_test.append("/drizzle/drizzletest.cnf"); 
5539
 
 
5540
 
    std::string user_config_dir_client(user_config_dir);
5541
 
    user_config_dir_client.append("/drizzle/client.cnf");
5542
 
 
5543
 
    ifstream user_test_ifs(user_config_dir_test.c_str());
5544
 
    po::store(parse_config_file(user_test_ifs, test_options), vm);
5545
 
 
5546
 
    ifstream user_client_ifs(user_config_dir_client.c_str());
5547
 
    po::store(parse_config_file(user_client_ifs, client_options), vm);
5548
 
 
5549
 
    ifstream system_test_ifs(system_config_dir_test.c_str());
5550
 
    store(parse_config_file(system_test_ifs, test_options), vm);
5551
 
 
5552
 
    ifstream system_client_ifs(system_config_dir_client.c_str());
5553
 
    po::store(parse_config_file(system_client_ifs, client_options), vm);
5554
 
  }
5555
 
 
5556
 
  po::notify(vm);
5557
 
 
5558
5441
  /* Init expected errors */
5559
5442
  memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
5560
5443
 
5578
5461
  cur_block->ok= true; /* Outer block should always be executed */
5579
5462
  cur_block->cmd= cmd_none;
5580
5463
 
5581
 
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_version());
 
5464
  if (hash_init(&var_hash, charset_info,
 
5465
                1024, 0, 0, get_var_key, var_free, MYF(0)))
 
5466
    die("Variable hash initialization failed");
 
5467
 
 
5468
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
5582
5469
 
5583
5470
  memset(&master_pos, 0, sizeof(master_pos));
5584
5471
 
5591
5478
  ds_progress.reserve(2048);
5592
5479
  ds_warning_messages.reserve(2048);
5593
5480
 
5594
 
 
5595
 
  if (vm.count("record"))
5596
 
  {
5597
 
    record = 1;
5598
 
  }
5599
 
 
5600
 
  if (vm.count("test-file"))
5601
 
  {
5602
 
    string tmp= vm["test-file"].as<string>();
5603
 
    char buff[FN_REFLEN];
5604
 
    if (!internal::test_if_hard_path(tmp.c_str()))
5605
 
    {
5606
 
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5607
 
      tmp= buff;
5608
 
    }
5609
 
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5610
 
    assert(cur_file == file_stack && cur_file->file == 0);
5611
 
    if (!(cur_file->file= fopen(buff, "r")))
5612
 
    {
5613
 
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5614
 
      return EXIT_ARGUMENT_INVALID;
5615
 
    }
5616
 
    if (!(cur_file->file_name= strdup(buff)))
5617
 
    {
5618
 
      fprintf(stderr, _("Out of memory"));
5619
 
      return EXIT_OUT_OF_MEMORY;
5620
 
    }
5621
 
    cur_file->lineno= 1;
5622
 
  }
5623
 
 
5624
 
  if (vm.count("timer-file"))
5625
 
  {
5626
 
    string tmp= vm["timer-file"].as<string>().c_str();
5627
 
    static char buff[FN_REFLEN];
5628
 
    if (!internal::test_if_hard_path(tmp.c_str()))
5629
 
    {
5630
 
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5631
 
      tmp= buff;
5632
 
    }
5633
 
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5634
 
    timer_file= buff;
5635
 
    unlink(timer_file);       /* Ignore error, may not exist */
5636
 
  }
5637
 
 
5638
 
  if (vm.count("protocol"))
5639
 
  {
5640
 
    std::transform(opt_protocol.begin(), opt_protocol.end(),
5641
 
      opt_protocol.begin(), ::tolower);
5642
 
 
5643
 
    if (not opt_protocol.compare("mysql"))
5644
 
      use_drizzle_protocol=false;
5645
 
    else if (not opt_protocol.compare("drizzle"))
5646
 
      use_drizzle_protocol=true;
5647
 
    else
5648
 
    {
5649
 
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
5650
 
      exit(-1);
5651
 
    }
5652
 
  }
5653
 
 
5654
 
  if (vm.count("port"))
5655
 
  {
5656
 
    /* If the port number is > 65535 it is not a valid port
5657
 
       This also helps with potential data loss casting unsigned long to a
5658
 
       uint32_t. */
5659
 
    if (opt_port > 65535)
5660
 
    {
5661
 
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
5662
 
      exit(EXIT_ARGUMENT_INVALID);
5663
 
    }
5664
 
  }
5665
 
 
5666
 
  if( vm.count("password") )
5667
 
  {
5668
 
    if (!opt_password.empty())
5669
 
      opt_password.erase();
5670
 
    if (password == PASSWORD_SENTINEL)
5671
 
    {
5672
 
      opt_password= "";
5673
 
    }
5674
 
    else
5675
 
    {
5676
 
      opt_password= password;
5677
 
      tty_password= false;
5678
 
    }
5679
 
  }
5680
 
  else
5681
 
  {
5682
 
      tty_password= true;
5683
 
  }
5684
 
 
5685
 
  if (vm.count("tmpdir"))
5686
 
  {
5687
 
    strncpy(TMPDIR, vm["tmpdir"].as<string>().c_str(), sizeof(TMPDIR));
5688
 
  }
5689
 
 
5690
 
  if (vm.count("version"))
5691
 
  {
5692
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5693
 
    drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5694
 
    exit(0);
5695
 
  }
5696
 
  
5697
 
  if (vm.count("help"))
5698
 
  {
5699
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5700
 
    drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5701
 
    printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
5702
 
    printf("Drizzle version modified by Brian, Jay, Monty Taylor, PatG and Stewart\n");
5703
 
    printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
5704
 
    printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
5705
 
    printf("Usage: %s [OPTIONS] [database] < test_file\n", internal::my_progname);
5706
 
    exit(0);
5707
 
  }
5708
 
 
5709
 
  if (tty_password)
5710
 
  {
5711
 
    opt_pass= client_get_tty_password(NULL);          /* purify tested */
5712
 
  }
 
5481
  parse_args(argc, argv);
5713
5482
 
5714
5483
  server_initialized= 1;
5715
5484
  if (cur_file == file_stack && cur_file->file == 0)
5716
5485
  {
5717
5486
    cur_file->file= stdin;
5718
 
    cur_file->file_name= strdup("<stdin>");
5719
 
    if (cur_file->file_name == NULL)
5720
 
      die("Out of memory");
 
5487
    cur_file->file_name= my_strdup("<stdin>", MYF(MY_WME));
5721
5488
    cur_file->lineno= 1;
5722
5489
  }
5723
5490
  cur_con= connections;
5724
 
  if ((cur_con->drizzle= drizzle_create(NULL)) == NULL)
 
5491
  if (!( drizzle_create(&cur_con->drizzle)))
5725
5492
    die("Failed in drizzle_create()");
5726
 
  if (!( drizzle_con_create(cur_con->drizzle, &cur_con->con)))
5727
 
    die("Failed in drizzle_con_create()");
5728
 
  drizzle_con_add_options(&cur_con->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
5493
  if (opt_compress)
 
5494
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NullS);
 
5495
  drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
5729
5496
 
5730
 
  if (!(cur_con->name = strdup("default")))
 
5497
  if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5731
5498
    die("Out of memory");
5732
 
  safe_connect(&cur_con->con, cur_con->name, opt_host, opt_user, opt_pass,
 
5499
 
 
5500
  safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
5733
5501
               opt_db, opt_port);
5734
5502
 
5735
 
  fill_global_error_names();
5736
 
 
5737
5503
  /* Use all time until exit if no explicit 'start_timer' */
5738
5504
  timer_start= timer_now();
5739
5505
 
5740
5506
  /*
5741
 
    Initialize $drizzleclient_errno with -1, so we can
 
5507
    Initialize $drizzle_errno with -1, so we can
5742
5508
    - distinguish it from valid values ( >= 0 ) and
5743
5509
    - detect if there was never a command sent to the server
5744
5510
  */
5745
5511
  var_set_errno(-1);
5746
5512
 
5747
 
  /* Update $drizzleclient_get_server_version to that of current connection */
5748
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
5513
  /* Update $drizzle_get_server_version to that of current connection */
 
5514
  var_set_drizzle_get_server_version(&cur_con->drizzle);
5749
5515
 
5750
 
  if (! opt_include.empty())
 
5516
  if (opt_include)
5751
5517
  {
5752
 
    open_file(opt_include.c_str());
 
5518
    open_file(opt_include);
5753
5519
  }
5754
5520
 
5755
5521
  while (!read_command(&command) && !abort_flag)
5863
5629
        /* Check for special property for this query */
5864
5630
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5865
5631
 
5866
 
        if (! save_file.empty())
 
5632
        if (save_file[0])
5867
5633
        {
5868
 
          command->require_file= save_file;
5869
 
          save_file.clear();
 
5634
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
 
5635
          save_file[0]= 0;
5870
5636
        }
5871
5637
        run_query(cur_con, command, flags);
5872
5638
        command_executed++;
5903
5669
        command->last_argument= command->end;
5904
5670
        break;
5905
5671
      case Q_REQUIRE:
5906
 
        do_get_file_name(command, save_file);
 
5672
        do_get_file_name(command, save_file, sizeof(save_file));
5907
5673
        break;
5908
5674
      case Q_ERROR:
5909
5675
        do_get_errcodes(command);
5933
5699
        command->last_argument= command->end;
5934
5700
        break;
5935
5701
      case Q_PING:
5936
 
        {
5937
 
          drizzle_result_st result;
5938
 
          drizzle_return_t ret;
5939
 
          (void) drizzle_ping(&cur_con->con, &result, &ret);
5940
 
          if (ret == DRIZZLE_RETURN_OK || ret == DRIZZLE_RETURN_ERROR_CODE)
5941
 
            drizzle_result_free(&result);
5942
 
        }
 
5702
        (void) drizzle_ping(&cur_con->drizzle);
5943
5703
        break;
5944
5704
      case Q_EXEC:
5945
5705
        do_exec(command);
5957
5717
        do_set_charset(command);
5958
5718
        break;
5959
5719
      case Q_DISABLE_RECONNECT:
5960
 
        set_reconnect(&cur_con->con, 0);
 
5720
        set_reconnect(&cur_con->drizzle, 0);
5961
5721
        break;
5962
5722
      case Q_ENABLE_RECONNECT:
5963
 
        set_reconnect(&cur_con->con, 1);
 
5723
        set_reconnect(&cur_con->drizzle, 1);
5964
5724
        break;
5965
5725
      case Q_DISABLE_PARSING:
5966
5726
        if (parsing_disabled == 0)
6053
5813
  */
6054
5814
  if (ds_res.length())
6055
5815
  {
6056
 
    if (! result_file_name.empty())
 
5816
    if (result_file_name)
6057
5817
    {
6058
5818
      /* A result file has been specified */
6059
5819
 
6060
5820
      if (record)
6061
5821
      {
6062
5822
        /* Recording - dump the output from test to result file */
6063
 
        str_to_file(result_file_name.c_str(), ds_res.c_str(), ds_res.length());
 
5823
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
6064
5824
      }
6065
5825
      else
6066
5826
      {
6083
5843
  }
6084
5844
 
6085
5845
  if (!command_executed &&
6086
 
      ! result_file_name.empty() && !stat(result_file_name.c_str(), &res_info))
 
5846
      result_file_name && !stat(result_file_name, &res_info))
6087
5847
  {
6088
5848
    /*
6089
5849
      my_stat() successful on result file. Check if we have not run a
6095
5855
    die("No queries executed but result file found!");
6096
5856
  }
6097
5857
 
6098
 
  if ( opt_mark_progress && ! result_file_name.empty() )
 
5858
  if ( opt_mark_progress && result_file_name )
6099
5859
    dump_progress();
6100
5860
 
6101
5861
  /* Dump warning messages */
6102
 
  if (! result_file_name.empty() && ds_warning_messages.length())
 
5862
  if (result_file_name && ds_warning_messages.length())
6103
5863
    dump_warning_messages();
6104
5864
 
6105
5865
  timer_output();
6106
5866
  /* Yes, if we got this far the test has suceeded! Sakila smiles */
6107
5867
  cleanup_and_exit(0);
6108
 
}
6109
 
 
6110
 
  catch(exception &err)
6111
 
  {
6112
 
    cerr<<err.what()<<endl;
6113
 
  }
6114
 
 
6115
5868
  return 0; /* Keep compiler happy too */
6116
5869
}
6117
5870
 
6141
5894
{
6142
5895
  if (timer_file)
6143
5896
  {
6144
 
    ostringstream buf;
 
5897
    char buf[32], *end;
6145
5898
    uint64_t timer= timer_now() - timer_start;
6146
 
    buf << timer;
6147
 
    str_to_file(timer_file,buf.str().c_str(), buf.str().size() );
 
5899
    end= int64_t2str(timer, buf, 10);
 
5900
    str_to_file(timer_file,buf, (int) (end-buf));
6148
5901
    /* Timer has been written to the file, don't use it anymore */
6149
5902
    timer_file= 0;
6150
5903
  }
6153
5906
 
6154
5907
uint64_t timer_now(void)
6155
5908
{
6156
 
#if defined(HAVE_GETHRTIME)
6157
 
  return gethrtime()/1000/1000;
6158
 
#else
6159
 
  uint64_t newtime;
6160
 
  struct timeval t;
6161
 
  /*
6162
 
    The following loop is here because gettimeofday may fail on some systems
6163
 
  */
6164
 
  while (gettimeofday(&t, NULL) != 0)
6165
 
  {}
6166
 
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
6167
 
  return newtime/1000;
6168
 
#endif  /* defined(HAVE_GETHRTIME) */
 
5909
  return my_micro_time() / 1000;
6169
5910
}
6170
5911
 
6171
5912
 
6188
5929
    die("Missing argument in %s", command->query);
6189
5930
 
6190
5931
  /* Allocate a buffer for results */
6191
 
  start= buff= (char *)malloc(strlen(from)+1);
 
5932
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6192
5933
  while (*from)
6193
5934
  {
6194
5935
    char *to;
6195
 
    uint32_t column_number;
 
5936
    uint column_number;
6196
5937
 
6197
5938
    to= get_string(&buff, &from, command);
6198
5939
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6200
5941
    if (!*from)
6201
5942
      die("Wrong number of arguments to replace_column in '%s'", command->query);
6202
5943
    to= get_string(&buff, &from, command);
6203
 
    free(replace_column[column_number-1]);
6204
 
    replace_column[column_number-1]= strdup(to);
6205
 
    if (replace_column[column_number-1] == NULL)
6206
 
      die("Out of memory");
 
5944
    my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
 
5945
    replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
6207
5946
    set_if_bigger(max_replace_column, column_number);
6208
5947
  }
6209
 
  free(start);
 
5948
  my_free(start, MYF(0));
6210
5949
  command->last_argument= command->end;
6211
5950
}
6212
5951
 
6213
5952
 
6214
5953
void free_replace_column()
6215
5954
{
6216
 
  uint32_t i;
 
5955
  uint i;
6217
5956
  for (i=0 ; i < max_replace_column ; i++)
6218
5957
  {
6219
5958
    if (replace_column[i])
6220
5959
    {
6221
 
      free(replace_column[i]);
 
5960
      my_free(replace_column[i], 0);
6222
5961
      replace_column[i]= 0;
6223
5962
    }
6224
5963
  }
6235
5974
 
6236
5975
typedef struct st_pointer_array {    /* when using array-strings */
6237
5976
  TYPELIB typelib;        /* Pointer to strings */
6238
 
  unsigned char  *str;          /* Strings is here */
6239
 
  uint8_t *flag;          /* Flag about each var. */
6240
 
  uint32_t  array_allocs,max_count,length,max_length;
 
5977
  uchar  *str;          /* Strings is here */
 
5978
  int7  *flag;          /* Flag about each var. */
 
5979
  uint  array_allocs,max_count,length,max_length;
6241
5980
} POINTER_ARRAY;
6242
5981
 
6243
5982
struct st_replace;
6244
 
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
 
5983
struct st_replace *init_replace(char * *from, char * *to, uint count,
6245
5984
                                char * word_end_chars);
6246
5985
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6247
5986
void replace_strings_append(struct st_replace *rep, string* ds,
6248
5987
                            const char *from, int len);
6249
5988
void free_pointer_array(POINTER_ARRAY *pa);
6250
5989
 
6251
 
struct st_replace *glob_replace= NULL;
 
5990
struct st_replace *glob_replace;
6252
5991
 
6253
5992
/*
6254
5993
  Get arguments for replace. The syntax is:
6260
5999
 
6261
6000
void do_get_replace(struct st_command *command)
6262
6001
{
6263
 
  uint32_t i;
 
6002
  uint i;
6264
6003
  char *from= command->first_argument;
6265
6004
  char *buff, *start;
6266
6005
  char word_end_chars[256], *pos;
6273
6012
  memset(&from_array, 0, sizeof(from_array));
6274
6013
  if (!*from)
6275
6014
    die("Missing argument in %s", command->query);
6276
 
  start= buff= (char *)malloc(strlen(from)+1);
 
6015
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6277
6016
  while (*from)
6278
6017
  {
6279
6018
    char *to= buff;
6291
6030
  *pos=0;          /* End pointer */
6292
6031
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
6293
6032
                                   (char**) to_array.typelib.type_names,
6294
 
                                   (uint32_t) from_array.typelib.count,
 
6033
                                   (uint) from_array.typelib.count,
6295
6034
                                   word_end_chars)))
6296
6035
    die("Can't initialize replace from '%s'", command->query);
6297
6036
  free_pointer_array(&from_array);
6298
6037
  free_pointer_array(&to_array);
6299
 
  free(start);
 
6038
  my_free(start, MYF(0));
6300
6039
  command->last_argument= command->end;
6301
6040
  return;
6302
6041
}
6307
6046
 
6308
6047
  if (glob_replace)
6309
6048
  {
6310
 
    free(glob_replace);
 
6049
    my_free(glob_replace,MYF(0));
6311
6050
    glob_replace=0;
6312
6051
  }
6313
6052
  return;
6322
6061
typedef struct st_replace_found {
6323
6062
  bool found;
6324
6063
  char *replace_string;
6325
 
  uint32_t to_offset;
 
6064
  uint to_offset;
6326
6065
  int from_offset;
6327
6066
} REPLACE_STRING;
6328
6067
 
6341
6080
  {
6342
6081
    /* Loop through states */
6343
6082
    while (!rep_pos->found)
6344
 
      rep_pos= rep_pos->next[(unsigned char) *from++];
 
6083
      rep_pos= rep_pos->next[(uchar) *from++];
6345
6084
 
6346
6085
    /* Does this state contain a string to be replaced */
6347
6086
    if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6380
6119
  char* pattern; /* Pattern to be replaced */
6381
6120
  char* replace; /* String or expression to replace the pattern with */
6382
6121
  int icase; /* true if the match is case insensitive */
6383
 
  int global; /* true if the match should be global -- 
6384
 
                 i.e. repeat the matching until the end of the string */
6385
6122
};
6386
6123
 
6387
6124
struct st_replace_regex
6405
6142
struct st_replace_regex *glob_replace_regex= 0;
6406
6143
 
6407
6144
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6408
 
                char *string, int icase, int global);
 
6145
                char *string, int icase);
6409
6146
 
6410
6147
 
6411
6148
 
6450
6187
  char* buf,*expr_end;
6451
6188
  char* p;
6452
6189
  char* buf_p;
6453
 
  uint32_t expr_len= strlen(expr);
 
6190
  uint expr_len= strlen(expr);
6454
6191
  char last_c = 0;
6455
6192
  struct st_regex reg;
6456
6193
 
6457
 
  res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
6458
 
  if (!res)
6459
 
    return NULL;
 
6194
  /* my_malloc() will die on fail with MY_FAE */
 
6195
  res=(struct st_replace_regex*)my_malloc(
 
6196
                                          sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
6460
6197
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
6461
6198
 
6462
6199
  buf= (char*)res + sizeof(*res);
6506
6243
 
6507
6244
    /* Check if we should do matching case insensitive */
6508
6245
    if (p < expr_end && *p == 'i')
6509
 
    {
6510
 
      p++;
6511
6246
      reg.icase= 1;
6512
 
    }
6513
 
 
6514
 
    /* Check if we should do matching globally */
6515
 
    if (p < expr_end && *p == 'g')
6516
 
    {
6517
 
      p++;
6518
 
      reg.global= 1;
6519
 
    }
6520
6247
 
6521
6248
    /* done parsing the statement, now place it in regex_arr */
6522
 
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6249
    if (insert_dynamic(&res->regex_arr,(uchar*) &reg))
6523
6250
      die("Out of memory");
6524
6251
  }
6525
6252
  res->odd_buf_len= res->even_buf_len= 8192;
6526
 
  res->even_buf= (char*)malloc(res->even_buf_len);
6527
 
  res->odd_buf= (char*)malloc(res->odd_buf_len);
 
6253
  res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
 
6254
  res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
6528
6255
  res->buf= res->even_buf;
6529
6256
 
6530
6257
  return res;
6531
6258
 
6532
6259
err:
6533
 
  free(res);
 
6260
  my_free(res,0);
6534
6261
  die("Error parsing replace_regex \"%s\"", expr);
6535
6262
  return 0;
6536
6263
}
6556
6283
 
6557
6284
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6558
6285
{
6559
 
  uint32_t i;
 
6286
  uint i;
6560
6287
  char* in_buf, *out_buf;
6561
6288
  int* buf_len_p;
6562
6289
 
6571
6298
    struct st_regex re;
6572
6299
    char* save_out_buf= out_buf;
6573
6300
 
6574
 
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6301
    get_dynamic(&r->regex_arr,(uchar*)&re,i);
6575
6302
 
6576
6303
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6577
 
                     in_buf, re.icase, re.global))
 
6304
                     in_buf, re.icase))
6578
6305
    {
6579
6306
      /* if the buffer has been reallocated, make adjustements */
6580
6307
      if (save_out_buf != out_buf)
6622
6349
  if (glob_replace_regex)
6623
6350
  {
6624
6351
    delete_dynamic(&glob_replace_regex->regex_arr);
6625
 
    free(glob_replace_regex->even_buf);
6626
 
    free(glob_replace_regex->odd_buf);
6627
 
    free(glob_replace_regex);
 
6352
    my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6353
    my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6354
    my_free(glob_replace_regex,MYF(0));
6628
6355
    glob_replace_regex=0;
6629
6356
  }
6630
6357
}
6632
6359
 
6633
6360
 
6634
6361
/*
 
6362
  auxiluary macro used by reg_replace
 
6363
  makes sure the result buffer has sufficient length
 
6364
*/
 
6365
#define SECURE_REG_BUF   if (buf_len < need_buf_len)                    \
 
6366
  {                                                                     \
 
6367
    int off= res_p - buf;                                               \
 
6368
    buf= (char*)my_realloc(buf,need_buf_len,MYF(MY_WME+MY_FAE));        \
 
6369
    res_p= buf + off;                                                   \
 
6370
    buf_len= need_buf_len;                                              \
 
6371
  }                                                                     \
 
6372
                                                                        \
 
6373
/*
6635
6374
  Performs a regex substitution
6636
6375
 
6637
6376
  IN:
6644
6383
  icase - flag, if set to 1 the match is case insensitive
6645
6384
*/
6646
6385
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
6647
 
                char *replace, char *in_string, int icase, int global)
 
6386
                char *replace, char *in_string, int icase)
6648
6387
{
6649
 
  const char *error= NULL;
6650
 
  int erroffset;
6651
 
  int ovector[3];
6652
 
  pcre *re= pcre_compile(pattern,
6653
 
                         icase ? PCRE_CASELESS | PCRE_MULTILINE : PCRE_MULTILINE,
6654
 
                         &error, &erroffset, NULL);
6655
 
  if (re == NULL)
6656
 
    return 1;
6657
 
 
6658
 
  if (! global)
6659
 
  {
6660
 
 
6661
 
    int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
6662
 
                      0, 0, ovector, 3);
6663
 
    if (rc < 0)
6664
 
    {
6665
 
      pcre_free(re);
6666
 
      return 1;
6667
 
    }
6668
 
 
6669
 
    char *substring_to_replace= in_string + ovector[0];
6670
 
    int substring_length= ovector[1] - ovector[0];
6671
 
    *buf_len_p= strlen(in_string) - substring_length + strlen(replace);
6672
 
    char * new_buf = (char *)malloc(*buf_len_p+1);
6673
 
    if (new_buf == NULL)
6674
 
    {
6675
 
      pcre_free(re);
6676
 
      return 1;
6677
 
    }
6678
 
 
6679
 
    memset(new_buf, 0, *buf_len_p+1);
6680
 
    strncpy(new_buf, in_string, substring_to_replace-in_string);
6681
 
    strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
6682
 
    strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
6683
 
            substring_to_replace + substring_length,
6684
 
            strlen(in_string)
6685
 
              - substring_length
6686
 
              - (substring_to_replace-in_string));
6687
 
    *buf_p= new_buf;
6688
 
 
6689
 
    pcre_free(re);
6690
 
    return 0;
6691
 
  }
6692
 
  else
6693
 
  {
6694
 
    /* Repeatedly replace the string with the matched regex */
6695
 
    string subject(in_string);
6696
 
    size_t replace_length= strlen(replace);
6697
 
    size_t length_of_replacement= strlen(replace);
6698
 
    size_t current_position= 0;
6699
 
    int rc= 0;
6700
 
 
6701
 
    while (true) 
6702
 
    {
6703
 
      rc= pcre_exec(re, NULL, subject.c_str(), subject.length(), 
6704
 
                    current_position, 0, ovector, 3);
6705
 
      if (rc < 0)
6706
 
      {
6707
 
        break;
6708
 
      }
6709
 
 
6710
 
      current_position= static_cast<size_t>(ovector[0]);
6711
 
      replace_length= static_cast<size_t>(ovector[1] - ovector[0]);
6712
 
      subject.replace(current_position, replace_length, replace, length_of_replacement);
6713
 
      current_position= current_position + length_of_replacement;
6714
 
    }
6715
 
 
6716
 
    char *new_buf = (char *) malloc(subject.length() + 1);
6717
 
    if (new_buf == NULL)
6718
 
    {
6719
 
      pcre_free(re);
6720
 
      return 1;
6721
 
    }
6722
 
    memset(new_buf, 0, subject.length() + 1);
6723
 
    strncpy(new_buf, subject.c_str(), subject.length());
6724
 
    *buf_len_p= subject.length() + 1;
6725
 
    *buf_p= new_buf;
6726
 
          
6727
 
    pcre_free(re);
6728
 
    return 0;
6729
 
  }
 
6388
  string string_to_match(in_string);
 
6389
  pcrecpp::RE_Options opt;
 
6390
 
 
6391
  if (icase)
 
6392
    opt.set_caseless(true);
 
6393
 
 
6394
  if (!pcrecpp::RE(pattern, opt).Replace(replace,&string_to_match)){
 
6395
    return 1;
 
6396
  }
 
6397
 
 
6398
  const char * new_str= string_to_match.c_str();
 
6399
  *buf_len_p= strlen(new_str);
 
6400
  char * new_buf = (char *)malloc(*buf_len_p+1);
 
6401
  if (new_buf == NULL)
 
6402
  {
 
6403
    return 1;
 
6404
  }
 
6405
  strcpy(new_buf, new_str);
 
6406
  buf_p= &new_buf;
 
6407
 
 
6408
  return 0;
6730
6409
}
6731
6410
 
6732
6411
 
6733
6412
#ifndef WORD_BIT
6734
 
#define WORD_BIT (8*sizeof(uint32_t))
 
6413
#define WORD_BIT (8*sizeof(uint))
6735
6414
#endif
6736
6415
 
6737
6416
#define SET_MALLOC_HUNC 64
6738
6417
#define LAST_CHAR_CODE 259
6739
6418
 
6740
6419
typedef struct st_rep_set {
6741
 
  uint32_t  *bits;        /* Pointer to used sets */
 
6420
  uint  *bits;        /* Pointer to used sets */
6742
6421
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6743
 
  uint32_t  found_len;      /* Best match to date */
 
6422
  uint  found_len;      /* Best match to date */
6744
6423
  int  found_offset;
6745
 
  uint32_t  table_offset;
6746
 
  uint32_t  size_of_bits;      /* For convinience */
 
6424
  uint  table_offset;
 
6425
  uint  size_of_bits;      /* For convinience */
6747
6426
} REP_SET;
6748
6427
 
6749
6428
typedef struct st_rep_sets {
6750
 
  uint32_t    count;      /* Number of sets */
6751
 
  uint32_t    extra;      /* Extra sets in buffer */
6752
 
  uint32_t    invisible;    /* Sets not chown */
6753
 
  uint32_t    size_of_bits;
 
6429
  uint    count;      /* Number of sets */
 
6430
  uint    extra;      /* Extra sets in buffer */
 
6431
  uint    invisible;    /* Sets not chown */
 
6432
  uint    size_of_bits;
6754
6433
  REP_SET  *set,*set_buffer;
6755
 
  uint32_t    *bit_buffer;
 
6434
  uint    *bit_buffer;
6756
6435
} REP_SETS;
6757
6436
 
6758
6437
typedef struct st_found_set {
6759
 
  uint32_t table_offset;
 
6438
  uint table_offset;
6760
6439
  int found_offset;
6761
6440
} FOUND_SET;
6762
6441
 
6763
6442
typedef struct st_follow {
6764
6443
  int chr;
6765
 
  uint32_t table_offset;
6766
 
  uint32_t len;
 
6444
  uint table_offset;
 
6445
  uint len;
6767
6446
} FOLLOWS;
6768
6447
 
6769
6448
 
6770
 
int init_sets(REP_SETS *sets,uint32_t states);
 
6449
int init_sets(REP_SETS *sets,uint states);
6771
6450
REP_SET *make_new_set(REP_SETS *sets);
6772
6451
void make_sets_invisible(REP_SETS *sets);
6773
6452
void free_last_set(REP_SETS *sets);
6774
6453
void free_sets(REP_SETS *sets);
6775
 
void internal_set_bit(REP_SET *set, uint32_t bit);
6776
 
void internal_clear_bit(REP_SET *set, uint32_t bit);
 
6454
void internal_set_bit(REP_SET *set, uint bit);
 
6455
void internal_clear_bit(REP_SET *set, uint bit);
6777
6456
void or_bits(REP_SET *to,REP_SET *from);
6778
6457
void copy_bits(REP_SET *to,REP_SET *from);
6779
6458
int cmp_bits(REP_SET *set1,REP_SET *set2);
6780
 
int get_next_bit(REP_SET *set,uint32_t lastpos);
 
6459
int get_next_bit(REP_SET *set,uint lastpos);
6781
6460
int find_set(REP_SETS *sets,REP_SET *find);
6782
 
int find_found(FOUND_SET *found_set,uint32_t table_offset,
 
6461
int find_found(FOUND_SET *found_set,uint table_offset,
6783
6462
               int found_offset);
6784
 
uint32_t start_at_word(char * pos);
6785
 
uint32_t end_of_word(char * pos);
6786
 
 
6787
 
static uint32_t found_sets=0;
6788
 
 
6789
 
 
6790
 
static uint32_t replace_len(char * str)
 
6463
uint start_at_word(char * pos);
 
6464
uint end_of_word(char * pos);
 
6465
 
 
6466
static uint found_sets=0;
 
6467
 
 
6468
 
 
6469
static uint replace_len(char * str)
6791
6470
{
6792
 
  uint32_t len=0;
 
6471
  uint len=0;
6793
6472
  while (*str)
6794
6473
  {
6795
6474
    if (str[0] == '\\' && str[1])
6802
6481
 
6803
6482
/* Init a replace structure for further calls */
6804
6483
 
6805
 
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
 
6484
REPLACE *init_replace(char * *from, char * *to,uint count,
6806
6485
                      char * word_end_chars)
6807
6486
{
6808
6487
  static const int SPACE_CHAR= 256;
6809
6488
  static const int START_OF_LINE= 257;
6810
6489
  static const int END_OF_LINE= 258;
6811
6490
 
6812
 
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
 
6491
  uint i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6813
6492
  int used_sets,chr,default_state;
6814
6493
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6815
6494
  char * pos, *to_pos, **to_array;
6831
6510
      return(0);
6832
6511
    }
6833
6512
    states+=len+1;
6834
 
    result_len+=(uint32_t) strlen(to[i])+1;
 
6513
    result_len+=(uint) strlen(to[i])+1;
6835
6514
    if (len > max_length)
6836
6515
      max_length=len;
6837
6516
  }
6838
6517
  memset(is_word_end, 0, sizeof(is_word_end));
6839
6518
  for (i=0 ; word_end_chars[i] ; i++)
6840
 
    is_word_end[(unsigned char) word_end_chars[i]]=1;
 
6519
    is_word_end[(uchar) word_end_chars[i]]=1;
6841
6520
 
6842
6521
  if (init_sets(&sets,states))
6843
6522
    return(0);
6844
6523
  found_sets=0;
6845
 
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
6846
 
                                
 
6524
  if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
 
6525
                                          MYF(MY_WME))))
6847
6526
  {
6848
6527
    free_sets(&sets);
6849
6528
    return(0);
6850
6529
  }
6851
 
  make_new_set(&sets);      /* Set starting set */
 
6530
  VOID(make_new_set(&sets));      /* Set starting set */
6852
6531
  make_sets_invisible(&sets);      /* Hide previus sets */
6853
6532
  used_sets=-1;
6854
6533
  word_states=make_new_set(&sets);    /* Start of new word */
6855
6534
  start_states=make_new_set(&sets);    /* This is first state */
6856
 
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
 
6535
  if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6857
6536
  {
6858
6537
    free_sets(&sets);
6859
 
    free(found_set);
 
6538
    my_free(found_set,MYF(0));
6860
6539
    return(0);
6861
6540
  }
6862
6541
 
6915
6594
          follow_ptr->chr = '\v';
6916
6595
          break;
6917
6596
        default:
6918
 
          follow_ptr->chr = (unsigned char) *pos;
 
6597
          follow_ptr->chr = (uchar) *pos;
6919
6598
          break;
6920
6599
        }
6921
6600
      }
6922
6601
      else
6923
 
        follow_ptr->chr= (unsigned char) *pos;
 
6602
        follow_ptr->chr= (uchar) *pos;
6924
6603
      follow_ptr->table_offset=i;
6925
6604
      follow_ptr->len= ++len;
6926
6605
      follow_ptr++;
6929
6608
    follow_ptr->table_offset=i;
6930
6609
    follow_ptr->len=len;
6931
6610
    follow_ptr++;
6932
 
    states+=(uint32_t) len+1;
 
6611
    states+=(uint) len+1;
6933
6612
  }
6934
6613
 
6935
6614
 
6966
6645
    /* Mark word_chars used if \b is in state */
6967
6646
    if (used_chars[SPACE_CHAR])
6968
6647
      for (pos= word_end_chars ; *pos ; pos++)
6969
 
        used_chars[(int) (unsigned char) *pos] = 1;
 
6648
        used_chars[(int) (uchar) *pos] = 1;
6970
6649
 
6971
6650
    /* Handle other used characters */
6972
6651
    for (chr= 0 ; chr < 256 ; chr++)
7045
6724
 
7046
6725
  /* Alloc replace structure for the replace-state-machine */
7047
6726
 
7048
 
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
7049
 
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
7050
 
                                 sizeof(char *)*count+result_len)))
 
6727
  if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+
 
6728
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
 
6729
                                    sizeof(char *)*count+result_len,
 
6730
                                    MYF(MY_WME | MY_ZEROFILL))))
7051
6731
  {
7052
 
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
7053
 
                       sizeof(REPLACE_STRING)*(found_sets+1)+
7054
 
                       sizeof(char *)*count+result_len);
7055
6732
    rep_str=(REPLACE_STRING*) (replace+sets.count);
7056
6733
    to_array= (char **) (rep_str+found_sets+1);
7057
6734
    to_pos=(char *) (to_array+count);
7058
6735
    for (i=0 ; i < count ; i++)
7059
6736
    {
7060
6737
      to_array[i]=to_pos;
7061
 
      to_pos=strcpy(to_pos,to[i])+strlen(to[i])+1;
 
6738
      to_pos=stpcpy(to_pos,to[i])+1;
7062
6739
    }
7063
6740
    rep_str[0].found=1;
7064
6741
    rep_str[0].replace_string=0;
7080
6757
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7081
6758
    }
7082
6759
  }
7083
 
  free(follow);
 
6760
  my_free(follow,MYF(0));
7084
6761
  free_sets(&sets);
7085
 
  free(found_set);
 
6762
  my_free(found_set,MYF(0));
7086
6763
  return(replace);
7087
6764
}
7088
6765
 
7089
6766
 
7090
 
int init_sets(REP_SETS *sets,uint32_t states)
 
6767
int init_sets(REP_SETS *sets,uint states)
7091
6768
{
7092
6769
  memset(sets, 0, sizeof(*sets));
7093
6770
  sets->size_of_bits=((states+7)/8);
7094
 
  if (!(sets->set_buffer=(REP_SET*) malloc(sizeof(REP_SET)*SET_MALLOC_HUNC)))
 
6771
  if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
 
6772
                                              MYF(MY_WME))))
7095
6773
    return 1;
7096
 
  if (!(sets->bit_buffer=(uint*) malloc(sizeof(uint32_t)*sets->size_of_bits*
7097
 
                                        SET_MALLOC_HUNC)))
 
6774
  if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
 
6775
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
7098
6776
  {
7099
 
    free(sets->set);
 
6777
    my_free(sets->set,MYF(0));
7100
6778
    return 1;
7101
6779
  }
7102
6780
  return 0;
7113
6791
 
7114
6792
REP_SET *make_new_set(REP_SETS *sets)
7115
6793
{
7116
 
  uint32_t i,count,*bit_buffer;
 
6794
  uint i,count,*bit_buffer;
7117
6795
  REP_SET *set;
7118
6796
  if (sets->extra)
7119
6797
  {
7120
6798
    sets->extra--;
7121
6799
    set=sets->set+ sets->count++;
7122
 
    memset(set->bits, 0, sizeof(uint32_t)*sets->size_of_bits);
 
6800
    memset(set->bits, 0, sizeof(uint)*sets->size_of_bits);
7123
6801
    memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
7124
6802
    set->found_offset=0;
7125
6803
    set->found_len=0;
7128
6806
    return set;
7129
6807
  }
7130
6808
  count=sets->count+sets->invisible+SET_MALLOC_HUNC;
7131
 
  if (!(set=(REP_SET*) realloc((unsigned char*) sets->set_buffer,
7132
 
                                  sizeof(REP_SET)*count)))
 
6809
  if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
 
6810
                                  sizeof(REP_SET)*count,
 
6811
                                  MYF(MY_WME))))
7133
6812
    return 0;
7134
6813
  sets->set_buffer=set;
7135
6814
  sets->set=set+sets->invisible;
7136
 
  if (!(bit_buffer=(uint*) realloc((unsigned char*) sets->bit_buffer,
7137
 
                                   (sizeof(uint32_t)*sets->size_of_bits)*count)))
 
6815
  if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
 
6816
                                      (sizeof(uint)*sets->size_of_bits)*count,
 
6817
                                      MYF(MY_WME))))
7138
6818
    return 0;
7139
6819
  sets->bit_buffer=bit_buffer;
7140
6820
  for (i=0 ; i < count ; i++)
7155
6835
 
7156
6836
void free_sets(REP_SETS *sets)
7157
6837
{
7158
 
  free(sets->set_buffer);
7159
 
  free(sets->bit_buffer);
 
6838
  my_free(sets->set_buffer,MYF(0));
 
6839
  my_free(sets->bit_buffer,MYF(0));
7160
6840
  return;
7161
6841
}
7162
6842
 
7163
 
void internal_set_bit(REP_SET *set, uint32_t bit)
 
6843
void internal_set_bit(REP_SET *set, uint bit)
7164
6844
{
7165
6845
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7166
6846
  return;
7167
6847
}
7168
6848
 
7169
 
void internal_clear_bit(REP_SET *set, uint32_t bit)
 
6849
void internal_clear_bit(REP_SET *set, uint bit)
7170
6850
{
7171
6851
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7172
6852
  return;
7175
6855
 
7176
6856
void or_bits(REP_SET *to,REP_SET *from)
7177
6857
{
7178
 
  register uint32_t i;
 
6858
  register uint i;
7179
6859
  for (i=0 ; i < to->size_of_bits ; i++)
7180
6860
    to->bits[i]|=from->bits[i];
7181
6861
  return;
7184
6864
void copy_bits(REP_SET *to,REP_SET *from)
7185
6865
{
7186
6866
  memcpy(to->bits,from->bits,
7187
 
         (size_t) (sizeof(uint32_t) * to->size_of_bits));
 
6867
         (size_t) (sizeof(uint) * to->size_of_bits));
7188
6868
}
7189
6869
 
7190
6870
int cmp_bits(REP_SET *set1,REP_SET *set2)
7191
6871
{
7192
 
  return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
 
6872
  return memcmp(set1->bits,set2->bits, sizeof(uint) * set1->size_of_bits);
7193
6873
}
7194
6874
 
7195
6875
 
7196
6876
/* Get next set bit from set. */
7197
6877
 
7198
 
int get_next_bit(REP_SET *set,uint32_t lastpos)
 
6878
int get_next_bit(REP_SET *set,uint lastpos)
7199
6879
{
7200
 
  uint32_t pos,*start,*end,bits;
 
6880
  uint pos,*start,*end,bits;
7201
6881
 
7202
6882
  start=set->bits+ ((lastpos+1) / WORD_BIT);
7203
6883
  end=set->bits + set->size_of_bits;
7207
6887
    bits=start[0];
7208
6888
  if (!bits)
7209
6889
    return 0;
7210
 
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
 
6890
  pos=(uint) (start-set->bits)*WORD_BIT;
7211
6891
  while (! (bits & 1))
7212
6892
  {
7213
6893
    bits>>=1;
7222
6902
 
7223
6903
int find_set(REP_SETS *sets,REP_SET *find)
7224
6904
{
7225
 
  uint32_t i;
 
6905
  uint i;
7226
6906
  for (i=0 ; i < sets->count-1 ; i++)
7227
6907
  {
7228
6908
    if (!cmp_bits(sets->set+i,find))
7241
6921
   set->next[] == -1 is reserved for end without replaces.
7242
6922
*/
7243
6923
 
7244
 
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
 
6924
int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
7245
6925
{
7246
6926
  int i;
7247
 
  for (i=0 ; (uint32_t) i < found_sets ; i++)
 
6927
  for (i=0 ; (uint) i < found_sets ; i++)
7248
6928
    if (found_set[i].table_offset == table_offset &&
7249
6929
        found_set[i].found_offset == found_offset)
7250
6930
      return -i-2;
7256
6936
 
7257
6937
/* Return 1 if regexp starts with \b or ends with \b*/
7258
6938
 
7259
 
uint32_t start_at_word(char * pos)
 
6939
uint start_at_word(char * pos)
7260
6940
{
7261
6941
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
7262
6942
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
7263
6943
}
7264
6944
 
7265
 
uint32_t end_of_word(char * pos)
 
6945
uint end_of_word(char * pos)
7266
6946
{
7267
6947
  char * end= strchr(pos, '\0');
7268
6948
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
7278
6958
 
7279
6959
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
7280
6960
{
7281
 
  uint32_t i,length,old_count;
7282
 
  unsigned char *new_pos;
 
6961
  uint i,length,old_count;
 
6962
  uchar *new_pos;
7283
6963
  const char **new_array;
7284
6964
 
7285
6965
 
7286
6966
  if (! pa->typelib.count)
7287
6967
  {
7288
6968
    if (!(pa->typelib.type_names=(const char **)
7289
 
          malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
 
6969
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7290
6970
                     (sizeof(char *)+sizeof(*pa->flag))*
7291
 
                     (sizeof(char *)+sizeof(*pa->flag))))))
 
6971
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
7292
6972
      return(-1);
7293
 
    if (!(pa->str= (unsigned char*) malloc(PS_MALLOC-MALLOC_OVERHEAD)))
 
6973
    if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
 
6974
                                      MYF(MY_WME))))
7294
6975
    {
7295
 
      free((char*) pa->typelib.type_names);
 
6976
      my_free((char*) pa->typelib.type_names,MYF(0));
7296
6977
      return (-1);
7297
6978
    }
7298
 
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(unsigned char*)+
 
6979
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7299
6980
                                               sizeof(*pa->flag));
7300
 
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
 
6981
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7301
6982
    pa->length=0;
7302
6983
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
7303
6984
    pa->array_allocs=1;
7304
6985
  }
7305
 
  length=(uint32_t) strlen(name)+1;
 
6986
  length=(uint) strlen(name)+1;
7306
6987
  if (pa->length+length >= pa->max_length)
7307
6988
  {
7308
 
    if (!(new_pos= (unsigned char*)realloc((unsigned char*)pa->str,
7309
 
                                           (size_t)(pa->max_length+PS_MALLOC))))
 
6989
    if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
 
6990
                                       (uint) (pa->max_length+PS_MALLOC),
 
6991
                                       MYF(MY_WME))))
7310
6992
      return(1);
7311
6993
    if (new_pos != pa->str)
7312
6994
    {
7313
 
      ptrdiff_t diff= PTR_BYTE_DIFF(new_pos,pa->str);
 
6995
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
7314
6996
      for (i=0 ; i < pa->typelib.count ; i++)
7315
6997
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
7316
6998
                                              char*);
7320
7002
  }
7321
7003
  if (pa->typelib.count >= pa->max_count-1)
7322
7004
  {
7323
 
    size_t len;
 
7005
    int len;
7324
7006
    pa->array_allocs++;
7325
7007
    len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7326
 
    if (!(new_array=
7327
 
         (const char **)realloc((unsigned char*) pa->typelib.type_names,
7328
 
                                 len/
7329
 
                                  (sizeof(unsigned char*)+sizeof(*pa->flag))*
7330
 
                                  (sizeof(unsigned char*)+sizeof(*pa->flag)))))
 
7008
    if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
 
7009
                                               (uint) len/
 
7010
                                               (sizeof(uchar*)+sizeof(*pa->flag))*
 
7011
                                               (sizeof(uchar*)+sizeof(*pa->flag)),
 
7012
                                               MYF(MY_WME))))
7331
7013
      return(1);
7332
7014
    pa->typelib.type_names=new_array;
7333
7015
    old_count=pa->max_count;
7334
 
    pa->max_count=len/(sizeof(unsigned char*) + sizeof(*pa->flag));
7335
 
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
 
7016
    pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
 
7017
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7336
7018
    memcpy(pa->flag, pa->typelib.type_names+old_count,
7337
7019
           old_count*sizeof(*pa->flag));
7338
7020
  }
7339
7021
  pa->flag[pa->typelib.count]=0;      /* Reset flag */
7340
7022
  pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
7341
 
  pa->typelib.type_names[pa->typelib.count]= NULL;  /* Put end-mark */
7342
 
  strcpy((char*) pa->str+pa->length,name);
 
7023
  pa->typelib.type_names[pa->typelib.count]= NullS;  /* Put end-mark */
 
7024
  VOID(stpcpy((char*) pa->str+pa->length,name));
7343
7025
  pa->length+=length;
7344
7026
  return(0);
7345
7027
} /* insert_pointer_name */
7352
7034
  if (pa->typelib.count)
7353
7035
  {
7354
7036
    pa->typelib.count=0;
7355
 
    free((char*) pa->typelib.type_names);
 
7037
    my_free((char*) pa->typelib.type_names,MYF(0));
7356
7038
    pa->typelib.type_names=0;
7357
 
    free(pa->str);
 
7039
    my_free(pa->str,MYF(0));
7358
7040
  }
7359
7041
} /* free_pointer_array */
7360
7042
 
7395
7077
  replace_append_mem(ds, val, strlen(val));
7396
7078
}
7397
7079
 
7398
 
/* Append uint32_t to ds, with optional replace */
7399
 
void replace_append_uint(string *ds, uint32_t val)
 
7080
/* Append uint to ds, with optional replace */
 
7081
void replace_append_uint(string *ds, uint val)
7400
7082
{
7401
 
  ostringstream buff;
7402
 
  buff << val;
7403
 
  replace_append_mem(ds, buff.str().c_str(), buff.str().size());
 
7083
  char buff[22]; /* This should be enough for any int */
 
7084
  char *end= int64_t10_to_str(val, buff, 10);
 
7085
  replace_append_mem(ds, buff, end - buff);
7404
7086
 
7405
7087
}
7406
7088
 
7421
7103
 
7422
7104
void append_sorted(string* ds, string *ds_input)
7423
7105
{
7424
 
  priority_queue<string, vector<string>, greater<string> > lines;
 
7106
  priority_queue<string> lines;
7425
7107
 
7426
7108
  if (ds_input->empty())
7427
7109
    return;  /* No input */
7432
7114
  if (eol_pos == string::npos)
7433
7115
    return; // We should have at least one header here
7434
7116
 
7435
 
  ds->append(ds_input->substr(0, eol_pos+1));
 
7117
  ds->append(ds_input->substr(0, eol_pos));
7436
7118
 
7437
7119
  unsigned long start_pos= eol_pos+1;
7438
7120
 
7441
7123
 
7442
7124
    eol_pos= ds_input->find_first_of('\n', start_pos);
7443
7125
    /* Find end of line */
7444
 
    lines.push(ds_input->substr(start_pos, eol_pos-start_pos+1));
 
7126
    lines.push(ds_input->substr(start_pos, eol_pos-start_pos));
7445
7127
    start_pos= eol_pos+1;
7446
7128
 
7447
7129
  } while ( eol_pos != string::npos);