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 */
395
382
void eval_expr(VAR* v, const char *p, const char** p_end);
396
383
bool match_delimiter(int c, const char *delim, uint length);
397
384
void dump_result_to_reject_file(char *buf, int size);
398
void dump_result_to_log_file(const char *buf, int size);
385
void dump_result_to_log_file(char *buf, int size);
399
386
void dump_warning_messages(void);
400
387
void dump_progress(void);
402
void do_eval(string *query_eval, const char *query,
389
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
403
390
const char *query_end, bool pass_through_escape_chars);
404
void str_to_file(const char *fname, const char *str, int size);
405
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);
407
394
/* For replace_column */
408
395
static char *replace_column[MAX_COLUMNS];
428
415
free_replace_column();
431
void replace_append_mem(string *ds, const char *val,
433
void replace_append(string *ds, const char *val);
434
void replace_append_uint(string *ds, uint val);
435
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);
437
424
void handle_error(struct st_command*,
438
425
unsigned int err_errno, const char *err_error,
439
const char *err_sqlstate, string *ds);
426
const char *err_sqlstate, DYNAMIC_STRING *ds);
440
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*/
443
491
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
445
void do_eval(string *query_eval, const char *query,
493
#endif /*EMBEDDED_LIBRARY*/
495
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
446
496
const char *query_end, bool pass_through_escape_chars)
461
query_eval->append(p, 1);
511
dynstr_append_mem(query_eval, p, 1);
465
if (!(v= var_get(p, &p, 0, 0)))
466
die("Bad variable in eval");
467
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);
475
query_eval->append(p, 1);
525
dynstr_append_mem(query_eval, p, 1);
477
527
else if (next_c == '\\' || next_c == '$' || next_c == '"')
479
529
/* Set escaped only if next char is \, " or $ */
482
532
if (pass_through_escape_chars)
484
534
/* The escape char should be added to the output string. */
485
query_eval->append(p, 1);
535
dynstr_append_mem(query_eval, p, 1);
489
query_eval->append(p, 1);
539
dynstr_append_mem(query_eval, p, 1);
493
query_eval->append(p, 1);
543
dynstr_append_mem(query_eval, p, 1);
502
Concatenates any number of strings, escapes any OS quote in the result then
503
surround the whole affair in another set of quotes which is finally appended
504
to specified string. This function is especially useful when
505
building strings to be executed with the system() function.
507
@param str string which will have addtional strings appended.
508
@param append string to be appended.
509
@param ... Optional. Additional string(s) to be appended.
511
@note The final argument in the list must be NULL even if no additional
515
void append_os_quoted(string *str, const char *append, ...)
517
const char *quote_str= "\'";
518
const uint quote_len= 1;
522
str->append(quote_str, quote_len); /* Leading quote */
523
va_start(dirty_text, append);
524
while (append != NULL)
526
const char *cur_pos= append;
527
const char *next_pos= cur_pos;
529
/* Search for quote in each string and replace with escaped quote */
530
while((next_pos= strrchr(cur_pos, quote_str[0])) != NULL)
532
str->append(cur_pos, next_pos - cur_pos);
533
str->append("\\", 1);
534
str->append(quote_str, quote_len);
535
cur_pos= next_pos + 1;
537
str->append(cur_pos);
538
append= va_arg(dirty_text, char *);
541
str->append(quote_str, quote_len); /* Trailing quote */
546
552
Run query and dump the result to stdout in vertical format
548
554
NOTE! This function should be safe to call when an error
836
844
hash_free(&var_hash);
838
vector<struct st_command *>::iterator iter;
839
for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
846
for (i= 0 ; i < q_lines.elements ; i++)
841
struct st_command * q_line= *(iter.base());
842
if (q_line->query_buf != NULL)
844
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));
849
852
for (i= 0; i < 10; i++)
851
854
if (var_reg[i].alloced_len)
852
free(var_reg[i].str_val);
855
my_free(var_reg[i].str_val, MYF(MY_WME));
854
857
while (embedded_server_arg_count > 1)
855
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);
857
863
free_all_replace();
864
my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
859
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();
922
932
/* Show results from queries just before failure */
923
if (ds_res.length() && opt_tail_lines)
933
if (ds_res.length && opt_tail_lines)
925
935
int tail_lines= opt_tail_lines;
926
const char* show_from= ds_res.c_str() + ds_res.length() - 1;
927
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 )
930
940
if (*show_from == '\n')
933
943
fprintf(stderr, "\nThe result from queries just before the failure was:\n");
934
if (show_from > ds_res.c_str())
944
if (show_from > ds_res.str)
935
945
fprintf(stderr, "< snip >");
936
946
fprintf(stderr, "%s", show_from);
940
950
/* Dump the result that has been accumulated so far to .log file */
941
if (result_file_name && ds_res.length())
942
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);
944
954
/* Dump warning messages */
945
if (result_file_name && ds_warning_messages.length())
955
if (result_file_name && ds_warning_messages.length)
946
956
dump_warning_messages();
1021
1031
va_start(args, fmt);
1022
ds_warning_messages.append("drizzletest: ");
1032
dynstr_append(&ds_warning_messages, "drizzletest: ");
1023
1033
if (start_lineno != 0)
1025
ds_warning_messages.append("Warning detected ");
1035
dynstr_append(&ds_warning_messages, "Warning detected ");
1026
1036
if (cur_file && cur_file != file_stack)
1028
1038
len= snprintf(buff, sizeof(buff), "in included file %s ",
1029
cur_file->file_name);
1030
ds_warning_messages.append(buff, len);
1039
cur_file->file_name);
1040
dynstr_append_mem(&ds_warning_messages,
1032
1043
len= snprintf(buff, sizeof(buff), "at line %d: ",
1034
ds_warning_messages.append(buff, len);
1045
dynstr_append_mem(&ds_warning_messages,
1037
1049
len= vsnprintf(buff, sizeof(buff), fmt, args);
1038
ds_warning_messages.append(buff, len);
1050
dynstr_append_mem(&ds_warning_messages, buff, len);
1040
ds_warning_messages.append("\n");
1052
dynstr_append(&ds_warning_messages, "\n");
1145
1165
tool_path - the name of the tool to run
1146
result - pointer to dynamic string where to store the result
1166
ds_res - pointer to dynamic string where to store the result
1147
1167
... - variable number of arguments that will be properly
1148
quoted and appended after the tool's name
1168
quoted and appended after the tool's name
1152
static int run_tool(const char *tool_path, string * result, ...)
1172
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1155
1175
const char* arg;
1160
append_os_quoted(&ds_cmdline, tool_path, NULL);
1161
ds_cmdline.append(" ");
1163
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);
1165
1187
while ((arg= va_arg(args, char *)))
1167
1189
/* Options should be os quoted */
1168
1190
if (strncmp(arg, "--", 2) == 0)
1169
append_os_quoted(&ds_cmdline, arg, NULL);
1191
dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1171
ds_cmdline.append(arg);
1172
ds_cmdline.append(" ");
1193
dynstr_append(&ds_cmdline, arg);
1194
dynstr_append(&ds_cmdline, " ");
1177
ret= run_command(ds_cmdline.c_str(), result);
1199
ret= run_command(ds_cmdline.str, ds_res);
1200
dynstr_free(&ds_cmdline);
1222
1248
Fallback to dump both files to result file and inform
1223
1249
about installing "diff"
1229
"The two files differ but it was not possible to execute 'diff' in\n"
1230
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1231
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
1232
"To get a better report you should install 'diff' on your system, which you\n"
1233
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1236
ds_tmp.append(" --- ");
1237
ds_tmp.append(filename1);
1238
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");
1239
1265
cat_file(&ds_tmp, filename1);
1240
ds_tmp.append("<<<\n --- ");
1241
ds_tmp.append(filename1);
1242
ds_tmp.append(" >>>\n");
1266
dynstr_append(&ds_tmp, "<<<\n --- ");
1267
dynstr_append(&ds_tmp, filename1);
1268
dynstr_append(&ds_tmp, " >>>\n");
1243
1269
cat_file(&ds_tmp, filename2);
1244
ds_tmp.append("<<<<\n");
1270
dynstr_append(&ds_tmp, "<<<<\n");
1250
1276
/* Add the diff to output */
1251
ds->append(ds_tmp.c_str(), ds_tmp.length());
1277
dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1255
1281
/* Print diff directly to stdout */
1256
fprintf(stderr, "%s\n", ds_tmp.c_str());
1282
fprintf(stderr, "%s\n", ds_tmp.str);
1285
dynstr_free(&ds_tmp);
1262
1290
enum compare_files_result_enum {
1264
RESULT_CONTENT_MISMATCH= 1,
1265
RESULT_LENGTH_MISMATCH= 2
1292
RESULT_CONTENT_MISMATCH= 1,
1293
RESULT_LENGTH_MISMATCH= 2
1368
1396
See 'compare_files2'
1371
static int string_cmp(string* ds, const char *fname)
1399
static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
1375
1403
char temp_file_path[FN_REFLEN];
1377
1405
if ((fd= create_temp_file(temp_file_path, NULL,
1378
"tmp", O_CREAT | O_RDWR,
1406
"tmp", O_CREAT | O_SHARE | O_RDWR,
1379
1407
MYF(MY_WME))) < 0)
1380
1408
die("Failed to create temporary file for ds");
1382
1410
/* Write ds to temporary file and set file pos to beginning*/
1383
if (my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
1411
if (my_write(fd, (uchar *) ds->str, ds->length,
1384
1412
MYF(MY_FNABP | MY_WME)) ||
1385
1413
my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1534
1562
static void strip_parentheses(struct st_command *command)
1536
1564
if (strip_surrounding(command->first_argument, '(', ')'))
1537
die("%.*s - argument list started with '%c' must be ended with '%c'",
1538
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, '(', ')');
1542
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,
1543
1571
bool __attribute__((unused)) t)
1545
1573
register char* key;
1546
1574
key = ((VAR*)var)->name;
1547
1575
*len = ((VAR*)var)->name_len;
1548
return (unsigned char*)key;
1799
1827
/* Eval the query, thus replacing all environment variables */
1828
init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
1800
1829
do_eval(&ds_query, query, end, false);
1802
if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1803
die("Error running query '%s': %d %s", ds_query.c_str(),
1804
drizzle_errno(drizzle), drizzle_error(drizzle));
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));
1805
1834
if (!(res= drizzle_store_result(drizzle)))
1806
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);
1808
1838
if ((row= drizzle_fetch_row(res)) && row[0])
1811
1841
Concatenate all fields in the first row with tab in between
1812
1842
and assign that string to the $variable
1844
DYNAMIC_STRING result;
1816
1846
uint32_t *lengths;
1848
init_dynamic_string(&result, "", 512, 512);
1818
1849
lengths= drizzle_fetch_lengths(res);
1819
1850
for (i= 0; i < drizzle_num_fields(res); i++)
1823
1854
/* Add column to tab separated string */
1824
result.append(row[i], lengths[i]);
1855
dynstr_append_mem(&result, row[i], lengths[i]);
1826
result.append("\t", 1);
1857
dynstr_append_mem(&result, "\t", 1);
1828
end= result.c_str() + result.length()-1;
1829
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);
1832
1864
eval_expr(var, "", 0);
1884
1916
/* Convert row number to int */
1885
if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1886
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);
1888
1921
/* Remove any surrounding "'s from the query - if there is any */
1889
// (Don't get me started on this)
1890
char * unstripped_query= strdup(ds_query.c_str());
1891
if (strip_surrounding(unstripped_query, '"', '"'))
1892
die("Mismatched \"'s around query '%s'", ds_query.c_str());
1893
ds_query= unstripped_query;
1922
if (strip_surrounding(ds_query.str, '"', '"'))
1923
die("Mismatched \"'s around query '%s'", ds_query.str);
1895
1925
/* Run the query */
1896
if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1897
die("Error running query '%s': %d %s", ds_query.c_str(),
1898
drizzle_errno(drizzle), drizzle_error(drizzle));
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));
1899
1929
if (!(res= drizzle_store_result(drizzle)))
1900
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);
1903
1933
/* Find column number from the given column name */
2105
2144
Replace a substring
2109
ds_str The string to search and perform the replace in
2110
search_str The string to search for
2111
search_len Length of the string to search for
2112
replace_str The string to replace with
2113
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
2117
1 Could not find search_str in str
2156
1 Could not find search_str in str
2120
static int replace(string *ds_str,
2121
const char *search_str, uint32_t search_len,
2122
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)
2125
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);
2128
ds_tmp.append(ds_str->c_str(), start - ds_str->c_str());
2129
ds_tmp.append(replace_str, replace_len);
2130
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);
2300
2365
static void do_system(struct st_command *command)
2367
DYNAMIC_STRING ds_cmd;
2305
2370
if (strlen(command->first_argument) == 0)
2306
2371
die("Missing arguments to system, nothing to do!");
2373
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
2308
2375
/* Eval the system command, thus replacing all environment variables */
2309
2376
do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2311
if (system(ds_cmd.c_str()))
2378
if (my_system(&ds_cmd))
2313
2380
if (command->abort_on_error)
2314
2381
die("system command '%s' failed", command->first_argument);
2316
2383
/* If ! abort_on_error, log message and continue */
2317
ds_res.append("system command '");
2318
replace_append(&ds_res, command->first_argument);
2319
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");
2322
2389
command->last_argument= command->end;
2390
dynstr_free(&ds_cmd);
2599
2675
/* If no delimiter was provided, use EOF */
2600
if (ds_delimiter.length() == 0)
2601
ds_delimiter= "EOF";
2676
if (ds_delimiter.length == 0)
2677
dynstr_set(&ds_delimiter, "EOF");
2603
if (!append && access(ds_filename.c_str(), F_OK) == 0)
2679
if (!append && access(ds_filename.str, F_OK) == 0)
2605
2681
/* The file should not be overwritten */
2606
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);
2609
2686
read_until_delimiter(&ds_content, &ds_delimiter);
2610
str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2611
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);
2893
2977
/* If no delimiter was provided, use EOF */
2894
if (ds_delimiter.length() == 0)
2895
ds_delimiter= "EOF";
2978
if (ds_delimiter.length == 0)
2979
dynstr_set(&ds_delimiter, "EOF");
2981
init_dynamic_string(&ds_script, "", 1024, 1024);
2897
2982
read_until_delimiter(&ds_script, &ds_delimiter);
2899
2984
/* Create temporary file name */
2900
2985
if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
2901
"tmp", O_CREAT | O_RDWR,
2986
"tmp", O_CREAT | O_SHARE | O_RDWR,
2902
2987
MYF(MY_WME))) < 0)
2903
2988
die("Failed to create temporary file for perl command");
2904
2989
my_close(fd, MYF(0));
2906
str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
2991
str_to_file(temp_file_path, ds_script.str, ds_script.length);
2908
2993
/* Format the "perl <filename>" command */
2909
2994
snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
3077
3166
if (drizzle_query(drizzle, query= "show master status"))
3078
3167
die("failed in 'show master status': %d %s",
3079
drizzle_errno(drizzle), drizzle_error(drizzle));
3168
drizzle_errno(drizzle), drizzle_error(drizzle));
3081
3170
if (!(res = drizzle_store_result(drizzle)))
3082
3171
die("drizzle_store_result() retuned NULL for '%s'", query);
3083
3172
if (!(row = drizzle_fetch_row(res)))
3084
3173
die("empty result in show master status");
3085
my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
3174
strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
3086
3175
master_pos.pos = strtoul(row[1], (char**) 0, 10);
3087
3176
drizzle_free_result(res);
3560
3653
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
3561
const char *user, const char *pass, const char *db,
3654
const char *user, const char *pass, const char *db,
3564
3657
int failed_attempts= 0;
3565
static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3658
static ulong connection_retry_sleep= 100000; /* Microseconds */
3568
3661
while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3569
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3662
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3626
3719
static int connect_n_handle_errors(struct st_command *command,
3627
DRIZZLE *con, const char* host,
3628
const char* user, const char* pass,
3629
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)
3632
3728
/* Only log if an error is expected */
3633
3729
if (!command->abort_on_error &&
3637
3733
Log the connect to result log
3639
ds_res.append("connect(");
3640
replace_append(&ds_res, host);
3642
replace_append(&ds_res, user);
3644
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);
3647
replace_append(&ds_res, db);
3649
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);
3652
replace_append(&ds_res, sock);
3654
ds_res.append(delimiter);
3655
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);
3657
3753
if (!drizzle_connect(con, host, user, pass, db, port, 0,
3658
CLIENT_MULTI_STATEMENTS))
3754
CLIENT_MULTI_STATEMENTS))
3660
3756
var_set_errno(drizzle_errno(con));
3661
3757
handle_error(command, drizzle_errno(con), drizzle_error(con),
3662
drizzle_sqlstate(con), &ds_res);
3758
drizzle_sqlstate(con), ds);
3663
3759
return 0; /* Not connected */
3689
3785
<port> - server port
3690
3786
<sock> - server socket
3691
3787
<opts> - options to use for the connection
3692
* SSL - use SSL if available
3693
* COMPRESS - use compression if available
3788
* SSL - use SSL if available
3789
* COMPRESS - use compression if available
3697
3793
static void do_connect(struct st_command *command)
3699
3795
int con_port= opt_port;
3700
const char *con_options;
3701
3797
bool con_ssl= 0, con_compress= 0;
3702
3798
struct st_connection* con_slot;
3704
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;
3712
3808
const struct command_arg connect_args[] = {
3713
3809
{ "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3714
3810
{ "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3730
if (ds_port.length())
3732
con_port= atoi(ds_port.c_str());
3828
con_port= atoi(ds_port.str);
3733
3829
if (con_port == 0)
3734
die("Illegal argument for port: '%s'", ds_port.c_str());
3830
die("Illegal argument for port: '%s'", ds_port.str);
3738
if (!ds_sock.empty())
3741
3837
If the socket is specified just as a name without path
3742
3838
append tmpdir in front
3744
if (*ds_sock.c_str() != FN_LIBCHAR)
3840
if (*ds_sock.str != FN_LIBCHAR)
3746
3842
char buff[FN_REFLEN];
3747
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);
3753
con_options= ds_options.c_str();
3854
con_options= ds_options.str;
3754
3855
while (*con_options)
3757
3858
/* Step past any spaces in beginning of option*/
3758
3859
while (*con_options && my_isspace(charset_info, *con_options))
3760
3861
/* Find end of this option */
3761
3862
end= con_options;
3762
3863
while (*end && !my_isspace(charset_info, *end))
3786
3885
(int) (sizeof(connections)/sizeof(struct st_connection)));
3888
#ifdef EMBEDDED_LIBRARY
3889
con_slot->query_done= 1;
3789
3891
if (!drizzle_create(&con_slot->drizzle))
3790
3892
die("Failed on drizzle_create()");
3791
3893
if (opt_compress || con_compress)
3792
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NULL);
3894
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NullS);
3793
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,
3795
3904
/* Use default db name */
3796
if (ds_database.length() == 0)
3797
ds_database= opt_db;
3905
if (ds_database.length == 0)
3906
dynstr_set(&ds_database, opt_db);
3799
3908
/* Special database to allow one to connect without a database name */
3800
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, "");
3803
3912
if (connect_n_handle_errors(command, &con_slot->drizzle,
3804
ds_host.c_str(),ds_user.c_str(),
3805
ds_password.c_str(), ds_database.c_str(),
3806
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))
3808
if (!(con_slot->name= strdup(ds_connection_name.c_str())))
3917
if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3809
3918
die("Out of memory");
3810
3919
cur_con= con_slot;
3812
3921
if (con_slot == next_con)
3813
3922
next_con++; /* if we used the next_con slot, advance the pointer */
4063
4180
if (end_of_query(c))
4068
4185
else if ((c == '{' &&
4069
(!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
4070
(unsigned char*) buf, cmin((long)5, p - buf), 0) ||
4071
!my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
4072
(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))))
4074
4191
/* Only if and while commands can be terminated by { */
4079
4196
else if (c == '\'' || c == '"' || c == '`')
4152
4269
/* completed before we pass buf_end */
4153
4270
if ((charlen > 1) && (p + charlen) <= buf_end)
4160
for (i= 1; i < charlen; i++)
4162
if (feof(cur_file->file))
4164
c= my_getc(cur_file->file);
4167
if (! my_ismbchar(charset_info, mb_start, p))
4169
/* It was not a multiline char, push back the characters */
4170
/* We leave first 'c', i.e. pretend it was a normal char */
4171
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)
4180
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" \
4181
4298
"check your query or increase MAX_QUERY and recompile");
4454
4571
{"password", 'p', "Password to use when connecting to server.",
4455
4572
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4456
4573
{"port", 'P', "Port number to use for connection or 0 for default to, in "
4457
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
4458
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
4574
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
4575
#if MYSQL_PORT_DEFAULT == 0
4578
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
4459
4579
(char**) &opt_port,
4460
4580
(char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4461
4581
{"quiet", 's', "Suppress all normal output.", (char**) &silent,
4497
4617
static void print_version(void)
4499
4619
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4500
drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
4620
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
4503
4623
static void usage(void)
4505
4625
print_version();
4506
printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4626
printf("DRIZZLE AB, by Sasha, Matt, Monty & Jani\n");
4507
4627
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4508
4628
printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
4509
4629
printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4534
4654
embedded_server_arg_count=1;
4535
4655
embedded_server_args[0]= (char*) ""; /* Progname */
4537
if (!(file=my_fopen(buff, O_RDONLY, MYF(MY_WME))))
4657
if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4538
4658
die("Failed to open file '%s'", buff);
4540
4660
while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4541
(str=fgets(argument,sizeof(argument), file)))
4661
(str=fgets(argument,sizeof(argument), file)))
4543
*(strchr(str, '\0')-1)=0; /* Remove end newline */
4663
*(strend(str)-1)=0; /* Remove end newline */
4544
4664
if (!(embedded_server_args[embedded_server_arg_count]=
4545
(char*) my_strdup(str,MYF(MY_WME))))
4665
(char*) my_strdup(str,MYF(MY_WME))))
4547
4667
my_fclose(file,MYF(0));
4548
4668
die("Out of memory");
4571
4691
char buff[FN_REFLEN];
4572
4692
if (!test_if_hard_path(argument))
4574
strxmov(buff, opt_basedir, argument, NULL);
4694
strxmov(buff, opt_basedir, argument, NullS);
4575
4695
argument= buff;
4577
4697
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4578
4698
assert(cur_file == file_stack && cur_file->file == 0);
4579
4699
if (!(cur_file->file=
4580
my_fopen(buff, O_RDONLY, MYF(0))))
4700
my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
4581
4701
die("Could not open '%s' for reading: errno = %d", buff, errno);
4582
4702
cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
4583
4703
cur_file->lineno= 1;
4673
4793
append - append to file instead of overwriting old file
4676
void str_to_file2(const char *fname, const char *str, int size, bool append)
4796
void str_to_file2(const char *fname, char *str, int size, bool append)
4679
4799
char buff[FN_REFLEN];
4680
4800
int flags= O_WRONLY | O_CREAT;
4681
4801
if (!test_if_hard_path(fname))
4683
strxmov(buff, opt_basedir, fname, NULL);
4803
strxmov(buff, opt_basedir, fname, NullS);
4686
4806
fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4766
4886
if (!display_result_vertically)
4770
replace_append_mem(ds, val, (int)len);
4889
dynstr_append_mem(ds, "\t", 1);
4890
replace_dynstr_append_mem(ds, val, (int)len);
4774
ds->append(field->name);
4776
replace_append_mem(ds, val, (int)len);
4894
dynstr_append(ds, field->name);
4895
dynstr_append_mem(ds, "\t", 1);
4896
replace_dynstr_append_mem(ds, val, (int)len);
4897
dynstr_append_mem(ds, "\n", 1);
4809
4928
Append metadata for fields to output
4812
static void append_metadata(string *ds,
4931
static void append_metadata(DYNAMIC_STRING *ds,
4813
4932
const DRIZZLE_FIELD *field,
4814
4933
uint num_fields)
4816
4935
const DRIZZLE_FIELD *field_end;
4817
ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4818
"Column_alias\tType\tLength\tMax length\tIs_null\t"
4819
"Flags\tDecimals\tCharsetnr\n");
4936
dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4937
"Column_alias\tType\tLength\tMax length\tIs_null\t"
4938
"Flags\tDecimals\tCharsetnr\n");
4821
4940
for (field_end= field+num_fields ;
4822
4941
field < field_end ;
4825
ds->append(field->catalog,
4826
field->catalog_length);
4827
ds->append("\t", 1);
4828
ds->append(field->db, field->db_length);
4829
ds->append("\t", 1);
4830
ds->append(field->org_table,
4831
field->org_table_length);
4832
ds->append("\t", 1);
4833
ds->append(field->table,
4834
field->table_length);
4835
ds->append("\t", 1);
4836
ds->append(field->org_name,
4837
field->org_name_length);
4838
ds->append("\t", 1);
4839
ds->append(field->name, field->name_length);
4840
ds->append("\t", 1);
4841
replace_append_uint(ds, field->type);
4842
ds->append("\t", 1);
4843
replace_append_uint(ds, field->length);
4844
ds->append("\t", 1);
4845
replace_append_uint(ds, field->max_length);
4846
ds->append("\t", 1);
4847
ds->append((char*) ((field->flags & NOT_NULL_FLAG) ?
4849
ds->append("\t", 1);
4850
replace_append_uint(ds, field->flags);
4851
ds->append("\t", 1);
4852
replace_append_uint(ds, field->decimals);
4853
ds->append("\t", 1);
4854
replace_append_uint(ds, field->charsetnr);
4855
ds->append("\n", 1);
4944
dynstr_append_mem(ds, field->catalog,
4945
field->catalog_length);
4946
dynstr_append_mem(ds, "\t", 1);
4947
dynstr_append_mem(ds, field->db, field->db_length);
4948
dynstr_append_mem(ds, "\t", 1);
4949
dynstr_append_mem(ds, field->org_table,
4950
field->org_table_length);
4951
dynstr_append_mem(ds, "\t", 1);
4952
dynstr_append_mem(ds, field->table,
4953
field->table_length);
4954
dynstr_append_mem(ds, "\t", 1);
4955
dynstr_append_mem(ds, field->org_name,
4956
field->org_name_length);
4957
dynstr_append_mem(ds, "\t", 1);
4958
dynstr_append_mem(ds, field->name, field->name_length);
4959
dynstr_append_mem(ds, "\t", 1);
4960
replace_dynstr_append_uint(ds, field->type);
4961
dynstr_append_mem(ds, "\t", 1);
4962
replace_dynstr_append_uint(ds, field->length);
4963
dynstr_append_mem(ds, "\t", 1);
4964
replace_dynstr_append_uint(ds, field->max_length);
4965
dynstr_append_mem(ds, "\t", 1);
4966
dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
4968
dynstr_append_mem(ds, "\t", 1);
4969
replace_dynstr_append_uint(ds, field->flags);
4970
dynstr_append_mem(ds, "\t", 1);
4971
replace_dynstr_append_uint(ds, field->decimals);
4972
dynstr_append_mem(ds, "\t", 1);
4973
replace_dynstr_append_uint(ds, field->charsetnr);
4974
dynstr_append_mem(ds, "\n", 1);
4934
5054
Run query using DRIZZLE C API
4938
drizzle DRIZZLE handle
4939
command current command pointer
4940
flags flags indicating if we should SEND and/or REAP
4941
query query string to execute
4942
query_len length query string to execute
4943
ds output buffer where to store result form query
5058
drizzle DRIZZLE handle
5059
command current command pointer
5060
flags flags indicating if we should SEND and/or REAP
5061
query query string to execute
5062
query_len length query string to execute
5063
ds output buffer where to store result form query
4946
5066
static void run_query_normal(struct st_connection *cn,
4947
5067
struct st_command *command,
4948
5068
int flags, char *query, int query_len,
4949
string *ds, string *ds_warnings)
5069
DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4951
5071
DRIZZLE_RES *res= 0;
4952
5072
DRIZZLE *drizzle= &cn->drizzle;
4955
5075
if (flags & QUERY_SEND_FLAG)
4960
5080
if (do_send_query(cn, query, query_len, flags))
4962
5082
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4963
drizzle_sqlstate(drizzle), ds);
5083
drizzle_sqlstate(drizzle), ds);
5087
#ifdef EMBEDDED_LIBRARY
5089
Here we handle 'reap' command, so we need to check if the
5090
query's thread was finished and probably wait
5092
else if (flags & QUERY_REAP_FLAG)
5093
wait_query_thread_end(cn);
5094
#endif /*EMBEDDED_LIBRARY*/
4967
5095
if (!(flags & QUERY_REAP_FLAG))
5024
5152
if (!disable_warnings && !drizzle_more_results(drizzle))
5026
if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
5028
ds->append("Warnings:\n", 10);
5029
ds->append(ds_warnings->c_str(), ds_warnings->length());
5154
if (append_warnings(ds_warnings, drizzle) || ds_warnings->length)
5156
dynstr_append_mem(ds, "Warnings:\n", 10);
5157
dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
5033
5161
if (!disable_info)
5034
append_info(ds, affected_rows, drizzle_info(drizzle));
5162
append_info(ds, affected_rows, drizzle_info(drizzle));
5121
5250
if (command->expected_errors.count == 1)
5123
5252
/* Only log error if there is one possible error */
5124
ds->append("ERROR ", 6);
5125
replace_append(ds, err_sqlstate);
5126
ds->append(": ", 2);
5127
replace_append(ds, err_error);
5253
dynstr_append_mem(ds, "ERROR ", 6);
5254
replace_dynstr_append(ds, err_sqlstate);
5255
dynstr_append_mem(ds, ": ", 2);
5256
replace_dynstr_append(ds, err_error);
5257
dynstr_append_mem(ds,"\n",1);
5130
5259
/* Don't log error if we may not get an error */
5131
5260
else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5132
5261
(command->expected_errors.err[0].type == ERR_ERRNO &&
5133
5262
command->expected_errors.err[0].code.errnum != 0))
5134
ds->append("Got one of the listed errors\n");
5263
dynstr_append(ds,"Got one of the listed errors\n");
5251
5383
if (command->require_file[0])
5385
init_dynamic_string(&ds_result, "", 1024, 1024);
5253
5386
ds= &ds_result;
5260
5392
Log the query into the output buffer
5262
5394
if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5264
replace_append_mem(ds, query, query_len);
5265
ds->append(delimiter, delimiter_length);
5396
replace_dynstr_append_mem(ds, query, query_len);
5397
dynstr_append_mem(ds, delimiter, delimiter_length);
5398
dynstr_append_mem(ds, "\n", 1);
5269
5401
if (display_result_sorted)
5272
Collect the query output in a separate string
5273
that can be sorted before it's added to the
5274
global result string
5404
Collect the query output in a separate string
5405
that can be sorted before it's added to the
5406
global result string
5408
init_dynamic_string(&ds_sorted, "", 1024, 1024);
5276
5409
save_ds= ds; /* Remember original ds */
5277
5410
ds= &ds_sorted;
5404
5543
/* Milliseconds since start */
5405
5544
end= int64_t2str(timer, buf, 10);
5406
ds_progress.append(buf, (int)(end-buf));
5407
ds_progress.append("\t", 1);
5545
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5546
dynstr_append_mem(&ds_progress, "\t", 1);
5409
5548
/* Parser line number */
5410
5549
end= int10_to_str(line, buf, 10);
5411
ds_progress.append(buf, (int)(end-buf));
5412
ds_progress.append("\t", 1);
5550
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5551
dynstr_append_mem(&ds_progress, "\t", 1);
5415
ds_progress.append(cur_file->file_name);
5416
ds_progress.append(":", 1);
5554
dynstr_append(&ds_progress, cur_file->file_name);
5555
dynstr_append_mem(&ds_progress, ":", 1);
5418
5557
/* Line in file */
5419
5558
end= int10_to_str(cur_file->lineno, buf, 10);
5420
ds_progress.append(buf, (int)(end-buf));
5423
ds_progress.append("\n", 1);
5559
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5562
dynstr_append_mem(&ds_progress, "\n", 1);
5460
5605
cur_block->ok= true; /* Outer block should always be executed */
5461
5606
cur_block->cmd= cmd_none;
5608
my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
5463
5610
if (hash_init(&var_hash, charset_info,
5464
5611
1024, 0, 0, get_var_key, var_free, MYF(0)))
5465
5612
die("Variable hash initialization failed");
5467
var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_get_client_info());
5614
var_set_string("$MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
5469
5616
memset(&master_pos, 0, sizeof(master_pos));
5490
5636
if (!( drizzle_create(&cur_con->drizzle)))
5491
5637
die("Failed in drizzle_create()");
5492
5638
if (opt_compress)
5493
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
5639
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NullS);
5494
5640
drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
5641
drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_NAME,
5642
charset_info->csname);
5643
int opt_protocol= DRIZZLE_PROTOCOL_TCP;
5644
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
5645
if (opt_charsets_dir)
5646
drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_DIR,
5496
5649
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5497
5650
die("Out of memory");
5656
5807
/* Remove "send" if this is first iteration */
5657
if (command->query == command->query_buf)
5658
command->query= command->first_argument;
5808
if (command->query == command->query_buf)
5809
command->query= command->first_argument;
5661
run_query() can execute a query partially, depending on the flags.
5662
QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5812
run_query() can execute a query partially, depending on the flags.
5813
QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5663
5814
the query and read the result some time later when reap instruction
5664
is given on this connection.
5815
is given on this connection.
5666
run_query(cur_con, command, QUERY_SEND_FLAG);
5817
run_query(cur_con, command, QUERY_SEND_FLAG);
5668
5819
command->last_argument= command->end;
5670
5821
case Q_REQUIRE:
5671
do_get_file_name(command, save_file, sizeof(save_file));
5822
do_get_file_name(command, save_file, sizeof(save_file));
5674
5825
do_get_errcodes(command);
5676
5827
case Q_REPLACE:
5677
do_get_replace(command);
5828
do_get_replace(command);
5679
5830
case Q_REPLACE_REGEX:
5680
5831
do_get_replace_regex(command);
5682
5833
case Q_REPLACE_COLUMN:
5683
do_get_replace_column(command);
5834
do_get_replace_column(command);
5685
5836
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5686
5837
case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5687
5838
case Q_SYNC_SLAVE_WITH_MASTER:
5689
do_save_master_pos();
5690
if (*command->first_argument)
5691
select_connection(command);
5693
select_connection_name("slave");
5694
do_sync_with_master2(0);
5840
do_save_master_pos();
5841
if (*command->first_argument)
5842
select_connection(command);
5844
select_connection_name("slave");
5845
do_sync_with_master2(0);
5697
5848
case Q_COMMENT: /* Ignore row */
5698
5849
command->last_argument= command->end;
5701
(void) drizzle_ping(&cur_con->drizzle);
5852
(void) drizzle_ping(&cur_con->drizzle);
5707
5858
case Q_START_TIMER:
5708
/* Overwrite possible earlier start of timer */
5709
timer_start= timer_now();
5859
/* Overwrite possible earlier start of timer */
5860
timer_start= timer_now();
5711
5862
case Q_END_TIMER:
5712
/* End timer before ending drizzletest */
5863
/* End timer before ending drizzletest */
5715
5866
case Q_CHARACTER_SET:
5716
do_set_charset(command);
5867
do_set_charset(command);
5718
5869
case Q_DISABLE_RECONNECT:
5719
5870
set_reconnect(&cur_con->drizzle, 0);
5821
/* Recording - dump the output from test to result file */
5822
str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
5972
/* Recording - dump the output from test to result file */
5973
str_to_file(result_file_name, ds_res.str, ds_res.length);
5826
/* Check that the output from test is equal to result file
5827
- detect missing result file
5828
- detect zero size result file
5977
/* Check that the output from test is equal to result file
5978
- detect missing result file
5979
- detect zero size result file
5830
check_result(&ds_res);
5981
check_result(&ds_res);
5835
5986
/* No result_file_name specified to compare with, print to stdout */
5836
printf("%s", ds_res.c_str());
5987
printf("%s", ds_res.str);
5974
6125
typedef struct st_pointer_array { /* when using array-strings */
5975
6126
TYPELIB typelib; /* Pointer to strings */
5976
unsigned char *str; /* Strings is here */
5977
uint8_t *flag; /* Flag about each var. */
6127
uchar *str; /* Strings is here */
6128
int7 *flag; /* Flag about each var. */
5978
6129
uint array_allocs,max_count,length,max_length;
5979
6130
} POINTER_ARRAY;
5981
6132
struct st_replace;
5982
6133
struct st_replace *init_replace(char * *from, char * *to, uint count,
5983
char * word_end_chars);
6134
char * word_end_chars);
5984
6135
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5985
void replace_strings_append(struct st_replace *rep, string* ds,
6136
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5986
6137
const char *from, int len);
5987
6138
void free_pointer_array(POINTER_ARRAY *pa);
6080
6232
/* Loop through states */
6081
6233
while (!rep_pos->found)
6082
rep_pos= rep_pos->next[(unsigned char) *from++];
6234
rep_pos= rep_pos->next[(uchar) *from++];
6084
6236
/* Does this state contain a string to be replaced */
6085
6237
if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6087
6239
/* No match found */
6088
ds->append(start, from - start - 1);
6240
dynstr_append_mem(ds, start, from - start - 1);
6092
6244
/* Append part of original string before replace string */
6093
ds->append(start, (from - rep_str->to_offset) - start);
6245
dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6095
6247
/* Append replace string */
6096
ds->append(rep_str->replace_string,
6097
strlen(rep_str->replace_string));
6248
dynstr_append_mem(ds, rep_str->replace_string,
6249
strlen(rep_str->replace_string));
6099
6251
if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6546
6698
internal_set_bit(start_states,states+1);
6547
6699
if (!from[i][2])
6549
start_states->table_offset=i;
6550
start_states->found_offset=1;
6701
start_states->table_offset=i;
6702
start_states->found_offset=1;
6553
6705
else if (from[i][0] == '\\' && from[i][1] == '$')
6555
6707
internal_set_bit(start_states,states);
6556
6708
internal_set_bit(word_states,states);
6557
if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6709
if (!from[i][2] && start_states->table_offset == (uint) ~0)
6559
start_states->table_offset=i;
6560
start_states->found_offset=0;
6711
start_states->table_offset=i;
6712
start_states->found_offset=0;
6565
6717
internal_set_bit(word_states,states);
6566
6718
if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6567
internal_set_bit(start_states,states+1);
6719
internal_set_bit(start_states,states+1);
6569
internal_set_bit(start_states,states);
6721
internal_set_bit(start_states,states);
6571
6723
for (pos=from[i], len=0; *pos ; pos++)
6573
6725
if (*pos == '\\' && *(pos+1))
6578
follow_ptr->chr = SPACE_CHAR;
6581
follow_ptr->chr = START_OF_LINE;
6584
follow_ptr->chr = END_OF_LINE;
6587
follow_ptr->chr = '\r';
6590
follow_ptr->chr = '\t';
6593
follow_ptr->chr = '\v';
6596
follow_ptr->chr = (unsigned char) *pos;
6730
follow_ptr->chr = SPACE_CHAR;
6733
follow_ptr->chr = START_OF_LINE;
6736
follow_ptr->chr = END_OF_LINE;
6739
follow_ptr->chr = '\r';
6742
follow_ptr->chr = '\t';
6745
follow_ptr->chr = '\v';
6748
follow_ptr->chr = (uchar) *pos;
6601
follow_ptr->chr= (unsigned char) *pos;
6753
follow_ptr->chr= (uchar) *pos;
6602
6754
follow_ptr->table_offset=i;
6603
6755
follow_ptr->len= ++len;
6634
6786
/* Find all chars that follows current sets */
6635
6787
memset(used_chars, 0, sizeof(used_chars));
6636
for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6788
for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6638
6790
used_chars[follow[i].chr]=1;
6639
6791
if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6640
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6792
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6644
6796
/* Mark word_chars used if \b is in state */
6645
6797
if (used_chars[SPACE_CHAR])
6646
6798
for (pos= word_end_chars ; *pos ; pos++)
6647
used_chars[(int) (unsigned char) *pos] = 1;
6799
used_chars[(int) (uchar) *pos] = 1;
6649
6801
/* Handle other used characters */
6650
6802
for (chr= 0 ; chr < 256 ; chr++)
6652
6804
if (! used_chars[chr])
6653
set->next[chr]= chr ? default_state : -1;
6805
set->next[chr]= chr ? default_state : -1;
6656
new_set=make_new_set(&sets);
6657
set=sets.set+set_nr; /* if realloc */
6658
new_set->table_offset=set->table_offset;
6659
new_set->found_len=set->found_len;
6660
new_set->found_offset=set->found_offset+1;
6808
new_set=make_new_set(&sets);
6809
set=sets.set+set_nr; /* if realloc */
6810
new_set->table_offset=set->table_offset;
6811
new_set->found_len=set->found_len;
6812
new_set->found_offset=set->found_offset+1;
6663
for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6665
if (!follow[i].chr || follow[i].chr == chr ||
6666
(follow[i].chr == SPACE_CHAR &&
6667
(is_word_end[chr] ||
6668
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6669
(follow[i].chr == END_OF_LINE && ! chr))
6671
if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6672
follow[i].len > found_end)
6673
found_end=follow[i].len;
6674
if (chr && follow[i].chr)
6675
internal_set_bit(new_set,i+1); /* To next set */
6677
internal_set_bit(new_set,i);
6682
new_set->found_len=0; /* Set for testing if first */
6684
for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6686
if ((follow[i].chr == SPACE_CHAR ||
6687
follow[i].chr == END_OF_LINE) && ! chr)
6691
if (follow[bit_nr-1].len < found_end ||
6692
(new_set->found_len &&
6693
(chr == 0 || !follow[bit_nr].chr)))
6694
internal_clear_bit(new_set,i);
6697
if (chr == 0 || !follow[bit_nr].chr)
6699
new_set->table_offset=follow[bit_nr].table_offset;
6700
if (chr || (follow[i].chr == SPACE_CHAR ||
6701
follow[i].chr == END_OF_LINE))
6702
new_set->found_offset=found_end; /* New match */
6703
new_set->found_len=found_end;
6710
set->next[chr] = find_found(found_set,
6711
new_set->table_offset,
6712
new_set->found_offset);
6713
free_last_set(&sets);
6716
set->next[chr] = find_set(&sets,new_set);
6719
set->next[chr] = find_set(&sets,new_set);
6815
for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6817
if (!follow[i].chr || follow[i].chr == chr ||
6818
(follow[i].chr == SPACE_CHAR &&
6819
(is_word_end[chr] ||
6820
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6821
(follow[i].chr == END_OF_LINE && ! chr))
6823
if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6824
follow[i].len > found_end)
6825
found_end=follow[i].len;
6826
if (chr && follow[i].chr)
6827
internal_set_bit(new_set,i+1); /* To next set */
6829
internal_set_bit(new_set,i);
6834
new_set->found_len=0; /* Set for testing if first */
6836
for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
6838
if ((follow[i].chr == SPACE_CHAR ||
6839
follow[i].chr == END_OF_LINE) && ! chr)
6843
if (follow[bit_nr-1].len < found_end ||
6844
(new_set->found_len &&
6845
(chr == 0 || !follow[bit_nr].chr)))
6846
internal_clear_bit(new_set,i);
6849
if (chr == 0 || !follow[bit_nr].chr)
6851
new_set->table_offset=follow[bit_nr].table_offset;
6852
if (chr || (follow[i].chr == SPACE_CHAR ||
6853
follow[i].chr == END_OF_LINE))
6854
new_set->found_offset=found_end; /* New match */
6855
new_set->found_len=found_end;
6862
set->next[chr] = find_found(found_set,
6863
new_set->table_offset,
6864
new_set->found_offset);
6865
free_last_set(&sets);
6868
set->next[chr] = find_set(&sets,new_set);
6871
set->next[chr] = find_set(&sets,new_set);
6800
6952
memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
6801
6953
set->found_offset=0;
6802
6954
set->found_len=0;
6803
set->table_offset= UINT32_MAX;
6955
set->table_offset= (uint) ~0;
6804
6956
set->size_of_bits=sets->size_of_bits;
6807
6959
count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6808
if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
6960
if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6809
6961
sizeof(REP_SET)*count,
6812
6964
sets->set_buffer=set;
6813
6965
sets->set=set+sets->invisible;
6814
if (!(bit_buffer=(uint*) my_realloc((unsigned char*) sets->bit_buffer,
6815
(sizeof(uint)*sets->size_of_bits)*count,
6966
if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
6967
(sizeof(uint)*sets->size_of_bits)*count,
6818
6970
sets->bit_buffer=bit_buffer;
6819
6971
for (i=0 ; i < count ; i++)
6958
7110
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6960
7112
uint i,length,old_count;
6961
unsigned char *new_pos;
6962
7114
const char **new_array;
6965
7117
if (! pa->typelib.count)
6967
7119
if (!(pa->typelib.type_names=(const char **)
6968
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
6969
(sizeof(char *)+sizeof(*pa->flag))*
6970
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
7120
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7121
(sizeof(char *)+sizeof(*pa->flag))*
7122
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6972
if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
7124
if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
6975
free((char*) pa->typelib.type_names);
7127
my_free((char*) pa->typelib.type_names,MYF(0));
6978
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(unsigned char*)+
6980
pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
7130
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7132
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6982
7134
pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6983
7135
pa->array_allocs=1;
6985
7137
length=(uint) strlen(name)+1;
6986
7138
if (pa->length+length >= pa->max_length)
6988
if (!(new_pos= (unsigned char*) my_realloc((unsigned char*) pa->str,
6989
(uint) (pa->max_length+PS_MALLOC),
7140
if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
7141
(uint) (pa->max_length+PS_MALLOC),
6992
7144
if (new_pos != pa->str)
6994
7146
my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
6995
7147
for (i=0 ; i < pa->typelib.count ; i++)
6996
pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
7148
pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
6998
7150
pa->str=new_pos;
7000
7152
pa->max_length+=PS_MALLOC;
7005
7157
pa->array_allocs++;
7006
7158
len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7007
if (!(new_array=(const char **) my_realloc((unsigned char*) pa->typelib.type_names,
7009
(sizeof(unsigned char*)+sizeof(*pa->flag))*
7010
(sizeof(unsigned char*)+sizeof(*pa->flag)),
7159
if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
7161
(sizeof(uchar*)+sizeof(*pa->flag))*
7162
(sizeof(uchar*)+sizeof(*pa->flag)),
7013
7165
pa->typelib.type_names=new_array;
7014
7166
old_count=pa->max_count;
7015
pa->max_count=len/(sizeof(unsigned char*) + sizeof(*pa->flag));
7016
pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
7167
pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
7168
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7017
7169
memcpy(pa->flag, pa->typelib.type_names+old_count,
7018
7170
old_count*sizeof(*pa->flag));
7020
7172
pa->flag[pa->typelib.count]=0; /* Reset flag */
7021
7173
pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
7022
pa->typelib.type_names[pa->typelib.count]= NULL; /* Put end-mark */
7023
my_stpcpy((char*) pa->str+pa->length,name);
7174
pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
7175
VOID(strmov((char*) pa->str+pa->length,name));
7024
7176
pa->length+=length;
7026
7178
} /* insert_pointer_name */
7043
7195
/* Functions that uses replace and replace_regex */
7045
7197
/* Append the string to ds, with optional replace */
7046
void replace_append_mem(string *ds,
7047
const char *val, int len)
7198
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
7199
const char *val, int len)
7049
char *v= strdup(val);
7051
7201
if (glob_replace_regex)
7053
7203
/* Regex replace */
7054
if (!multi_reg_replace(glob_replace_regex, v))
7204
if (!multi_reg_replace(glob_replace_regex, (char*)val))
7056
v= glob_replace_regex->buf;
7206
val= glob_replace_regex->buf;
7061
7211
if (glob_replace)
7063
7213
/* Normal replace */
7064
replace_strings_append(glob_replace, ds, v, len);
7214
replace_strings_append(glob_replace, ds, val, len);
7217
dynstr_append_mem(ds, val, len);
7073
7221
/* Append zero-terminated string to ds, with optional replace */
7074
void replace_append(string *ds, const char *val)
7222
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7076
replace_append_mem(ds, val, strlen(val));
7224
replace_dynstr_append_mem(ds, val, strlen(val));
7079
7227
/* Append uint to ds, with optional replace */
7080
void replace_append_uint(string *ds, uint val)
7228
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7082
7230
char buff[22]; /* This should be enough for any int */
7083
7231
char *end= int64_t10_to_str(val, buff, 10);
7084
replace_append_mem(ds, buff, end - buff);
7232
replace_dynstr_append_mem(ds, buff, end - buff);
7103
void append_sorted(string* ds, string *ds_input)
7105
priority_queue<string, vector<string>, greater<string> > lines;
7107
if (ds_input->empty())
7249
static int comp_lines(const char **a, const char **b)
7251
return (strcmp(*a,*b));
7254
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
7257
char *start= ds_input->str;
7258
DYNAMIC_ARRAY lines;
7108
7262
return; /* No input */
7110
unsigned long eol_pos= 0;
7112
eol_pos= ds_input->find_first_of('\n', 0);
7113
if (eol_pos == string::npos)
7114
return; // We should have at least one header here
7116
ds->append(ds_input->substr(0, eol_pos+1));
7118
unsigned long start_pos= eol_pos+1;
7264
my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
7266
/* First line is result header, skip past it */
7267
while (*start && *start != '\n')
7269
start++; /* Skip past \n */
7270
dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
7120
7272
/* Insert line(s) in array */
7275
char* line_end= (char*)start;
7123
eol_pos= ds_input->find_first_of('\n', start_pos);
7124
7277
/* Find end of line */
7125
lines.push(ds_input->substr(start_pos, eol_pos-start_pos+1));
7126
start_pos= eol_pos+1;
7128
} while ( eol_pos != string::npos);
7278
while (*line_end && *line_end != '\n')
7282
/* Insert pointer to the line in array */
7283
if (insert_dynamic(&lines, (uchar*) &start))
7284
die("Out of memory inserting lines to sort");
7290
qsort(lines.buffer, lines.elements,
7291
sizeof(char**), (qsort_cmp)comp_lines);
7130
7293
/* Create new result */
7131
while (!lines.empty()) {
7132
ds->append(lines.top());
7294
for (i= 0; i < lines.elements ; i++)
7296
const char **line= dynamic_element(&lines, i, const char**);
7297
dynstr_append(ds, *line);
7298
dynstr_append(ds, "\n");
7301
delete_dynamic(&lines);