1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 MySQL
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1
/* Copyright (C) 2008 Drizzle Open Source Development Team
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
394
382
void eval_expr(VAR* v, const char *p, const char** p_end);
395
383
bool match_delimiter(int c, const char *delim, uint length);
396
384
void dump_result_to_reject_file(char *buf, int size);
397
void dump_result_to_log_file(const char *buf, int size);
385
void dump_result_to_log_file(char *buf, int size);
398
386
void dump_warning_messages(void);
399
387
void dump_progress(void);
401
void do_eval(string *query_eval, const char *query,
389
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
402
390
const char *query_end, bool pass_through_escape_chars);
403
void str_to_file(const char *fname, const char *str, int size);
404
void str_to_file2(const char *fname, const char *str, int size, bool append);
391
void str_to_file(const char *fname, char *str, int size);
392
void str_to_file2(const char *fname, char *str, int size, bool append);
406
394
/* For replace_column */
407
395
static char *replace_column[MAX_COLUMNS];
427
415
free_replace_column();
430
void replace_append_mem(string *ds, const char *val,
432
void replace_append(string *ds, const char *val);
433
void replace_append_uint(string *ds, uint val);
434
void append_sorted(string* ds, string* ds_input);
418
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
420
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
421
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
422
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input);
436
424
void handle_error(struct st_command*,
437
425
unsigned int err_errno, const char *err_error,
438
const char *err_sqlstate, string *ds);
426
const char *err_sqlstate, DYNAMIC_STRING *ds);
439
427
void handle_no_error(struct st_command*);
429
#ifdef EMBEDDED_LIBRARY
431
/* attributes of the query thread */
432
pthread_attr_t cn_thd_attrib;
435
send_one_query executes query in separate thread, which is
436
necessary in embedded library to run 'send' in proper way.
437
This implementation doesn't handle errors returned
438
by drizzle_send_query. It's technically possible, though
439
I don't see where it is needed.
441
pthread_handler_t send_one_query(void *arg)
443
struct st_connection *cn= (struct st_connection*)arg;
445
drizzle_thread_init();
446
VOID(drizzle_send_query(&cn->drizzle, cn->cur_query, cn->cur_query_len));
448
drizzle_thread_end();
449
pthread_mutex_lock(&cn->mutex);
451
VOID(pthread_cond_signal(&cn->cond));
452
pthread_mutex_unlock(&cn->mutex);
457
static int do_send_query(struct st_connection *cn, const char *q, int q_len,
462
if (flags & QUERY_REAP_FLAG)
463
return drizzle_send_query(&cn->drizzle, q, q_len);
465
if (pthread_mutex_init(&cn->mutex, NULL) ||
466
pthread_cond_init(&cn->cond, NULL))
467
die("Error in the thread library");
470
cn->cur_query_len= q_len;
472
if (pthread_create(&tid, &cn_thd_attrib, send_one_query, (void*)cn))
473
die("Cannot start new thread for query");
478
static void wait_query_thread_end(struct st_connection *con)
480
if (!con->query_done)
482
pthread_mutex_lock(&con->mutex);
483
while (!con->query_done)
484
pthread_cond_wait(&con->cond, &con->mutex);
485
pthread_mutex_unlock(&con->mutex);
489
#else /*EMBEDDED_LIBRARY*/
442
491
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
444
void do_eval(string *query_eval, const char *query,
493
#endif /*EMBEDDED_LIBRARY*/
495
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
445
496
const char *query_end, bool pass_through_escape_chars)
460
query_eval->append(p, 1);
511
dynstr_append_mem(query_eval, p, 1);
464
if (!(v= var_get(p, &p, 0, 0)))
465
die("Bad variable in eval");
466
query_eval->append(v->str_val, v->str_val_len);
515
if (!(v= var_get(p, &p, 0, 0)))
516
die("Bad variable in eval");
517
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
474
query_eval->append(p, 1);
525
dynstr_append_mem(query_eval, p, 1);
476
527
else if (next_c == '\\' || next_c == '$' || next_c == '"')
478
529
/* Set escaped only if next char is \, " or $ */
481
532
if (pass_through_escape_chars)
483
534
/* The escape char should be added to the output string. */
484
query_eval->append(p, 1);
535
dynstr_append_mem(query_eval, p, 1);
488
query_eval->append(p, 1);
539
dynstr_append_mem(query_eval, p, 1);
492
query_eval->append(p, 1);
543
dynstr_append_mem(query_eval, p, 1);
501
Concatenates any number of strings, escapes any OS quote in the result then
502
surround the whole affair in another set of quotes which is finally appended
503
to specified string. This function is especially useful when
504
building strings to be executed with the system() function.
506
@param str string which will have addtional strings appended.
507
@param append string to be appended.
508
@param ... Optional. Additional string(s) to be appended.
510
@note The final argument in the list must be NULL even if no additional
514
void append_os_quoted(string *str, const char *append, ...)
516
const char *quote_str= "\'";
517
const uint quote_len= 1;
521
str->append(quote_str, quote_len); /* Leading quote */
522
va_start(dirty_text, append);
523
while (append != NULL)
525
const char *cur_pos= append;
526
const char *next_pos= cur_pos;
528
/* Search for quote in each string and replace with escaped quote */
529
while((next_pos= strrchr(cur_pos, quote_str[0])) != NULL)
531
str->append(cur_pos, next_pos - cur_pos);
532
str->append("\\", 1);
533
str->append(quote_str, quote_len);
534
cur_pos= next_pos + 1;
536
str->append(cur_pos, next_pos - cur_pos);
537
append= va_arg(dirty_text, char *);
540
str->append(quote_str, quote_len); /* Trailing quote */
545
552
Run query and dump the result to stdout in vertical format
547
554
NOTE! This function should be safe to call when an error
835
844
hash_free(&var_hash);
837
vector<struct st_command *>::iterator iter;
838
for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
846
for (i= 0 ; i < q_lines.elements ; i++)
840
struct st_command * q_line= *(iter.base());
841
if (q_line->query_buf != NULL)
843
free(q_line->query_buf);
848
struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
849
my_free((*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
850
my_free((*q),MYF(0));
848
852
for (i= 0; i < 10; i++)
850
854
if (var_reg[i].alloced_len)
851
free(var_reg[i].str_val);
855
my_free(var_reg[i].str_val, MYF(MY_WME));
853
857
while (embedded_server_arg_count > 1)
854
free(embedded_server_args[--embedded_server_arg_count]);
858
my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
859
delete_dynamic(&q_lines);
860
dynstr_free(&ds_res);
861
dynstr_free(&ds_progress);
862
dynstr_free(&ds_warning_messages);
856
863
free_all_replace();
864
my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
858
865
free_defaults(default_argv);
867
/* Only call drizzle_server_end if drizzle_server_init has been called */
868
if (server_initialized)
869
drizzle_server_end();
921
932
/* Show results from queries just before failure */
922
if (ds_res.length() && opt_tail_lines)
933
if (ds_res.length && opt_tail_lines)
924
935
int tail_lines= opt_tail_lines;
925
const char* show_from= ds_res.c_str() + ds_res.length() - 1;
926
while(show_from > ds_res.c_str() && tail_lines > 0 )
936
char* show_from= ds_res.str + ds_res.length - 1;
937
while(show_from > ds_res.str && tail_lines > 0 )
929
940
if (*show_from == '\n')
932
943
fprintf(stderr, "\nThe result from queries just before the failure was:\n");
933
if (show_from > ds_res.c_str())
944
if (show_from > ds_res.str)
934
945
fprintf(stderr, "< snip >");
935
946
fprintf(stderr, "%s", show_from);
939
950
/* Dump the result that has been accumulated so far to .log file */
940
if (result_file_name && ds_res.length())
941
dump_result_to_log_file(ds_res.c_str(), ds_res.length());
951
if (result_file_name && ds_res.length)
952
dump_result_to_log_file(ds_res.str, ds_res.length);
943
954
/* Dump warning messages */
944
if (result_file_name && ds_warning_messages.length())
955
if (result_file_name && ds_warning_messages.length)
945
956
dump_warning_messages();
1020
1031
va_start(args, fmt);
1021
ds_warning_messages.append("drizzletest: ");
1032
dynstr_append(&ds_warning_messages, "drizzletest: ");
1022
1033
if (start_lineno != 0)
1024
ds_warning_messages.append("Warning detected ");
1035
dynstr_append(&ds_warning_messages, "Warning detected ");
1025
1036
if (cur_file && cur_file != file_stack)
1027
1038
len= snprintf(buff, sizeof(buff), "in included file %s ",
1028
cur_file->file_name);
1029
ds_warning_messages.append(buff, len);
1039
cur_file->file_name);
1040
dynstr_append_mem(&ds_warning_messages,
1031
1043
len= snprintf(buff, sizeof(buff), "at line %d: ",
1033
ds_warning_messages.append(buff, len);
1045
dynstr_append_mem(&ds_warning_messages,
1036
1049
len= vsnprintf(buff, sizeof(buff), fmt, args);
1037
ds_warning_messages.append(buff, len);
1050
dynstr_append_mem(&ds_warning_messages, buff, len);
1039
ds_warning_messages.append("\n");
1052
dynstr_append(&ds_warning_messages, "\n");
1144
1165
tool_path - the name of the tool to run
1145
result - pointer to dynamic string where to store the result
1166
ds_res - pointer to dynamic string where to store the result
1146
1167
... - variable number of arguments that will be properly
1147
quoted and appended after the tool's name
1168
quoted and appended after the tool's name
1151
static int run_tool(const char *tool_path, string * result, ...)
1172
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1154
1175
const char* arg;
1159
append_os_quoted(&ds_cmdline, tool_path);
1160
ds_cmdline.append(" ");
1162
va_start(args, result);
1177
DYNAMIC_STRING ds_cmdline;
1179
if (init_dynamic_string(&ds_cmdline, "", FN_REFLEN, FN_REFLEN))
1180
die("Out of memory");
1182
dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
1183
dynstr_append(&ds_cmdline, " ");
1185
va_start(args, ds_res);
1164
1187
while ((arg= va_arg(args, char *)))
1166
1189
/* Options should be os quoted */
1167
1190
if (strncmp(arg, "--", 2) == 0)
1168
append_os_quoted(&ds_cmdline, arg, NULL);
1191
dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1170
ds_cmdline.append(arg);
1171
ds_cmdline.append(" ");
1193
dynstr_append(&ds_cmdline, arg);
1194
dynstr_append(&ds_cmdline, " ");
1176
ret= run_command(ds_cmdline.c_str(), result);
1199
ret= run_command(ds_cmdline.str, ds_res);
1200
dynstr_free(&ds_cmdline);
1221
1248
Fallback to dump both files to result file and inform
1222
1249
about installing "diff"
1228
"The two files differ but it was not possible to execute 'diff' in\n"
1229
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1230
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
1231
"To get a better report you should install 'diff' on your system, which you\n"
1232
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1235
ds_tmp.append(" --- ");
1236
ds_tmp.append(filename1);
1237
ds_tmp.append(" >>>\n");
1251
dynstr_set(&ds_tmp, "");
1253
dynstr_append(&ds_tmp,
1255
"The two files differ but it was not possible to execute 'diff' in\n"
1256
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1257
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
1258
"To get a better report you should install 'diff' on your system, which you\n"
1259
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1262
dynstr_append(&ds_tmp, " --- ");
1263
dynstr_append(&ds_tmp, filename1);
1264
dynstr_append(&ds_tmp, " >>>\n");
1238
1265
cat_file(&ds_tmp, filename1);
1239
ds_tmp.append("<<<\n --- ");
1240
ds_tmp.append(filename1);
1241
ds_tmp.append(" >>>\n");
1266
dynstr_append(&ds_tmp, "<<<\n --- ");
1267
dynstr_append(&ds_tmp, filename1);
1268
dynstr_append(&ds_tmp, " >>>\n");
1242
1269
cat_file(&ds_tmp, filename2);
1243
ds_tmp.append("<<<<\n");
1270
dynstr_append(&ds_tmp, "<<<<\n");
1249
1276
/* Add the diff to output */
1250
ds->append(ds_tmp.c_str(), ds_tmp.length());
1277
dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1254
1281
/* Print diff directly to stdout */
1255
fprintf(stderr, "%s\n", ds_tmp.c_str());
1282
fprintf(stderr, "%s\n", ds_tmp.str);
1285
dynstr_free(&ds_tmp);
1261
1290
enum compare_files_result_enum {
1263
RESULT_CONTENT_MISMATCH= 1,
1264
RESULT_LENGTH_MISMATCH= 2
1292
RESULT_CONTENT_MISMATCH= 1,
1293
RESULT_LENGTH_MISMATCH= 2
1533
1562
static void strip_parentheses(struct st_command *command)
1535
1564
if (strip_surrounding(command->first_argument, '(', ')'))
1536
die("%.*s - argument list started with '%c' must be ended with '%c'",
1537
command->first_word_len, command->query, '(', ')');
1565
die("%.*s - argument list started with '%c' must be ended with '%c'",
1566
command->first_word_len, command->query, '(', ')');
1541
static unsigned char *get_var_key(const unsigned char* var, size_t *len,
1570
static uchar *get_var_key(const uchar* var, size_t *len,
1542
1571
bool __attribute__((unused)) t)
1544
1573
register char* key;
1545
1574
key = ((VAR*)var)->name;
1546
1575
*len = ((VAR*)var)->name_len;
1547
return (unsigned char*)key;
1798
1827
/* Eval the query, thus replacing all environment variables */
1828
init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
1799
1829
do_eval(&ds_query, query, end, false);
1801
if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1802
die("Error running query '%s': %d %s", ds_query.c_str(),
1803
drizzle_errno(drizzle), drizzle_error(drizzle));
1831
if (drizzle_real_query(drizzle, ds_query.str, ds_query.length))
1832
die("Error running query '%s': %d %s", ds_query.str,
1833
drizzle_errno(drizzle), drizzle_error(drizzle));
1804
1834
if (!(res= drizzle_store_result(drizzle)))
1805
die("Query '%s' didn't return a result set", ds_query.c_str());
1835
die("Query '%s' didn't return a result set", ds_query.str);
1836
dynstr_free(&ds_query);
1807
1838
if ((row= drizzle_fetch_row(res)) && row[0])
1810
1841
Concatenate all fields in the first row with tab in between
1811
1842
and assign that string to the $variable
1844
DYNAMIC_STRING result;
1815
1846
uint32_t *lengths;
1848
init_dynamic_string(&result, "", 512, 512);
1817
1849
lengths= drizzle_fetch_lengths(res);
1818
1850
for (i= 0; i < drizzle_num_fields(res); i++)
1822
1854
/* Add column to tab separated string */
1823
result.append(row[i], lengths[i]);
1855
dynstr_append_mem(&result, row[i], lengths[i]);
1825
result.append("\t", 1);
1857
dynstr_append_mem(&result, "\t", 1);
1827
end= result.c_str() + result.length()-1;
1828
eval_expr(var, result.c_str(), (const char**) &end);
1859
end= result.str + result.length-1;
1860
eval_expr(var, result.str, (const char**) &end);
1861
dynstr_free(&result);
1831
1864
eval_expr(var, "", 0);
1883
1916
/* Convert row number to int */
1884
if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1885
die("Invalid row number: '%s'", ds_row.c_str());
1917
if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
1918
die("Invalid row number: '%s'", ds_row.str);
1919
dynstr_free(&ds_row);
1887
1921
/* Remove any surrounding "'s from the query - if there is any */
1888
// (Don't get me started on this)
1889
char * unstripped_query= strdup(ds_query.c_str());
1890
if (strip_surrounding(unstripped_query, '"', '"'))
1891
die("Mismatched \"'s around query '%s'", ds_query.c_str());
1892
ds_query= unstripped_query;
1922
if (strip_surrounding(ds_query.str, '"', '"'))
1923
die("Mismatched \"'s around query '%s'", ds_query.str);
1894
1925
/* Run the query */
1895
if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1896
die("Error running query '%s': %d %s", ds_query.c_str(),
1897
drizzle_errno(drizzle), drizzle_error(drizzle));
1926
if (drizzle_real_query(drizzle, ds_query.str, ds_query.length))
1927
die("Error running query '%s': %d %s", ds_query.str,
1928
drizzle_errno(drizzle), drizzle_error(drizzle));
1898
1929
if (!(res= drizzle_store_result(drizzle)))
1899
die("Query '%s' didn't return a result set", ds_query.c_str());
1930
die("Query '%s' didn't return a result set", ds_query.str);
1902
1933
/* Find column number from the given column name */
2104
2144
Replace a substring
2108
ds_str The string to search and perform the replace in
2109
search_str The string to search for
2110
search_len Length of the string to search for
2111
replace_str The string to replace with
2112
replace_len Length of the string to replace with
2148
ds_str The string to search and perform the replace in
2149
search_str The string to search for
2150
search_len Length of the string to search for
2151
replace_str The string to replace with
2152
replace_len Length of the string to replace with
2116
1 Could not find search_str in str
2156
1 Could not find search_str in str
2119
static int replace(string *ds_str,
2120
const char *search_str, uint32_t search_len,
2121
const char *replace_str, uint32_t replace_len)
2159
static int replace(DYNAMIC_STRING *ds_str,
2160
const char *search_str, ulong search_len,
2161
const char *replace_str, ulong replace_len)
2124
const char *start= strstr(ds_str->c_str(), search_str);
2163
DYNAMIC_STRING ds_tmp;
2164
const char *start= strstr(ds_str->str, search_str);
2127
ds_tmp.append(ds_str->c_str(), start - ds_str->c_str());
2128
ds_tmp.append(replace_str, replace_len);
2129
ds_tmp.append(start + search_len);
2167
init_dynamic_string(&ds_tmp, "",
2168
ds_str->length + replace_len, 256);
2169
dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
2170
dynstr_append_mem(&ds_tmp, replace_str, replace_len);
2171
dynstr_append(&ds_tmp, start + search_len);
2172
dynstr_set(ds_str, ds_tmp.str);
2173
dynstr_free(&ds_tmp);
2299
2365
static void do_system(struct st_command *command)
2367
DYNAMIC_STRING ds_cmd;
2304
2370
if (strlen(command->first_argument) == 0)
2305
2371
die("Missing arguments to system, nothing to do!");
2373
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
2307
2375
/* Eval the system command, thus replacing all environment variables */
2308
2376
do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2310
if (system(ds_cmd.c_str()))
2378
if (my_system(&ds_cmd))
2312
2380
if (command->abort_on_error)
2313
2381
die("system command '%s' failed", command->first_argument);
2315
2383
/* If ! abort_on_error, log message and continue */
2316
ds_res.append("system command '");
2317
replace_append(&ds_res, command->first_argument);
2318
ds_res.append("' failed\n");
2384
dynstr_append(&ds_res, "system command '");
2385
replace_dynstr_append(&ds_res, command->first_argument);
2386
dynstr_append(&ds_res, "' failed\n");
2321
2389
command->last_argument= command->end;
2390
dynstr_free(&ds_cmd);
2598
2675
/* If no delimiter was provided, use EOF */
2599
if (ds_delimiter.length() == 0)
2600
ds_delimiter= "EOF";
2676
if (ds_delimiter.length == 0)
2677
dynstr_set(&ds_delimiter, "EOF");
2602
if (!append && access(ds_filename.c_str(), F_OK) == 0)
2679
if (!append && access(ds_filename.str, F_OK) == 0)
2604
2681
/* The file should not be overwritten */
2605
die("File already exist: '%s'", ds_filename.c_str());
2682
die("File already exist: '%s'", ds_filename.str);
2685
init_dynamic_string(&ds_content, "", 1024, 1024);
2608
2686
read_until_delimiter(&ds_content, &ds_delimiter);
2609
str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2610
ds_content.length(), append);
2687
str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
2688
dynstr_free(&ds_content);
2689
dynstr_free(&ds_filename);
2690
dynstr_free(&ds_delimiter);
3076
3166
if (drizzle_query(drizzle, query= "show master status"))
3077
3167
die("failed in 'show master status': %d %s",
3078
drizzle_errno(drizzle), drizzle_error(drizzle));
3168
drizzle_errno(drizzle), drizzle_error(drizzle));
3080
3170
if (!(res = drizzle_store_result(drizzle)))
3081
3171
die("drizzle_store_result() retuned NULL for '%s'", query);
3082
3172
if (!(row = drizzle_fetch_row(res)))
3083
3173
die("empty result in show master status");
3084
my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
3174
stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
3085
3175
master_pos.pos = strtoul(row[1], (char**) 0, 10);
3086
3176
drizzle_free_result(res);
3559
3653
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
3560
const char *user, const char *pass, const char *db,
3654
const char *user, const char *pass, const char *db,
3563
3657
int failed_attempts= 0;
3564
static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3658
static ulong connection_retry_sleep= 100000; /* Microseconds */
3567
3661
while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3568
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3662
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3625
3719
static int connect_n_handle_errors(struct st_command *command,
3626
DRIZZLE *con, const char* host,
3627
const char* user, const char* pass,
3628
const char* db, int port, const char* sock)
3720
DRIZZLE *con, const char* host,
3721
const char* user, const char* pass,
3722
const char* db, int port, const char* sock)
3631
3728
/* Only log if an error is expected */
3632
3729
if (!command->abort_on_error &&
3636
3733
Log the connect to result log
3638
ds_res.append("connect(");
3639
replace_append(&ds_res, host);
3641
replace_append(&ds_res, user);
3643
replace_append(&ds_res, pass);
3735
dynstr_append_mem(ds, "connect(", 8);
3736
replace_dynstr_append(ds, host);
3737
dynstr_append_mem(ds, ",", 1);
3738
replace_dynstr_append(ds, user);
3739
dynstr_append_mem(ds, ",", 1);
3740
replace_dynstr_append(ds, pass);
3741
dynstr_append_mem(ds, ",", 1);
3646
replace_append(&ds_res, db);
3648
replace_append_uint(&ds_res, port);
3743
replace_dynstr_append(ds, db);
3744
dynstr_append_mem(ds, ",", 1);
3745
replace_dynstr_append_uint(ds, port);
3746
dynstr_append_mem(ds, ",", 1);
3651
replace_append(&ds_res, sock);
3653
ds_res.append(delimiter);
3654
ds_res.append("\n");
3748
replace_dynstr_append(ds, sock);
3749
dynstr_append_mem(ds, ")", 1);
3750
dynstr_append_mem(ds, delimiter, delimiter_length);
3751
dynstr_append_mem(ds, "\n", 1);
3656
3753
if (!drizzle_connect(con, host, user, pass, db, port, 0,
3657
CLIENT_MULTI_STATEMENTS))
3754
CLIENT_MULTI_STATEMENTS))
3659
3756
var_set_errno(drizzle_errno(con));
3660
3757
handle_error(command, drizzle_errno(con), drizzle_error(con),
3661
drizzle_sqlstate(con), &ds_res);
3758
drizzle_sqlstate(con), ds);
3662
3759
return 0; /* Not connected */
3688
3785
<port> - server port
3689
3786
<sock> - server socket
3690
3787
<opts> - options to use for the connection
3691
* SSL - use SSL if available
3692
* COMPRESS - use compression if available
3788
* SSL - use SSL if available
3789
* COMPRESS - use compression if available
3696
3793
static void do_connect(struct st_command *command)
3698
3795
int con_port= opt_port;
3699
const char *con_options;
3700
3797
bool con_ssl= 0, con_compress= 0;
3701
3798
struct st_connection* con_slot;
3703
string ds_connection_name;
3800
static DYNAMIC_STRING ds_connection_name;
3801
static DYNAMIC_STRING ds_host;
3802
static DYNAMIC_STRING ds_user;
3803
static DYNAMIC_STRING ds_password;
3804
static DYNAMIC_STRING ds_database;
3805
static DYNAMIC_STRING ds_port;
3806
static DYNAMIC_STRING ds_sock;
3807
static DYNAMIC_STRING ds_options;
3711
3808
const struct command_arg connect_args[] = {
3712
3809
{ "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3713
3810
{ "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3729
if (ds_port.length())
3731
con_port= atoi(ds_port.c_str());
3828
con_port= atoi(ds_port.str);
3732
3829
if (con_port == 0)
3733
die("Illegal argument for port: '%s'", ds_port.c_str());
3830
die("Illegal argument for port: '%s'", ds_port.str);
3737
if (!ds_sock.empty())
3740
3837
If the socket is specified just as a name without path
3741
3838
append tmpdir in front
3743
if (*ds_sock.c_str() != FN_LIBCHAR)
3840
if (*ds_sock.str != FN_LIBCHAR)
3745
3842
char buff[FN_REFLEN];
3746
fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3843
fn_format(buff, ds_sock.str, TMPDIR, "", 0);
3844
dynstr_set(&ds_sock, buff);
3849
/* No socket specified, use default */
3850
dynstr_set(&ds_sock, unix_sock);
3752
con_options= ds_options.c_str();
3854
con_options= ds_options.str;
3753
3855
while (*con_options)
3756
3858
/* Step past any spaces in beginning of option*/
3757
3859
while (*con_options && my_isspace(charset_info, *con_options))
3759
3861
/* Find end of this option */
3760
3862
end= con_options;
3761
3863
while (*end && !my_isspace(charset_info, *end))
3785
3885
(int) (sizeof(connections)/sizeof(struct st_connection)));
3888
#ifdef EMBEDDED_LIBRARY
3889
con_slot->query_done= 1;
3788
3891
if (!drizzle_create(&con_slot->drizzle))
3789
3892
die("Failed on drizzle_create()");
3790
3893
if (opt_compress || con_compress)
3791
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NULL);
3894
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NullS);
3792
3895
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
3896
drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_NAME,
3897
charset_info->csname);
3898
int opt_protocol= DRIZZLE_PROTOCOL_TCP;
3899
drizzle_options(&con_slot->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
3900
if (opt_charsets_dir)
3901
drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_DIR,
3794
3904
/* Use default db name */
3795
if (ds_database.length() == 0)
3796
ds_database= opt_db;
3905
if (ds_database.length == 0)
3906
dynstr_set(&ds_database, opt_db);
3798
3908
/* Special database to allow one to connect without a database name */
3799
if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
3909
if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
3910
dynstr_set(&ds_database, "");
3802
3912
if (connect_n_handle_errors(command, &con_slot->drizzle,
3803
ds_host.c_str(),ds_user.c_str(),
3804
ds_password.c_str(), ds_database.c_str(),
3805
con_port, ds_sock.c_str()))
3913
ds_host.str,ds_user.str,
3914
ds_password.str, ds_database.str,
3915
con_port, ds_sock.str))
3807
if (!(con_slot->name= strdup(ds_connection_name.c_str())))
3917
if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3808
3918
die("Out of memory");
3809
3919
cur_con= con_slot;
3811
3921
if (con_slot == next_con)
3812
3922
next_con++; /* if we used the next_con slot, advance the pointer */
4062
4180
if (end_of_query(c))
4067
4185
else if ((c == '{' &&
4068
(!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
4069
(unsigned char*) buf, cmin((long)5, p - buf), 0) ||
4070
!my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
4071
(unsigned char*) buf, cmin((long)2, p - buf), 0))))
4186
(!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
4187
(uchar*) buf, min(5, p - buf), 0) ||
4188
!my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
4189
(uchar*) buf, min(2, p - buf), 0))))
4073
4191
/* Only if and while commands can be terminated by { */
4078
4196
else if (c == '\'' || c == '"' || c == '`')
4151
4269
/* completed before we pass buf_end */
4152
4270
if ((charlen > 1) && (p + charlen) <= buf_end)
4159
for (i= 1; i < charlen; i++)
4161
if (feof(cur_file->file))
4163
c= my_getc(cur_file->file);
4166
if (! my_ismbchar(charset_info, mb_start, p))
4168
/* It was not a multiline char, push back the characters */
4169
/* We leave first 'c', i.e. pretend it was a normal char */
4170
while (p > mb_start)
4277
for (i= 1; i < charlen; i++)
4279
if (feof(cur_file->file))
4281
c= my_getc(cur_file->file);
4284
if (! my_ismbchar(charset_info, mb_start, p))
4286
/* It was not a multiline char, push back the characters */
4287
/* We leave first 'c', i.e. pretend it was a normal char */
4288
while (p > mb_start)
4179
die("The input buffer is too small for this query.x\n" \
4297
die("The input buffer is too small for this query.x\n" \
4180
4298
"check your query or increase MAX_QUERY and recompile");
4453
4571
{"password", 'p', "Password to use when connecting to server.",
4454
4572
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4455
4573
{"port", 'P', "Port number to use for connection or 0 for default to, in "
4456
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
4457
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
4574
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
4575
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
4458
4576
(char**) &opt_port,
4459
4577
(char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4460
4578
{"quiet", 's', "Suppress all normal output.", (char**) &silent,
4496
4614
static void print_version(void)
4498
4616
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4499
drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
4617
drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
4502
4620
static void usage(void)
4504
4622
print_version();
4505
printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4623
printf("DRIZZLE AB, by Sasha, Matt, Monty & Jani\n");
4506
4624
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4507
4625
printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
4508
4626
printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4672
4790
append - append to file instead of overwriting old file
4675
void str_to_file2(const char *fname, const char *str, int size, bool append)
4793
void str_to_file2(const char *fname, char *str, int size, bool append)
4678
4796
char buff[FN_REFLEN];
4679
4797
int flags= O_WRONLY | O_CREAT;
4680
4798
if (!test_if_hard_path(fname))
4682
strxmov(buff, opt_basedir, fname, NULL);
4800
strxmov(buff, opt_basedir, fname, NullS);
4685
4803
fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4765
4883
if (!display_result_vertically)
4769
replace_append_mem(ds, val, (int)len);
4886
dynstr_append_mem(ds, "\t", 1);
4887
replace_dynstr_append_mem(ds, val, (int)len);
4773
ds->append(field->name);
4775
replace_append_mem(ds, val, (int)len);
4891
dynstr_append(ds, field->name);
4892
dynstr_append_mem(ds, "\t", 1);
4893
replace_dynstr_append_mem(ds, val, (int)len);
4894
dynstr_append_mem(ds, "\n", 1);
4808
4925
Append metadata for fields to output
4811
static void append_metadata(string *ds,
4928
static void append_metadata(DYNAMIC_STRING *ds,
4812
4929
const DRIZZLE_FIELD *field,
4813
4930
uint num_fields)
4815
4932
const DRIZZLE_FIELD *field_end;
4816
ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4817
"Column_alias\tType\tLength\tMax length\tIs_null\t"
4818
"Flags\tDecimals\tCharsetnr\n");
4933
dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4934
"Column_alias\tType\tLength\tMax length\tIs_null\t"
4935
"Flags\tDecimals\tCharsetnr\n");
4820
4937
for (field_end= field+num_fields ;
4821
4938
field < field_end ;
4824
ds->append(field->catalog,
4825
field->catalog_length);
4826
ds->append("\t", 1);
4827
ds->append(field->db, field->db_length);
4828
ds->append("\t", 1);
4829
ds->append(field->org_table,
4830
field->org_table_length);
4831
ds->append("\t", 1);
4832
ds->append(field->table,
4833
field->table_length);
4834
ds->append("\t", 1);
4835
ds->append(field->org_name,
4836
field->org_name_length);
4837
ds->append("\t", 1);
4838
ds->append(field->name, field->name_length);
4839
ds->append("\t", 1);
4840
replace_append_uint(ds, field->type);
4841
ds->append("\t", 1);
4842
replace_append_uint(ds, field->length);
4843
ds->append("\t", 1);
4844
replace_append_uint(ds, field->max_length);
4845
ds->append("\t", 1);
4846
ds->append((char*) ((field->flags & NOT_NULL_FLAG) ?
4848
ds->append("\t", 1);
4849
replace_append_uint(ds, field->flags);
4850
ds->append("\t", 1);
4851
replace_append_uint(ds, field->decimals);
4852
ds->append("\t", 1);
4853
replace_append_uint(ds, field->charsetnr);
4854
ds->append("\n", 1);
4941
dynstr_append_mem(ds, field->catalog,
4942
field->catalog_length);
4943
dynstr_append_mem(ds, "\t", 1);
4944
dynstr_append_mem(ds, field->db, field->db_length);
4945
dynstr_append_mem(ds, "\t", 1);
4946
dynstr_append_mem(ds, field->org_table,
4947
field->org_table_length);
4948
dynstr_append_mem(ds, "\t", 1);
4949
dynstr_append_mem(ds, field->table,
4950
field->table_length);
4951
dynstr_append_mem(ds, "\t", 1);
4952
dynstr_append_mem(ds, field->org_name,
4953
field->org_name_length);
4954
dynstr_append_mem(ds, "\t", 1);
4955
dynstr_append_mem(ds, field->name, field->name_length);
4956
dynstr_append_mem(ds, "\t", 1);
4957
replace_dynstr_append_uint(ds, field->type);
4958
dynstr_append_mem(ds, "\t", 1);
4959
replace_dynstr_append_uint(ds, field->length);
4960
dynstr_append_mem(ds, "\t", 1);
4961
replace_dynstr_append_uint(ds, field->max_length);
4962
dynstr_append_mem(ds, "\t", 1);
4963
dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
4965
dynstr_append_mem(ds, "\t", 1);
4966
replace_dynstr_append_uint(ds, field->flags);
4967
dynstr_append_mem(ds, "\t", 1);
4968
replace_dynstr_append_uint(ds, field->decimals);
4969
dynstr_append_mem(ds, "\t", 1);
4970
replace_dynstr_append_uint(ds, field->charsetnr);
4971
dynstr_append_mem(ds, "\n", 1);
4933
5051
Run query using DRIZZLE C API
4937
drizzle DRIZZLE handle
4938
command current command pointer
4939
flags flags indicating if we should SEND and/or REAP
4940
query query string to execute
4941
query_len length query string to execute
4942
ds output buffer where to store result form query
5055
drizzle DRIZZLE handle
5056
command current command pointer
5057
flags flags indicating if we should SEND and/or REAP
5058
query query string to execute
5059
query_len length query string to execute
5060
ds output buffer where to store result form query
4945
5063
static void run_query_normal(struct st_connection *cn,
4946
5064
struct st_command *command,
4947
5065
int flags, char *query, int query_len,
4948
string *ds, string *ds_warnings)
5066
DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4950
5068
DRIZZLE_RES *res= 0;
4951
5069
DRIZZLE *drizzle= &cn->drizzle;
4954
5072
if (flags & QUERY_SEND_FLAG)
4959
5077
if (do_send_query(cn, query, query_len, flags))
4961
5079
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4962
drizzle_sqlstate(drizzle), ds);
5080
drizzle_sqlstate(drizzle), ds);
5084
#ifdef EMBEDDED_LIBRARY
5086
Here we handle 'reap' command, so we need to check if the
5087
query's thread was finished and probably wait
5089
else if (flags & QUERY_REAP_FLAG)
5090
wait_query_thread_end(cn);
5091
#endif /*EMBEDDED_LIBRARY*/
4966
5092
if (!(flags & QUERY_REAP_FLAG))
5023
5149
if (!disable_warnings && !drizzle_more_results(drizzle))
5025
if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
5027
ds->append("Warnings:\n", 10);
5028
ds->append(ds_warnings->c_str(), ds_warnings->length());
5151
if (append_warnings(ds_warnings, drizzle) || ds_warnings->length)
5153
dynstr_append_mem(ds, "Warnings:\n", 10);
5154
dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
5032
5158
if (!disable_info)
5033
append_info(ds, affected_rows, drizzle_info(drizzle));
5159
append_info(ds, affected_rows, drizzle_info(drizzle));
5120
5247
if (command->expected_errors.count == 1)
5122
5249
/* Only log error if there is one possible error */
5123
ds->append("ERROR ", 6);
5124
replace_append(ds, err_sqlstate);
5125
ds->append(": ", 2);
5126
replace_append(ds, err_error);
5250
dynstr_append_mem(ds, "ERROR ", 6);
5251
replace_dynstr_append(ds, err_sqlstate);
5252
dynstr_append_mem(ds, ": ", 2);
5253
replace_dynstr_append(ds, err_error);
5254
dynstr_append_mem(ds,"\n",1);
5129
5256
/* Don't log error if we may not get an error */
5130
5257
else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5131
5258
(command->expected_errors.err[0].type == ERR_ERRNO &&
5132
5259
command->expected_errors.err[0].code.errnum != 0))
5133
ds->append("Got one of the listed errors\n");
5260
dynstr_append(ds,"Got one of the listed errors\n");
5250
5380
if (command->require_file[0])
5382
init_dynamic_string(&ds_result, "", 1024, 1024);
5252
5383
ds= &ds_result;
5259
5389
Log the query into the output buffer
5261
5391
if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5263
replace_append_mem(ds, query, query_len);
5264
ds->append(delimiter, delimiter_length);
5393
replace_dynstr_append_mem(ds, query, query_len);
5394
dynstr_append_mem(ds, delimiter, delimiter_length);
5395
dynstr_append_mem(ds, "\n", 1);
5268
5398
if (display_result_sorted)
5271
Collect the query output in a separate string
5272
that can be sorted before it's added to the
5273
global result string
5401
Collect the query output in a separate string
5402
that can be sorted before it's added to the
5403
global result string
5405
init_dynamic_string(&ds_sorted, "", 1024, 1024);
5275
5406
save_ds= ds; /* Remember original ds */
5276
5407
ds= &ds_sorted;
5403
5540
/* Milliseconds since start */
5404
5541
end= int64_t2str(timer, buf, 10);
5405
ds_progress.append(buf, (int)(end-buf));
5406
ds_progress.append("\t", 1);
5542
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5543
dynstr_append_mem(&ds_progress, "\t", 1);
5408
5545
/* Parser line number */
5409
5546
end= int10_to_str(line, buf, 10);
5410
ds_progress.append(buf, (int)(end-buf));
5411
ds_progress.append("\t", 1);
5547
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5548
dynstr_append_mem(&ds_progress, "\t", 1);
5414
ds_progress.append(cur_file->file_name);
5415
ds_progress.append(":", 1);
5551
dynstr_append(&ds_progress, cur_file->file_name);
5552
dynstr_append_mem(&ds_progress, ":", 1);
5417
5554
/* Line in file */
5418
5555
end= int10_to_str(cur_file->lineno, buf, 10);
5419
ds_progress.append(buf, (int)(end-buf));
5422
ds_progress.append("\n", 1);
5556
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5559
dynstr_append_mem(&ds_progress, "\n", 1);
5459
5602
cur_block->ok= true; /* Outer block should always be executed */
5460
5603
cur_block->cmd= cmd_none;
5605
my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
5462
5607
if (hash_init(&var_hash, charset_info,
5463
5608
1024, 0, 0, get_var_key, var_free, MYF(0)))
5464
5609
die("Variable hash initialization failed");
5466
var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
5611
var_set_string("$MYSQL_SERVER_VERSION", drizzle_get_client_info());
5468
5613
memset(&master_pos, 0, sizeof(master_pos));
5489
5633
if (!( drizzle_create(&cur_con->drizzle)))
5490
5634
die("Failed in drizzle_create()");
5491
5635
if (opt_compress)
5492
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
5636
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NullS);
5493
5637
drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
5638
drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_NAME,
5639
charset_info->csname);
5640
int opt_protocol= DRIZZLE_PROTOCOL_TCP;
5641
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
5642
if (opt_charsets_dir)
5643
drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_DIR,
5495
5646
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5496
5647
die("Out of memory");
5655
5804
/* Remove "send" if this is first iteration */
5656
if (command->query == command->query_buf)
5657
command->query= command->first_argument;
5805
if (command->query == command->query_buf)
5806
command->query= command->first_argument;
5660
run_query() can execute a query partially, depending on the flags.
5661
QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5809
run_query() can execute a query partially, depending on the flags.
5810
QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5662
5811
the query and read the result some time later when reap instruction
5663
is given on this connection.
5812
is given on this connection.
5665
run_query(cur_con, command, QUERY_SEND_FLAG);
5814
run_query(cur_con, command, QUERY_SEND_FLAG);
5667
5816
command->last_argument= command->end;
5669
5818
case Q_REQUIRE:
5670
do_get_file_name(command, save_file, sizeof(save_file));
5819
do_get_file_name(command, save_file, sizeof(save_file));
5673
5822
do_get_errcodes(command);
5675
5824
case Q_REPLACE:
5676
do_get_replace(command);
5825
do_get_replace(command);
5678
5827
case Q_REPLACE_REGEX:
5679
5828
do_get_replace_regex(command);
5681
5830
case Q_REPLACE_COLUMN:
5682
do_get_replace_column(command);
5831
do_get_replace_column(command);
5684
5833
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5685
5834
case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5686
5835
case Q_SYNC_SLAVE_WITH_MASTER:
5688
do_save_master_pos();
5689
if (*command->first_argument)
5690
select_connection(command);
5692
select_connection_name("slave");
5693
do_sync_with_master2(0);
5837
do_save_master_pos();
5838
if (*command->first_argument)
5839
select_connection(command);
5841
select_connection_name("slave");
5842
do_sync_with_master2(0);
5696
5845
case Q_COMMENT: /* Ignore row */
5697
5846
command->last_argument= command->end;
5700
(void) drizzle_ping(&cur_con->drizzle);
5849
(void) drizzle_ping(&cur_con->drizzle);
5706
5855
case Q_START_TIMER:
5707
/* Overwrite possible earlier start of timer */
5708
timer_start= timer_now();
5856
/* Overwrite possible earlier start of timer */
5857
timer_start= timer_now();
5710
5859
case Q_END_TIMER:
5711
/* End timer before ending drizzletest */
5860
/* End timer before ending drizzletest */
5714
5863
case Q_CHARACTER_SET:
5715
do_set_charset(command);
5864
do_set_charset(command);
5717
5866
case Q_DISABLE_RECONNECT:
5718
5867
set_reconnect(&cur_con->drizzle, 0);
5820
/* Recording - dump the output from test to result file */
5821
str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
5969
/* Recording - dump the output from test to result file */
5970
str_to_file(result_file_name, ds_res.str, ds_res.length);
5825
/* Check that the output from test is equal to result file
5826
- detect missing result file
5827
- detect zero size result file
5974
/* Check that the output from test is equal to result file
5975
- detect missing result file
5976
- detect zero size result file
5829
check_result(&ds_res);
5978
check_result(&ds_res);
5834
5983
/* No result_file_name specified to compare with, print to stdout */
5835
printf("%s", ds_res.c_str());
5984
printf("%s", ds_res.str);
5973
6122
typedef struct st_pointer_array { /* when using array-strings */
5974
6123
TYPELIB typelib; /* Pointer to strings */
5975
unsigned char *str; /* Strings is here */
5976
uint8_t *flag; /* Flag about each var. */
6124
uchar *str; /* Strings is here */
6125
int7 *flag; /* Flag about each var. */
5977
6126
uint array_allocs,max_count,length,max_length;
5978
6127
} POINTER_ARRAY;
5980
6129
struct st_replace;
5981
6130
struct st_replace *init_replace(char * *from, char * *to, uint count,
5982
char * word_end_chars);
6131
char * word_end_chars);
5983
6132
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5984
void replace_strings_append(struct st_replace *rep, string* ds,
6133
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5985
6134
const char *from, int len);
5986
6135
void free_pointer_array(POINTER_ARRAY *pa);
6079
6229
/* Loop through states */
6080
6230
while (!rep_pos->found)
6081
rep_pos= rep_pos->next[(unsigned char) *from++];
6231
rep_pos= rep_pos->next[(uchar) *from++];
6083
6233
/* Does this state contain a string to be replaced */
6084
6234
if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6086
6236
/* No match found */
6087
ds->append(start, from - start - 1);
6237
dynstr_append_mem(ds, start, from - start - 1);
6091
6241
/* Append part of original string before replace string */
6092
ds->append(start, (from - rep_str->to_offset) - start);
6242
dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6094
6244
/* Append replace string */
6095
ds->append(rep_str->replace_string,
6096
strlen(rep_str->replace_string));
6245
dynstr_append_mem(ds, rep_str->replace_string,
6246
strlen(rep_str->replace_string));
6098
6248
if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6545
6695
internal_set_bit(start_states,states+1);
6546
6696
if (!from[i][2])
6548
start_states->table_offset=i;
6549
start_states->found_offset=1;
6698
start_states->table_offset=i;
6699
start_states->found_offset=1;
6552
6702
else if (from[i][0] == '\\' && from[i][1] == '$')
6554
6704
internal_set_bit(start_states,states);
6555
6705
internal_set_bit(word_states,states);
6556
if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6706
if (!from[i][2] && start_states->table_offset == (uint) ~0)
6558
start_states->table_offset=i;
6559
start_states->found_offset=0;
6708
start_states->table_offset=i;
6709
start_states->found_offset=0;
6564
6714
internal_set_bit(word_states,states);
6565
6715
if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6566
internal_set_bit(start_states,states+1);
6716
internal_set_bit(start_states,states+1);
6568
internal_set_bit(start_states,states);
6718
internal_set_bit(start_states,states);
6570
6720
for (pos=from[i], len=0; *pos ; pos++)
6572
6722
if (*pos == '\\' && *(pos+1))
6577
follow_ptr->chr = SPACE_CHAR;
6580
follow_ptr->chr = START_OF_LINE;
6583
follow_ptr->chr = END_OF_LINE;
6586
follow_ptr->chr = '\r';
6589
follow_ptr->chr = '\t';
6592
follow_ptr->chr = '\v';
6595
follow_ptr->chr = (unsigned char) *pos;
6727
follow_ptr->chr = SPACE_CHAR;
6730
follow_ptr->chr = START_OF_LINE;
6733
follow_ptr->chr = END_OF_LINE;
6736
follow_ptr->chr = '\r';
6739
follow_ptr->chr = '\t';
6742
follow_ptr->chr = '\v';
6745
follow_ptr->chr = (uchar) *pos;
6600
follow_ptr->chr= (unsigned char) *pos;
6750
follow_ptr->chr= (uchar) *pos;
6601
6751
follow_ptr->table_offset=i;
6602
6752
follow_ptr->len= ++len;
6633
6783
/* Find all chars that follows current sets */
6634
6784
memset(used_chars, 0, sizeof(used_chars));
6635
for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6785
for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6637
6787
used_chars[follow[i].chr]=1;
6638
6788
if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6639
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6789
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6643
6793
/* Mark word_chars used if \b is in state */
6644
6794
if (used_chars[SPACE_CHAR])
6645
6795
for (pos= word_end_chars ; *pos ; pos++)
6646
used_chars[(int) (unsigned char) *pos] = 1;
6796
used_chars[(int) (uchar) *pos] = 1;
6648
6798
/* Handle other used characters */
6649
6799
for (chr= 0 ; chr < 256 ; chr++)
6651
6801
if (! used_chars[chr])
6652
set->next[chr]= chr ? default_state : -1;
6802
set->next[chr]= chr ? default_state : -1;
6655
new_set=make_new_set(&sets);
6656
set=sets.set+set_nr; /* if realloc */
6657
new_set->table_offset=set->table_offset;
6658
new_set->found_len=set->found_len;
6659
new_set->found_offset=set->found_offset+1;
6805
new_set=make_new_set(&sets);
6806
set=sets.set+set_nr; /* if realloc */
6807
new_set->table_offset=set->table_offset;
6808
new_set->found_len=set->found_len;
6809
new_set->found_offset=set->found_offset+1;
6662
for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6664
if (!follow[i].chr || follow[i].chr == chr ||
6665
(follow[i].chr == SPACE_CHAR &&
6666
(is_word_end[chr] ||
6667
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6668
(follow[i].chr == END_OF_LINE && ! chr))
6670
if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6671
follow[i].len > found_end)
6672
found_end=follow[i].len;
6673
if (chr && follow[i].chr)
6674
internal_set_bit(new_set,i+1); /* To next set */
6676
internal_set_bit(new_set,i);
6681
new_set->found_len=0; /* Set for testing if first */
6683
for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6685
if ((follow[i].chr == SPACE_CHAR ||
6686
follow[i].chr == END_OF_LINE) && ! chr)
6690
if (follow[bit_nr-1].len < found_end ||
6691
(new_set->found_len &&
6692
(chr == 0 || !follow[bit_nr].chr)))
6693
internal_clear_bit(new_set,i);
6696
if (chr == 0 || !follow[bit_nr].chr)
6698
new_set->table_offset=follow[bit_nr].table_offset;
6699
if (chr || (follow[i].chr == SPACE_CHAR ||
6700
follow[i].chr == END_OF_LINE))
6701
new_set->found_offset=found_end; /* New match */
6702
new_set->found_len=found_end;
6709
set->next[chr] = find_found(found_set,
6710
new_set->table_offset,
6711
new_set->found_offset);
6712
free_last_set(&sets);
6715
set->next[chr] = find_set(&sets,new_set);
6718
set->next[chr] = find_set(&sets,new_set);
6812
for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6814
if (!follow[i].chr || follow[i].chr == chr ||
6815
(follow[i].chr == SPACE_CHAR &&
6816
(is_word_end[chr] ||
6817
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6818
(follow[i].chr == END_OF_LINE && ! chr))
6820
if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6821
follow[i].len > found_end)
6822
found_end=follow[i].len;
6823
if (chr && follow[i].chr)
6824
internal_set_bit(new_set,i+1); /* To next set */
6826
internal_set_bit(new_set,i);
6831
new_set->found_len=0; /* Set for testing if first */
6833
for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
6835
if ((follow[i].chr == SPACE_CHAR ||
6836
follow[i].chr == END_OF_LINE) && ! chr)
6840
if (follow[bit_nr-1].len < found_end ||
6841
(new_set->found_len &&
6842
(chr == 0 || !follow[bit_nr].chr)))
6843
internal_clear_bit(new_set,i);
6846
if (chr == 0 || !follow[bit_nr].chr)
6848
new_set->table_offset=follow[bit_nr].table_offset;
6849
if (chr || (follow[i].chr == SPACE_CHAR ||
6850
follow[i].chr == END_OF_LINE))
6851
new_set->found_offset=found_end; /* New match */
6852
new_set->found_len=found_end;
6859
set->next[chr] = find_found(found_set,
6860
new_set->table_offset,
6861
new_set->found_offset);
6862
free_last_set(&sets);
6865
set->next[chr] = find_set(&sets,new_set);
6868
set->next[chr] = find_set(&sets,new_set);
6799
6949
memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
6800
6950
set->found_offset=0;
6801
6951
set->found_len=0;
6802
set->table_offset= UINT32_MAX;
6952
set->table_offset= (uint) ~0;
6803
6953
set->size_of_bits=sets->size_of_bits;
6806
6956
count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6807
if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
6957
if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6808
6958
sizeof(REP_SET)*count,
6811
6961
sets->set_buffer=set;
6812
6962
sets->set=set+sets->invisible;
6813
if (!(bit_buffer=(uint*) my_realloc((unsigned char*) sets->bit_buffer,
6814
(sizeof(uint)*sets->size_of_bits)*count,
6963
if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
6964
(sizeof(uint)*sets->size_of_bits)*count,
6817
6967
sets->bit_buffer=bit_buffer;
6818
6968
for (i=0 ; i < count ; i++)
6957
7107
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6959
7109
uint i,length,old_count;
6960
unsigned char *new_pos;
6961
7111
const char **new_array;
6964
7114
if (! pa->typelib.count)
6966
7116
if (!(pa->typelib.type_names=(const char **)
6967
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
6968
(sizeof(char *)+sizeof(*pa->flag))*
6969
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
7117
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7118
(sizeof(char *)+sizeof(*pa->flag))*
7119
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6971
if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
7121
if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
6974
free((char*) pa->typelib.type_names);
7124
my_free((char*) pa->typelib.type_names,MYF(0));
6977
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(unsigned char*)+
6979
pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
7127
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7129
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6981
7131
pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6982
7132
pa->array_allocs=1;
6984
7134
length=(uint) strlen(name)+1;
6985
7135
if (pa->length+length >= pa->max_length)
6987
if (!(new_pos= (unsigned char*) my_realloc((unsigned char*) pa->str,
6988
(uint) (pa->max_length+PS_MALLOC),
7137
if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
7138
(uint) (pa->max_length+PS_MALLOC),
6991
7141
if (new_pos != pa->str)
6993
7143
my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
6994
7144
for (i=0 ; i < pa->typelib.count ; i++)
6995
pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
7145
pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
6997
7147
pa->str=new_pos;
6999
7149
pa->max_length+=PS_MALLOC;
7004
7154
pa->array_allocs++;
7005
7155
len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7006
if (!(new_array=(const char **) my_realloc((unsigned char*) pa->typelib.type_names,
7008
(sizeof(unsigned char*)+sizeof(*pa->flag))*
7009
(sizeof(unsigned char*)+sizeof(*pa->flag)),
7156
if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
7158
(sizeof(uchar*)+sizeof(*pa->flag))*
7159
(sizeof(uchar*)+sizeof(*pa->flag)),
7012
7162
pa->typelib.type_names=new_array;
7013
7163
old_count=pa->max_count;
7014
pa->max_count=len/(sizeof(unsigned char*) + sizeof(*pa->flag));
7015
pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
7164
pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
7165
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7016
7166
memcpy(pa->flag, pa->typelib.type_names+old_count,
7017
7167
old_count*sizeof(*pa->flag));
7019
7169
pa->flag[pa->typelib.count]=0; /* Reset flag */
7020
7170
pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
7021
pa->typelib.type_names[pa->typelib.count]= NULL; /* Put end-mark */
7022
my_stpcpy((char*) pa->str+pa->length,name);
7171
pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
7172
VOID(stpcpy((char*) pa->str+pa->length,name));
7023
7173
pa->length+=length;
7025
7175
} /* insert_pointer_name */
7042
7192
/* Functions that uses replace and replace_regex */
7044
7194
/* Append the string to ds, with optional replace */
7045
void replace_append_mem(string *ds,
7046
const char *val, int len)
7195
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
7196
const char *val, int len)
7048
char *v= strdup(val);
7050
7198
if (glob_replace_regex)
7052
7200
/* Regex replace */
7053
if (!multi_reg_replace(glob_replace_regex, v))
7201
if (!multi_reg_replace(glob_replace_regex, (char*)val))
7055
v= glob_replace_regex->buf;
7203
val= glob_replace_regex->buf;
7060
7208
if (glob_replace)
7062
7210
/* Normal replace */
7063
replace_strings_append(glob_replace, ds, v, len);
7211
replace_strings_append(glob_replace, ds, val, len);
7214
dynstr_append_mem(ds, val, len);
7072
7218
/* Append zero-terminated string to ds, with optional replace */
7073
void replace_append(string *ds, const char *val)
7219
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7075
replace_append_mem(ds, val, strlen(val));
7221
replace_dynstr_append_mem(ds, val, strlen(val));
7078
7224
/* Append uint to ds, with optional replace */
7079
void replace_append_uint(string *ds, uint val)
7225
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7081
7227
char buff[22]; /* This should be enough for any int */
7082
7228
char *end= int64_t10_to_str(val, buff, 10);
7083
replace_append_mem(ds, buff, end - buff);
7229
replace_dynstr_append_mem(ds, buff, end - buff);
7102
void append_sorted(string* ds, string *ds_input)
7104
priority_queue<string> lines;
7106
if (ds_input->empty())
7246
static int comp_lines(const char **a, const char **b)
7248
return (strcmp(*a,*b));
7251
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
7254
char *start= ds_input->str;
7255
DYNAMIC_ARRAY lines;
7107
7259
return; /* No input */
7109
unsigned long eol_pos= 0;
7111
eol_pos= ds_input->find_first_of('\n', 0);
7112
if (eol_pos == string::npos)
7113
return; // We should have at least one header here
7115
ds->append(ds_input->substr(0, eol_pos));
7117
unsigned long start_pos= eol_pos+1;
7261
my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
7263
/* First line is result header, skip past it */
7264
while (*start && *start != '\n')
7266
start++; /* Skip past \n */
7267
dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
7119
7269
/* Insert line(s) in array */
7272
char* line_end= (char*)start;
7122
eol_pos= ds_input->find_first_of('\n', start_pos);
7123
7274
/* Find end of line */
7124
lines.push(ds_input->substr(start_pos, eol_pos-start_pos));
7125
start_pos= eol_pos+1;
7127
} while ( eol_pos != string::npos);
7275
while (*line_end && *line_end != '\n')
7279
/* Insert pointer to the line in array */
7280
if (insert_dynamic(&lines, (uchar*) &start))
7281
die("Out of memory inserting lines to sort");
7287
qsort(lines.buffer, lines.elements,
7288
sizeof(char**), (qsort_cmp)comp_lines);
7129
7290
/* Create new result */
7130
while (!lines.empty()) {
7131
ds->append(lines.top());
7291
for (i= 0; i < lines.elements ; i++)
7293
const char **line= dynamic_element(&lines, i, const char**);
7294
dynstr_append(ds, *line);
7295
dynstr_append(ds, "\n");
7298
delete_dynamic(&lines);