~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Monty Taylor
  • Date: 2010-04-22 02:46:23 UTC
  • mto: (1497.3.4 enable-dtrace)
  • mto: This revision was merged to the branch mainline in revision 1527.
  • Revision ID: mordred@inaugust.com-20100422024623-4urw8fi8eraci08p
Don't overwrite the pandora_vc_revinfo file if we don't have new
authoratative information.

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
45
44
#include <map>
46
45
#include <string>
47
46
#include <sstream>
48
 
#include <fstream>
49
47
#include <iostream>
50
48
#include <vector>
51
49
#include <algorithm>
56
54
#include <sys/stat.h>
57
55
#include <sys/types.h>
58
56
#include <fcntl.h>
59
 
#include <boost/program_options.hpp>
60
57
 
61
58
#include PCRE_HEADER
62
59
 
63
60
#include <stdarg.h>
64
 
#include <boost/unordered_map.hpp>
 
61
#include <drizzled/unordered_map.h>
 
62
 
 
63
#include "errname.h"
65
64
 
66
65
/* Added this for string translation. */
67
66
#include "drizzled/gettext.h"
68
67
#include "drizzled/drizzle_time.h"
69
68
#include "drizzled/charset.h"
70
 
#include <drizzled/configmake.h>
71
69
 
72
70
#ifndef DRIZZLE_RETURN_SERVER_GONE
73
71
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
74
72
#endif
75
 
namespace po= boost::program_options;
 
73
 
76
74
using namespace std;
77
75
using namespace drizzled;
78
76
 
88
86
#define QUERY_SEND_FLAG  1
89
87
#define QUERY_REAP_FLAG  2
90
88
 
91
 
typedef boost::unordered_map<std::string, uint32_t> ErrorCodes;
92
89
ErrorCodes global_error_names;
93
90
 
94
91
enum {
98
95
};
99
96
 
100
97
static int record= 0, opt_sleep= -1;
101
 
static char *opt_pass= NULL;
102
 
const char *unix_sock= NULL;
 
98
static char *opt_db= NULL, *opt_pass= NULL;
 
99
const char *opt_user= NULL, *opt_host= NULL, *unix_sock= NULL,
 
100
           *opt_basedir= "./";
 
101
const char *opt_logdir= "";
 
102
const char *opt_include= NULL, *opt_charsets_dir;
 
103
const char *opt_testdir= NULL;
103
104
static uint32_t opt_port= 0;
104
 
static uint32_t opt_max_connect_retries;
 
105
static int opt_max_connect_retries;
105
106
static bool silent= false, verbose= false;
 
107
static bool tty_password= false;
106
108
static bool opt_mark_progress= false;
107
109
static bool parsing_disabled= false;
108
110
static bool display_result_vertically= false,
113
115
static bool abort_on_error= true;
114
116
static bool server_initialized= false;
115
117
static bool is_windows= false;
116
 
static bool use_drizzle_protocol= false;
 
118
static bool opt_mysql= false;
 
119
static char **default_argv;
 
120
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
117
121
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
118
122
 
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
123
static uint32_t start_lineno= 0; /* Start line of current command */
133
124
 
134
125
/* Number of lines of the result to include in failure report */
198
189
master_pos_st master_pos;
199
190
 
200
191
/* if set, all results are concated and compared against this file */
 
192
const char *result_file_name= NULL;
201
193
 
202
194
typedef struct st_var
203
195
{
216
208
VAR var_reg[10];
217
209
 
218
210
 
219
 
boost::unordered_map<string, VAR *> var_hash;
 
211
unordered_map<string, VAR *> var_hash;
220
212
 
221
213
struct st_connection
222
214
{
782
774
    const struct command_arg *arg= &args[i];
783
775
    arg->ds->clear();
784
776
 
785
 
    bool known_arg_type= true;
786
777
    switch (arg->type) {
787
778
      /* A string */
788
779
    case ARG_STRING:
817
808
      break;
818
809
 
819
810
    default:
820
 
      known_arg_type= false;
 
811
      assert("Unknown argument type");
821
812
      break;
822
813
    }
823
 
    assert(known_arg_type);
824
814
 
825
815
    /* Check required arg */
826
816
    if (arg->ds->length() == 0 && arg->required)
930
920
 
931
921
  free_all_replace();
932
922
  free(opt_pass);
 
923
  internal::free_defaults(default_argv);
933
924
 
934
925
  return;
935
926
}
1011
1002
  }
1012
1003
 
1013
1004
  /* Dump the result that has been accumulated so far to .log file */
1014
 
  if (! result_file_name.empty() && ds_res.length())
 
1005
  if (result_file_name && ds_res.length())
1015
1006
    dump_result_to_log_file(ds_res.c_str(), ds_res.length());
1016
1007
 
1017
1008
  /* Dump warning messages */
1018
 
  if (! result_file_name.empty() && ds_warning_messages.length())
 
1009
  if (result_file_name && ds_warning_messages.length())
1019
1010
    dump_warning_messages();
1020
1011
 
1021
1012
  /*
1363
1354
  if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
1364
1355
  {
1365
1356
    internal::my_close(fd, MYF(0));
1366
 
    if (! opt_testdir.empty())
 
1357
    if (opt_testdir != NULL)
1367
1358
    {
1368
1359
      tmpfile= opt_testdir;
1369
1360
      if (tmpfile[tmpfile.length()] != '/')
1461
1452
  int fd;
1462
1453
  char temp_file_path[FN_REFLEN];
1463
1454
 
1464
 
  if ((fd= internal::create_temp_file(temp_file_path, TMPDIR,
 
1455
  if ((fd= internal::create_temp_file(temp_file_path, NULL,
1465
1456
                            "tmp", MYF(MY_WME))) < 0)
1466
1457
    die("Failed to create temporary file for ds");
1467
1458
 
1503
1494
  const char* mess= "Result content mismatch\n";
1504
1495
 
1505
1496
 
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())) {
 
1497
  assert(result_file_name);
 
1498
 
 
1499
  if (access(result_file_name, F_OK) != 0)
 
1500
    die("The specified result file does not exist: '%s'", result_file_name);
 
1501
 
 
1502
  switch (string_cmp(ds, result_file_name)) {
1512
1503
  case RESULT_OK:
1513
1504
    break; /* ok */
1514
1505
  case RESULT_LENGTH_MISMATCH:
1522
1513
    */
1523
1514
    char reject_file[FN_REFLEN];
1524
1515
    size_t reject_length;
1525
 
    internal::dirname_part(reject_file, result_file_name.c_str(), &reject_length);
 
1516
    internal::dirname_part(reject_file, result_file_name, &reject_length);
1526
1517
 
1527
1518
    if (access(reject_file, W_OK) == 0)
1528
1519
    {
1529
1520
      /* Result file directory is writable, save reject file there */
1530
 
      internal::fn_format(reject_file, result_file_name.c_str(), NULL,
 
1521
      internal::fn_format(reject_file, result_file_name, NULL,
1531
1522
                ".reject", MY_REPLACE_EXT);
1532
1523
    }
1533
1524
    else
1534
1525
    {
1535
1526
      /* Put reject file in opt_logdir */
1536
 
      internal::fn_format(reject_file, result_file_name.c_str(), opt_logdir.c_str(),
 
1527
      internal::fn_format(reject_file, result_file_name, opt_logdir,
1537
1528
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1538
1529
    }
1539
1530
    str_to_file(reject_file, ds->c_str(), ds->length());
1540
1531
 
1541
1532
    ds->erase(); /* Don't create a .log file */
1542
1533
 
1543
 
    show_diff(NULL, result_file_name.c_str(), reject_file);
 
1534
    show_diff(NULL, result_file_name, reject_file);
1544
1535
    die("%s",mess);
1545
1536
    break;
1546
1537
  }
1712
1703
      die("Too long variable name: %s", save_var_name);
1713
1704
 
1714
1705
    string save_var_name_str(save_var_name, length);
1715
 
    boost::unordered_map<string, VAR*>::iterator iter=
 
1706
    unordered_map<string, VAR*>::iterator iter=
1716
1707
      var_hash.find(save_var_name_str);
1717
1708
    if (iter == var_hash.end())
1718
1709
    {
1750
1741
static VAR *var_obtain(const char *name, int len)
1751
1742
{
1752
1743
  string var_name(name, len);
1753
 
  boost::unordered_map<string, VAR*>::iterator iter=
 
1744
  unordered_map<string, VAR*>::iterator iter=
1754
1745
    var_hash.find(var_name);
1755
1746
  if (iter != var_hash.end())
1756
1747
    return (*iter).second;
2156
2147
 
2157
2148
  if (!internal::test_if_hard_path(name))
2158
2149
  {
2159
 
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),name);
 
2150
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir,name);
2160
2151
    name=buff;
2161
2152
  }
2162
2153
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2210
2201
    ; /* Do nothing */
2211
2202
  else
2212
2203
  {
2213
 
    if (! opt_testdir.empty())
 
2204
    if (opt_testdir != NULL)
2214
2205
    {
2215
2206
      string testdir(opt_testdir);
2216
2207
      if (testdir[testdir.length()] != '/')
3317
3308
  bool error= false;
3318
3309
  char *p= command->first_argument;
3319
3310
  char *sleep_start, *sleep_end= command->end;
3320
 
  double sleep_val= 0;
 
3311
  double sleep_val;
3321
3312
 
3322
3313
  while (my_isspace(charset_info, *p))
3323
3314
    p++;
3357
3348
  if (*p)
3358
3349
    *p++= 0;
3359
3350
  command->last_argument= p;
3360
 
  if (! opt_testdir.empty())
 
3351
  if (opt_testdir != NULL)
3361
3352
  {
3362
3353
    dest= opt_testdir;
3363
3354
    if (dest[dest.length()] != '/')
3386
3377
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3387
3378
}
3388
3379
 
3389
 
static void fill_global_error_names()
3390
 
{
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])
3423
 
  {
3424
 
    /*
3425
 
      Concatenate all fields in the first row with tab in between
3426
 
      and assign that string to the $variable
3427
 
    */
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
3380
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3449
3381
{
3450
3382
  size_t err_name_len= error_end - error_name;
3451
3383
  string error_name_s(error_name, err_name_len);
3452
3384
 
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;
 
3385
  uint32_t code= global_error_names.getErrorCode(error_name_s);
 
3386
 
 
3387
  if (!code)
 
3388
    die("Unknown SQL error name '%s'", error_name_s.c_str());
 
3389
 
 
3390
  return(code);
3461
3391
}
3462
3392
 
3463
3393
static void do_get_errcodes(struct st_command *command)
3755
3685
*/
3756
3686
 
3757
3687
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)
 
3688
                         const char *host, const char *user, const char *pass,
 
3689
                         const char *db, int port)
3760
3690
{
3761
 
  uint32_t failed_attempts= 0;
 
3691
  int failed_attempts= 0;
3762
3692
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3763
3693
  drizzle_return_t ret;
3764
3694
 
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());
 
3695
  drizzle_con_set_tcp(con, host, port);
 
3696
  drizzle_con_set_auth(con, user, pass);
 
3697
  drizzle_con_set_db(con, db);
3768
3698
  while((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
3769
3699
  {
3770
3700
    /*
3906
3836
 
3907
3837
static void do_connect(struct st_command *command)
3908
3838
{
3909
 
  uint32_t con_port= opt_port;
 
3839
  int con_port= opt_port;
3910
3840
  const char *con_options;
3911
 
  bool con_ssl= 0;
 
3841
  bool con_ssl= 0, con_compress= 0;
3912
3842
  struct st_connection* con_slot;
3913
3843
 
3914
3844
  string ds_connection_name;
3974
3904
      end++;
3975
3905
    if (!strncmp(con_options, "SSL", 3))
3976
3906
      con_ssl= 1;
 
3907
    else if (!strncmp(con_options, "COMPRESS", 8))
 
3908
      con_compress= 1;
3977
3909
    else
3978
3910
      die("Illegal option to connect: %.*s",
3979
3911
          (int) (end - con_options), con_options);
3999
3931
    die("Failed on drizzle_create()");
4000
3932
  if (!drizzle_con_create(con_slot->drizzle, &con_slot->con))
4001
3933
    die("Failed on drizzle_con_create()");
4002
 
  drizzle_con_add_options(&con_slot->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
3934
  if (opt_mysql)
 
3935
    drizzle_con_add_options(&con_slot->con, DRIZZLE_CON_MYSQL);
4003
3936
 
4004
3937
  /* Use default db name */
4005
3938
  if (ds_database.length() == 0)
4563
4496
  return;
4564
4497
}
4565
4498
 
 
4499
 
 
4500
 
4566
4501
/*
4567
4502
  Create a command from a set of lines
4568
4503
 
4580
4515
  terminated by new line '\n' regardless how many "delimiter" it contain.
4581
4516
*/
4582
4517
 
4583
 
#define MAX_QUERY (768*1024*2) /* 256K -- a test in sp-big is >128K */
 
4518
#define MAX_QUERY (256*1024*2) /* 256K -- a test in sp-big is >128K */
4584
4519
static char read_command_buf[MAX_QUERY];
4585
4520
 
4586
4521
static int read_command(struct st_command** command_ptr)
4642
4577
  return(0);
4643
4578
}
4644
4579
 
 
4580
 
 
4581
static struct option my_long_options[] =
 
4582
{
 
4583
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
 
4584
   0, 0, 0, 0, 0, 0},
 
4585
  {"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
 
4586
   (char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4587
  {"character-sets-dir", OPT_CHARSETS_DIR,
 
4588
   "Directory where character sets are.", (char**) &opt_charsets_dir,
 
4589
   (char**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4590
  {"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
 
4591
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4592
  {"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
 
4593
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4594
  {"include", 'i', "Include SQL before each test case.", (char**) &opt_include,
 
4595
   (char**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4596
  {"testdir", OPT_TESTDIR, "Path to use to search for test files",
 
4597
   (char**) &opt_testdir,
 
4598
   (char**) &opt_testdir, 0,GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4599
  {"logdir", OPT_LOG_DIR, "Directory for log files", (char**) &opt_logdir,
 
4600
   (char**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4601
  {"mark-progress", OPT_MARK_PROGRESS,
 
4602
   "Write linenumber and elapsed time to <testname>.progress ",
 
4603
   (char**) &opt_mark_progress, (char**) &opt_mark_progress, 0,
 
4604
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4605
  {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
 
4606
   "Max number of connection attempts when connecting to server",
 
4607
   (char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
 
4608
   GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
 
4609
  {"mysql", 'm', N_("Use MySQL Protocol."),
 
4610
   (char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
 
4611
   0, 0, 0},
 
4612
  {"password", 'P', "Password to use when connecting to server.",
 
4613
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
4614
  {"port", 'p', "Port number to use for connection or 0 for default to, in "
 
4615
   "order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
 
4616
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
 
4617
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4618
  {"quiet", 's', "Suppress all normal output.", (char**) &silent,
 
4619
   (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4620
  {"record", 'r', "Record output of test_file into result file.",
 
4621
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4622
  {"result-file", 'R', "Read/Store result from/in this file.",
 
4623
   (char**) &result_file_name, (char**) &result_file_name, 0,
 
4624
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4625
  {"silent", 's', "Suppress all normal output. Synonym for --quiet.",
 
4626
   (char**) &silent, (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4627
  {"sleep", 'T', "Sleep always this many seconds on sleep commands.",
 
4628
   (char**) &opt_sleep, (char**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
 
4629
   0, 0, 0},
 
4630
  {"tail-lines", OPT_TAIL_LINES,
 
4631
   "Number of lines of the resul to include in a failure report",
 
4632
   (char**) &opt_tail_lines, (char**) &opt_tail_lines, 0,
 
4633
   GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
 
4634
  {"test-file", 'x', "Read test from/in this file (default stdin).",
 
4635
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4636
  {"timer-file", 'm', "File where the timing in micro seconds is stored.",
 
4637
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4638
  {"tmpdir", 't', "Temporary directory where sockets are put.",
 
4639
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4640
  {"user", 'u', "User for login.", (char**) &opt_user, (char**) &opt_user, 0,
 
4641
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
4642
  {"verbose", 'v', "Write more.", (char**) &verbose, (char**) &verbose, 0,
 
4643
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4644
  {"version", 'V', "Output version information and exit.",
 
4645
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
4646
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
4647
};
 
4648
 
 
4649
 
 
4650
static void print_version(void)
 
4651
{
 
4652
  printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
 
4653
         drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
 
4654
}
 
4655
 
 
4656
static void usage(void)
 
4657
{
 
4658
  print_version();
 
4659
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
 
4660
  printf("Drizzle version modified by Brian, Jay, Monty Taylor, PatG and Stewart\n");
 
4661
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
 
4662
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
 
4663
  printf("Usage: %s [OPTIONS] [database] < test_file\n", internal::my_progname);
 
4664
  my_print_help(my_long_options);
 
4665
  printf("  --no-defaults       Don't read default options from any options file.\n");
 
4666
  my_print_variables(my_long_options);
 
4667
}
 
4668
 
 
4669
int get_one_option(int optid, const struct option *, char *argument)
 
4670
{
 
4671
  char *endchar= NULL;
 
4672
  uint64_t temp_drizzle_port= 0;
 
4673
 
 
4674
  switch(optid) {
 
4675
  case 'r':
 
4676
    record = 1;
 
4677
    break;
 
4678
  case 'x':
 
4679
  {
 
4680
    char buff[FN_REFLEN];
 
4681
    if (!internal::test_if_hard_path(argument))
 
4682
    {
 
4683
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir,argument);
 
4684
      argument= buff;
 
4685
    }
 
4686
    internal::fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4687
    assert(cur_file == file_stack && cur_file->file == 0);
 
4688
    if (!(cur_file->file= fopen(buff, "r")))
 
4689
    {
 
4690
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
 
4691
      return EXIT_ARGUMENT_INVALID;
 
4692
    }
 
4693
    if (!(cur_file->file_name= strdup(buff)))
 
4694
    {
 
4695
      fprintf(stderr, _("Out of memory"));
 
4696
      return EXIT_OUT_OF_MEMORY;
 
4697
    }
 
4698
    cur_file->lineno= 1;
 
4699
    break;
 
4700
  }
 
4701
  case 'm':
 
4702
  {
 
4703
    static char buff[FN_REFLEN];
 
4704
    if (!internal::test_if_hard_path(argument))
 
4705
    {
 
4706
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir,argument);
 
4707
      argument= buff;
 
4708
    }
 
4709
    internal::fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4710
    timer_file= buff;
 
4711
    unlink(timer_file);       /* Ignore error, may not exist */
 
4712
    break;
 
4713
  }
 
4714
  case 'p':
 
4715
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
 
4716
    /* if there is an alpha character this is not a valid port */
 
4717
    if (strlen(endchar) != 0)
 
4718
    {
 
4719
      fprintf(stderr, _("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead.\n"));
 
4720
      return EXIT_ARGUMENT_INVALID;
 
4721
    }
 
4722
    /* If the port number is > 65535 it is not a valid port
 
4723
       This also helps with potential data loss casting unsigned long to a
 
4724
       uint32_t. */
 
4725
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
 
4726
    {
 
4727
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
 
4728
      return EXIT_ARGUMENT_INVALID;
 
4729
    }
 
4730
    else
 
4731
    {
 
4732
      opt_port= (uint32_t) temp_drizzle_port;
 
4733
    }
 
4734
    break;
 
4735
  case 'P':
 
4736
    if (argument)
 
4737
    {
 
4738
      if (opt_pass)
 
4739
        free(opt_pass);
 
4740
      opt_pass = strdup(argument);
 
4741
      if (opt_pass == NULL)
 
4742
      {
 
4743
        fprintf(stderr, _("Out of memory"));
 
4744
        return EXIT_OUT_OF_MEMORY;
 
4745
      }
 
4746
      while (*argument)
 
4747
      {
 
4748
        /* Overwriting password with 'x' */
 
4749
        *argument++= 'x';
 
4750
      }
 
4751
      tty_password= 0;
 
4752
    }
 
4753
    else
 
4754
      tty_password= 1;
 
4755
    break;
 
4756
  case 't':
 
4757
    strncpy(TMPDIR, argument, sizeof(TMPDIR));
 
4758
    break;
 
4759
  case 'V':
 
4760
    print_version();
 
4761
    exit(0);
 
4762
  case '?':
 
4763
    usage();
 
4764
    exit(0);
 
4765
  }
 
4766
  return 0;
 
4767
}
 
4768
 
 
4769
 
 
4770
static int parse_args(int argc, char **argv)
 
4771
{
 
4772
  internal::load_defaults("drizzle",load_default_groups,&argc,&argv);
 
4773
  default_argv= argv;
 
4774
 
 
4775
  if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
 
4776
    exit(1);
 
4777
 
 
4778
  if (argc > 1)
 
4779
  {
 
4780
    usage();
 
4781
    exit(1);
 
4782
  }
 
4783
  if (argc == 1)
 
4784
    opt_db= *argv;
 
4785
  if (tty_password)
 
4786
    opt_pass= client_get_tty_password(NULL);          /* purify tested */
 
4787
 
 
4788
  return 0;
 
4789
}
 
4790
 
4645
4791
/*
4646
4792
  Write the content of str into file
4647
4793
 
4660
4806
  int flags= O_WRONLY | O_CREAT;
4661
4807
  if (!internal::test_if_hard_path(fname))
4662
4808
  {
4663
 
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),fname);
 
4809
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir,fname);
4664
4810
    fname= buff;
4665
4811
  }
4666
4812
  internal::fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4696
4842
void dump_result_to_log_file(const char *buf, int size)
4697
4843
{
4698
4844
  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 :
 
4845
  str_to_file(internal::fn_format(log_file, result_file_name, opt_logdir, ".log",
 
4846
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4701
4847
                        MY_REPLACE_EXT),
4702
4848
              buf, size);
4703
4849
  fprintf(stderr, "\nMore results from queries before failure can be found in %s\n",
4707
4853
void dump_progress(void)
4708
4854
{
4709
4855
  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 :
 
4856
  str_to_file(internal::fn_format(progress_file, result_file_name,
 
4857
                        opt_logdir, ".progress",
 
4858
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4713
4859
                        MY_REPLACE_EXT),
4714
4860
              ds_progress.c_str(), ds_progress.length());
4715
4861
}
4718
4864
{
4719
4865
  char warn_file[FN_REFLEN];
4720
4866
 
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 :
 
4867
  str_to_file(internal::fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
 
4868
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4723
4869
                        MY_REPLACE_EXT),
4724
4870
              ds_warning_messages.c_str(), ds_warning_messages.length());
4725
4871
}
5417
5563
 
5418
5564
}
5419
5565
 
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
 
}
5449
5566
 
5450
5567
int main(int argc, char **argv)
5451
5568
{
5452
 
try
5453
 
{
5454
5569
  struct st_command *command;
5455
5570
  bool q_send_flag= 0, abort_flag= 0;
5456
5571
  uint32_t command_executed= 0, last_command_executed= 0;
5457
5572
  string save_file("");
5458
5573
  struct stat res_info;
 
5574
  MY_INIT(argv[0]);
5459
5575
 
5460
5576
  TMPDIR[0]= 0;
5461
5577
 
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
5578
  /* Init expected errors */
5581
5579
  memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
5582
5580
 
5613
5611
  ds_progress.reserve(2048);
5614
5612
  ds_warning_messages.reserve(2048);
5615
5613
 
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
 
  }
 
5614
  parse_args(argc, argv);
5735
5615
 
5736
5616
  server_initialized= 1;
5737
5617
  if (cur_file == file_stack && cur_file->file == 0)
5747
5627
    die("Failed in drizzle_create()");
5748
5628
  if (!( drizzle_con_create(cur_con->drizzle, &cur_con->con)))
5749
5629
    die("Failed in drizzle_con_create()");
5750
 
  drizzle_con_add_options(&cur_con->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
5630
  if (opt_mysql)
 
5631
    drizzle_con_add_options(&cur_con->con, DRIZZLE_CON_MYSQL);
5751
5632
 
5752
5633
  if (!(cur_con->name = strdup("default")))
5753
5634
    die("Out of memory");
 
5635
 
5754
5636
  safe_connect(&cur_con->con, cur_con->name, opt_host, opt_user, opt_pass,
5755
5637
               opt_db, opt_port);
5756
5638
 
5757
 
  fill_global_error_names();
5758
 
 
5759
5639
  /* Use all time until exit if no explicit 'start_timer' */
5760
5640
  timer_start= timer_now();
5761
5641
 
5769
5649
  /* Update $drizzleclient_get_server_version to that of current connection */
5770
5650
  var_set_drizzleclient_get_server_version(&cur_con->con);
5771
5651
 
5772
 
  if (! opt_include.empty())
 
5652
  if (opt_include)
5773
5653
  {
5774
 
    open_file(opt_include.c_str());
 
5654
    open_file(opt_include);
5775
5655
  }
5776
5656
 
5777
5657
  while (!read_command(&command) && !abort_flag)
6075
5955
  */
6076
5956
  if (ds_res.length())
6077
5957
  {
6078
 
    if (! result_file_name.empty())
 
5958
    if (result_file_name)
6079
5959
    {
6080
5960
      /* A result file has been specified */
6081
5961
 
6082
5962
      if (record)
6083
5963
      {
6084
5964
        /* 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());
 
5965
        str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
6086
5966
      }
6087
5967
      else
6088
5968
      {
6105
5985
  }
6106
5986
 
6107
5987
  if (!command_executed &&
6108
 
      ! result_file_name.empty() && !stat(result_file_name.c_str(), &res_info))
 
5988
      result_file_name && !stat(result_file_name, &res_info))
6109
5989
  {
6110
5990
    /*
6111
5991
      my_stat() successful on result file. Check if we have not run a
6117
5997
    die("No queries executed but result file found!");
6118
5998
  }
6119
5999
 
6120
 
  if ( opt_mark_progress && ! result_file_name.empty() )
 
6000
  if ( opt_mark_progress && result_file_name )
6121
6001
    dump_progress();
6122
6002
 
6123
6003
  /* Dump warning messages */
6124
 
  if (! result_file_name.empty() && ds_warning_messages.length())
 
6004
  if (result_file_name && ds_warning_messages.length())
6125
6005
    dump_warning_messages();
6126
6006
 
6127
6007
  timer_output();
6128
6008
  /* Yes, if we got this far the test has suceeded! Sakila smiles */
6129
6009
  cleanup_and_exit(0);
6130
 
}
6131
 
 
6132
 
  catch(exception &err)
6133
 
  {
6134
 
    cerr<<err.what()<<endl;
6135
 
  }
6136
 
 
6137
6010
  return 0; /* Keep compiler happy too */
6138
6011
}
6139
6012
 
6716
6589
    /* Repeatedly replace the string with the matched regex */
6717
6590
    string subject(in_string);
6718
6591
    size_t replace_length= strlen(replace);
6719
 
    size_t length_of_replacement= strlen(replace);
6720
6592
    size_t current_position= 0;
6721
6593
    int rc= 0;
6722
 
 
6723
 
    while (true) 
 
6594
    while(0 >= (rc= pcre_exec(re, NULL, subject.c_str() + current_position, subject.length() - current_position,
 
6595
                      0, 0, ovector, 3)))
6724
6596
    {
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
6597
      current_position= static_cast<size_t>(ovector[0]);
6733
6598
      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;
 
6599
      subject.replace(current_position, replace_length, replace, replace_length);
6736
6600
    }
6737
6601
 
6738
6602
    char *new_buf = (char *) malloc(subject.length() + 1);