~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Jay Pipes
  • Date: 2008-09-11 16:03:22 UTC
  • mto: (383.5.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 386.
  • Revision ID: jay@mysql.com-20080911160322-vrl0k1djo6q6ytv1
Removed SQL_MODE variances from comment_table.test and ensured correct error thrown when a comment that is too long was input.  After moving to proto buffer definition for table, the 2048 length will go away.

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/drizzle_time.h"
69
 
#include "drizzled/charset.h"
70
 
#include <drizzled/configmake.h>
71
 
 
72
 
#ifndef DRIZZLE_RETURN_SERVER_GONE
73
 
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
74
 
#endif
75
 
namespace po= boost::program_options;
 
50
#include <vio/violite.h>
 
51
 
 
52
#include "errname.h"
 
53
 
76
54
using namespace std;
77
 
using namespace drizzled;
78
 
 
79
 
extern "C"
80
 
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
81
 
 
82
 
int get_one_option(int optid, const struct option *, char *argument);
83
55
 
84
56
#define MAX_VAR_NAME_LENGTH    256
85
57
#define MAX_COLUMNS            256
 
58
#define MAX_EMBEDDED_SERVER_ARGS 64
86
59
#define MAX_DELIMITER_LENGTH 16
 
60
 
87
61
/* Flags controlling send and reap */
88
62
#define QUERY_SEND_FLAG  1
89
63
#define QUERY_REAP_FLAG  2
90
64
 
91
 
typedef boost::unordered_map<std::string, uint32_t> ErrorCodes;
92
 
ErrorCodes global_error_names;
93
 
 
94
65
enum {
 
66
  OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
95
67
  OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
96
 
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
97
 
  OPT_TESTDIR
 
68
  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
98
69
};
99
70
 
100
71
static int record= 0, opt_sleep= -1;
101
 
static char *opt_pass= NULL;
102
 
const char *unix_sock= NULL;
103
 
static uint32_t opt_port= 0;
104
 
static uint32_t opt_max_connect_retries;
105
 
static bool silent= false, verbose= false;
106
 
static bool opt_mark_progress= false;
107
 
static bool parsing_disabled= false;
 
72
static char *opt_db= 0, *opt_pass= 0;
 
73
const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./";
 
74
const char *opt_logdir= "";
 
75
const char *opt_include= 0, *opt_charsets_dir;
 
76
static int opt_port= 0;
 
77
static int opt_max_connect_retries;
 
78
static bool opt_compress= 0, silent= 0, verbose= 0;
 
79
static bool debug_info_flag= 0, debug_check_flag= 0;
 
80
static bool tty_password= 0;
 
81
static bool opt_mark_progress= 0;
 
82
static bool parsing_disabled= 0;
108
83
static bool display_result_vertically= false,
109
84
  display_metadata= false, display_result_sorted= false;
110
 
static bool disable_query_log= false, disable_result_log= false;
111
 
static bool disable_warnings= false;
112
 
static bool disable_info= true;
113
 
static bool abort_on_error= true;
114
 
static bool server_initialized= false;
115
 
static bool is_windows= false;
116
 
static bool use_drizzle_protocol= false;
 
85
static bool disable_query_log= 0, disable_result_log= 0;
 
86
static bool disable_warnings= 0;
 
87
static bool disable_info= 1;
 
88
static bool abort_on_error= 1;
 
89
static bool server_initialized= 0;
 
90
static bool is_windows= 0;
 
91
static char **default_argv;
 
92
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
117
93
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
118
94
 
119
 
std::string opt_basedir,
120
 
  opt_charsets_dir,
121
 
  opt_db,
122
 
  opt_host,
123
 
  opt_include,
124
 
  opt_testdir,
125
 
  opt_logdir,
126
 
  password,
127
 
  opt_password,
128
 
  result_file_name,
129
 
  opt_user,
130
 
  opt_protocol;
131
 
 
132
 
static uint32_t start_lineno= 0; /* Start line of current command */
 
95
static uint start_lineno= 0; /* Start line of current command */
 
96
static uint my_end_arg= 0;
133
97
 
134
98
/* Number of lines of the result to include in failure report */
135
 
static uint32_t opt_tail_lines= 0;
 
99
static uint opt_tail_lines= 0;
136
100
 
137
101
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
138
 
static uint32_t delimiter_length= 1;
 
102
static uint delimiter_length= 1;
139
103
 
140
104
static char TMPDIR[FN_REFLEN];
141
105
 
161
125
{
162
126
  FILE* file;
163
127
  const char *file_name;
164
 
  uint32_t lineno; /* Current line in file */
 
128
  uint lineno; /* Current line in file */
165
129
};
166
130
 
167
131
static struct st_test_file file_stack[16];
171
135
 
172
136
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
173
137
 
 
138
static int embedded_server_arg_count=0;
 
139
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
 
140
 
174
141
/*
175
142
  Timer related variables
176
143
  See the timer_output() definition for details
198
165
master_pos_st master_pos;
199
166
 
200
167
/* if set, all results are concated and compared against this file */
 
168
const char *result_file_name= 0;
201
169
 
202
170
typedef struct st_var
203
171
{
215
183
/*Perl/shell-like variable registers */
216
184
VAR var_reg[10];
217
185
 
218
 
 
219
 
boost::unordered_map<string, VAR *> var_hash;
 
186
HASH var_hash;
220
187
 
221
188
struct st_connection
222
189
{
223
 
  drizzle_st *drizzle;
224
 
  drizzle_con_st con;
 
190
  DRIZZLE drizzle;
225
191
  /* Used when creating views and sp, to avoid implicit commit */
226
 
  drizzle_con_st *util_con;
 
192
  DRIZZLE *util_drizzle;
227
193
  char *name;
228
194
};
229
195
struct st_connection connections[128];
261
227
  Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
262
228
  Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
263
229
  Q_START_TIMER, Q_END_TIMER,
264
 
  Q_CHARACTER_SET,
 
230
  Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
265
231
  Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
266
232
  Q_IF,
267
233
  Q_DISABLE_PARSING, Q_ENABLE_PARSING,
379
345
  enum match_err_type type;
380
346
  union
381
347
  {
382
 
    uint32_t errnum;
383
 
    char sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE+1];  /* \0 terminated string */
 
348
    uint errnum;
 
349
    char sqlstate[SQLSTATE_LENGTH+1];  /* \0 terminated string */
384
350
  } code;
385
351
};
386
352
 
387
353
struct st_expected_errors
388
354
{
389
355
  struct st_match_err err[10];
390
 
  uint32_t count;
 
356
  uint count;
391
357
};
392
358
static struct st_expected_errors saved_expected_errors;
393
359
 
396
362
  char *query, *query_buf,*first_argument,*last_argument,*end;
397
363
  int first_word_len, query_len;
398
364
  bool abort_on_error;
399
 
  st_expected_errors expected_errors;
400
 
  string require_file;
 
365
  struct st_expected_errors expected_errors;
 
366
  char require_file[FN_REFLEN];
401
367
  enum enum_commands type;
402
 
 
403
 
  st_command()
404
 
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
405
 
      end(NULL), first_word_len(0), query_len(0), abort_on_error(false),
406
 
      require_file(""), type(Q_CONNECTION)
407
 
  {
408
 
    memset(&expected_errors, 0, sizeof(st_expected_errors));
409
 
  }
410
 
 
411
 
  ~st_command()
412
 
  {
413
 
    if (query_buf != NULL)
414
 
    {
415
 
      free(query_buf);
416
 
    }
417
 
  }
418
368
};
419
369
 
420
370
TYPELIB command_typelib= {array_elements(command_names),"",
438
388
VAR* var_from_env(const char *, const char *);
439
389
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
440
390
              int val_len);
441
 
void var_free(pair<string, VAR*> v);
 
391
void var_free(void* v);
442
392
VAR* var_get(const char *var_name, const char** var_name_end,
443
393
             bool raw, bool ignore_not_existing);
444
394
void eval_expr(VAR* v, const char *p, const char** p_end);
445
 
bool match_delimiter(int c, const char *delim, uint32_t length);
 
395
bool match_delimiter(int c, const char *delim, uint length);
446
396
void dump_result_to_reject_file(char *buf, int size);
447
397
void dump_result_to_log_file(const char *buf, int size);
448
398
void dump_warning_messages(void);
455
405
 
456
406
/* For replace_column */
457
407
static char *replace_column[MAX_COLUMNS];
458
 
static uint32_t max_replace_column= 0;
 
408
static uint max_replace_column= 0;
459
409
void do_get_replace_column(struct st_command*);
460
410
void free_replace_column(void);
461
411
 
480
430
void replace_append_mem(string *ds, const char *val,
481
431
                        int len);
482
432
void replace_append(string *ds, const char *val);
483
 
void replace_append_uint(string *ds, uint32_t val);
 
433
void replace_append_uint(string *ds, uint val);
484
434
void append_sorted(string* ds, string* ds_input);
485
435
 
486
436
void handle_error(struct st_command*,
489
439
void handle_no_error(struct st_command*);
490
440
 
491
441
 
 
442
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
 
443
 
492
444
void do_eval(string *query_eval, const char *query,
493
445
             const char *query_end, bool pass_through_escape_chars)
494
446
{
555
507
  @param append string to be appended.
556
508
  @param ... Optional. Additional string(s) to be appended.
557
509
 
558
 
  @note The final argument in the list must be NULL even if no additional
 
510
  @note The final argument in the list must be NullS even if no additional
559
511
  options are passed.
560
512
*/
561
513
 
562
 
static void append_os_quoted(string *str, const char *append, ...)
 
514
void append_os_quoted(string *str, const char *append, ...)
563
515
{
564
516
  const char *quote_str= "\'";
565
 
  const uint32_t  quote_len= 1;
 
517
  const uint  quote_len= 1;
566
518
 
567
519
  va_list dirty_text;
568
520
 
569
521
  str->append(quote_str, quote_len); /* Leading quote */
570
522
  va_start(dirty_text, append);
571
 
  while (append != NULL)
 
523
  while (append != NullS)
572
524
  {
573
525
    const char  *cur_pos= append;
574
526
    const char *next_pos= cur_pos;
581
533
      str->append(quote_str, quote_len);
582
534
      cur_pos= next_pos + 1;
583
535
    }
584
 
    str->append(cur_pos);
 
536
    str->append(cur_pos, next_pos - cur_pos);
585
537
    append= va_arg(dirty_text, char *);
586
538
  }
587
539
  va_end(dirty_text);
602
554
 
603
555
*/
604
556
 
605
 
static void show_query(drizzle_con_st *con, const char* query)
 
557
static void show_query(DRIZZLE *drizzle, const char* query)
606
558
{
607
 
  drizzle_result_st res;
608
 
  drizzle_return_t ret;
609
 
 
610
 
  if (!con)
 
559
  DRIZZLE_RES* res;
 
560
 
 
561
 
 
562
  if (!drizzle)
611
563
    return;
612
564
 
613
 
  if (drizzle_query_str(con, &res, query, &ret) == NULL ||
614
 
      ret != DRIZZLE_RETURN_OK)
 
565
  if (drizzle_query(drizzle, query))
615
566
  {
616
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
617
 
    {
618
 
      log_msg("Error running query '%s': %d %s",
619
 
              query, drizzle_result_error_code(&res),
620
 
              drizzle_result_error(&res));
621
 
      drizzle_result_free(&res);
622
 
    }
623
 
    else
624
 
    {
625
 
      log_msg("Error running query '%s': %d %s",
626
 
              query, ret, drizzle_con_error(con));
627
 
    }
 
567
    log_msg("Error running query '%s': %d %s",
 
568
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
628
569
    return;
629
570
  }
630
571
 
631
 
  if (drizzle_result_column_count(&res) == 0 ||
632
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
572
  if ((res= drizzle_store_result(drizzle)) == NULL)
633
573
  {
634
574
    /* No result set returned */
635
 
    drizzle_result_free(&res);
636
575
    return;
637
576
  }
638
577
 
639
578
  {
640
 
    drizzle_row_t row;
 
579
    DRIZZLE_ROW row;
641
580
    unsigned int i;
642
581
    unsigned int row_num= 0;
643
 
    unsigned int num_fields= drizzle_result_column_count(&res);
644
 
    drizzle_column_st *column;
 
582
    unsigned int num_fields= drizzle_num_fields(res);
 
583
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
645
584
 
646
585
    fprintf(stderr, "=== %s ===\n", query);
647
 
    while ((row= drizzle_row_next(&res)))
 
586
    while ((row= drizzle_fetch_row(res)))
648
587
    {
649
 
      size_t *lengths= drizzle_row_field_sizes(&res);
 
588
      uint32_t *lengths= drizzle_fetch_lengths(res);
650
589
      row_num++;
651
590
 
652
591
      fprintf(stderr, "---- %d. ----\n", row_num);
653
 
      drizzle_column_seek(&res, 0);
654
592
      for(i= 0; i < num_fields; i++)
655
593
      {
656
 
        column= drizzle_column_next(&res);
657
594
        fprintf(stderr, "%s\t%.*s\n",
658
 
                drizzle_column_name(column),
 
595
                fields[i].name,
659
596
                (int)lengths[i], row[i] ? row[i] : "NULL");
660
597
      }
661
598
    }
663
600
      fprintf(stderr, "=");
664
601
    fprintf(stderr, "\n\n");
665
602
  }
666
 
  drizzle_result_free(&res);
 
603
  drizzle_free_result(res);
667
604
 
668
605
  return;
669
606
}
682
619
 
683
620
*/
684
621
 
685
 
static void show_warnings_before_error(drizzle_con_st *con)
 
622
static void show_warnings_before_error(DRIZZLE *drizzle)
686
623
{
687
 
  drizzle_result_st res;
688
 
  drizzle_return_t ret;
 
624
  DRIZZLE_RES* res;
689
625
  const char* query= "SHOW WARNINGS";
690
626
 
691
 
  if (!con)
 
627
 
 
628
  if (!drizzle)
692
629
    return;
693
630
 
694
 
  if (drizzle_query_str(con, &res, query, &ret) == NULL ||
695
 
      ret != DRIZZLE_RETURN_OK)
 
631
  if (drizzle_query(drizzle, query))
696
632
  {
697
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
698
 
    {
699
 
      log_msg("Error running query '%s': %d %s",
700
 
              query, drizzle_result_error_code(&res),
701
 
              drizzle_result_error(&res));
702
 
      drizzle_result_free(&res);
703
 
    }
704
 
    else
705
 
    {
706
 
      log_msg("Error running query '%s': %d %s",
707
 
              query, ret, drizzle_con_error(con));
708
 
    }
 
633
    log_msg("Error running query '%s': %d %s",
 
634
            query, drizzle_errno(drizzle), drizzle_error(drizzle));
709
635
    return;
710
636
  }
711
637
 
712
 
  if (drizzle_result_column_count(&res) == 0 ||
713
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
638
  if ((res= drizzle_store_result(drizzle)) == NULL)
714
639
  {
715
640
    /* No result set returned */
716
 
    drizzle_result_free(&res);
717
641
    return;
718
642
  }
719
643
 
720
 
  if (drizzle_result_row_count(&res) <= 1)
 
644
  if (drizzle_num_rows(res) <= 1)
721
645
  {
722
646
    /* Don't display the last row, it's "last error" */
723
647
  }
724
648
  else
725
649
  {
726
 
    drizzle_row_t row;
 
650
    DRIZZLE_ROW row;
727
651
    unsigned int row_num= 0;
728
 
    unsigned int num_fields= drizzle_result_column_count(&res);
 
652
    unsigned int num_fields= drizzle_num_fields(res);
729
653
 
730
654
    fprintf(stderr, "\nWarnings from just before the error:\n");
731
 
    while ((row= drizzle_row_next(&res)))
 
655
    while ((row= drizzle_fetch_row(res)))
732
656
    {
733
657
      uint32_t i;
734
 
      size_t *lengths= drizzle_row_field_sizes(&res);
 
658
      uint32_t *lengths= drizzle_fetch_lengths(res);
735
659
 
736
 
      if (++row_num >= drizzle_result_row_count(&res))
 
660
      if (++row_num >= drizzle_num_rows(res))
737
661
      {
738
662
        /* Don't display the last row, it's "last error" */
739
663
        break;
747
671
      fprintf(stderr, "\n");
748
672
    }
749
673
  }
750
 
  drizzle_result_free(&res);
 
674
  drizzle_free_result(res);
751
675
 
752
676
  return;
753
677
}
780
704
  for (i= 0; i < num_args; i++)
781
705
  {
782
706
    const struct command_arg *arg= &args[i];
783
 
    arg->ds->clear();
784
707
 
785
 
    bool known_arg_type= true;
786
708
    switch (arg->type) {
787
709
      /* A string */
788
710
    case ARG_STRING:
817
739
      break;
818
740
 
819
741
    default:
820
 
      known_arg_type= false;
 
742
      assert("Unknown argument type");
821
743
      break;
822
744
    }
823
 
    assert(known_arg_type);
824
745
 
825
746
    /* Check required arg */
826
747
    if (arg->ds->length() == 0 && arg->required)
841
762
}
842
763
 
843
764
 
844
 
static void handle_command_error(struct st_command *command, uint32_t error)
 
765
static void handle_command_error(struct st_command *command, uint error)
845
766
{
846
767
 
847
768
  if (error != 0)
848
769
  {
849
 
    uint32_t i;
 
770
    uint i;
850
771
 
851
772
    if (command->abort_on_error)
852
773
      die("command \"%.*s\" failed with error %d",
876
797
 
877
798
static void close_connections(void)
878
799
{
 
800
 
879
801
  for (--next_con; next_con >= connections; --next_con)
880
802
  {
881
 
    if (next_con->drizzle != NULL)
882
 
    {
883
 
      drizzle_free(next_con->drizzle);
884
 
      next_con->drizzle= NULL;
885
 
    }
886
 
    free(next_con->name);
 
803
    drizzle_close(&next_con->drizzle);
 
804
    if (next_con->util_drizzle)
 
805
      drizzle_close(next_con->util_drizzle);
 
806
    my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
887
807
  }
888
808
  return;
889
809
}
896
816
  {
897
817
    if (cur_file->file && cur_file->file != stdin)
898
818
    {
899
 
      fclose(cur_file->file);
 
819
      my_fclose(cur_file->file, MYF(0));
900
820
    }
901
 
    free((unsigned char*) cur_file->file_name);
 
821
    my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
902
822
    cur_file->file_name= 0;
903
823
  }
904
824
  return;
907
827
 
908
828
static void free_used_memory(void)
909
829
{
910
 
  uint32_t i;
 
830
  uint i;
911
831
 
912
832
 
913
833
  close_connections();
914
834
  close_files();
915
 
  for_each(var_hash.begin(), var_hash.end(), var_free);
916
 
  var_hash.clear();
 
835
  hash_free(&var_hash);
917
836
 
918
 
  vector<st_command *>::iterator iter;
 
837
  vector<struct st_command *>::iterator iter;
919
838
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
920
839
  {
921
 
    struct st_command * q_line= *iter;
922
 
    delete q_line;
 
840
    struct st_command * q_line= *(iter.base());
 
841
    if (q_line->query_buf != NULL)
 
842
    {
 
843
      free(q_line->query_buf);
 
844
    }
 
845
    free(q_line);
923
846
  }
924
847
 
925
848
  for (i= 0; i < 10; i++)
926
849
  {
927
850
    if (var_reg[i].alloced_len)
928
 
      free(var_reg[i].str_val);
 
851
      my_free(var_reg[i].str_val, MYF(MY_WME));
929
852
  }
 
853
  while (embedded_server_arg_count > 1)
 
854
    my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
930
855
 
931
856
  free_all_replace();
932
 
  free(opt_pass);
 
857
  my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
 
858
  free_defaults(default_argv);
 
859
 
 
860
  /* Only call drizzle_server_end if drizzle_server_init has been called */
 
861
  if (server_initialized)
 
862
    drizzle_server_end();
933
863
 
934
864
  return;
935
865
}
938
868
static void cleanup_and_exit(int exit_code)
939
869
{
940
870
  free_used_memory();
941
 
  internal::my_end();
 
871
  my_end(my_end_arg);
942
872
 
943
873
  if (!silent) {
944
874
    switch (exit_code) {
1011
941
  }
1012
942
 
1013
943
  /* Dump the result that has been accumulated so far to .log file */
1014
 
  if (! result_file_name.empty() && ds_res.length())
 
944
  if (result_file_name && ds_res.length())
1015
945
    dump_result_to_log_file(ds_res.c_str(), ds_res.length());
1016
946
 
1017
947
  /* Dump warning messages */
1018
 
  if (! result_file_name.empty() && ds_warning_messages.length())
 
948
  if (result_file_name && ds_warning_messages.length())
1019
949
    dump_warning_messages();
1020
950
 
1021
951
  /*
1023
953
    been produced prior to the error
1024
954
  */
1025
955
  if (cur_con)
1026
 
    show_warnings_before_error(&cur_con->con);
 
956
    show_warnings_before_error(&cur_con->drizzle);
1027
957
 
1028
958
  cleanup_and_exit(1);
1029
959
}
1148
1078
static void cat_file(string* ds, const char* filename)
1149
1079
{
1150
1080
  int fd;
1151
 
  uint32_t len;
 
1081
  uint len;
1152
1082
  char buff[512];
1153
1083
 
1154
 
  if ((fd= internal::my_open(filename, O_RDONLY, MYF(0))) < 0)
 
1084
  if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
1155
1085
    die("Failed to open file '%s'", filename);
1156
 
  while((len= internal::my_read(fd, (unsigned char*)&buff,
 
1086
  while((len= my_read(fd, (uchar*)&buff,
1157
1087
                      sizeof(buff), MYF(0))) > 0)
1158
1088
  {
1159
1089
    char *p= buff, *start= buff;
1175
1105
    /* Output any chars that might be left */
1176
1106
    ds->append(start, p-start);
1177
1107
  }
1178
 
  internal::my_close(fd, MYF(0));
 
1108
  my_close(fd, MYF(0));
1179
1109
}
1180
1110
 
1181
1111
 
1230
1160
  string ds_cmdline;
1231
1161
 
1232
1162
 
1233
 
  append_os_quoted(&ds_cmdline, tool_path, NULL);
 
1163
  append_os_quoted(&ds_cmdline, tool_path);
1234
1164
  ds_cmdline.append(" ");
1235
1165
 
1236
1166
  va_start(args, result);
1239
1169
  {
1240
1170
    /* Options should be os quoted */
1241
1171
    if (strncmp(arg, "--", 2) == 0)
1242
 
      append_os_quoted(&ds_cmdline, arg, NULL);
 
1172
      append_os_quoted(&ds_cmdline, arg, NullS);
1243
1173
    else
1244
1174
      ds_cmdline.append(arg);
1245
1175
    ds_cmdline.append(" ");
1280
1210
               "2>&1",
1281
1211
               NULL) > 1) /* Most "diff" tools return >1 if error */
1282
1212
  {
 
1213
    ds_tmp= "";
1283
1214
 
1284
1215
    /* Fallback to context diff with "diff -c" */
1285
1216
    if (run_tool("diff",
1294
1225
        Fallback to dump both files to result file and inform
1295
1226
        about installing "diff"
1296
1227
      */
1297
 
      ds_tmp.clear();
 
1228
      ds_tmp= "";
1298
1229
 
1299
1230
      ds_tmp.append(
1300
1231
                    "\n"
1351
1282
 
1352
1283
*/
1353
1284
 
1354
 
static int compare_files2(int fd, const char* filename2)
 
1285
static int compare_files2(File fd, const char* filename2)
1355
1286
{
1356
1287
  int error= RESULT_OK;
1357
 
  int fd2;
1358
 
  uint32_t len, len2;
 
1288
  File fd2;
 
1289
  uint len, len2;
1359
1290
  char buff[512], buff2[512];
1360
 
  const char *fname= filename2;
1361
 
  string tmpfile;
1362
1291
 
1363
 
  if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
 
1292
  if ((fd2= my_open(filename2, O_RDONLY, MYF(0))) < 0)
1364
1293
  {
1365
 
    internal::my_close(fd, MYF(0));
1366
 
    if (! opt_testdir.empty())
1367
 
    {
1368
 
      tmpfile= opt_testdir;
1369
 
      if (tmpfile[tmpfile.length()] != '/')
1370
 
        tmpfile.append("/");
1371
 
      tmpfile.append(filename2);
1372
 
      fname= tmpfile.c_str();
1373
 
    }
1374
 
    if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
1375
 
    {
1376
 
      internal::my_close(fd, MYF(0));
1377
 
    
1378
 
      die("Failed to open second file: '%s'", fname);
1379
 
    }
 
1294
    my_close(fd, MYF(0));
 
1295
    die("Failed to open second file: '%s'", filename2);
1380
1296
  }
1381
 
  while((len= internal::my_read(fd, (unsigned char*)&buff,
 
1297
  while((len= my_read(fd, (uchar*)&buff,
1382
1298
                      sizeof(buff), MYF(0))) > 0)
1383
1299
  {
1384
 
    if ((len2= internal::my_read(fd2, (unsigned char*)&buff2,
 
1300
    if ((len2= my_read(fd2, (uchar*)&buff2,
1385
1301
                       sizeof(buff2), MYF(0))) < len)
1386
1302
    {
1387
1303
      /* File 2 was smaller */
1401
1317
      break;
1402
1318
    }
1403
1319
  }
1404
 
  if (!error && internal::my_read(fd2, (unsigned char*)&buff2,
 
1320
  if (!error && my_read(fd2, (uchar*)&buff2,
1405
1321
                        sizeof(buff2), MYF(0)) > 0)
1406
1322
  {
1407
1323
    /* File 1 was smaller */
1408
1324
    error= RESULT_LENGTH_MISMATCH;
1409
1325
  }
1410
1326
 
1411
 
  internal::my_close(fd2, MYF(0));
 
1327
  my_close(fd2, MYF(0));
1412
1328
 
1413
1329
  return error;
1414
1330
}
1429
1345
 
1430
1346
static int compare_files(const char* filename1, const char* filename2)
1431
1347
{
1432
 
  int fd;
 
1348
  File fd;
1433
1349
  int error;
1434
1350
 
1435
 
  if ((fd= internal::my_open(filename1, O_RDONLY, MYF(0))) < 0)
 
1351
  if ((fd= my_open(filename1, O_RDONLY, MYF(0))) < 0)
1436
1352
    die("Failed to open first file: '%s'", filename1);
1437
1353
 
1438
1354
  error= compare_files2(fd, filename2);
1439
1355
 
1440
 
  internal::my_close(fd, MYF(0));
 
1356
  my_close(fd, MYF(0));
1441
1357
 
1442
1358
  return error;
1443
1359
}
1458
1374
static int string_cmp(string* ds, const char *fname)
1459
1375
{
1460
1376
  int error;
1461
 
  int fd;
 
1377
  File fd;
1462
1378
  char temp_file_path[FN_REFLEN];
1463
1379
 
1464
 
  if ((fd= internal::create_temp_file(temp_file_path, TMPDIR,
1465
 
                            "tmp", MYF(MY_WME))) < 0)
 
1380
  if ((fd= create_temp_file(temp_file_path, NULL,
 
1381
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
 
1382
                            MYF(MY_WME))) < 0)
1466
1383
    die("Failed to create temporary file for ds");
1467
1384
 
1468
1385
  /* Write ds to temporary file and set file pos to beginning*/
1469
 
  if (internal::my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
 
1386
  if (my_write(fd, (uchar *) ds->c_str(), ds->length(),
1470
1387
               MYF(MY_FNABP | MY_WME)) ||
1471
 
      lseek(fd, 0, SEEK_SET) == MY_FILEPOS_ERROR)
 
1388
      my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1472
1389
  {
1473
 
    internal::my_close(fd, MYF(0));
 
1390
    my_close(fd, MYF(0));
1474
1391
    /* Remove the temporary file */
1475
 
    internal::my_delete(temp_file_path, MYF(0));
 
1392
    my_delete(temp_file_path, MYF(0));
1476
1393
    die("Failed to write file '%s'", temp_file_path);
1477
1394
  }
1478
1395
 
1479
1396
  error= compare_files2(fd, fname);
1480
1397
 
1481
 
  internal::my_close(fd, MYF(0));
 
1398
  my_close(fd, MYF(0));
1482
1399
  /* Remove the temporary file */
1483
 
  internal::my_delete(temp_file_path, MYF(0));
 
1400
  my_delete(temp_file_path, MYF(0));
1484
1401
 
1485
1402
  return(error);
1486
1403
}
1503
1420
  const char* mess= "Result content mismatch\n";
1504
1421
 
1505
1422
 
1506
 
  assert(result_file_name.c_str());
1507
 
 
1508
 
  if (access(result_file_name.c_str(), F_OK) != 0)
1509
 
    die("The specified result file does not exist: '%s'", result_file_name.c_str());
1510
 
 
1511
 
  switch (string_cmp(ds, result_file_name.c_str())) {
 
1423
  assert(result_file_name);
 
1424
 
 
1425
  if (access(result_file_name, F_OK) != 0)
 
1426
    die("The specified result file does not exist: '%s'", result_file_name);
 
1427
 
 
1428
  switch (string_cmp(ds, result_file_name)) {
1512
1429
  case RESULT_OK:
1513
1430
    break; /* ok */
1514
1431
  case RESULT_LENGTH_MISMATCH:
1522
1439
    */
1523
1440
    char reject_file[FN_REFLEN];
1524
1441
    size_t reject_length;
1525
 
    internal::dirname_part(reject_file, result_file_name.c_str(), &reject_length);
 
1442
    dirname_part(reject_file, result_file_name, &reject_length);
1526
1443
 
1527
1444
    if (access(reject_file, W_OK) == 0)
1528
1445
    {
1529
1446
      /* Result file directory is writable, save reject file there */
1530
 
      internal::fn_format(reject_file, result_file_name.c_str(), NULL,
 
1447
      fn_format(reject_file, result_file_name, NULL,
1531
1448
                ".reject", MY_REPLACE_EXT);
1532
1449
    }
1533
1450
    else
1534
1451
    {
1535
1452
      /* Put reject file in opt_logdir */
1536
 
      internal::fn_format(reject_file, result_file_name.c_str(), opt_logdir.c_str(),
 
1453
      fn_format(reject_file, result_file_name, opt_logdir,
1537
1454
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1538
1455
    }
1539
1456
    str_to_file(reject_file, ds->c_str(), ds->length());
1540
1457
 
1541
1458
    ds->erase(); /* Don't create a .log file */
1542
1459
 
1543
 
    show_diff(NULL, result_file_name.c_str(), reject_file);
1544
 
    die("%s",mess);
 
1460
    show_diff(NULL, result_file_name, reject_file);
 
1461
    die(mess);
1545
1462
    break;
1546
1463
  }
1547
1464
  default: /* impossible */
1567
1484
 
1568
1485
*/
1569
1486
 
1570
 
static void check_require(string* ds, const string &fname)
 
1487
static void check_require(string* ds, const char *fname)
1571
1488
{
1572
1489
 
1573
1490
 
1574
 
  if (string_cmp(ds, fname.c_str()))
 
1491
  if (string_cmp(ds, fname))
1575
1492
  {
1576
1493
    char reason[FN_REFLEN];
1577
 
    internal::fn_format(reason, fname.c_str(), "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
 
1494
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1578
1495
    abort_not_supported_test("Test requires: '%s'", reason);
1579
1496
  }
1580
1497
  return;
1625
1542
}
1626
1543
 
1627
1544
 
 
1545
static uchar *get_var_key(const uchar* var, size_t *len,
 
1546
                          bool __attribute__((unused)) t)
 
1547
{
 
1548
  register char* key;
 
1549
  key = ((VAR*)var)->name;
 
1550
  *len = ((VAR*)var)->name_len;
 
1551
  return (uchar*)key;
 
1552
}
 
1553
 
1628
1554
 
1629
1555
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1630
1556
              int val_len)
1636
1562
  if (!val_len && val)
1637
1563
    val_len = strlen(val) ;
1638
1564
  val_alloc_len = val_len + 16; /* room to grow */
1639
 
  if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
1640
 
                                               + name_len+1)))
 
1565
  if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
 
1566
                                                  + name_len+1, MYF(MY_WME))))
1641
1567
    die("Out of memory");
1642
1568
 
1643
1569
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1644
1570
  tmp_var->alloced = (v == 0);
1645
1571
 
1646
 
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
 
1572
  if (!(tmp_var->str_val = (char *)my_malloc(val_alloc_len+1, MYF(MY_WME))))
1647
1573
    die("Out of memory");
1648
1574
 
1649
1575
  memcpy(tmp_var->name, name, name_len);
1662
1588
}
1663
1589
 
1664
1590
 
1665
 
void var_free(pair<string, VAR *> v)
 
1591
void var_free(void *v)
1666
1592
{
1667
 
  free(v.second->str_val);
1668
 
  free(v.second->env_s);
1669
 
  if (v.second->alloced)
1670
 
    free(v.second);
 
1593
  my_free(((VAR*) v)->str_val, MYF(MY_WME));
 
1594
  my_free(((VAR*) v)->env_s, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
 
1595
  if (((VAR*)v)->alloced)
 
1596
    my_free(v, MYF(MY_WME));
1671
1597
}
1672
1598
 
1673
1599
 
1679
1605
    tmp = def_val;
1680
1606
 
1681
1607
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1682
 
  string var_name(name);
1683
 
  var_hash.insert(make_pair(var_name, v));
 
1608
  my_hash_insert(&var_hash, (uchar*)v);
1684
1609
  return v;
1685
1610
}
1686
1611
 
1697
1622
  if (digit < 0 || digit >= 10)
1698
1623
  {
1699
1624
    const char *save_var_name = var_name, *end;
1700
 
    uint32_t length;
 
1625
    uint length;
1701
1626
    end = (var_name_end) ? *var_name_end : 0;
1702
1627
    while (my_isvar(charset_info,*var_name) && var_name != end)
1703
1628
      var_name++;
1707
1632
        return(0);
1708
1633
      die("Empty variable");
1709
1634
    }
1710
 
    length= (uint32_t) (var_name - save_var_name);
 
1635
    length= (uint) (var_name - save_var_name);
1711
1636
    if (length >= MAX_VAR_NAME_LENGTH)
1712
1637
      die("Too long variable name: %s", save_var_name);
1713
1638
 
1714
 
    string save_var_name_str(save_var_name, length);
1715
 
    boost::unordered_map<string, VAR*>::iterator iter=
1716
 
      var_hash.find(save_var_name_str);
1717
 
    if (iter == var_hash.end())
 
1639
    if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
 
1640
                                 length)))
1718
1641
    {
1719
1642
      char buff[MAX_VAR_NAME_LENGTH+1];
1720
 
      strncpy(buff, save_var_name, length);
1721
 
      buff[length]= '\0';
 
1643
      strmake(buff, save_var_name, length);
1722
1644
      v= var_from_env(buff, "");
1723
1645
    }
1724
 
    else
1725
 
    {
1726
 
      v= (*iter).second;
1727
 
    }
1728
1646
    var_name--;  /* Point at last character */
1729
1647
  }
1730
1648
  else
1749
1667
 
1750
1668
static VAR *var_obtain(const char *name, int len)
1751
1669
{
1752
 
  string var_name(name, len);
1753
 
  boost::unordered_map<string, VAR*>::iterator iter=
1754
 
    var_hash.find(var_name);
1755
 
  if (iter != var_hash.end())
1756
 
    return (*iter).second;
1757
 
  VAR *v = var_init(0, name, len, "", 0);
1758
 
  var_hash.insert(make_pair(var_name, v));
 
1670
  VAR* v;
 
1671
  if ((v = (VAR*)hash_search(&var_hash, (const uchar *) name, len)))
 
1672
    return v;
 
1673
  v = var_init(0, name, len, "", 0);
 
1674
  my_hash_insert(&var_hash, (uchar*)v);
1759
1675
  return v;
1760
1676
}
1761
1677
 
1780
1696
  digit= *var_name - '0';
1781
1697
  if (!(digit < 10 && digit >= 0))
1782
1698
  {
1783
 
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
 
1699
    v= var_obtain(var_name, (uint) (var_name_end - var_name));
1784
1700
  }
1785
1701
  else
1786
1702
    v= var_reg + digit;
1799
1715
    snprintf(buf, sizeof(buf), "%.*s=%.*s",
1800
1716
             v->name_len, v->name,
1801
1717
             v->str_val_len, v->str_val);
1802
 
    if (!(v->env_s= strdup(buf)))
 
1718
    if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
1803
1719
      die("Out of memory");
1804
1720
    putenv(v->env_s);
1805
 
    free(old_env_s);
 
1721
    my_free(old_env_s, MYF(MY_ALLOW_ZERO_PTR));
1806
1722
  }
1807
1723
  return;
1808
1724
}
1824
1740
 
1825
1741
/*
1826
1742
  Store an integer (typically the returncode of the last SQL)
1827
 
  statement in the drizzletest builtin variable $drizzleclient_errno
 
1743
  statement in the drizzletest builtin variable $drizzle_errno
1828
1744
*/
1829
1745
 
1830
1746
static void var_set_errno(int sql_errno)
1831
1747
{
1832
 
  var_set_int("$drizzleclient_errno", sql_errno);
 
1748
  var_set_int("$drizzle_errno", sql_errno);
1833
1749
}
1834
1750
 
1835
1751
 
1836
1752
/*
1837
 
  Update $drizzleclient_get_server_version variable with version
 
1753
  Update $drizzle_get_server_version variable with version
1838
1754
  of the currently connected server
1839
1755
*/
1840
1756
 
1841
 
static void var_set_drizzleclient_get_server_version(drizzle_con_st *con)
 
1757
static void var_set_drizzle_get_server_version(DRIZZLE *drizzle)
1842
1758
{
1843
 
  var_set_int("$drizzle_con_server_version", drizzle_con_server_version_number(con));
 
1759
  var_set_int("$drizzle_get_server_version", drizzle_get_server_version(drizzle));
1844
1760
}
1845
1761
 
1846
1762
 
1871
1787
{
1872
1788
  const char *end = (char*)((query_end && *query_end) ?
1873
1789
                            *query_end : query + strlen(query));
1874
 
  drizzle_result_st res;
1875
 
  drizzle_return_t ret;
1876
 
  drizzle_row_t row;
1877
 
  drizzle_con_st *con= &cur_con->con;
 
1790
  DRIZZLE_RES *res;
 
1791
  DRIZZLE_ROW row;
 
1792
  DRIZZLE *drizzle= &cur_con->drizzle;
1878
1793
  string ds_query;
1879
1794
 
1880
1795
 
1887
1802
  /* Eval the query, thus replacing all environment variables */
1888
1803
  do_eval(&ds_query, query, end, false);
1889
1804
 
1890
 
  if (drizzle_query(con, &res, ds_query.c_str(), ds_query.length(),
1891
 
                    &ret) == NULL ||
1892
 
      ret != DRIZZLE_RETURN_OK)
1893
 
  {
1894
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
1895
 
    {
1896
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
1897
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
1898
 
      drizzle_result_free(&res);
1899
 
    }
1900
 
    else
1901
 
    {
1902
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
1903
 
          drizzle_con_error(con));
1904
 
    }
1905
 
  }
1906
 
  if (drizzle_result_column_count(&res) == 0 ||
1907
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
1805
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
 
1806
    die("Error running query '%s': %d %s", ds_query.c_str(),
 
1807
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
1808
  if (!(res= drizzle_store_result(drizzle)))
1908
1809
    die("Query '%s' didn't return a result set", ds_query.c_str());
1909
1810
 
1910
 
  if ((row= drizzle_row_next(&res)) && row[0])
 
1811
  if ((row= drizzle_fetch_row(res)) && row[0])
1911
1812
  {
1912
1813
    /*
1913
1814
      Concatenate all fields in the first row with tab in between
1915
1816
    */
1916
1817
    string result;
1917
1818
    uint32_t i;
1918
 
    size_t *lengths;
 
1819
    uint32_t *lengths;
1919
1820
 
1920
 
    lengths= drizzle_row_field_sizes(&res);
1921
 
    for (i= 0; i < drizzle_result_column_count(&res); i++)
 
1821
    lengths= drizzle_fetch_lengths(res);
 
1822
    for (i= 0; i < drizzle_num_fields(res); i++)
1922
1823
    {
1923
1824
      if (row[i])
1924
1825
      {
1933
1834
  else
1934
1835
    eval_expr(var, "", 0);
1935
1836
 
1936
 
  drizzle_result_free(&res);
 
1837
  drizzle_free_result(res);
1937
1838
  return;
1938
1839
}
1939
1840
 
1964
1865
{
1965
1866
  long row_no;
1966
1867
  int col_no= -1;
1967
 
  drizzle_result_st res;
1968
 
  drizzle_return_t ret;
1969
 
  drizzle_con_st *con= &cur_con->con;
 
1868
  DRIZZLE_RES* res;
 
1869
  DRIZZLE *drizzle= &cur_con->drizzle;
1970
1870
 
1971
1871
  string ds_query;
1972
1872
  string ds_col;
1985
1885
                     ',');
1986
1886
 
1987
1887
  /* Convert row number to int */
1988
 
  row_no= atoi(ds_row.c_str());
1989
 
  
1990
 
  istringstream buff(ds_row);
1991
 
  if ((buff >> row_no).fail())
 
1888
  if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1992
1889
    die("Invalid row number: '%s'", ds_row.c_str());
1993
1890
 
1994
1891
  /* Remove any surrounding "'s from the query - if there is any */
1996
1893
  char * unstripped_query= strdup(ds_query.c_str());
1997
1894
  if (strip_surrounding(unstripped_query, '"', '"'))
1998
1895
    die("Mismatched \"'s around query '%s'", ds_query.c_str());
1999
 
  ds_query.clear();
2000
 
  ds_query.append(unstripped_query);
 
1896
  ds_query= unstripped_query;
2001
1897
 
2002
1898
  /* Run the query */
2003
 
  if (drizzle_query(con, &res, ds_query.c_str(), ds_query.length(),
2004
 
                    &ret) == NULL ||
2005
 
      ret != DRIZZLE_RETURN_OK)
2006
 
  {
2007
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
2008
 
    {
2009
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
2010
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
2011
 
      drizzle_result_free(&res);
2012
 
    }
2013
 
    else
2014
 
    {
2015
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
2016
 
          drizzle_con_error(con));
2017
 
    }
2018
 
  }
2019
 
  if (drizzle_result_column_count(&res) == 0 ||
2020
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
1899
  if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
 
1900
    die("Error running query '%s': %d %s", ds_query.c_str(),
 
1901
        drizzle_errno(drizzle), drizzle_error(drizzle));
 
1902
  if (!(res= drizzle_store_result(drizzle)))
2021
1903
    die("Query '%s' didn't return a result set", ds_query.c_str());
2022
1904
 
2023
1905
  {
2024
1906
    /* Find column number from the given column name */
2025
 
    uint32_t i;
2026
 
    uint32_t num_fields= drizzle_result_column_count(&res);
2027
 
    drizzle_column_st *column;
 
1907
    uint i;
 
1908
    uint num_fields= drizzle_num_fields(res);
 
1909
    const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
2028
1910
 
2029
1911
    for (i= 0; i < num_fields; i++)
2030
1912
    {
2031
 
      column= drizzle_column_next(&res);
2032
 
      if (strcmp(drizzle_column_name(column), ds_col.c_str()) == 0 &&
2033
 
          strlen(drizzle_column_name(column)) == ds_col.length())
 
1913
      if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
 
1914
          strlen(fields[i].name) == ds_col.length())
2034
1915
      {
2035
1916
        col_no= i;
2036
1917
        break;
2038
1919
    }
2039
1920
    if (col_no == -1)
2040
1921
    {
2041
 
      drizzle_result_free(&res);
 
1922
      drizzle_free_result(res);
2042
1923
      die("Could not find column '%s' in the result of '%s'",
2043
1924
          ds_col.c_str(), ds_query.c_str());
2044
1925
    }
2046
1927
 
2047
1928
  {
2048
1929
    /* Get the value */
2049
 
    drizzle_row_t row;
 
1930
    DRIZZLE_ROW row;
2050
1931
    long rows= 0;
2051
1932
    const char* value= "No such row";
2052
1933
 
2053
 
    while ((row= drizzle_row_next(&res)))
 
1934
    while ((row= drizzle_fetch_row(res)))
2054
1935
    {
2055
1936
      if (++rows == row_no)
2056
1937
      {
2066
1947
    }
2067
1948
    eval_expr(var, value, 0);
2068
1949
  }
2069
 
  drizzle_result_free(&res);
 
1950
  drizzle_free_result(res);
2070
1951
 
2071
1952
  return;
2072
1953
}
2078
1959
  dest->int_dirty= src->int_dirty;
2079
1960
 
2080
1961
  /* Alloc/realloc data for str_val in dest */
2081
 
  if (dest->alloced_len < src->alloced_len)
2082
 
  {
2083
 
    char *tmpptr= (char *)realloc(dest->str_val, src->alloced_len);
2084
 
    if (tmpptr == NULL)
2085
 
      die("Out of memory");
2086
 
    dest->str_val= tmpptr;
2087
 
  }
 
1962
  if (dest->alloced_len < src->alloced_len &&
 
1963
      !(dest->str_val= dest->str_val
 
1964
        ? (char *)my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
 
1965
        : (char *)my_malloc(src->alloced_len, MYF(MY_WME))))
 
1966
    die("Out of memory");
2088
1967
  else
2089
1968
    dest->alloced_len= src->alloced_len;
2090
1969
 
2117
1996
    const size_t len= strlen(get_value_str);
2118
1997
    if (strncmp(p, get_value_str, len)==0)
2119
1998
    {
2120
 
      st_command command;
 
1999
      struct st_command command;
 
2000
      memset(&command, 0, sizeof(command));
2121
2001
      command.query= (char*)p;
2122
2002
      command.first_word_len= len;
2123
2003
      command.first_argument= command.query + len;
2135
2015
      static int MIN_VAR_ALLOC= 32;
2136
2016
      v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
2137
2017
        MIN_VAR_ALLOC : new_val_len + 1;
2138
 
      char *tmpptr= (char *)realloc(v->str_val, v->alloced_len+1);
2139
 
      if (tmpptr == NULL)
 
2018
      if (!(v->str_val =
 
2019
            v->str_val ? (char *)my_realloc(v->str_val, v->alloced_len+1,
 
2020
                                            MYF(MY_WME)) :
 
2021
            (char *)my_malloc(v->alloced_len+1, MYF(MY_WME))))
2140
2022
        die("Out of memory");
2141
 
      v->str_val= tmpptr;
2142
2023
    }
2143
2024
    v->str_val_len = new_val_len;
2144
2025
    memcpy(v->str_val, p, new_val_len);
2154
2035
{
2155
2036
  char buff[FN_REFLEN];
2156
2037
 
2157
 
  if (!internal::test_if_hard_path(name))
 
2038
  if (!test_if_hard_path(name))
2158
2039
  {
2159
 
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),name);
 
2040
    strxmov(buff, opt_basedir, name, NullS);
2160
2041
    name=buff;
2161
2042
  }
2162
 
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
 
2043
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2163
2044
 
2164
2045
  if (cur_file == file_stack_end)
2165
2046
    die("Source directives are nesting too deep");
2166
2047
  cur_file++;
2167
 
  if (!(cur_file->file= fopen(buff, "r")))
 
2048
  if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
2168
2049
  {
2169
2050
    cur_file--;
2170
2051
    die("Could not open '%s' for reading", buff);
2171
2052
  }
2172
 
  if (!(cur_file->file_name= strdup(buff)))
2173
 
    die("Out of memory");
 
2053
  cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
2174
2054
  cur_file->lineno=1;
2175
2055
  return(0);
2176
2056
}
2210
2090
    ; /* Do nothing */
2211
2091
  else
2212
2092
  {
2213
 
    if (! opt_testdir.empty())
2214
 
    {
2215
 
      string testdir(opt_testdir);
2216
 
      if (testdir[testdir.length()] != '/')
2217
 
        testdir.append("/");
2218
 
      testdir.append(ds_filename);
2219
 
      ds_filename.swap(testdir);
2220
 
    }
2221
2093
    open_file(ds_filename.c_str());
2222
2094
  }
2223
2095
 
2329
2201
  error= pclose(res_file);
2330
2202
  if (error > 0)
2331
2203
  {
2332
 
    uint32_t status= WEXITSTATUS(error), i;
 
2204
    uint status= WEXITSTATUS(error), i;
2333
2205
    bool ok= 0;
2334
2206
 
2335
2207
    if (command->abort_on_error)
2478
2350
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2479
2351
                     ' ');
2480
2352
 
2481
 
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2353
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
2482
2354
  handle_command_error(command, error);
2483
2355
  return;
2484
2356
}
2512
2384
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2513
2385
                     ' ');
2514
2386
 
2515
 
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2387
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2516
2388
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2517
2389
  handle_command_error(command, error);
2518
2390
  return;
2547
2419
                     ' ');
2548
2420
 
2549
2421
  /* Parse what mode to set */
2550
 
  istringstream buff(ds_mode);
2551
2422
  if (ds_mode.length() != 4 ||
2552
 
      (buff >> oct >> mode).fail())
 
2423
      str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NullS)
2553
2424
    die("You must write a 4 digit octal number for mode");
2554
2425
 
2555
2426
  handle_command_error(command, chmod(ds_file.c_str(), mode));
2599
2470
 
2600
2471
static void do_mkdir(struct st_command *command)
2601
2472
{
 
2473
  int error;
2602
2474
  string ds_dirname;
2603
 
  int error;
2604
2475
  const struct command_arg mkdir_args[] = {
2605
2476
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
2606
2477
  };
2610
2481
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2611
2482
                     ' ');
2612
2483
 
2613
 
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
 
2484
  error= my_mkdir(ds_dirname.c_str(), 0777, MYF(0)) != 0;
2614
2485
  handle_command_error(command, error);
2615
2486
  return;
2616
2487
}
2730
2601
 
2731
2602
  /* If no delimiter was provided, use EOF */
2732
2603
  if (ds_delimiter.length() == 0)
2733
 
    ds_delimiter.append("EOF");
 
2604
    ds_delimiter= "EOF";
2734
2605
 
2735
2606
  if (!append && access(ds_filename.c_str(), F_OK) == 0)
2736
2607
  {
2911
2782
{
2912
2783
  char *p= command->first_argument, *name;
2913
2784
  struct st_connection *con;
2914
 
  drizzle_result_st result;
2915
 
  drizzle_return_t ret;
2916
2785
 
2917
2786
  if (!*p)
2918
2787
    die("Missing connection name in send_quit");
2927
2796
  if (!(con= find_connection_by_name(name)))
2928
2797
    die("connection '%s' not found in connection pool", name);
2929
2798
 
2930
 
  if (drizzle_quit(&con->con,&result, &ret))
2931
 
    drizzle_result_free(&result);
 
2799
  simple_command(&con->drizzle,COM_QUIT,0,0,1);
2932
2800
 
2933
2801
  return;
2934
2802
}
2950
2818
 
2951
2819
*/
2952
2820
 
2953
 
static void do_change_user(struct st_command *)
 
2821
static void do_change_user(struct st_command *command)
2954
2822
{
2955
 
  assert(0);
 
2823
  DRIZZLE *drizzle= &cur_con->drizzle;
 
2824
  /* static keyword to make the NetWare compiler happy. */
 
2825
  string ds_user, ds_passwd, ds_db;
 
2826
  const struct command_arg change_user_args[] = {
 
2827
    { "user", ARG_STRING, false, &ds_user, "User to connect as" },
 
2828
    { "password", ARG_STRING, false, &ds_passwd, "Password used when connecting" },
 
2829
    { "database", ARG_STRING, false, &ds_db, "Database to select after connect" },
 
2830
  };
 
2831
 
 
2832
 
 
2833
 
 
2834
  check_command_args(command, command->first_argument,
 
2835
                     change_user_args,
 
2836
                     sizeof(change_user_args)/sizeof(struct command_arg),
 
2837
                     ',');
 
2838
 
 
2839
  if (!ds_user.length())
 
2840
    ds_user= drizzle->user;
 
2841
 
 
2842
  if (!ds_passwd.length())
 
2843
    ds_passwd= drizzle->passwd;
 
2844
 
 
2845
  if (!ds_db.length())
 
2846
    ds_db= drizzle->db;
 
2847
 
 
2848
  if (drizzle_change_user(drizzle, ds_user.c_str(),
 
2849
                          ds_passwd.c_str(), ds_db.c_str()))
 
2850
    die("change user failed: %s", drizzle_error(drizzle));
 
2851
 
 
2852
 
 
2853
  return;
2956
2854
}
2957
2855
 
 
2856
 
2958
2857
/*
2959
2858
  SYNOPSIS
2960
2859
  do_perl
2977
2876
static void do_perl(struct st_command *command)
2978
2877
{
2979
2878
  int error;
2980
 
  int fd;
 
2879
  File fd;
2981
2880
  FILE *res_file;
2982
2881
  char buf[FN_REFLEN];
2983
2882
  char temp_file_path[FN_REFLEN];
2996
2895
 
2997
2896
  /* If no delimiter was provided, use EOF */
2998
2897
  if (ds_delimiter.length() == 0)
2999
 
    ds_delimiter.append("EOF");
 
2898
    ds_delimiter= "EOF";
3000
2899
 
3001
2900
  read_until_delimiter(&ds_script, &ds_delimiter);
3002
2901
 
3003
2902
  /* Create temporary file name */
3004
 
  if ((fd= internal::create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
3005
 
                            "tmp", MYF(MY_WME))) < 0)
 
2903
  if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
 
2904
                            "tmp", O_CREAT | O_SHARE | O_RDWR,
 
2905
                            MYF(MY_WME))) < 0)
3006
2906
    die("Failed to create temporary file for perl command");
3007
 
  internal::my_close(fd, MYF(0));
 
2907
  my_close(fd, MYF(0));
3008
2908
 
3009
2909
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
3010
2910
 
3024
2924
  error= pclose(res_file);
3025
2925
 
3026
2926
  /* Remove the temporary file */
3027
 
  internal::my_delete(temp_file_path, MYF(0));
 
2927
  my_delete(temp_file_path, MYF(0));
3028
2928
 
3029
2929
  handle_command_error(command, WEXITSTATUS(error));
3030
2930
  return;
3069
2969
 
3070
2970
 
3071
2971
static void
3072
 
do_wait_for_slave_to_stop(struct st_command *)
 
2972
do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
3073
2973
{
3074
2974
  static int SLAVE_POLL_INTERVAL= 300000;
3075
 
  drizzle_con_st *con= &cur_con->con;
 
2975
  DRIZZLE *drizzle= &cur_con->drizzle;
3076
2976
  for (;;)
3077
2977
  {
3078
 
    drizzle_result_st res;
3079
 
    drizzle_return_t ret;
3080
 
    drizzle_row_t row;
 
2978
    DRIZZLE_RES *res= NULL;
 
2979
    DRIZZLE_ROW row;
3081
2980
    int done;
3082
2981
 
3083
 
    if (drizzle_query_str(con,&res,"show status like 'Slave_running'",
3084
 
                          &ret) == NULL || ret != DRIZZLE_RETURN_OK)
3085
 
    {
3086
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
3087
 
      {
3088
 
        die("Query failed while probing slave for stop: %s",
3089
 
            drizzle_result_error(&res));
3090
 
        drizzle_result_free(&res);
3091
 
      }
3092
 
      else
3093
 
      {
3094
 
        die("Query failed while probing slave for stop: %s",
3095
 
            drizzle_con_error(con));
3096
 
      }
3097
 
    }
3098
 
 
3099
 
    if (drizzle_result_column_count(&res) == 0 ||
3100
 
        drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3101
 
    {
 
2982
    if (drizzle_query(drizzle,"show status like 'Slave_running'") ||
 
2983
        !(res=drizzle_store_result(drizzle)))
3102
2984
      die("Query failed while probing slave for stop: %s",
3103
 
          drizzle_con_error(con));
3104
 
    }
3105
 
 
3106
 
    if (!(row=drizzle_row_next(&res)) || !row[1])
 
2985
          drizzle_error(drizzle));
 
2986
    if (!(row=drizzle_fetch_row(res)) || !row[1])
3107
2987
    {
3108
 
      drizzle_result_free(&res);
 
2988
      drizzle_free_result(res);
3109
2989
      die("Strange result from query while probing slave for stop");
3110
2990
    }
3111
2991
    done = !strcmp(row[1],"OFF");
3112
 
    drizzle_result_free(&res);
 
2992
    drizzle_free_result(res);
3113
2993
    if (done)
3114
2994
      break;
3115
 
    usleep(SLAVE_POLL_INTERVAL);
 
2995
    my_sleep(SLAVE_POLL_INTERVAL);
3116
2996
  }
3117
2997
  return;
3118
2998
}
3120
3000
 
3121
3001
static void do_sync_with_master2(long offset)
3122
3002
{
3123
 
  drizzle_result_st res;
3124
 
  drizzle_return_t ret;
3125
 
  drizzle_row_t row;
3126
 
  drizzle_con_st *con= &cur_con->con;
 
3003
  DRIZZLE_RES *res;
 
3004
  DRIZZLE_ROW row;
 
3005
  DRIZZLE *drizzle= &cur_con->drizzle;
3127
3006
  char query_buf[FN_REFLEN+128];
3128
3007
  int tries= 0;
3129
3008
 
3130
3009
  if (!master_pos.file[0])
3131
3010
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3132
3011
 
3133
 
  snprintf(query_buf, sizeof(query_buf), "select master_pos_wait('%s', %ld)", master_pos.file,
 
3012
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3134
3013
          master_pos.pos + offset);
3135
3014
 
3136
3015
wait_for_position:
3137
3016
 
3138
 
  if (drizzle_query_str(con, &res, query_buf, &ret) == NULL ||
3139
 
      ret != DRIZZLE_RETURN_OK)
3140
 
  {
3141
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3142
 
    {
3143
 
      die("failed in '%s': %d: %s", query_buf, drizzle_result_error_code(&res),
3144
 
           drizzle_result_error(&res));
3145
 
      drizzle_result_free(&res);
3146
 
    }
3147
 
    else
3148
 
      die("failed in '%s': %d: %s", query_buf, ret, drizzle_con_error(con));
3149
 
  }
3150
 
 
3151
 
  if (drizzle_result_column_count(&res) == 0 ||
3152
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3153
 
    die("drizzle_result_buffer() returned NULL for '%s'", query_buf);
3154
 
 
3155
 
  if (!(row= drizzle_row_next(&res)))
3156
 
  {
3157
 
    drizzle_result_free(&res);
 
3017
  if (drizzle_query(drizzle, query_buf))
 
3018
    die("failed in '%s': %d: %s", query_buf, drizzle_errno(drizzle),
 
3019
        drizzle_error(drizzle));
 
3020
 
 
3021
  if (!(res= drizzle_store_result(drizzle)))
 
3022
    die("drizzle_store_result() returned NULL for '%s'", query_buf);
 
3023
  if (!(row= drizzle_fetch_row(res)))
 
3024
  {
 
3025
    drizzle_free_result(res);
3158
3026
    die("empty result in %s", query_buf);
3159
3027
  }
3160
3028
  if (!row[0])
3163
3031
      It may be that the slave SQL thread has not started yet, though START
3164
3032
      SLAVE has been issued ?
3165
3033
    */
3166
 
    drizzle_result_free(&res);
 
3034
    drizzle_free_result(res);
3167
3035
    if (tries++ == 30)
3168
3036
    {
3169
 
      show_query(con, "SHOW MASTER STATUS");
3170
 
      show_query(con, "SHOW SLAVE STATUS");
 
3037
      show_query(drizzle, "SHOW MASTER STATUS");
 
3038
      show_query(drizzle, "SHOW SLAVE STATUS");
3171
3039
      die("could not sync with master ('%s' returned NULL)", query_buf);
3172
3040
    }
3173
3041
    sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
3174
3042
    goto wait_for_position;
3175
3043
  }
3176
 
  drizzle_result_free(&res);
 
3044
  drizzle_free_result(res);
3177
3045
  return;
3178
3046
}
3179
3047
 
3203
3071
*/
3204
3072
static int do_save_master_pos(void)
3205
3073
{
3206
 
  drizzle_result_st res;
3207
 
  drizzle_return_t ret;
3208
 
  drizzle_row_t row;
3209
 
  drizzle_con_st *con= &cur_con->con;
 
3074
  DRIZZLE_RES *res;
 
3075
  DRIZZLE_ROW row;
 
3076
  DRIZZLE *drizzle= &cur_con->drizzle;
3210
3077
  const char *query;
3211
3078
 
3212
3079
 
3213
 
  if (drizzle_query_str(con, &res, query= "show master status", &ret) == NULL ||
3214
 
      ret != DRIZZLE_RETURN_OK)
3215
 
  {
3216
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3217
 
    {
3218
 
      die("failed in '%s': %d: %s", query, drizzle_result_error_code(&res),
3219
 
           drizzle_result_error(&res));
3220
 
      drizzle_result_free(&res);
3221
 
    }
3222
 
    else
3223
 
      die("failed in '%s': %d: %s", query, ret, drizzle_con_error(con));
3224
 
  }
 
3080
  if (drizzle_query(drizzle, query= "show master status"))
 
3081
    die("failed in 'show master status': %d %s",
 
3082
        drizzle_errno(drizzle), drizzle_error(drizzle));
3225
3083
 
3226
 
  if (drizzle_result_column_count(&res) == 0 ||
3227
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3228
 
    die("drizzleclient_store_result() retuned NULL for '%s'", query);
3229
 
  if (!(row = drizzle_row_next(&res)))
 
3084
  if (!(res = drizzle_store_result(drizzle)))
 
3085
    die("drizzle_store_result() retuned NULL for '%s'", query);
 
3086
  if (!(row = drizzle_fetch_row(res)))
3230
3087
    die("empty result in show master status");
3231
 
  strncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
 
3088
  stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
3232
3089
  master_pos.pos = strtoul(row[1], (char**) 0, 10);
3233
 
  drizzle_result_free(&res);
 
3090
  drizzle_free_result(res);
3234
3091
  return(0);
3235
3092
}
3236
3093
 
3314
3171
 
3315
3172
static int do_sleep(struct st_command *command, bool real_sleep)
3316
3173
{
3317
 
  bool error= false;
 
3174
  int error= 0;
3318
3175
  char *p= command->first_argument;
3319
3176
  char *sleep_start, *sleep_end= command->end;
3320
 
  double sleep_val= 0;
 
3177
  double sleep_val;
3321
3178
 
3322
3179
  while (my_isspace(charset_info, *p))
3323
3180
    p++;
3324
3181
  if (!*p)
3325
3182
    die("Missing argument to %.*s", command->first_word_len, command->query);
3326
3183
  sleep_start= p;
3327
 
  /* Check that arg starts with a digit, not handled by internal::my_strtod */
 
3184
  /* Check that arg starts with a digit, not handled by my_strtod */
3328
3185
  if (!my_isdigit(charset_info, *sleep_start))
3329
3186
    die("Invalid argument to %.*s \"%s\"", command->first_word_len,
3330
3187
        command->query,command->first_argument);
3331
 
  string buff_str(sleep_start, sleep_end-sleep_start);
3332
 
  istringstream buff(buff_str);
3333
 
  error= (buff >> sleep_val).fail();
 
3188
  sleep_val= my_strtod(sleep_start, &sleep_end, &error);
3334
3189
  if (error)
3335
3190
    die("Invalid argument to %.*s \"%s\"", command->first_word_len,
3336
3191
        command->query, command->first_argument);
3340
3195
    sleep_val= opt_sleep;
3341
3196
 
3342
3197
  if (sleep_val)
3343
 
    usleep((uint32_t) (sleep_val * 1000000L));
 
3198
    my_sleep((uint32_t) (sleep_val * 1000000L));
3344
3199
  command->last_argument= sleep_end;
3345
3200
  return 0;
3346
3201
}
3347
3202
 
3348
3203
 
3349
 
static void do_get_file_name(struct st_command *command, string &dest)
 
3204
static void do_get_file_name(struct st_command *command,
 
3205
                             char* dest, uint dest_max_len)
3350
3206
{
3351
3207
  char *p= command->first_argument, *name;
3352
3208
  if (!*p)
3357
3213
  if (*p)
3358
3214
    *p++= 0;
3359
3215
  command->last_argument= p;
3360
 
  if (! opt_testdir.empty())
3361
 
  {
3362
 
    dest= opt_testdir;
3363
 
    if (dest[dest.length()] != '/')
3364
 
      dest.append("/");
3365
 
  }
3366
 
  dest.append(name);
 
3216
  strmake(dest, name, dest_max_len - 1);
3367
3217
}
3368
3218
 
3369
3219
 
3381
3231
  if(*p)
3382
3232
    *p++= 0;
3383
3233
  command->last_argument= p;
3384
 
  charset_info= get_charset_by_csname(charset_name, MY_CS_PRIMARY);
 
3234
  charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
3385
3235
  if (!charset_info)
3386
3236
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3387
3237
}
3388
3238
 
3389
 
static void fill_global_error_names()
 
3239
static uint get_errcode_from_name(char *error_name, char *error_end)
3390
3240
{
3391
 
  drizzle_result_st res;
3392
 
  drizzle_return_t ret;
3393
 
  drizzle_row_t row;
3394
 
  drizzle_con_st *con= &cur_con->con;
3395
 
 
3396
 
  global_error_names.clear();
3397
 
 
3398
 
  const std::string ds_query("select error_name, error_code "
3399
 
                             "from data_dictionary.errors");
3400
 
  if (drizzle_query_str(con, &res, ds_query.c_str(), &ret) == NULL ||
3401
 
      ret != DRIZZLE_RETURN_OK)
3402
 
  {
3403
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3404
 
    {
3405
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
3406
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
3407
 
      drizzle_result_free(&res);
3408
 
    }
3409
 
    else
3410
 
    {
3411
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
3412
 
          drizzle_con_error(con));
3413
 
    }
3414
 
  }
3415
 
  if (drizzle_result_column_count(&res) == 0 ||
3416
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3417
 
  {
3418
 
    drizzle_result_free(&res);
3419
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
3420
 
  }
3421
 
 
3422
 
  while ((row= drizzle_row_next(&res)) && row[0])
 
3241
  /* SQL error as string */
 
3242
  st_error *e= global_error_names;
 
3243
 
 
3244
  /* Loop through the array of known error names */
 
3245
  for (; e->name; e++)
3423
3246
  {
3424
3247
    /*
3425
 
      Concatenate all fields in the first row with tab in between
3426
 
      and assign that string to the $variable
 
3248
      If we get a match, we need to check the length of the name we
 
3249
      matched against in case it was longer than what we are checking
 
3250
      (as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
3427
3251
    */
3428
 
    size_t *lengths= drizzle_row_field_sizes(&res);
3429
 
    const std::string error_name(row[0], lengths[0]);
3430
 
    const std::string error_code(row[1], lengths[1]);
3431
 
 
3432
 
    try
3433
 
    {
3434
 
      global_error_names.insert(ErrorCodes::value_type(error_name,
3435
 
                                                       boost::lexical_cast<uint32_t>(error_code)));
3436
 
    }
3437
 
    catch (boost::bad_lexical_cast &ex)
3438
 
    {
3439
 
      drizzle_result_free(&res);
3440
 
      die("Invalid error_code from Drizzle: %s", ex.what());
3441
 
    }
3442
 
 
3443
 
  }
3444
 
 
3445
 
  drizzle_result_free(&res);
3446
 
}
3447
 
 
3448
 
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3449
 
{
3450
 
  size_t err_name_len= error_end - error_name;
3451
 
  string error_name_s(error_name, err_name_len);
3452
 
 
3453
 
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3454
 
  if (it != global_error_names.end())
3455
 
  {
3456
 
    return (*it).second;
3457
 
  }
3458
 
 
3459
 
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3460
 
  return 0;
 
3252
    if (!strncmp(error_name, e->name, (int) (error_end - error_name)) &&
 
3253
        (uint) strlen(e->name) == (uint) (error_end - error_name))
 
3254
    {
 
3255
      return(e->code);
 
3256
    }
 
3257
  }
 
3258
  if (!e->name)
 
3259
    die("Unknown SQL error name '%s'", error_name);
 
3260
  return(0);
3461
3261
}
3462
3262
 
3463
3263
static void do_get_errcodes(struct st_command *command)
3464
3264
{
3465
3265
  struct st_match_err *to= saved_expected_errors.err;
3466
3266
  char *p= command->first_argument;
3467
 
  uint32_t count= 0;
 
3267
  uint count= 0;
3468
3268
 
3469
3269
 
3470
3270
 
3490
3290
 
3491
3291
      /*
3492
3292
        SQLSTATE string
3493
 
        - Must be DRIZZLE_MAX_SQLSTATE_SIZE long
 
3293
        - Must be SQLSTATE_LENGTH long
3494
3294
        - May contain only digits[0-9] and _uppercase_ letters
3495
3295
      */
3496
3296
      p++; /* Step past the S */
3497
 
      if ((end - p) != DRIZZLE_MAX_SQLSTATE_SIZE)
3498
 
        die("The sqlstate must be exactly %d chars long", DRIZZLE_MAX_SQLSTATE_SIZE);
 
3297
      if ((end - p) != SQLSTATE_LENGTH)
 
3298
        die("The sqlstate must be exactly %d chars long", SQLSTATE_LENGTH);
3499
3299
 
3500
3300
      /* Check sqlstate string validity */
3501
3301
      while (*p && p < end)
3540
3340
      }
3541
3341
 
3542
3342
      /* Convert the sting to int */
3543
 
      istringstream buff(start);
3544
 
      if ((buff >> val).fail())
 
3343
      if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
3545
3344
        die("Invalid argument to error: '%s'", command->first_argument);
3546
3345
 
3547
 
      to->code.errnum= (uint32_t) val;
 
3346
      to->code.errnum= (uint) val;
3548
3347
      to->type= ERR_ERRNO;
3549
3348
    }
3550
3349
    to++;
3651
3450
}
3652
3451
 
3653
3452
 
3654
 
static void set_reconnect(drizzle_con_st *con, int val)
 
3453
static void set_reconnect(DRIZZLE *drizzle, int val)
3655
3454
{
3656
 
  (void) con;
3657
 
  (void) val;
3658
 
/* XXX
3659
3455
  bool reconnect= val;
3660
3456
 
3661
 
  drizzleclient_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
3662
 
*/
 
3457
  drizzle_options(drizzle, DRIZZLE_OPT_RECONNECT, (char *)&reconnect);
 
3458
 
 
3459
  return;
3663
3460
}
3664
3461
 
3665
3462
 
3668
3465
  if (!(cur_con= find_connection_by_name(name)))
3669
3466
    die("connection '%s' not found in connection pool", name);
3670
3467
 
3671
 
  /* Update $drizzleclient_get_server_version to that of current connection */
3672
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
3468
  /* Update $drizzle_get_server_version to that of current connection */
 
3469
  var_set_drizzle_get_server_version(&cur_con->drizzle);
3673
3470
 
3674
3471
  return(0);
3675
3472
}
3711
3508
  if (!(con= find_connection_by_name(name)))
3712
3509
    die("connection '%s' not found in connection pool", name);
3713
3510
 
3714
 
  if (con->drizzle != NULL)
 
3511
  if (command->type == Q_DIRTY_CLOSE)
3715
3512
  {
3716
 
    drizzle_free(con->drizzle);
3717
 
    con->drizzle= NULL;
 
3513
    if (con->drizzle.net.vio)
 
3514
    {
 
3515
      vio_delete(con->drizzle.net.vio);
 
3516
      con->drizzle.net.vio = 0;
 
3517
    }
3718
3518
  }
3719
 
  free(con->name);
 
3519
 
 
3520
  drizzle_close(&con->drizzle);
 
3521
 
 
3522
  if (con->util_drizzle)
 
3523
    drizzle_close(con->util_drizzle);
 
3524
  con->util_drizzle= 0;
 
3525
 
 
3526
  my_free(con->name, MYF(0));
3720
3527
 
3721
3528
  /*
3722
3529
    When the connection is closed set name to "-closed_connection-"
3723
3530
    to make it possible to reuse the connection name.
3724
3531
  */
3725
 
  if (!(con->name = strdup("-closed_connection-")))
 
3532
  if (!(con->name = my_strdup("-closed_connection-", MYF(MY_WME))))
3726
3533
    die("Out of memory");
3727
3534
 
3728
3535
  return;
3754
3561
 
3755
3562
*/
3756
3563
 
3757
 
static void safe_connect(drizzle_con_st *con, const char *name,
3758
 
                         const string host, const string user, const char *pass,
3759
 
                         const string db, uint32_t port)
 
3564
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
 
3565
                         const char *user, const char *pass, const char *db,
 
3566
                         int port)
3760
3567
{
3761
 
  uint32_t failed_attempts= 0;
 
3568
  int failed_attempts= 0;
3762
3569
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3763
 
  drizzle_return_t ret;
3764
 
 
3765
 
  drizzle_con_set_tcp(con, host.c_str(), port);
3766
 
  drizzle_con_set_auth(con, user.c_str(), pass);
3767
 
  drizzle_con_set_db(con, db.c_str());
3768
 
  while((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
 
3570
 
 
3571
 
 
3572
  while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
 
3573
                         CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3769
3574
  {
3770
3575
    /*
3771
3576
      Connect failed
3775
3580
      on protocol/connection type
3776
3581
    */
3777
3582
 
3778
 
    if ((ret == DRIZZLE_RETURN_GETADDRINFO ||
3779
 
         ret == DRIZZLE_RETURN_COULD_NOT_CONNECT) &&
 
3583
    if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
 
3584
         drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
3780
3585
        failed_attempts < opt_max_connect_retries)
3781
3586
    {
3782
3587
      verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3783
 
                  opt_max_connect_retries, ret, drizzle_con_error(con));
3784
 
      usleep(connection_retry_sleep);
 
3588
                  opt_max_connect_retries, drizzle_errno(drizzle),
 
3589
                  drizzle_error(drizzle));
 
3590
      my_sleep(connection_retry_sleep);
3785
3591
    }
3786
3592
    else
3787
3593
    {
3788
3594
      if (failed_attempts > 0)
3789
3595
        die("Could not open connection '%s' after %d attempts: %d %s", name,
3790
 
            failed_attempts, ret, drizzle_con_error(con));
 
3596
            failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
3791
3597
      else
3792
 
        die("Could not open connection '%s': %d %s", name, ret,
3793
 
            drizzle_con_error(con));
 
3598
        die("Could not open connection '%s': %d %s", name,
 
3599
            drizzle_errno(drizzle), drizzle_error(drizzle));
3794
3600
    }
3795
3601
    failed_attempts++;
3796
3602
  }
3822
3628
*/
3823
3629
 
3824
3630
static int connect_n_handle_errors(struct st_command *command,
3825
 
                                   drizzle_con_st *con, const char* host,
 
3631
                                   DRIZZLE *con, const char* host,
3826
3632
                                   const char* user, const char* pass,
3827
3633
                                   const char* db, int port, const char* sock)
3828
3634
{
3829
 
  drizzle_return_t ret;
3830
3635
 
3831
3636
  /* Only log if an error is expected */
3832
3637
  if (!command->abort_on_error &&
3853
3658
    ds_res.append(delimiter);
3854
3659
    ds_res.append("\n");
3855
3660
  }
3856
 
  drizzle_con_set_tcp(con, host, port);
3857
 
  drizzle_con_set_auth(con, user, pass);
3858
 
  drizzle_con_set_db(con, db);
3859
 
  if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
 
3661
  if (!drizzle_connect(con, host, user, pass, db, port, 0,
 
3662
                       CLIENT_MULTI_STATEMENTS))
3860
3663
  {
3861
 
    if (ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
3862
 
    {
3863
 
      var_set_errno(drizzle_con_error_code(con));
3864
 
      handle_error(command, drizzle_con_error_code(con), drizzle_con_error(con),
3865
 
                   drizzle_con_sqlstate(con), &ds_res);
3866
 
    }
3867
 
    else
3868
 
    {
3869
 
      var_set_errno(ret);
3870
 
      handle_error(command, ret, drizzle_con_error(con), "", &ds_res);
3871
 
    }
3872
 
 
 
3664
    var_set_errno(drizzle_errno(con));
 
3665
    handle_error(command, drizzle_errno(con), drizzle_error(con),
 
3666
                 drizzle_sqlstate(con), &ds_res);
3873
3667
    return 0; /* Not connected */
3874
3668
  }
3875
3669
 
3906
3700
 
3907
3701
static void do_connect(struct st_command *command)
3908
3702
{
3909
 
  uint32_t con_port= opt_port;
 
3703
  int con_port= opt_port;
3910
3704
  const char *con_options;
3911
 
  bool con_ssl= 0;
 
3705
  bool con_ssl= 0, con_compress= 0;
3912
3706
  struct st_connection* con_slot;
3913
3707
 
3914
3708
  string ds_connection_name;
3954
3748
    if (*ds_sock.c_str() != FN_LIBCHAR)
3955
3749
    {
3956
3750
      char buff[FN_REFLEN];
3957
 
      internal::fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3958
 
      ds_sock.clear();
3959
 
      ds_sock.append(buff);
 
3751
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
 
3752
      ds_sock= buff;
3960
3753
    }
3961
3754
  }
3962
3755
 
3974
3767
      end++;
3975
3768
    if (!strncmp(con_options, "SSL", 3))
3976
3769
      con_ssl= 1;
 
3770
    else if (!strncmp(con_options, "COMPRESS", 8))
 
3771
      con_compress= 1;
3977
3772
    else
3978
3773
      die("Illegal option to connect: %.*s",
3979
3774
          (int) (end - con_options), con_options);
3995
3790
          (int) (sizeof(connections)/sizeof(struct st_connection)));
3996
3791
  }
3997
3792
 
3998
 
  if ((con_slot->drizzle= drizzle_create(NULL)) == NULL)
 
3793
  if (!drizzle_create(&con_slot->drizzle))
3999
3794
    die("Failed on drizzle_create()");
4000
 
  if (!drizzle_con_create(con_slot->drizzle, &con_slot->con))
4001
 
    die("Failed on drizzle_con_create()");
4002
 
  drizzle_con_add_options(&con_slot->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
3795
  if (opt_compress || con_compress)
 
3796
    drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NullS);
 
3797
  drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
3798
  drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_NAME,
 
3799
                  charset_info->csname);
 
3800
  int opt_protocol= DRIZZLE_PROTOCOL_TCP;
 
3801
  drizzle_options(&con_slot->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
 
3802
  if (opt_charsets_dir)
 
3803
    drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_DIR,
 
3804
                    opt_charsets_dir);
4003
3805
 
4004
3806
  /* Use default db name */
4005
3807
  if (ds_database.length() == 0)
4006
 
    ds_database.append(opt_db);
 
3808
    ds_database= opt_db;
4007
3809
 
4008
3810
  /* Special database to allow one to connect without a database name */
4009
3811
  if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
4010
 
    ds_database.clear();
 
3812
    ds_database= "";
4011
3813
 
4012
 
  if (connect_n_handle_errors(command, &con_slot->con,
 
3814
  if (connect_n_handle_errors(command, &con_slot->drizzle,
4013
3815
                              ds_host.c_str(),ds_user.c_str(),
4014
3816
                              ds_password.c_str(), ds_database.c_str(),
4015
3817
                              con_port, ds_sock.c_str()))
4022
3824
      next_con++; /* if we used the next_con slot, advance the pointer */
4023
3825
  }
4024
3826
 
4025
 
  /* Update $drizzleclient_get_server_version to that of current connection */
4026
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
3827
  /* Update $drizzle_get_server_version to that of current connection */
 
3828
  var_set_drizzle_get_server_version(&cur_con->drizzle);
4027
3829
 
4028
3830
  return;
4029
3831
}
4140
3942
  if (not_expr)
4141
3943
    cur_block->ok = !cur_block->ok;
4142
3944
 
4143
 
  free(v.str_val);
4144
 
  free(v.env_s);
4145
 
 
 
3945
  var_free(&v);
4146
3946
  return;
4147
3947
}
4148
3948
 
4157
3957
  if (!(*p))
4158
3958
    die("Can't set empty delimiter");
4159
3959
 
4160
 
  strncpy(delimiter, p, sizeof(delimiter) - 1);
 
3960
  strmake(delimiter, p, sizeof(delimiter) - 1);
4161
3961
  delimiter_length= strlen(delimiter);
4162
3962
 
4163
3963
  command->last_argument= p + delimiter_length;
4165
3965
}
4166
3966
 
4167
3967
 
4168
 
bool match_delimiter(int c, const char *delim, uint32_t length)
 
3968
bool match_delimiter(int c, const char *delim, uint length)
4169
3969
{
4170
 
  uint32_t i;
 
3970
  uint i;
4171
3971
  char tmp[MAX_DELIMITER_LENGTH];
4172
3972
 
4173
3973
  if (c != *delim)
4219
4019
 
4220
4020
*/
4221
4021
 
4222
 
 
4223
 
static int my_strnncoll_simple(const CHARSET_INFO * const  cs, const unsigned char *s, size_t slen,
4224
 
                               const unsigned char *t, size_t tlen,
4225
 
                               bool t_is_prefix)
4226
 
{
4227
 
  size_t len = ( slen > tlen ) ? tlen : slen;
4228
 
  unsigned char *map= cs->sort_order;
4229
 
  if (t_is_prefix && slen > tlen)
4230
 
    slen=tlen;
4231
 
  while (len--)
4232
 
  {
4233
 
    if (map[*s++] != map[*t++])
4234
 
      return ((int) map[s[-1]] - (int) map[t[-1]]);
4235
 
  }
4236
 
  /*
4237
 
    We can't use (slen - tlen) here as the result may be outside of the
4238
 
    precision of a signed int
4239
 
  */
4240
 
  return slen > tlen ? 1 : slen < tlen ? -1 : 0 ;
4241
 
}
4242
 
 
4243
4022
static int read_line(char *buf, int size)
4244
4023
{
4245
4024
  char c, last_quote= 0;
4259
4038
  found_eof:
4260
4039
      if (cur_file->file != stdin)
4261
4040
      {
4262
 
        fclose(cur_file->file);
 
4041
        my_fclose(cur_file->file, MYF(0));
4263
4042
        cur_file->file= 0;
4264
4043
      }
4265
 
      free((unsigned char*) cur_file->file_name);
 
4044
      my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
4266
4045
      cur_file->file_name= 0;
4267
4046
      if (cur_file == file_stack)
4268
4047
      {
4298
4077
        return(0);
4299
4078
      }
4300
4079
      else if ((c == '{' &&
4301
 
                (!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
4302
 
                                      (unsigned char*) buf, min((ptrdiff_t)5, p - buf), 0) ||
4303
 
                 !my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
4304
 
                                      (unsigned char*) buf, min((ptrdiff_t)2, p - buf), 0))))
 
4080
                (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
 
4081
                                      (uchar*) buf, min((long)5, p - buf), 0) ||
 
4082
                 !my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
 
4083
                                      (uchar*) buf, min((long)2, p - buf), 0))))
4305
4084
      {
4306
4085
        /* Only if and while commands can be terminated by { */
4307
4086
        *p++= c;
4378
4157
    {
4379
4158
      /* Could be a multibyte character */
4380
4159
      /* This code is based on the code in "sql_load.cc" */
 
4160
#ifdef USE_MB
4381
4161
      int charlen = my_mbcharlen(charset_info, c);
4382
4162
      /* We give up if multibyte character is started but not */
4383
4163
      /* completed before we pass buf_end */
4404
4184
        }
4405
4185
      }
4406
4186
      else
 
4187
#endif
4407
4188
        *p++= c;
4408
4189
    }
4409
4190
  }
4486
4267
        ptr[2] && ptr[2] == '-' &&
4487
4268
        ptr[3])
4488
4269
    {
4489
 
      uint32_t type;
 
4270
      uint type;
4490
4271
      char save;
4491
4272
      char *end, *start= (char*)ptr+3;
4492
4273
      /* Skip leading spaces */
4563
4344
  return;
4564
4345
}
4565
4346
 
 
4347
 
 
4348
 
4566
4349
/*
4567
4350
  Create a command from a set of lines
4568
4351
 
4580
4363
  terminated by new line '\n' regardless how many "delimiter" it contain.
4581
4364
*/
4582
4365
 
4583
 
#define MAX_QUERY (768*1024*2) /* 256K -- a test in sp-big is >128K */
 
4366
#define MAX_QUERY (256*1024*2) /* 256K -- a test in sp-big is >128K */
4584
4367
static char read_command_buf[MAX_QUERY];
4585
4368
 
4586
4369
static int read_command(struct st_command** command_ptr)
4594
4377
    *command_ptr= q_lines[parser.current_line];
4595
4378
    return(0);
4596
4379
  }
4597
 
  if (!(*command_ptr= command= new st_command))
4598
 
    die("command construction failed");
 
4380
  if (!(*command_ptr= command=
 
4381
        (struct st_command*) my_malloc(sizeof(*command),
 
4382
                                       MYF(MY_WME|MY_ZEROFILL))))
 
4383
    die(NullS);
4599
4384
  q_lines.push_back(command);
4600
4385
  command->type= Q_UNKNOWN;
4601
4386
 
4622
4407
  while (*p && my_isspace(charset_info, *p))
4623
4408
    p++;
4624
4409
 
4625
 
  if (!(command->query_buf= command->query= strdup(p)))
 
4410
  if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME))))
4626
4411
    die("Out of memory");
4627
4412
 
4628
4413
  /* Calculate first word length(the command), terminated by space or ( */
4629
4414
  p= command->query;
4630
4415
  while (*p && !my_isspace(charset_info, *p) && *p != '(')
4631
4416
    p++;
4632
 
  command->first_word_len= (uint32_t) (p - command->query);
 
4417
  command->first_word_len= (uint) (p - command->query);
4633
4418
 
4634
4419
  /* Skip spaces between command and first argument */
4635
4420
  while (*p && my_isspace(charset_info, *p))
4642
4427
  return(0);
4643
4428
}
4644
4429
 
 
4430
 
 
4431
static struct my_option my_long_options[] =
 
4432
{
 
4433
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
 
4434
   0, 0, 0, 0, 0, 0},
 
4435
  {"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
 
4436
   (char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4437
  {"character-sets-dir", OPT_CHARSETS_DIR,
 
4438
   "Directory where character sets are.", (char**) &opt_charsets_dir,
 
4439
   (char**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4440
  {"compress", 'C', "Use the compressed server/client protocol.",
 
4441
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
4442
   0, 0, 0},
 
4443
  {"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
 
4444
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4445
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
 
4446
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
 
4447
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4448
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
 
4449
   (char**) &debug_info_flag, (char**) &debug_info_flag,
 
4450
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4451
  {"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
 
4452
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4453
  {"include", 'i', "Include SQL before each test case.", (char**) &opt_include,
 
4454
   (char**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4455
  {"logdir", OPT_LOG_DIR, "Directory for log files", (char**) &opt_logdir,
 
4456
   (char**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4457
  {"mark-progress", OPT_MARK_PROGRESS,
 
4458
   "Write linenumber and elapsed time to <testname>.progress ",
 
4459
   (char**) &opt_mark_progress, (char**) &opt_mark_progress, 0,
 
4460
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4461
  {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
 
4462
   "Max number of connection attempts when connecting to server",
 
4463
   (char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
 
4464
   GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
 
4465
  {"password", 'p', "Password to use when connecting to server.",
 
4466
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
4467
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
 
4468
   "order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
 
4469
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
 
4470
   (char**) &opt_port,
 
4471
   (char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4472
  {"quiet", 's', "Suppress all normal output.", (char**) &silent,
 
4473
   (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4474
  {"record", 'r', "Record output of test_file into result file.",
 
4475
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4476
  {"result-file", 'R', "Read/Store result from/in this file.",
 
4477
   (char**) &result_file_name, (char**) &result_file_name, 0,
 
4478
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4479
  {"server-arg", 'A', "Send option value to embedded server as a parameter.",
 
4480
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4481
  {"server-file", 'F', "Read embedded server arguments from file.",
 
4482
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4483
  {"silent", 's', "Suppress all normal output. Synonym for --quiet.",
 
4484
   (char**) &silent, (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4485
  {"sleep", 'T', "Sleep always this many seconds on sleep commands.",
 
4486
   (char**) &opt_sleep, (char**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
 
4487
   0, 0, 0},
 
4488
  {"tail-lines", OPT_TAIL_LINES,
 
4489
   "Number of lines of the resul to include in a failure report",
 
4490
   (char**) &opt_tail_lines, (char**) &opt_tail_lines, 0,
 
4491
   GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
 
4492
  {"test-file", 'x', "Read test from/in this file (default stdin).",
 
4493
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4494
  {"timer-file", 'm', "File where the timing in micro seconds is stored.",
 
4495
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4496
  {"tmpdir", 't', "Temporary directory where sockets are put.",
 
4497
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4498
  {"user", 'u', "User for login.", (char**) &opt_user, (char**) &opt_user, 0,
 
4499
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4500
  {"verbose", 'v', "Write more.", (char**) &verbose, (char**) &verbose, 0,
 
4501
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4502
  {"version", 'V', "Output version information and exit.",
 
4503
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4504
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
4505
};
 
4506
 
 
4507
 
 
4508
static void print_version(void)
 
4509
{
 
4510
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
 
4511
         drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
4512
}
 
4513
 
 
4514
static void usage(void)
 
4515
{
 
4516
  print_version();
 
4517
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
 
4518
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
 
4519
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
 
4520
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
 
4521
  my_print_help(my_long_options);
 
4522
  printf("  --no-defaults       Don't read default options from any options file.\n");
 
4523
  my_print_variables(my_long_options);
 
4524
}
 
4525
 
 
4526
/*
 
4527
  Read arguments for embedded server and put them into
 
4528
  embedded_server_args[]
 
4529
*/
 
4530
 
 
4531
static void read_embedded_server_arguments(const char *name)
 
4532
{
 
4533
  char argument[1024],buff[FN_REFLEN], *str=0;
 
4534
  FILE *file;
 
4535
 
 
4536
  if (!test_if_hard_path(name))
 
4537
  {
 
4538
    strxmov(buff, opt_basedir, name, NullS);
 
4539
    name=buff;
 
4540
  }
 
4541
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
 
4542
 
 
4543
  if (!embedded_server_arg_count)
 
4544
  {
 
4545
    embedded_server_arg_count=1;
 
4546
    embedded_server_args[0]= (char*) "";    /* Progname */
 
4547
  }
 
4548
  if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
 
4549
    die("Failed to open file '%s'", buff);
 
4550
 
 
4551
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
 
4552
         (str=fgets(argument,sizeof(argument), file)))
 
4553
  {
 
4554
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
 
4555
    if (!(embedded_server_args[embedded_server_arg_count]=
 
4556
          (char*) my_strdup(str,MYF(MY_WME))))
 
4557
    {
 
4558
      my_fclose(file,MYF(0));
 
4559
      die("Out of memory");
 
4560
 
 
4561
    }
 
4562
    embedded_server_arg_count++;
 
4563
  }
 
4564
  my_fclose(file,MYF(0));
 
4565
  if (str)
 
4566
    die("Too many arguments in option file: %s",name);
 
4567
 
 
4568
  return;
 
4569
}
 
4570
 
 
4571
 
 
4572
static bool
 
4573
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
 
4574
               char *argument)
 
4575
{
 
4576
  switch(optid) {
 
4577
  case 'r':
 
4578
    record = 1;
 
4579
    break;
 
4580
  case 'x':
 
4581
  {
 
4582
    char buff[FN_REFLEN];
 
4583
    if (!test_if_hard_path(argument))
 
4584
    {
 
4585
      strxmov(buff, opt_basedir, argument, NullS);
 
4586
      argument= buff;
 
4587
    }
 
4588
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4589
    assert(cur_file == file_stack && cur_file->file == 0);
 
4590
    if (!(cur_file->file=
 
4591
          my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
 
4592
      die("Could not open '%s' for reading: errno = %d", buff, errno);
 
4593
    cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
 
4594
    cur_file->lineno= 1;
 
4595
    break;
 
4596
  }
 
4597
  case 'm':
 
4598
  {
 
4599
    static char buff[FN_REFLEN];
 
4600
    if (!test_if_hard_path(argument))
 
4601
    {
 
4602
      strxmov(buff, opt_basedir, argument, NullS);
 
4603
      argument= buff;
 
4604
    }
 
4605
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4606
    timer_file= buff;
 
4607
    unlink(timer_file);       /* Ignore error, may not exist */
 
4608
    break;
 
4609
  }
 
4610
  case 'p':
 
4611
    if (argument)
 
4612
    {
 
4613
      my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
 
4614
      opt_pass= my_strdup(argument, MYF(MY_FAE));
 
4615
      while (*argument) *argument++= 'x';    /* Destroy argument */
 
4616
      tty_password= 0;
 
4617
    }
 
4618
    else
 
4619
      tty_password= 1;
 
4620
    break;
 
4621
  case 't':
 
4622
    stpncpy(TMPDIR, argument, sizeof(TMPDIR));
 
4623
    break;
 
4624
  case 'A':
 
4625
    if (!embedded_server_arg_count)
 
4626
    {
 
4627
      embedded_server_arg_count=1;
 
4628
      embedded_server_args[0]= (char*) "";
 
4629
    }
 
4630
    if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
 
4631
        !(embedded_server_args[embedded_server_arg_count++]=
 
4632
          my_strdup(argument, MYF(MY_FAE))))
 
4633
    {
 
4634
      die("Can't use server argument");
 
4635
    }
 
4636
    break;
 
4637
  case 'F':
 
4638
    read_embedded_server_arguments(argument);
 
4639
    break;
 
4640
  case 'V':
 
4641
    print_version();
 
4642
    exit(0);
 
4643
  case '?':
 
4644
    usage();
 
4645
    exit(0);
 
4646
  }
 
4647
  return 0;
 
4648
}
 
4649
 
 
4650
 
 
4651
static int parse_args(int argc, char **argv)
 
4652
{
 
4653
  load_defaults("my",load_default_groups,&argc,&argv);
 
4654
  default_argv= argv;
 
4655
 
 
4656
  if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
 
4657
    exit(1);
 
4658
 
 
4659
  if (argc > 1)
 
4660
  {
 
4661
    usage();
 
4662
    exit(1);
 
4663
  }
 
4664
  if (argc == 1)
 
4665
    opt_db= *argv;
 
4666
  if (tty_password)
 
4667
    opt_pass= get_tty_password(NullS);          /* purify tested */
 
4668
  if (debug_info_flag)
 
4669
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
 
4670
  if (debug_check_flag)
 
4671
    my_end_arg= MY_CHECK_ERROR;
 
4672
 
 
4673
  return 0;
 
4674
}
 
4675
 
4645
4676
/*
4646
4677
  Write the content of str into file
4647
4678
 
4658
4689
  int fd;
4659
4690
  char buff[FN_REFLEN];
4660
4691
  int flags= O_WRONLY | O_CREAT;
4661
 
  if (!internal::test_if_hard_path(fname))
 
4692
  if (!test_if_hard_path(fname))
4662
4693
  {
4663
 
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),fname);
 
4694
    strxmov(buff, opt_basedir, fname, NullS);
4664
4695
    fname= buff;
4665
4696
  }
4666
 
  internal::fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
 
4697
  fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4667
4698
 
4668
4699
  if (!append)
4669
4700
    flags|= O_TRUNC;
4670
 
  if ((fd= internal::my_open(buff, flags,
 
4701
  if ((fd= my_open(buff, flags,
4671
4702
                   MYF(MY_WME | MY_FFNF))) < 0)
4672
4703
    die("Could not open '%s' for writing: errno = %d", buff, errno);
4673
 
  if (append && lseek(fd, 0, SEEK_END) == MY_FILEPOS_ERROR)
 
4704
  if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
4674
4705
    die("Could not find end of file '%s': errno = %d", buff, errno);
4675
 
  if (internal::my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
 
4706
  if (my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP)))
4676
4707
    die("write failed");
4677
 
  internal::my_close(fd, MYF(0));
 
4708
  my_close(fd, MYF(0));
4678
4709
}
4679
4710
 
4680
4711
/*
4696
4727
void dump_result_to_log_file(const char *buf, int size)
4697
4728
{
4698
4729
  char log_file[FN_REFLEN];
4699
 
  str_to_file(internal::fn_format(log_file, result_file_name.c_str(), opt_logdir.c_str(), ".log",
4700
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4730
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
 
4731
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4701
4732
                        MY_REPLACE_EXT),
4702
4733
              buf, size);
4703
4734
  fprintf(stderr, "\nMore results from queries before failure can be found in %s\n",
4707
4738
void dump_progress(void)
4708
4739
{
4709
4740
  char progress_file[FN_REFLEN];
4710
 
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4711
 
                        opt_logdir.c_str(), ".progress",
4712
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4741
  str_to_file(fn_format(progress_file, result_file_name,
 
4742
                        opt_logdir, ".progress",
 
4743
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4713
4744
                        MY_REPLACE_EXT),
4714
4745
              ds_progress.c_str(), ds_progress.length());
4715
4746
}
4718
4749
{
4719
4750
  char warn_file[FN_REFLEN];
4720
4751
 
4721
 
  str_to_file(internal::fn_format(warn_file, result_file_name.c_str(), opt_logdir.c_str(), ".warnings",
4722
 
                        ! opt_logdir.empty() ? MY_REPLACE_DIR | MY_REPLACE_EXT :
 
4752
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
 
4753
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4723
4754
                        MY_REPLACE_EXT),
4724
4755
              ds_warning_messages.c_str(), ds_warning_messages.length());
4725
4756
}
4729
4760
  Append the result for one field to the dynamic string ds
4730
4761
*/
4731
4762
 
4732
 
static void append_field(string *ds, uint32_t col_idx, drizzle_column_st *column,
 
4763
static void append_field(string *ds, uint col_idx, const DRIZZLE_FIELD* field,
4733
4764
                         const char* val, uint64_t len, bool is_null)
4734
4765
{
4735
4766
  if (col_idx < max_replace_column && replace_column[col_idx])
4751
4782
  }
4752
4783
  else
4753
4784
  {
4754
 
    ds->append(drizzle_column_name(column));
 
4785
    ds->append(field->name);
4755
4786
    ds->append("\t");
4756
4787
    replace_append_mem(ds, val, (int)len);
4757
4788
    ds->append("\n");
4764
4795
  Values may be converted with 'replace_column'
4765
4796
*/
4766
4797
 
4767
 
static void append_result(string *ds, drizzle_result_st *res)
 
4798
static void append_result(string *ds, DRIZZLE_RES *res)
4768
4799
{
4769
 
  drizzle_row_t row;
4770
 
  uint32_t num_fields= drizzle_result_column_count(res);
4771
 
  drizzle_column_st *column;
4772
 
  size_t *lengths;
 
4800
  DRIZZLE_ROW row;
 
4801
  uint32_t num_fields= drizzle_num_fields(res);
 
4802
  const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
4803
  uint32_t *lengths;
4773
4804
 
4774
 
  while ((row = drizzle_row_next(res)))
 
4805
  while ((row = drizzle_fetch_row(res)))
4775
4806
  {
4776
4807
    uint32_t i;
4777
 
    lengths = drizzle_row_field_sizes(res);
4778
 
    drizzle_column_seek(res, 0);
 
4808
    lengths = drizzle_fetch_lengths(res);
4779
4809
    for (i = 0; i < num_fields; i++)
4780
 
    {
4781
 
      column= drizzle_column_next(res);
4782
 
      append_field(ds, i, column,
 
4810
      append_field(ds, i, &fields[i],
4783
4811
                   (const char*)row[i], lengths[i], !row[i]);
4784
 
    }
4785
4812
    if (!display_result_vertically)
4786
4813
      ds->append("\n");
4787
4814
 
4793
4820
  Append metadata for fields to output
4794
4821
*/
4795
4822
 
4796
 
static void append_metadata(string *ds, drizzle_result_st *res)
 
4823
static void append_metadata(string *ds,
 
4824
                            const DRIZZLE_FIELD *field,
 
4825
                            uint num_fields)
4797
4826
{
4798
 
  drizzle_column_st *column;
 
4827
  const DRIZZLE_FIELD *field_end;
4799
4828
  ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4800
4829
             "Column_alias\tType\tLength\tMax length\tIs_null\t"
4801
4830
             "Flags\tDecimals\tCharsetnr\n");
4802
4831
 
4803
 
  drizzle_column_seek(res, 0);
4804
 
  while ((column= drizzle_column_next(res)))
 
4832
  for (field_end= field+num_fields ;
 
4833
       field < field_end ;
 
4834
       field++)
4805
4835
  {
4806
 
    ds->append(drizzle_column_catalog(column),
4807
 
               strlen(drizzle_column_catalog(column)));
4808
 
    ds->append("\t", 1);
4809
 
    ds->append(drizzle_column_db(column), strlen(drizzle_column_db(column)));
4810
 
    ds->append("\t", 1);
4811
 
    ds->append(drizzle_column_orig_table(column),
4812
 
               strlen(drizzle_column_orig_table(column)));
4813
 
    ds->append("\t", 1);
4814
 
    ds->append(drizzle_column_table(column),
4815
 
               strlen(drizzle_column_table(column)));
4816
 
    ds->append("\t", 1);
4817
 
    ds->append(drizzle_column_orig_name(column),
4818
 
               strlen(drizzle_column_orig_name(column)));
4819
 
    ds->append("\t", 1);
4820
 
    ds->append(drizzle_column_name(column),
4821
 
               strlen(drizzle_column_name(column)));
4822
 
    ds->append("\t", 1);
4823
 
    replace_append_uint(ds, drizzle_column_type_drizzle(column));
4824
 
    ds->append("\t", 1);
4825
 
    replace_append_uint(ds, drizzle_column_size(column));
4826
 
    ds->append("\t", 1);
4827
 
    replace_append_uint(ds, drizzle_column_max_size(column));
4828
 
    ds->append("\t", 1);
4829
 
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4830
 
    ds->append("\t", 1);
4831
 
    replace_append_uint(ds, drizzle_column_flags(column));
4832
 
    ds->append("\t", 1);
4833
 
    replace_append_uint(ds, drizzle_column_decimals(column));
4834
 
    ds->append("\t", 1);
4835
 
    replace_append_uint(ds, drizzle_column_charset(column));
 
4836
    ds->append(field->catalog,
 
4837
               field->catalog_length);
 
4838
    ds->append("\t", 1);
 
4839
    ds->append(field->db, field->db_length);
 
4840
    ds->append("\t", 1);
 
4841
    ds->append(field->org_table,
 
4842
               field->org_table_length);
 
4843
    ds->append("\t", 1);
 
4844
    ds->append(field->table,
 
4845
               field->table_length);
 
4846
    ds->append("\t", 1);
 
4847
    ds->append(field->org_name,
 
4848
               field->org_name_length);
 
4849
    ds->append("\t", 1);
 
4850
    ds->append(field->name, field->name_length);
 
4851
    ds->append("\t", 1);
 
4852
    replace_append_uint(ds, field->type);
 
4853
    ds->append("\t", 1);
 
4854
    replace_append_uint(ds, field->length);
 
4855
    ds->append("\t", 1);
 
4856
    replace_append_uint(ds, field->max_length);
 
4857
    ds->append("\t", 1);
 
4858
    ds->append((char*) (IS_NOT_NULL(field->flags) ?
 
4859
                        "N" : "Y"), 1);
 
4860
    ds->append("\t", 1);
 
4861
    replace_append_uint(ds, field->flags);
 
4862
    ds->append("\t", 1);
 
4863
    replace_append_uint(ds, field->decimals);
 
4864
    ds->append("\t", 1);
 
4865
    replace_append_uint(ds, field->charsetnr);
4836
4866
    ds->append("\n", 1);
4837
4867
  }
4838
4868
}
4845
4875
static void append_info(string *ds, uint64_t affected_rows,
4846
4876
                        const char *info)
4847
4877
{
4848
 
  ostringstream buf;
4849
 
  buf << "affected rows: " << affected_rows << endl;
4850
 
  ds->append(buf.str());
4851
 
  if (info && strcmp(info, ""))
 
4878
  char buf[40], buff2[21];
 
4879
  sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
 
4880
  ds->append(buf);
 
4881
  if (info)
4852
4882
  {
4853
4883
    ds->append("info: ");
4854
4884
    ds->append(info);
4861
4891
  Display the table headings with the names tab separated
4862
4892
*/
4863
4893
 
4864
 
static void append_table_headings(string *ds, drizzle_result_st *res)
 
4894
static void append_table_headings(string *ds,
 
4895
                                  const DRIZZLE_FIELD *field,
 
4896
                                  uint num_fields)
4865
4897
{
4866
 
  uint32_t col_idx= 0;
4867
 
  drizzle_column_st *column;
4868
 
  drizzle_column_seek(res, 0);
4869
 
  while ((column= drizzle_column_next(res)))
 
4898
  uint col_idx;
 
4899
  for (col_idx= 0; col_idx < num_fields; col_idx++)
4870
4900
  {
4871
4901
    if (col_idx)
4872
4902
      ds->append("\t", 1);
4873
 
    replace_append(ds, drizzle_column_name(column));
4874
 
    col_idx++;
 
4903
    replace_append(ds, field[col_idx].name);
4875
4904
  }
4876
4905
  ds->append("\n", 1);
4877
4906
}
4883
4912
  Number of warnings appended to ds
4884
4913
*/
4885
4914
 
4886
 
static int append_warnings(string *ds, drizzle_con_st *con,
4887
 
                           drizzle_result_st *res)
 
4915
static int append_warnings(string *ds, DRIZZLE *drizzle)
4888
4916
{
4889
 
  uint32_t count;
4890
 
  drizzle_result_st warn_res;
4891
 
  drizzle_return_t ret;
4892
 
 
4893
 
 
4894
 
  if (!(count= drizzle_result_warning_count(res)))
 
4917
  uint count;
 
4918
  DRIZZLE_RES *warn_res;
 
4919
 
 
4920
 
 
4921
  if (!(count= drizzle_warning_count(drizzle)))
4895
4922
    return(0);
4896
4923
 
4897
 
  if (drizzle_query_str(con, &warn_res, "SHOW WARNINGS", &ret) == NULL ||
4898
 
      ret != DRIZZLE_RETURN_OK)
4899
 
  {
4900
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
4901
 
      die("Error running query \"SHOW WARNINGS\": %s", drizzle_result_error(&warn_res));
4902
 
    else
4903
 
      die("Error running query \"SHOW WARNINGS\": %s", drizzle_con_error(con));
4904
 
  }
4905
 
 
4906
 
  if (drizzle_result_column_count(&warn_res) == 0 ||
4907
 
      drizzle_result_buffer(&warn_res) != DRIZZLE_RETURN_OK)
4908
 
    die("Warning count is %u but didn't get any warnings", count);
4909
 
 
4910
 
  append_result(ds, &warn_res);
4911
 
  drizzle_result_free(&warn_res);
 
4924
  /*
 
4925
    If one day we will support execution of multi-statements
 
4926
    through PS API we should not issue SHOW WARNINGS until
 
4927
    we have not read all results...
 
4928
  */
 
4929
  assert(!drizzle_more_results(drizzle));
 
4930
 
 
4931
  if (drizzle_real_query(drizzle, "SHOW WARNINGS", 13))
 
4932
    die("Error running query \"SHOW WARNINGS\": %s", drizzle_error(drizzle));
 
4933
 
 
4934
  if (!(warn_res= drizzle_store_result(drizzle)))
 
4935
    die("Warning count is %u but didn't get any warnings",
 
4936
        count);
 
4937
 
 
4938
  append_result(ds, warn_res);
4912
4939
 
4913
4940
  return(count);
4914
4941
}
4932
4959
                             int flags, char *query, int query_len,
4933
4960
                             string *ds, string *ds_warnings)
4934
4961
{
4935
 
  drizzle_result_st res;
4936
 
  drizzle_return_t ret;
4937
 
  drizzle_con_st *con= &cn->con;
4938
 
  int err= 0;
4939
 
 
4940
 
  drizzle_con_add_options(con, DRIZZLE_CON_NO_RESULT_READ);
 
4962
  DRIZZLE_RES *res= 0;
 
4963
  DRIZZLE *drizzle= &cn->drizzle;
 
4964
  int err= 0, counter= 0;
4941
4965
 
4942
4966
  if (flags & QUERY_SEND_FLAG)
4943
4967
  {
4944
4968
    /*
4945
4969
     * Send the query
4946
4970
     */
4947
 
 
4948
 
    (void) drizzle_query(con, &res, query, query_len, &ret);
4949
 
    if (ret != DRIZZLE_RETURN_OK)
 
4971
    if (do_send_query(cn, query, query_len, flags))
4950
4972
    {
4951
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE ||
4952
 
          ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
4953
 
      {
4954
 
        err= drizzle_result_error_code(&res);
4955
 
        handle_error(command, err, drizzle_result_error(&res),
4956
 
                     drizzle_result_sqlstate(&res), ds);
4957
 
        if (ret == DRIZZLE_RETURN_ERROR_CODE)
4958
 
          drizzle_result_free(&res);
4959
 
      }
4960
 
      else
4961
 
      {
4962
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4963
 
        err= ret;
4964
 
      }
 
4973
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
4974
                   drizzle_sqlstate(drizzle), ds);
4965
4975
      goto end;
4966
4976
    }
4967
4977
  }
4968
4978
  if (!(flags & QUERY_REAP_FLAG))
4969
4979
    return;
4970
4980
 
 
4981
  do
4971
4982
  {
4972
4983
    /*
4973
 
     * Read the result packet
4974
 
     */
4975
 
    if (drizzle_result_read(con, &res, &ret) == NULL ||
4976
 
        ret != DRIZZLE_RETURN_OK)
 
4984
      When  on first result set, call drizzle_read_query_result to retrieve
 
4985
      answer to the query sent earlier
 
4986
    */
 
4987
    if ((counter==0) && drizzle_read_query_result(drizzle))
4977
4988
    {
4978
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
4979
 
      {
4980
 
        handle_error(command, drizzle_result_error_code(&res),
4981
 
                     drizzle_result_error(&res), drizzle_result_sqlstate(&res),
4982
 
                     ds);
4983
 
      }
4984
 
      else
4985
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
4986
 
      drizzle_result_free(&res);
4987
 
      err= ret;
 
4989
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
4990
                   drizzle_sqlstate(drizzle), ds);
4988
4991
      goto end;
 
4992
 
4989
4993
    }
4990
4994
 
4991
4995
    /*
4992
4996
      Store the result of the query if it will return any fields
4993
4997
    */
4994
 
    if (drizzle_result_column_count(&res) &&
4995
 
        (ret= drizzle_result_buffer(&res)) != DRIZZLE_RETURN_OK)
 
4998
    if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
4996
4999
    {
4997
 
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
4998
 
      {
4999
 
        handle_error(command, drizzle_result_error_code(&res),
5000
 
                     drizzle_result_error(&res), drizzle_result_sqlstate(&res),
5001
 
                     ds);
5002
 
      }
5003
 
      else
5004
 
        handle_error(command, ret, drizzle_con_error(con), "", ds);
5005
 
      drizzle_result_free(&res);
5006
 
      err= ret;
 
5000
      handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
5001
                   drizzle_sqlstate(drizzle), ds);
5007
5002
      goto end;
5008
5003
    }
5009
5004
 
5011
5006
    {
5012
5007
      uint64_t affected_rows= 0;    /* Ok to be undef if 'disable_info' is set */
5013
5008
 
5014
 
      if (drizzle_result_column_count(&res))
 
5009
      if (res)
5015
5010
      {
 
5011
        const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
 
5012
        uint num_fields= drizzle_num_fields(res);
 
5013
 
5016
5014
        if (display_metadata)
5017
 
          append_metadata(ds, &res);
 
5015
          append_metadata(ds, fields, num_fields);
5018
5016
 
5019
5017
        if (!display_result_vertically)
5020
 
          append_table_headings(ds, &res);
 
5018
          append_table_headings(ds, fields, num_fields);
5021
5019
 
5022
 
        append_result(ds, &res);
 
5020
        append_result(ds, res);
5023
5021
      }
5024
5022
 
5025
5023
      /*
5026
 
        Need to call drizzle_result_affected_rows() before the "new"
 
5024
        Need to call drizzle_affected_rows() before the "new"
5027
5025
        query to find the warnings
5028
5026
      */
5029
5027
      if (!disable_info)
5030
 
        affected_rows= drizzle_result_affected_rows(&res);
 
5028
        affected_rows= drizzle_affected_rows(drizzle);
5031
5029
 
5032
5030
      /*
5033
5031
        Add all warnings to the result. We can't do this if we are in
5034
5032
        the middle of processing results from multi-statement, because
5035
5033
        this will break protocol.
5036
5034
      */
5037
 
      if (!disable_warnings)
 
5035
      if (!disable_warnings && !drizzle_more_results(drizzle))
5038
5036
      {
5039
 
        drizzle_con_remove_options(con, DRIZZLE_CON_NO_RESULT_READ);
5040
 
        if (append_warnings(ds_warnings, con, &res) || ds_warnings->length())
 
5037
        if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
5041
5038
        {
5042
5039
          ds->append("Warnings:\n", 10);
5043
5040
          ds->append(ds_warnings->c_str(), ds_warnings->length());
5045
5042
      }
5046
5043
 
5047
5044
      if (!disable_info)
5048
 
        append_info(ds, affected_rows, drizzle_result_info(&res));
 
5045
        append_info(ds, affected_rows, drizzle_info(drizzle));
5049
5046
    }
5050
5047
 
5051
 
    drizzle_result_free(&res);
 
5048
    if (res)
 
5049
    {
 
5050
      drizzle_free_result(res);
 
5051
      res= 0;
 
5052
    }
 
5053
    counter++;
 
5054
  } while (!(err= drizzle_next_result(drizzle)));
 
5055
  if (err > 0)
 
5056
  {
 
5057
    /* We got an error from drizzle_next_result, maybe expected */
 
5058
    handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
 
5059
                 drizzle_sqlstate(drizzle), ds);
 
5060
    goto end;
5052
5061
  }
 
5062
  assert(err == -1); /* Successful and there are no more results */
5053
5063
 
5054
5064
  /* If we come here the query is both executed and read successfully */
5055
5065
  handle_no_error(command);
5057
5067
end:
5058
5068
 
5059
5069
  /*
5060
 
    We save the return code (drizzleclient_errno(drizzle)) from the last call sent
5061
 
    to the server into the drizzletest builtin variable $drizzleclient_errno. This
 
5070
    We save the return code (drizzle_errno(drizzle)) from the last call sent
 
5071
    to the server into the drizzletest builtin variable $drizzle_errno. This
5062
5072
    variable then can be used from the test case itself.
5063
5073
  */
5064
 
  drizzle_con_remove_options(con, DRIZZLE_CON_NO_RESULT_READ);
5065
 
  var_set_errno(err);
 
5074
  var_set_errno(drizzle_errno(drizzle));
5066
5075
  return;
5067
5076
}
5068
5077
 
5087
5096
                  unsigned int err_errno, const char *err_error,
5088
5097
                  const char *err_sqlstate, string *ds)
5089
5098
{
5090
 
  uint32_t i;
5091
 
 
5092
 
 
5093
 
  if (! command->require_file.empty())
 
5099
  uint i;
 
5100
 
 
5101
 
 
5102
  if (command->require_file[0])
5094
5103
  {
5095
5104
    /*
5096
5105
      The query after a "--require" failed. This is fine as long the server
5097
5106
      returned a valid reponse. Don't allow 2013 or 2006 to trigger an
5098
5107
      abort_not_supported_test
5099
5108
    */
5100
 
    if (err_errno == DRIZZLE_RETURN_SERVER_GONE)
 
5109
    if (err_errno == CR_SERVER_LOST ||
 
5110
        err_errno == CR_SERVER_GONE_ERROR)
5101
5111
      die("require query '%s' failed: %d: %s", command->query,
5102
5112
          err_errno, err_error);
5103
5113
 
5109
5119
  if (command->abort_on_error)
5110
5120
    die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
5111
5121
 
5112
 
  for (i= 0 ; (uint32_t) i < command->expected_errors.count ; i++)
 
5122
  for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
5113
5123
  {
5114
5124
    if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
5115
5125
         (command->expected_errors.err[i].code.errnum == err_errno)) ||
5116
5126
        ((command->expected_errors.err[i].type == ERR_SQLSTATE) &&
5117
5127
         (strncmp(command->expected_errors.err[i].code.sqlstate,
5118
 
                  err_sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE) == 0)))
 
5128
                  err_sqlstate, SQLSTATE_LENGTH) == 0)))
5119
5129
    {
5120
5130
      if (!disable_result_log)
5121
5131
      {
5249
5259
    Create a temporary dynamic string to contain the output from
5250
5260
    this query.
5251
5261
  */
5252
 
  if (! command->require_file.empty())
 
5262
  if (command->require_file[0])
5253
5263
  {
5254
5264
    ds= &ds_result;
5255
5265
  }
5292
5302
    ds= save_ds;
5293
5303
  }
5294
5304
 
5295
 
  if (! command->require_file.empty())
 
5305
  if (command->require_file[0])
5296
5306
  {
5297
5307
    /* A result file was specified for _this_ query
5298
5308
       and the output should be checked against an already
5310
5320
static void get_command_type(struct st_command* command)
5311
5321
{
5312
5322
  char save;
5313
 
  uint32_t type;
 
5323
  uint type;
5314
5324
 
5315
5325
 
5316
5326
  if (*command->query == '}')
5393
5403
 
5394
5404
*/
5395
5405
 
5396
 
static void mark_progress(struct st_command*, int line)
 
5406
static void mark_progress(struct st_command* command __attribute__((unused)),
 
5407
                          int line)
5397
5408
{
 
5409
  char buf[32], *end;
5398
5410
  uint64_t timer= timer_now();
5399
5411
  if (!progress_start)
5400
5412
    progress_start= timer;
5401
5413
  timer-= progress_start;
5402
5414
 
5403
 
  ostringstream buf;
5404
5415
  /* Milliseconds since start */
5405
 
  buf << timer << "\t";
 
5416
  end= int64_t2str(timer, buf, 10);
 
5417
  ds_progress.append(buf, (int)(end-buf));
 
5418
  ds_progress.append("\t", 1);
5406
5419
 
5407
5420
  /* Parser line number */
5408
 
  buf << line << "\t";
 
5421
  end= int10_to_str(line, buf, 10);
 
5422
  ds_progress.append(buf, (int)(end-buf));
 
5423
  ds_progress.append("\t", 1);
5409
5424
 
5410
5425
  /* Filename */
5411
 
  buf << cur_file->file_name << ":";
 
5426
  ds_progress.append(cur_file->file_name);
 
5427
  ds_progress.append(":", 1);
5412
5428
 
5413
5429
  /* Line in file */
5414
 
  buf << cur_file->lineno << endl;
5415
 
 
5416
 
  ds_progress.append(buf.str());
5417
 
 
5418
 
}
5419
 
 
5420
 
static void check_retries(uint32_t in_opt_max_connect_retries)
5421
 
{
5422
 
  if (in_opt_max_connect_retries > 10000 || opt_max_connect_retries<1)
5423
 
  {
5424
 
    cout << N_("Error: Invalid Value for opt_max_connect_retries"); 
5425
 
    exit(-1);
5426
 
  }
5427
 
  opt_max_connect_retries= in_opt_max_connect_retries;
5428
 
}
5429
 
 
5430
 
static void check_tail_lines(uint32_t in_opt_tail_lines)
5431
 
{
5432
 
  if (in_opt_tail_lines > 10000)
5433
 
  {
5434
 
    cout << N_("Error: Invalid Value for opt_tail_lines"); 
5435
 
    exit(-1);
5436
 
  }
5437
 
  opt_tail_lines= in_opt_tail_lines;
5438
 
}
5439
 
 
5440
 
static void check_sleep(int32_t in_opt_sleep)
5441
 
{
5442
 
  if (in_opt_sleep < -1)
5443
 
  {
5444
 
    cout << N_("Error: Invalid Value for opt_sleep"); 
5445
 
    exit(-1);
5446
 
  }
5447
 
  opt_sleep= in_opt_sleep;
5448
 
}
 
5430
  end= int10_to_str(cur_file->lineno, buf, 10);
 
5431
  ds_progress.append(buf, (int)(end-buf));
 
5432
 
 
5433
 
 
5434
  ds_progress.append("\n", 1);
 
5435
 
 
5436
}
 
5437
 
5449
5438
 
5450
5439
int main(int argc, char **argv)
5451
5440
{
5452
 
try
5453
 
{
5454
5441
  struct st_command *command;
5455
5442
  bool q_send_flag= 0, abort_flag= 0;
5456
 
  uint32_t command_executed= 0, last_command_executed= 0;
5457
 
  string save_file("");
 
5443
  uint command_executed= 0, last_command_executed= 0;
 
5444
  char save_file[FN_REFLEN];
5458
5445
  struct stat res_info;
 
5446
  MY_INIT(argv[0]);
5459
5447
 
 
5448
  save_file[0]= 0;
5460
5449
  TMPDIR[0]= 0;
5461
5450
 
5462
 
  internal::my_init();
5463
 
 
5464
 
  po::options_description commandline_options("Options used only in command line");
5465
 
  commandline_options.add_options()
5466
 
  ("help,?", "Display this help and exit.")
5467
 
  ("mark-progress", po::value<bool>(&opt_mark_progress)->default_value(false)->zero_tokens(),
5468
 
  "Write linenumber and elapsed time to <testname>.progress ")
5469
 
  ("sleep,T", po::value<int32_t>(&opt_sleep)->default_value(-1)->notifier(&check_sleep),
5470
 
  "Sleep always this many seconds on sleep commands.")
5471
 
  ("test-file,x", po::value<string>(),
5472
 
  "Read test from/in this file (default stdin).")
5473
 
  ("timer-file,f", po::value<string>(),
5474
 
  "File where the timing in micro seconds is stored.")
5475
 
  ("tmpdir,t", po::value<string>(),
5476
 
  "Temporary directory where sockets are put.")
5477
 
  ("verbose,v", po::value<bool>(&verbose)->default_value(false),
5478
 
  "Write more.")
5479
 
  ("version,V", "Output version information and exit.")
5480
 
  ("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
5481
 
  "Configuration file defaults are not used if no-defaults is set")
5482
 
  ;
5483
 
 
5484
 
  po::options_description test_options("Options specific to the drizzleimport");
5485
 
  test_options.add_options()
5486
 
  ("basedir,b", po::value<string>(&opt_basedir)->default_value(""),
5487
 
  "Basedir for tests.")
5488
 
  ("character-sets-dir", po::value<string>(&opt_charsets_dir)->default_value(""),
5489
 
  "Directory where character sets are.")
5490
 
  ("database,D", po::value<string>(&opt_db)->default_value(""),
5491
 
  "Database to use.")
5492
 
  ("include,i", po::value<string>(&opt_include)->default_value(""),
5493
 
  "Include SQL before each test case.")  
5494
 
  ("testdir", po::value<string>(&opt_testdir)->default_value(""),
5495
 
  "Path to use to search for test files")
5496
 
  ("logdir", po::value<string>(&opt_logdir)->default_value(""),
5497
 
  "Directory for log files")
5498
 
  ("max-connect-retries", po::value<uint32_t>(&opt_max_connect_retries)->default_value(500)->notifier(&check_retries),
5499
 
  "Max number of connection attempts when connecting to server")
5500
 
  ("quiet,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5501
 
  "Suppress all normal output.")
5502
 
  ("record,r", "Record output of test_file into result file.")
5503
 
  ("result-file,R", po::value<string>(&result_file_name)->default_value(""),
5504
 
  "Read/Store result from/in this file.")
5505
 
  ("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5506
 
  "Suppress all normal output. Synonym for --quiet.")
5507
 
  ("tail-lines", po::value<uint32_t>(&opt_tail_lines)->default_value(0)->notifier(&check_tail_lines),
5508
 
  "Number of lines of the resul to include in a failure report")
5509
 
  ;
5510
 
 
5511
 
  po::options_description client_options("Options specific to the client");
5512
 
  client_options.add_options()
5513
 
 
5514
 
  ("host,h", po::value<string>(&opt_host)->default_value("localhost"),
5515
 
  "Connect to host.")
5516
 
  ("password,P", po::value<string>(&password)->default_value("PASSWORD_SENTINEL"),
5517
 
  "Password to use when connecting to server.")
5518
 
  ("port,p", po::value<uint32_t>(&opt_port)->default_value(0),
5519
 
  "Port number to use for connection or 0 for default")
5520
 
  ("protocol", po::value<string>(&opt_protocol),
5521
 
  "The protocol of connection (mysql or drizzle).")
5522
 
  ("user,u", po::value<string>(&opt_user)->default_value(""),
5523
 
  "User for login.")
5524
 
  ;
5525
 
 
5526
 
  po::positional_options_description p;
5527
 
  p.add("database", 1);
5528
 
 
5529
 
  po::options_description long_options("Allowed Options");
5530
 
  long_options.add(commandline_options).add(test_options).add(client_options);
5531
 
 
5532
 
  std::string system_config_dir_test(SYSCONFDIR); 
5533
 
  system_config_dir_test.append("/drizzle/drizzletest.cnf");
5534
 
 
5535
 
  std::string system_config_dir_client(SYSCONFDIR); 
5536
 
  system_config_dir_client.append("/drizzle/client.cnf");
5537
 
 
5538
 
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
5539
 
 
5540
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
5541
 
  {
5542
 
    char *homedir;
5543
 
    homedir= getenv("HOME");
5544
 
    if (homedir != NULL)
5545
 
      user_config_dir.replace(0, 1, homedir);
5546
 
  }
5547
 
 
5548
 
  po::variables_map vm;
5549
 
 
5550
 
  // Disable allow_guessing
5551
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
5552
 
 
5553
 
  po::store(po::command_line_parser(argc, argv).options(long_options).
5554
 
            style(style).positional(p).extra_parser(parse_password_arg).run(),
5555
 
            vm);
5556
 
 
5557
 
  if (! vm["no-defaults"].as<bool>())
5558
 
  {
5559
 
    std::string user_config_dir_test(user_config_dir);
5560
 
    user_config_dir_test.append("/drizzle/drizzletest.cnf"); 
5561
 
 
5562
 
    std::string user_config_dir_client(user_config_dir);
5563
 
    user_config_dir_client.append("/drizzle/client.cnf");
5564
 
 
5565
 
    ifstream user_test_ifs(user_config_dir_test.c_str());
5566
 
    po::store(parse_config_file(user_test_ifs, test_options), vm);
5567
 
 
5568
 
    ifstream user_client_ifs(user_config_dir_client.c_str());
5569
 
    po::store(parse_config_file(user_client_ifs, client_options), vm);
5570
 
 
5571
 
    ifstream system_test_ifs(system_config_dir_test.c_str());
5572
 
    store(parse_config_file(system_test_ifs, test_options), vm);
5573
 
 
5574
 
    ifstream system_client_ifs(system_config_dir_client.c_str());
5575
 
    po::store(parse_config_file(system_client_ifs, client_options), vm);
5576
 
  }
5577
 
 
5578
 
  po::notify(vm);
5579
 
 
5580
5451
  /* Init expected errors */
5581
5452
  memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
5582
5453
 
5600
5471
  cur_block->ok= true; /* Outer block should always be executed */
5601
5472
  cur_block->cmd= cmd_none;
5602
5473
 
5603
 
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_version());
 
5474
  if (hash_init(&var_hash, charset_info,
 
5475
                1024, 0, 0, get_var_key, var_free, MYF(0)))
 
5476
    die("Variable hash initialization failed");
 
5477
 
 
5478
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
5604
5479
 
5605
5480
  memset(&master_pos, 0, sizeof(master_pos));
5606
5481
 
5613
5488
  ds_progress.reserve(2048);
5614
5489
  ds_warning_messages.reserve(2048);
5615
5490
 
5616
 
 
5617
 
  if (vm.count("record"))
5618
 
  {
5619
 
    record = 1;
5620
 
  }
5621
 
 
5622
 
  if (vm.count("test-file"))
5623
 
  {
5624
 
    string tmp= vm["test-file"].as<string>();
5625
 
    char buff[FN_REFLEN];
5626
 
    if (!internal::test_if_hard_path(tmp.c_str()))
5627
 
    {
5628
 
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5629
 
      tmp= buff;
5630
 
    }
5631
 
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5632
 
    assert(cur_file == file_stack && cur_file->file == 0);
5633
 
    if (!(cur_file->file= fopen(buff, "r")))
5634
 
    {
5635
 
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5636
 
      return EXIT_ARGUMENT_INVALID;
5637
 
    }
5638
 
    if (!(cur_file->file_name= strdup(buff)))
5639
 
    {
5640
 
      fprintf(stderr, _("Out of memory"));
5641
 
      return EXIT_OUT_OF_MEMORY;
5642
 
    }
5643
 
    cur_file->lineno= 1;
5644
 
  }
5645
 
 
5646
 
  if (vm.count("timer-file"))
5647
 
  {
5648
 
    string tmp= vm["timer-file"].as<string>().c_str();
5649
 
    static char buff[FN_REFLEN];
5650
 
    if (!internal::test_if_hard_path(tmp.c_str()))
5651
 
    {
5652
 
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5653
 
      tmp= buff;
5654
 
    }
5655
 
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5656
 
    timer_file= buff;
5657
 
    unlink(timer_file);       /* Ignore error, may not exist */
5658
 
  }
5659
 
 
5660
 
  if (vm.count("protocol"))
5661
 
  {
5662
 
    std::transform(opt_protocol.begin(), opt_protocol.end(),
5663
 
      opt_protocol.begin(), ::tolower);
5664
 
 
5665
 
    if (not opt_protocol.compare("mysql"))
5666
 
      use_drizzle_protocol=false;
5667
 
    else if (not opt_protocol.compare("drizzle"))
5668
 
      use_drizzle_protocol=true;
5669
 
    else
5670
 
    {
5671
 
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
5672
 
      exit(-1);
5673
 
    }
5674
 
  }
5675
 
 
5676
 
  if (vm.count("port"))
5677
 
  {
5678
 
    /* If the port number is > 65535 it is not a valid port
5679
 
       This also helps with potential data loss casting unsigned long to a
5680
 
       uint32_t. */
5681
 
    if (opt_port > 65535)
5682
 
    {
5683
 
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
5684
 
      exit(EXIT_ARGUMENT_INVALID);
5685
 
    }
5686
 
  }
5687
 
 
5688
 
  if( vm.count("password") )
5689
 
  {
5690
 
    if (!opt_password.empty())
5691
 
      opt_password.erase();
5692
 
    if (password == PASSWORD_SENTINEL)
5693
 
    {
5694
 
      opt_password= "";
5695
 
    }
5696
 
    else
5697
 
    {
5698
 
      opt_password= password;
5699
 
      tty_password= false;
5700
 
    }
5701
 
  }
5702
 
  else
5703
 
  {
5704
 
      tty_password= true;
5705
 
  }
5706
 
 
5707
 
  if (vm.count("tmpdir"))
5708
 
  {
5709
 
    strncpy(TMPDIR, vm["tmpdir"].as<string>().c_str(), sizeof(TMPDIR));
5710
 
  }
5711
 
 
5712
 
  if (vm.count("version"))
5713
 
  {
5714
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5715
 
    drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5716
 
    exit(0);
5717
 
  }
5718
 
  
5719
 
  if (vm.count("help"))
5720
 
  {
5721
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5722
 
    drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5723
 
    printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
5724
 
    printf("Drizzle version modified by Brian, Jay, Monty Taylor, PatG and Stewart\n");
5725
 
    printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
5726
 
    printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
5727
 
    printf("Usage: %s [OPTIONS] [database] < test_file\n", internal::my_progname);
5728
 
    exit(0);
5729
 
  }
5730
 
 
5731
 
  if (tty_password)
5732
 
  {
5733
 
    opt_pass= client_get_tty_password(NULL);          /* purify tested */
5734
 
  }
 
5491
  parse_args(argc, argv);
5735
5492
 
5736
5493
  server_initialized= 1;
5737
5494
  if (cur_file == file_stack && cur_file->file == 0)
5738
5495
  {
5739
5496
    cur_file->file= stdin;
5740
 
    cur_file->file_name= strdup("<stdin>");
5741
 
    if (cur_file->file_name == NULL)
5742
 
      die("Out of memory");
 
5497
    cur_file->file_name= my_strdup("<stdin>", MYF(MY_WME));
5743
5498
    cur_file->lineno= 1;
5744
5499
  }
5745
5500
  cur_con= connections;
5746
 
  if ((cur_con->drizzle= drizzle_create(NULL)) == NULL)
 
5501
  if (!( drizzle_create(&cur_con->drizzle)))
5747
5502
    die("Failed in drizzle_create()");
5748
 
  if (!( drizzle_con_create(cur_con->drizzle, &cur_con->con)))
5749
 
    die("Failed in drizzle_con_create()");
5750
 
  drizzle_con_add_options(&cur_con->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
5503
  if (opt_compress)
 
5504
    drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NullS);
 
5505
  drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
 
5506
  drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_NAME,
 
5507
                  charset_info->csname);
 
5508
  int opt_protocol= DRIZZLE_PROTOCOL_TCP;
 
5509
  drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
 
5510
  if (opt_charsets_dir)
 
5511
    drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_DIR,
 
5512
                    opt_charsets_dir);
5751
5513
 
5752
 
  if (!(cur_con->name = strdup("default")))
 
5514
  if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5753
5515
    die("Out of memory");
5754
 
  safe_connect(&cur_con->con, cur_con->name, opt_host, opt_user, opt_pass,
 
5516
 
 
5517
  safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
5755
5518
               opt_db, opt_port);
5756
5519
 
5757
 
  fill_global_error_names();
5758
 
 
5759
5520
  /* Use all time until exit if no explicit 'start_timer' */
5760
5521
  timer_start= timer_now();
5761
5522
 
5762
5523
  /*
5763
 
    Initialize $drizzleclient_errno with -1, so we can
 
5524
    Initialize $drizzle_errno with -1, so we can
5764
5525
    - distinguish it from valid values ( >= 0 ) and
5765
5526
    - detect if there was never a command sent to the server
5766
5527
  */
5767
5528
  var_set_errno(-1);
5768
5529
 
5769
 
  /* Update $drizzleclient_get_server_version to that of current connection */
5770
 
  var_set_drizzleclient_get_server_version(&cur_con->con);
 
5530
  /* Update $drizzle_get_server_version to that of current connection */
 
5531
  var_set_drizzle_get_server_version(&cur_con->drizzle);
5771
5532
 
5772
 
  if (! opt_include.empty())
 
5533
  if (opt_include)
5773
5534
  {
5774
 
    open_file(opt_include.c_str());
 
5535
    open_file(opt_include);
5775
5536
  }
5776
5537
 
5777
5538
  while (!read_command(&command) && !abort_flag)
5885
5646
        /* Check for special property for this query */
5886
5647
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5887
5648
 
5888
 
        if (! save_file.empty())
 
5649
        if (save_file[0])
5889
5650
        {
5890
 
          command->require_file= save_file;
5891
 
          save_file.clear();
 
5651
          strmake(command->require_file, save_file, sizeof(save_file) - 1);
 
5652
          save_file[0]= 0;
5892
5653
        }
5893
5654
        run_query(cur_con, command, flags);
5894
5655
        command_executed++;
5925
5686
        command->last_argument= command->end;
5926
5687
        break;
5927
5688
      case Q_REQUIRE:
5928
 
        do_get_file_name(command, save_file);
 
5689
        do_get_file_name(command, save_file, sizeof(save_file));
5929
5690
        break;
5930
5691
      case Q_ERROR:
5931
5692
        do_get_errcodes(command);
5955
5716
        command->last_argument= command->end;
5956
5717
        break;
5957
5718
      case Q_PING:
5958
 
        {
5959
 
          drizzle_result_st result;
5960
 
          drizzle_return_t ret;
5961
 
          (void) drizzle_ping(&cur_con->con, &result, &ret);
5962
 
          if (ret == DRIZZLE_RETURN_OK || ret == DRIZZLE_RETURN_ERROR_CODE)
5963
 
            drizzle_result_free(&result);
5964
 
        }
 
5719
        (void) drizzle_ping(&cur_con->drizzle);
5965
5720
        break;
5966
5721
      case Q_EXEC:
5967
5722
        do_exec(command);
5979
5734
        do_set_charset(command);
5980
5735
        break;
5981
5736
      case Q_DISABLE_RECONNECT:
5982
 
        set_reconnect(&cur_con->con, 0);
 
5737
        set_reconnect(&cur_con->drizzle, 0);
5983
5738
        break;
5984
5739
      case Q_ENABLE_RECONNECT:
5985
 
        set_reconnect(&cur_con->con, 1);
 
5740
        set_reconnect(&cur_con->drizzle, 1);
5986
5741
        break;
5987
5742
      case Q_DISABLE_PARSING:
5988
5743
        if (parsing_disabled == 0)
6075
5830
  */
6076
5831
  if (ds_res.length())
6077
5832
  {
6078
 
    if (! result_file_name.empty())
 
5833
    if (result_file_name)
6079
5834
    {
6080
5835
      /* A result file has been specified */
6081
5836
 
6082
5837
      if (record)
6083
5838
      {
6084
5839
        /* Recording - dump the output from test to result file */
6085
 
        str_to_file(result_file_name.c_str(), ds_res.c_str(), ds_res.length());
 
5840
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
6086
5841
      }
6087
5842
      else
6088
5843
      {
6105
5860
  }
6106
5861
 
6107
5862
  if (!command_executed &&
6108
 
      ! result_file_name.empty() && !stat(result_file_name.c_str(), &res_info))
 
5863
      result_file_name && !stat(result_file_name, &res_info))
6109
5864
  {
6110
5865
    /*
6111
5866
      my_stat() successful on result file. Check if we have not run a
6117
5872
    die("No queries executed but result file found!");
6118
5873
  }
6119
5874
 
6120
 
  if ( opt_mark_progress && ! result_file_name.empty() )
 
5875
  if ( opt_mark_progress && result_file_name )
6121
5876
    dump_progress();
6122
5877
 
6123
5878
  /* Dump warning messages */
6124
 
  if (! result_file_name.empty() && ds_warning_messages.length())
 
5879
  if (result_file_name && ds_warning_messages.length())
6125
5880
    dump_warning_messages();
6126
5881
 
6127
5882
  timer_output();
6128
5883
  /* Yes, if we got this far the test has suceeded! Sakila smiles */
6129
5884
  cleanup_and_exit(0);
6130
 
}
6131
 
 
6132
 
  catch(exception &err)
6133
 
  {
6134
 
    cerr<<err.what()<<endl;
6135
 
  }
6136
 
 
6137
5885
  return 0; /* Keep compiler happy too */
6138
5886
}
6139
5887
 
6163
5911
{
6164
5912
  if (timer_file)
6165
5913
  {
6166
 
    ostringstream buf;
 
5914
    char buf[32], *end;
6167
5915
    uint64_t timer= timer_now() - timer_start;
6168
 
    buf << timer;
6169
 
    str_to_file(timer_file,buf.str().c_str(), buf.str().size() );
 
5916
    end= int64_t2str(timer, buf, 10);
 
5917
    str_to_file(timer_file,buf, (int) (end-buf));
6170
5918
    /* Timer has been written to the file, don't use it anymore */
6171
5919
    timer_file= 0;
6172
5920
  }
6175
5923
 
6176
5924
uint64_t timer_now(void)
6177
5925
{
6178
 
#if defined(HAVE_GETHRTIME)
6179
 
  return gethrtime()/1000/1000;
6180
 
#else
6181
 
  uint64_t newtime;
6182
 
  struct timeval t;
6183
 
  /*
6184
 
    The following loop is here because gettimeofday may fail on some systems
6185
 
  */
6186
 
  while (gettimeofday(&t, NULL) != 0)
6187
 
  {}
6188
 
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
6189
 
  return newtime/1000;
6190
 
#endif  /* defined(HAVE_GETHRTIME) */
 
5926
  return my_micro_time() / 1000;
6191
5927
}
6192
5928
 
6193
5929
 
6210
5946
    die("Missing argument in %s", command->query);
6211
5947
 
6212
5948
  /* Allocate a buffer for results */
6213
 
  start= buff= (char *)malloc(strlen(from)+1);
 
5949
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6214
5950
  while (*from)
6215
5951
  {
6216
5952
    char *to;
6217
 
    uint32_t column_number;
 
5953
    uint column_number;
6218
5954
 
6219
5955
    to= get_string(&buff, &from, command);
6220
5956
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6222
5958
    if (!*from)
6223
5959
      die("Wrong number of arguments to replace_column in '%s'", command->query);
6224
5960
    to= get_string(&buff, &from, command);
6225
 
    free(replace_column[column_number-1]);
6226
 
    replace_column[column_number-1]= strdup(to);
6227
 
    if (replace_column[column_number-1] == NULL)
6228
 
      die("Out of memory");
 
5961
    my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
 
5962
    replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
6229
5963
    set_if_bigger(max_replace_column, column_number);
6230
5964
  }
6231
 
  free(start);
 
5965
  my_free(start, MYF(0));
6232
5966
  command->last_argument= command->end;
6233
5967
}
6234
5968
 
6235
5969
 
6236
5970
void free_replace_column()
6237
5971
{
6238
 
  uint32_t i;
 
5972
  uint i;
6239
5973
  for (i=0 ; i < max_replace_column ; i++)
6240
5974
  {
6241
5975
    if (replace_column[i])
6242
5976
    {
6243
 
      free(replace_column[i]);
 
5977
      my_free(replace_column[i], 0);
6244
5978
      replace_column[i]= 0;
6245
5979
    }
6246
5980
  }
6257
5991
 
6258
5992
typedef struct st_pointer_array {    /* when using array-strings */
6259
5993
  TYPELIB typelib;        /* Pointer to strings */
6260
 
  unsigned char  *str;          /* Strings is here */
6261
 
  uint8_t *flag;          /* Flag about each var. */
6262
 
  uint32_t  array_allocs,max_count,length,max_length;
 
5994
  uchar  *str;          /* Strings is here */
 
5995
  int7  *flag;          /* Flag about each var. */
 
5996
  uint  array_allocs,max_count,length,max_length;
6263
5997
} POINTER_ARRAY;
6264
5998
 
6265
5999
struct st_replace;
6266
 
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
 
6000
struct st_replace *init_replace(char * *from, char * *to, uint count,
6267
6001
                                char * word_end_chars);
6268
6002
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6269
6003
void replace_strings_append(struct st_replace *rep, string* ds,
6270
6004
                            const char *from, int len);
6271
6005
void free_pointer_array(POINTER_ARRAY *pa);
6272
6006
 
6273
 
struct st_replace *glob_replace= NULL;
 
6007
struct st_replace *glob_replace;
6274
6008
 
6275
6009
/*
6276
6010
  Get arguments for replace. The syntax is:
6282
6016
 
6283
6017
void do_get_replace(struct st_command *command)
6284
6018
{
6285
 
  uint32_t i;
 
6019
  uint i;
6286
6020
  char *from= command->first_argument;
6287
6021
  char *buff, *start;
6288
6022
  char word_end_chars[256], *pos;
6295
6029
  memset(&from_array, 0, sizeof(from_array));
6296
6030
  if (!*from)
6297
6031
    die("Missing argument in %s", command->query);
6298
 
  start= buff= (char *)malloc(strlen(from)+1);
 
6032
  start= buff= (char *)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
6299
6033
  while (*from)
6300
6034
  {
6301
6035
    char *to= buff;
6313
6047
  *pos=0;          /* End pointer */
6314
6048
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
6315
6049
                                   (char**) to_array.typelib.type_names,
6316
 
                                   (uint32_t) from_array.typelib.count,
 
6050
                                   (uint) from_array.typelib.count,
6317
6051
                                   word_end_chars)))
6318
6052
    die("Can't initialize replace from '%s'", command->query);
6319
6053
  free_pointer_array(&from_array);
6320
6054
  free_pointer_array(&to_array);
6321
 
  free(start);
 
6055
  my_free(start, MYF(0));
6322
6056
  command->last_argument= command->end;
6323
6057
  return;
6324
6058
}
6329
6063
 
6330
6064
  if (glob_replace)
6331
6065
  {
6332
 
    free(glob_replace);
 
6066
    my_free(glob_replace,MYF(0));
6333
6067
    glob_replace=0;
6334
6068
  }
6335
6069
  return;
6344
6078
typedef struct st_replace_found {
6345
6079
  bool found;
6346
6080
  char *replace_string;
6347
 
  uint32_t to_offset;
 
6081
  uint to_offset;
6348
6082
  int from_offset;
6349
6083
} REPLACE_STRING;
6350
6084
 
6363
6097
  {
6364
6098
    /* Loop through states */
6365
6099
    while (!rep_pos->found)
6366
 
      rep_pos= rep_pos->next[(unsigned char) *from++];
 
6100
      rep_pos= rep_pos->next[(uchar) *from++];
6367
6101
 
6368
6102
    /* Does this state contain a string to be replaced */
6369
6103
    if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6402
6136
  char* pattern; /* Pattern to be replaced */
6403
6137
  char* replace; /* String or expression to replace the pattern with */
6404
6138
  int icase; /* true if the match is case insensitive */
6405
 
  int global; /* true if the match should be global -- 
6406
 
                 i.e. repeat the matching until the end of the string */
6407
6139
};
6408
6140
 
6409
6141
struct st_replace_regex
6427
6159
struct st_replace_regex *glob_replace_regex= 0;
6428
6160
 
6429
6161
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6430
 
                char *string, int icase, int global);
 
6162
                char *string, int icase);
6431
6163
 
6432
6164
 
6433
6165
 
6472
6204
  char* buf,*expr_end;
6473
6205
  char* p;
6474
6206
  char* buf_p;
6475
 
  uint32_t expr_len= strlen(expr);
 
6207
  uint expr_len= strlen(expr);
6476
6208
  char last_c = 0;
6477
6209
  struct st_regex reg;
6478
6210
 
6479
 
  res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
6480
 
  if (!res)
6481
 
    return NULL;
 
6211
  /* my_malloc() will die on fail with MY_FAE */
 
6212
  res=(struct st_replace_regex*)my_malloc(
 
6213
                                          sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
6482
6214
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
6483
6215
 
6484
6216
  buf= (char*)res + sizeof(*res);
6528
6260
 
6529
6261
    /* Check if we should do matching case insensitive */
6530
6262
    if (p < expr_end && *p == 'i')
6531
 
    {
6532
 
      p++;
6533
6263
      reg.icase= 1;
6534
 
    }
6535
 
 
6536
 
    /* Check if we should do matching globally */
6537
 
    if (p < expr_end && *p == 'g')
6538
 
    {
6539
 
      p++;
6540
 
      reg.global= 1;
6541
 
    }
6542
6264
 
6543
6265
    /* done parsing the statement, now place it in regex_arr */
6544
 
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6266
    if (insert_dynamic(&res->regex_arr,(uchar*) &reg))
6545
6267
      die("Out of memory");
6546
6268
  }
6547
6269
  res->odd_buf_len= res->even_buf_len= 8192;
6548
 
  res->even_buf= (char*)malloc(res->even_buf_len);
6549
 
  res->odd_buf= (char*)malloc(res->odd_buf_len);
 
6270
  res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
 
6271
  res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
6550
6272
  res->buf= res->even_buf;
6551
6273
 
6552
6274
  return res;
6553
6275
 
6554
6276
err:
6555
 
  free(res);
 
6277
  my_free(res,0);
6556
6278
  die("Error parsing replace_regex \"%s\"", expr);
6557
6279
  return 0;
6558
6280
}
6578
6300
 
6579
6301
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6580
6302
{
6581
 
  uint32_t i;
 
6303
  uint i;
6582
6304
  char* in_buf, *out_buf;
6583
6305
  int* buf_len_p;
6584
6306
 
6593
6315
    struct st_regex re;
6594
6316
    char* save_out_buf= out_buf;
6595
6317
 
6596
 
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6318
    get_dynamic(&r->regex_arr,(uchar*)&re,i);
6597
6319
 
6598
6320
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6599
 
                     in_buf, re.icase, re.global))
 
6321
                     in_buf, re.icase))
6600
6322
    {
6601
6323
      /* if the buffer has been reallocated, make adjustements */
6602
6324
      if (save_out_buf != out_buf)
6644
6366
  if (glob_replace_regex)
6645
6367
  {
6646
6368
    delete_dynamic(&glob_replace_regex->regex_arr);
6647
 
    free(glob_replace_regex->even_buf);
6648
 
    free(glob_replace_regex->odd_buf);
6649
 
    free(glob_replace_regex);
 
6369
    my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6370
    my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
 
6371
    my_free(glob_replace_regex,MYF(0));
6650
6372
    glob_replace_regex=0;
6651
6373
  }
6652
6374
}
6654
6376
 
6655
6377
 
6656
6378
/*
 
6379
  auxiluary macro used by reg_replace
 
6380
  makes sure the result buffer has sufficient length
 
6381
*/
 
6382
#define SECURE_REG_BUF   if (buf_len < need_buf_len)                    \
 
6383
  {                                                                     \
 
6384
    int off= res_p - buf;                                               \
 
6385
    buf= (char*)my_realloc(buf,need_buf_len,MYF(MY_WME+MY_FAE));        \
 
6386
    res_p= buf + off;                                                   \
 
6387
    buf_len= need_buf_len;                                              \
 
6388
  }                                                                     \
 
6389
                                                                        \
 
6390
/*
6657
6391
  Performs a regex substitution
6658
6392
 
6659
6393
  IN:
6666
6400
  icase - flag, if set to 1 the match is case insensitive
6667
6401
*/
6668
6402
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
6669
 
                char *replace, char *in_string, int icase, int global)
 
6403
                char *replace, char *in_string, int icase)
6670
6404
{
6671
 
  const char *error= NULL;
6672
 
  int erroffset;
6673
 
  int ovector[3];
6674
 
  pcre *re= pcre_compile(pattern,
6675
 
                         icase ? PCRE_CASELESS | PCRE_MULTILINE : PCRE_MULTILINE,
6676
 
                         &error, &erroffset, NULL);
6677
 
  if (re == NULL)
6678
 
    return 1;
6679
 
 
6680
 
  if (! global)
6681
 
  {
6682
 
 
6683
 
    int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
6684
 
                      0, 0, ovector, 3);
6685
 
    if (rc < 0)
6686
 
    {
6687
 
      pcre_free(re);
6688
 
      return 1;
6689
 
    }
6690
 
 
6691
 
    char *substring_to_replace= in_string + ovector[0];
6692
 
    int substring_length= ovector[1] - ovector[0];
6693
 
    *buf_len_p= strlen(in_string) - substring_length + strlen(replace);
6694
 
    char * new_buf = (char *)malloc(*buf_len_p+1);
6695
 
    if (new_buf == NULL)
6696
 
    {
6697
 
      pcre_free(re);
6698
 
      return 1;
6699
 
    }
6700
 
 
6701
 
    memset(new_buf, 0, *buf_len_p+1);
6702
 
    strncpy(new_buf, in_string, substring_to_replace-in_string);
6703
 
    strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
6704
 
    strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
6705
 
            substring_to_replace + substring_length,
6706
 
            strlen(in_string)
6707
 
              - substring_length
6708
 
              - (substring_to_replace-in_string));
6709
 
    *buf_p= new_buf;
6710
 
 
6711
 
    pcre_free(re);
6712
 
    return 0;
6713
 
  }
6714
 
  else
6715
 
  {
6716
 
    /* Repeatedly replace the string with the matched regex */
6717
 
    string subject(in_string);
6718
 
    size_t replace_length= strlen(replace);
6719
 
    size_t length_of_replacement= strlen(replace);
6720
 
    size_t current_position= 0;
6721
 
    int rc= 0;
6722
 
 
6723
 
    while (true) 
6724
 
    {
6725
 
      rc= pcre_exec(re, NULL, subject.c_str(), subject.length(), 
6726
 
                    current_position, 0, ovector, 3);
6727
 
      if (rc < 0)
6728
 
      {
6729
 
        break;
6730
 
      }
6731
 
 
6732
 
      current_position= static_cast<size_t>(ovector[0]);
6733
 
      replace_length= static_cast<size_t>(ovector[1] - ovector[0]);
6734
 
      subject.replace(current_position, replace_length, replace, length_of_replacement);
6735
 
      current_position= current_position + length_of_replacement;
6736
 
    }
6737
 
 
6738
 
    char *new_buf = (char *) malloc(subject.length() + 1);
6739
 
    if (new_buf == NULL)
6740
 
    {
6741
 
      pcre_free(re);
6742
 
      return 1;
6743
 
    }
6744
 
    memset(new_buf, 0, subject.length() + 1);
6745
 
    strncpy(new_buf, subject.c_str(), subject.length());
6746
 
    *buf_len_p= subject.length() + 1;
6747
 
    *buf_p= new_buf;
6748
 
          
6749
 
    pcre_free(re);
6750
 
    return 0;
6751
 
  }
 
6405
  string string_to_match(in_string);
 
6406
  pcrecpp::RE_Options opt;
 
6407
 
 
6408
  if (icase)
 
6409
    opt.set_caseless(true);
 
6410
 
 
6411
  if (!pcrecpp::RE(pattern, opt).Replace(replace,&string_to_match)){
 
6412
    return 1;
 
6413
  }
 
6414
 
 
6415
  const char * new_str= string_to_match.c_str();
 
6416
  *buf_len_p= strlen(new_str);
 
6417
  char * new_buf = (char *)malloc(*buf_len_p+1);
 
6418
  if (new_buf == NULL)
 
6419
  {
 
6420
    return 1;
 
6421
  }
 
6422
  strcpy(new_buf, new_str);
 
6423
  buf_p= &new_buf;
 
6424
 
 
6425
  return 0;
6752
6426
}
6753
6427
 
6754
6428
 
6755
6429
#ifndef WORD_BIT
6756
 
#define WORD_BIT (8*sizeof(uint32_t))
 
6430
#define WORD_BIT (8*sizeof(uint))
6757
6431
#endif
6758
6432
 
6759
6433
#define SET_MALLOC_HUNC 64
6760
6434
#define LAST_CHAR_CODE 259
6761
6435
 
6762
6436
typedef struct st_rep_set {
6763
 
  uint32_t  *bits;        /* Pointer to used sets */
 
6437
  uint  *bits;        /* Pointer to used sets */
6764
6438
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6765
 
  uint32_t  found_len;      /* Best match to date */
 
6439
  uint  found_len;      /* Best match to date */
6766
6440
  int  found_offset;
6767
 
  uint32_t  table_offset;
6768
 
  uint32_t  size_of_bits;      /* For convinience */
 
6441
  uint  table_offset;
 
6442
  uint  size_of_bits;      /* For convinience */
6769
6443
} REP_SET;
6770
6444
 
6771
6445
typedef struct st_rep_sets {
6772
 
  uint32_t    count;      /* Number of sets */
6773
 
  uint32_t    extra;      /* Extra sets in buffer */
6774
 
  uint32_t    invisible;    /* Sets not chown */
6775
 
  uint32_t    size_of_bits;
 
6446
  uint    count;      /* Number of sets */
 
6447
  uint    extra;      /* Extra sets in buffer */
 
6448
  uint    invisible;    /* Sets not chown */
 
6449
  uint    size_of_bits;
6776
6450
  REP_SET  *set,*set_buffer;
6777
 
  uint32_t    *bit_buffer;
 
6451
  uint    *bit_buffer;
6778
6452
} REP_SETS;
6779
6453
 
6780
6454
typedef struct st_found_set {
6781
 
  uint32_t table_offset;
 
6455
  uint table_offset;
6782
6456
  int found_offset;
6783
6457
} FOUND_SET;
6784
6458
 
6785
6459
typedef struct st_follow {
6786
6460
  int chr;
6787
 
  uint32_t table_offset;
6788
 
  uint32_t len;
 
6461
  uint table_offset;
 
6462
  uint len;
6789
6463
} FOLLOWS;
6790
6464
 
6791
6465
 
6792
 
int init_sets(REP_SETS *sets,uint32_t states);
 
6466
int init_sets(REP_SETS *sets,uint states);
6793
6467
REP_SET *make_new_set(REP_SETS *sets);
6794
6468
void make_sets_invisible(REP_SETS *sets);
6795
6469
void free_last_set(REP_SETS *sets);
6796
6470
void free_sets(REP_SETS *sets);
6797
 
void internal_set_bit(REP_SET *set, uint32_t bit);
6798
 
void internal_clear_bit(REP_SET *set, uint32_t bit);
 
6471
void internal_set_bit(REP_SET *set, uint bit);
 
6472
void internal_clear_bit(REP_SET *set, uint bit);
6799
6473
void or_bits(REP_SET *to,REP_SET *from);
6800
6474
void copy_bits(REP_SET *to,REP_SET *from);
6801
6475
int cmp_bits(REP_SET *set1,REP_SET *set2);
6802
 
int get_next_bit(REP_SET *set,uint32_t lastpos);
 
6476
int get_next_bit(REP_SET *set,uint lastpos);
6803
6477
int find_set(REP_SETS *sets,REP_SET *find);
6804
 
int find_found(FOUND_SET *found_set,uint32_t table_offset,
 
6478
int find_found(FOUND_SET *found_set,uint table_offset,
6805
6479
               int found_offset);
6806
 
uint32_t start_at_word(char * pos);
6807
 
uint32_t end_of_word(char * pos);
6808
 
 
6809
 
static uint32_t found_sets=0;
6810
 
 
6811
 
 
6812
 
static uint32_t replace_len(char * str)
 
6480
uint start_at_word(char * pos);
 
6481
uint end_of_word(char * pos);
 
6482
 
 
6483
static uint found_sets=0;
 
6484
 
 
6485
 
 
6486
static uint replace_len(char * str)
6813
6487
{
6814
 
  uint32_t len=0;
 
6488
  uint len=0;
6815
6489
  while (*str)
6816
6490
  {
6817
6491
    if (str[0] == '\\' && str[1])
6824
6498
 
6825
6499
/* Init a replace structure for further calls */
6826
6500
 
6827
 
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
 
6501
REPLACE *init_replace(char * *from, char * *to,uint count,
6828
6502
                      char * word_end_chars)
6829
6503
{
6830
6504
  static const int SPACE_CHAR= 256;
6831
6505
  static const int START_OF_LINE= 257;
6832
6506
  static const int END_OF_LINE= 258;
6833
6507
 
6834
 
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
 
6508
  uint i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6835
6509
  int used_sets,chr,default_state;
6836
6510
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6837
6511
  char * pos, *to_pos, **to_array;
6853
6527
      return(0);
6854
6528
    }
6855
6529
    states+=len+1;
6856
 
    result_len+=(uint32_t) strlen(to[i])+1;
 
6530
    result_len+=(uint) strlen(to[i])+1;
6857
6531
    if (len > max_length)
6858
6532
      max_length=len;
6859
6533
  }
6860
6534
  memset(is_word_end, 0, sizeof(is_word_end));
6861
6535
  for (i=0 ; word_end_chars[i] ; i++)
6862
 
    is_word_end[(unsigned char) word_end_chars[i]]=1;
 
6536
    is_word_end[(uchar) word_end_chars[i]]=1;
6863
6537
 
6864
6538
  if (init_sets(&sets,states))
6865
6539
    return(0);
6866
6540
  found_sets=0;
6867
 
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
6868
 
                                
 
6541
  if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
 
6542
                                          MYF(MY_WME))))
6869
6543
  {
6870
6544
    free_sets(&sets);
6871
6545
    return(0);
6872
6546
  }
6873
 
  make_new_set(&sets);      /* Set starting set */
 
6547
  VOID(make_new_set(&sets));      /* Set starting set */
6874
6548
  make_sets_invisible(&sets);      /* Hide previus sets */
6875
6549
  used_sets=-1;
6876
6550
  word_states=make_new_set(&sets);    /* Start of new word */
6877
6551
  start_states=make_new_set(&sets);    /* This is first state */
6878
 
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
 
6552
  if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6879
6553
  {
6880
6554
    free_sets(&sets);
6881
 
    free(found_set);
 
6555
    my_free(found_set,MYF(0));
6882
6556
    return(0);
6883
6557
  }
6884
6558
 
6937
6611
          follow_ptr->chr = '\v';
6938
6612
          break;
6939
6613
        default:
6940
 
          follow_ptr->chr = (unsigned char) *pos;
 
6614
          follow_ptr->chr = (uchar) *pos;
6941
6615
          break;
6942
6616
        }
6943
6617
      }
6944
6618
      else
6945
 
        follow_ptr->chr= (unsigned char) *pos;
 
6619
        follow_ptr->chr= (uchar) *pos;
6946
6620
      follow_ptr->table_offset=i;
6947
6621
      follow_ptr->len= ++len;
6948
6622
      follow_ptr++;
6951
6625
    follow_ptr->table_offset=i;
6952
6626
    follow_ptr->len=len;
6953
6627
    follow_ptr++;
6954
 
    states+=(uint32_t) len+1;
 
6628
    states+=(uint) len+1;
6955
6629
  }
6956
6630
 
6957
6631
 
6988
6662
    /* Mark word_chars used if \b is in state */
6989
6663
    if (used_chars[SPACE_CHAR])
6990
6664
      for (pos= word_end_chars ; *pos ; pos++)
6991
 
        used_chars[(int) (unsigned char) *pos] = 1;
 
6665
        used_chars[(int) (uchar) *pos] = 1;
6992
6666
 
6993
6667
    /* Handle other used characters */
6994
6668
    for (chr= 0 ; chr < 256 ; chr++)
7067
6741
 
7068
6742
  /* Alloc replace structure for the replace-state-machine */
7069
6743
 
7070
 
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
7071
 
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
7072
 
                                 sizeof(char *)*count+result_len)))
 
6744
  if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+
 
6745
                                    sizeof(REPLACE_STRING)*(found_sets+1)+
 
6746
                                    sizeof(char *)*count+result_len,
 
6747
                                    MYF(MY_WME | MY_ZEROFILL))))
7073
6748
  {
7074
 
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
7075
 
                       sizeof(REPLACE_STRING)*(found_sets+1)+
7076
 
                       sizeof(char *)*count+result_len);
7077
6749
    rep_str=(REPLACE_STRING*) (replace+sets.count);
7078
6750
    to_array= (char **) (rep_str+found_sets+1);
7079
6751
    to_pos=(char *) (to_array+count);
7080
6752
    for (i=0 ; i < count ; i++)
7081
6753
    {
7082
6754
      to_array[i]=to_pos;
7083
 
      to_pos=strcpy(to_pos,to[i])+strlen(to[i])+1;
 
6755
      to_pos=stpcpy(to_pos,to[i])+1;
7084
6756
    }
7085
6757
    rep_str[0].found=1;
7086
6758
    rep_str[0].replace_string=0;
7102
6774
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7103
6775
    }
7104
6776
  }
7105
 
  free(follow);
 
6777
  my_free(follow,MYF(0));
7106
6778
  free_sets(&sets);
7107
 
  free(found_set);
 
6779
  my_free(found_set,MYF(0));
7108
6780
  return(replace);
7109
6781
}
7110
6782
 
7111
6783
 
7112
 
int init_sets(REP_SETS *sets,uint32_t states)
 
6784
int init_sets(REP_SETS *sets,uint states)
7113
6785
{
7114
6786
  memset(sets, 0, sizeof(*sets));
7115
6787
  sets->size_of_bits=((states+7)/8);
7116
 
  if (!(sets->set_buffer=(REP_SET*) malloc(sizeof(REP_SET)*SET_MALLOC_HUNC)))
 
6788
  if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
 
6789
                                              MYF(MY_WME))))
7117
6790
    return 1;
7118
 
  if (!(sets->bit_buffer=(uint*) malloc(sizeof(uint32_t)*sets->size_of_bits*
7119
 
                                        SET_MALLOC_HUNC)))
 
6791
  if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
 
6792
                                           SET_MALLOC_HUNC,MYF(MY_WME))))
7120
6793
  {
7121
 
    free(sets->set);
 
6794
    my_free(sets->set,MYF(0));
7122
6795
    return 1;
7123
6796
  }
7124
6797
  return 0;
7135
6808
 
7136
6809
REP_SET *make_new_set(REP_SETS *sets)
7137
6810
{
7138
 
  uint32_t i,count,*bit_buffer;
 
6811
  uint i,count,*bit_buffer;
7139
6812
  REP_SET *set;
7140
6813
  if (sets->extra)
7141
6814
  {
7142
6815
    sets->extra--;
7143
6816
    set=sets->set+ sets->count++;
7144
 
    memset(set->bits, 0, sizeof(uint32_t)*sets->size_of_bits);
 
6817
    memset(set->bits, 0, sizeof(uint)*sets->size_of_bits);
7145
6818
    memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
7146
6819
    set->found_offset=0;
7147
6820
    set->found_len=0;
7150
6823
    return set;
7151
6824
  }
7152
6825
  count=sets->count+sets->invisible+SET_MALLOC_HUNC;
7153
 
  if (!(set=(REP_SET*) realloc((unsigned char*) sets->set_buffer,
7154
 
                                  sizeof(REP_SET)*count)))
 
6826
  if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
 
6827
                                  sizeof(REP_SET)*count,
 
6828
                                  MYF(MY_WME))))
7155
6829
    return 0;
7156
6830
  sets->set_buffer=set;
7157
6831
  sets->set=set+sets->invisible;
7158
 
  if (!(bit_buffer=(uint*) realloc((unsigned char*) sets->bit_buffer,
7159
 
                                   (sizeof(uint32_t)*sets->size_of_bits)*count)))
 
6832
  if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
 
6833
                                      (sizeof(uint)*sets->size_of_bits)*count,
 
6834
                                      MYF(MY_WME))))
7160
6835
    return 0;
7161
6836
  sets->bit_buffer=bit_buffer;
7162
6837
  for (i=0 ; i < count ; i++)
7177
6852
 
7178
6853
void free_sets(REP_SETS *sets)
7179
6854
{
7180
 
  free(sets->set_buffer);
7181
 
  free(sets->bit_buffer);
 
6855
  my_free(sets->set_buffer,MYF(0));
 
6856
  my_free(sets->bit_buffer,MYF(0));
7182
6857
  return;
7183
6858
}
7184
6859
 
7185
 
void internal_set_bit(REP_SET *set, uint32_t bit)
 
6860
void internal_set_bit(REP_SET *set, uint bit)
7186
6861
{
7187
6862
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7188
6863
  return;
7189
6864
}
7190
6865
 
7191
 
void internal_clear_bit(REP_SET *set, uint32_t bit)
 
6866
void internal_clear_bit(REP_SET *set, uint bit)
7192
6867
{
7193
6868
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7194
6869
  return;
7197
6872
 
7198
6873
void or_bits(REP_SET *to,REP_SET *from)
7199
6874
{
7200
 
  register uint32_t i;
 
6875
  register uint i;
7201
6876
  for (i=0 ; i < to->size_of_bits ; i++)
7202
6877
    to->bits[i]|=from->bits[i];
7203
6878
  return;
7206
6881
void copy_bits(REP_SET *to,REP_SET *from)
7207
6882
{
7208
6883
  memcpy(to->bits,from->bits,
7209
 
         (size_t) (sizeof(uint32_t) * to->size_of_bits));
 
6884
         (size_t) (sizeof(uint) * to->size_of_bits));
7210
6885
}
7211
6886
 
7212
6887
int cmp_bits(REP_SET *set1,REP_SET *set2)
7213
6888
{
7214
 
  return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
 
6889
  return memcmp(set1->bits,set2->bits, sizeof(uint) * set1->size_of_bits);
7215
6890
}
7216
6891
 
7217
6892
 
7218
6893
/* Get next set bit from set. */
7219
6894
 
7220
 
int get_next_bit(REP_SET *set,uint32_t lastpos)
 
6895
int get_next_bit(REP_SET *set,uint lastpos)
7221
6896
{
7222
 
  uint32_t pos,*start,*end,bits;
 
6897
  uint pos,*start,*end,bits;
7223
6898
 
7224
6899
  start=set->bits+ ((lastpos+1) / WORD_BIT);
7225
6900
  end=set->bits + set->size_of_bits;
7229
6904
    bits=start[0];
7230
6905
  if (!bits)
7231
6906
    return 0;
7232
 
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
 
6907
  pos=(uint) (start-set->bits)*WORD_BIT;
7233
6908
  while (! (bits & 1))
7234
6909
  {
7235
6910
    bits>>=1;
7244
6919
 
7245
6920
int find_set(REP_SETS *sets,REP_SET *find)
7246
6921
{
7247
 
  uint32_t i;
 
6922
  uint i;
7248
6923
  for (i=0 ; i < sets->count-1 ; i++)
7249
6924
  {
7250
6925
    if (!cmp_bits(sets->set+i,find))
7263
6938
   set->next[] == -1 is reserved for end without replaces.
7264
6939
*/
7265
6940
 
7266
 
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
 
6941
int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
7267
6942
{
7268
6943
  int i;
7269
 
  for (i=0 ; (uint32_t) i < found_sets ; i++)
 
6944
  for (i=0 ; (uint) i < found_sets ; i++)
7270
6945
    if (found_set[i].table_offset == table_offset &&
7271
6946
        found_set[i].found_offset == found_offset)
7272
6947
      return -i-2;
7278
6953
 
7279
6954
/* Return 1 if regexp starts with \b or ends with \b*/
7280
6955
 
7281
 
uint32_t start_at_word(char * pos)
 
6956
uint start_at_word(char * pos)
7282
6957
{
7283
6958
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
7284
6959
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
7285
6960
}
7286
6961
 
7287
 
uint32_t end_of_word(char * pos)
 
6962
uint end_of_word(char * pos)
7288
6963
{
7289
6964
  char * end= strchr(pos, '\0');
7290
6965
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
7300
6975
 
7301
6976
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
7302
6977
{
7303
 
  uint32_t i,length,old_count;
7304
 
  unsigned char *new_pos;
 
6978
  uint i,length,old_count;
 
6979
  uchar *new_pos;
7305
6980
  const char **new_array;
7306
6981
 
7307
6982
 
7308
6983
  if (! pa->typelib.count)
7309
6984
  {
7310
6985
    if (!(pa->typelib.type_names=(const char **)
7311
 
          malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
 
6986
          my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7312
6987
                     (sizeof(char *)+sizeof(*pa->flag))*
7313
 
                     (sizeof(char *)+sizeof(*pa->flag))))))
 
6988
                     (sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
7314
6989
      return(-1);
7315
 
    if (!(pa->str= (unsigned char*) malloc(PS_MALLOC-MALLOC_OVERHEAD)))
 
6990
    if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
 
6991
                                      MYF(MY_WME))))
7316
6992
    {
7317
 
      free((char*) pa->typelib.type_names);
 
6993
      my_free((char*) pa->typelib.type_names,MYF(0));
7318
6994
      return (-1);
7319
6995
    }
7320
 
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(unsigned char*)+
 
6996
    pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7321
6997
                                               sizeof(*pa->flag));
7322
 
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
 
6998
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7323
6999
    pa->length=0;
7324
7000
    pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
7325
7001
    pa->array_allocs=1;
7326
7002
  }
7327
 
  length=(uint32_t) strlen(name)+1;
 
7003
  length=(uint) strlen(name)+1;
7328
7004
  if (pa->length+length >= pa->max_length)
7329
7005
  {
7330
 
    if (!(new_pos= (unsigned char*)realloc((unsigned char*)pa->str,
7331
 
                                           (size_t)(pa->max_length+PS_MALLOC))))
 
7006
    if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
 
7007
                                       (uint) (pa->max_length+PS_MALLOC),
 
7008
                                       MYF(MY_WME))))
7332
7009
      return(1);
7333
7010
    if (new_pos != pa->str)
7334
7011
    {
7335
 
      ptrdiff_t diff= PTR_BYTE_DIFF(new_pos,pa->str);
 
7012
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
7336
7013
      for (i=0 ; i < pa->typelib.count ; i++)
7337
7014
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
7338
7015
                                              char*);
7342
7019
  }
7343
7020
  if (pa->typelib.count >= pa->max_count-1)
7344
7021
  {
7345
 
    size_t len;
 
7022
    int len;
7346
7023
    pa->array_allocs++;
7347
7024
    len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7348
 
    if (!(new_array=
7349
 
         (const char **)realloc((unsigned char*) pa->typelib.type_names,
7350
 
                                 len/
7351
 
                                  (sizeof(unsigned char*)+sizeof(*pa->flag))*
7352
 
                                  (sizeof(unsigned char*)+sizeof(*pa->flag)))))
 
7025
    if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
 
7026
                                               (uint) len/
 
7027
                                               (sizeof(uchar*)+sizeof(*pa->flag))*
 
7028
                                               (sizeof(uchar*)+sizeof(*pa->flag)),
 
7029
                                               MYF(MY_WME))))
7353
7030
      return(1);
7354
7031
    pa->typelib.type_names=new_array;
7355
7032
    old_count=pa->max_count;
7356
 
    pa->max_count=len/(sizeof(unsigned char*) + sizeof(*pa->flag));
7357
 
    pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
 
7033
    pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
 
7034
    pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7358
7035
    memcpy(pa->flag, pa->typelib.type_names+old_count,
7359
7036
           old_count*sizeof(*pa->flag));
7360
7037
  }
7361
7038
  pa->flag[pa->typelib.count]=0;      /* Reset flag */
7362
7039
  pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
7363
 
  pa->typelib.type_names[pa->typelib.count]= NULL;  /* Put end-mark */
7364
 
  strcpy((char*) pa->str+pa->length,name);
 
7040
  pa->typelib.type_names[pa->typelib.count]= NullS;  /* Put end-mark */
 
7041
  VOID(stpcpy((char*) pa->str+pa->length,name));
7365
7042
  pa->length+=length;
7366
7043
  return(0);
7367
7044
} /* insert_pointer_name */
7374
7051
  if (pa->typelib.count)
7375
7052
  {
7376
7053
    pa->typelib.count=0;
7377
 
    free((char*) pa->typelib.type_names);
 
7054
    my_free((char*) pa->typelib.type_names,MYF(0));
7378
7055
    pa->typelib.type_names=0;
7379
 
    free(pa->str);
 
7056
    my_free(pa->str,MYF(0));
7380
7057
  }
7381
7058
} /* free_pointer_array */
7382
7059
 
7417
7094
  replace_append_mem(ds, val, strlen(val));
7418
7095
}
7419
7096
 
7420
 
/* Append uint32_t to ds, with optional replace */
7421
 
void replace_append_uint(string *ds, uint32_t val)
 
7097
/* Append uint to ds, with optional replace */
 
7098
void replace_append_uint(string *ds, uint val)
7422
7099
{
7423
 
  ostringstream buff;
7424
 
  buff << val;
7425
 
  replace_append_mem(ds, buff.str().c_str(), buff.str().size());
 
7100
  char buff[22]; /* This should be enough for any int */
 
7101
  char *end= int64_t10_to_str(val, buff, 10);
 
7102
  replace_append_mem(ds, buff, end - buff);
7426
7103
 
7427
7104
}
7428
7105
 
7443
7120
 
7444
7121
void append_sorted(string* ds, string *ds_input)
7445
7122
{
7446
 
  priority_queue<string, vector<string>, greater<string> > lines;
 
7123
  priority_queue<string> lines;
7447
7124
 
7448
7125
  if (ds_input->empty())
7449
7126
    return;  /* No input */
7454
7131
  if (eol_pos == string::npos)
7455
7132
    return; // We should have at least one header here
7456
7133
 
7457
 
  ds->append(ds_input->substr(0, eol_pos+1));
 
7134
  ds->append(ds_input->substr(0, eol_pos));
7458
7135
 
7459
7136
  unsigned long start_pos= eol_pos+1;
7460
7137
 
7463
7140
 
7464
7141
    eol_pos= ds_input->find_first_of('\n', start_pos);
7465
7142
    /* Find end of line */
7466
 
    lines.push(ds_input->substr(start_pos, eol_pos-start_pos+1));
 
7143
    lines.push(ds_input->substr(start_pos, eol_pos-start_pos));
7467
7144
    start_pos= eol_pos+1;
7468
7145
 
7469
7146
  } while ( eol_pos != string::npos);