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 */
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
382
393
void eval_expr(VAR* v, const char *p, const char** p_end);
383
394
bool match_delimiter(int c, const char *delim, uint length);
384
395
void dump_result_to_reject_file(char *buf, int size);
385
void dump_result_to_log_file(char *buf, int size);
396
void dump_result_to_log_file(const char *buf, int size);
386
397
void dump_warning_messages(void);
387
398
void dump_progress(void);
389
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
400
void do_eval(string *query_eval, const char *query,
390
401
const char *query_end, bool pass_through_escape_chars);
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);
402
void str_to_file(const char *fname, const char *str, int size);
403
void str_to_file2(const char *fname, const char *str, int size, bool append);
394
405
/* For replace_column */
395
406
static char *replace_column[MAX_COLUMNS];
415
426
free_replace_column();
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);
429
void replace_append_mem(string *ds, const char *val,
431
void replace_append(string *ds, const char *val);
432
void replace_append_uint(string *ds, uint val);
433
void append_sorted(string* ds, string* ds_input);
424
435
void handle_error(struct st_command*,
425
436
unsigned int err_errno, const char *err_error,
426
const char *err_sqlstate, DYNAMIC_STRING *ds);
437
const char *err_sqlstate, string *ds);
427
438
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*/
491
441
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
493
#endif /*EMBEDDED_LIBRARY*/
495
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
443
void do_eval(string *query_eval, const char *query,
496
444
const char *query_end, bool pass_through_escape_chars)
511
dynstr_append_mem(query_eval, p, 1);
459
query_eval->append(p, 1);
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);
463
if (!(v= var_get(p, &p, 0, 0)))
464
die("Bad variable in eval");
465
query_eval->append(v->str_val, v->str_val_len);
525
dynstr_append_mem(query_eval, p, 1);
473
query_eval->append(p, 1);
527
475
else if (next_c == '\\' || next_c == '$' || next_c == '"')
529
477
/* Set escaped only if next char is \, " or $ */
532
480
if (pass_through_escape_chars)
534
482
/* The escape char should be added to the output string. */
535
dynstr_append_mem(query_eval, p, 1);
483
query_eval->append(p, 1);
539
dynstr_append_mem(query_eval, p, 1);
487
query_eval->append(p, 1);
543
dynstr_append_mem(query_eval, p, 1);
491
query_eval->append(p, 1);
500
Concatenates any number of strings, escapes any OS quote in the result then
501
surround the whole affair in another set of quotes which is finally appended
502
to specified string. This function is especially useful when
503
building strings to be executed with the system() function.
505
@param str string which will have addtional strings appended.
506
@param append string to be appended.
507
@param ... Optional. Additional string(s) to be appended.
509
@note The final argument in the list must be NullS even if no additional
513
void append_os_quoted(string *str, const char *append, ...)
515
const char *quote_str= "\'";
516
const uint quote_len= 1;
520
str->append(quote_str, quote_len); /* Leading quote */
521
va_start(dirty_text, append);
522
while (append != NullS)
524
const char *cur_pos= append;
525
const char *next_pos= cur_pos;
527
/* Search for quote in each string and replace with escaped quote */
528
while((next_pos= strrchr(cur_pos, quote_str[0])) != NULL)
530
str->append(cur_pos, next_pos - cur_pos);
531
str->append("\\", 1);
532
str->append(quote_str, quote_len);
533
cur_pos= next_pos + 1;
535
str->append(cur_pos, next_pos - cur_pos);
536
append= va_arg(dirty_text, char *);
539
str->append(quote_str, quote_len); /* Trailing quote */
552
544
Run query and dump the result to stdout in vertical format
554
546
NOTE! This function should be safe to call when an error
932
924
/* Show results from queries just before failure */
933
if (ds_res.length && opt_tail_lines)
925
if (ds_res.length() && opt_tail_lines)
935
927
int tail_lines= opt_tail_lines;
936
char* show_from= ds_res.str + ds_res.length - 1;
937
while(show_from > ds_res.str && tail_lines > 0 )
928
const char* show_from= ds_res.c_str() + ds_res.length() - 1;
929
while(show_from > ds_res.c_str() && tail_lines > 0 )
940
932
if (*show_from == '\n')
943
935
fprintf(stderr, "\nThe result from queries just before the failure was:\n");
944
if (show_from > ds_res.str)
936
if (show_from > ds_res.c_str())
945
937
fprintf(stderr, "< snip >");
946
938
fprintf(stderr, "%s", show_from);
950
942
/* Dump the result that has been accumulated so far to .log file */
951
if (result_file_name && ds_res.length)
952
dump_result_to_log_file(ds_res.str, ds_res.length);
943
if (result_file_name && ds_res.length())
944
dump_result_to_log_file(ds_res.c_str(), ds_res.length());
954
946
/* Dump warning messages */
955
if (result_file_name && ds_warning_messages.length)
947
if (result_file_name && ds_warning_messages.length())
956
948
dump_warning_messages();
1031
1023
va_start(args, fmt);
1032
dynstr_append(&ds_warning_messages, "drizzletest: ");
1024
ds_warning_messages.append("drizzletest: ");
1033
1025
if (start_lineno != 0)
1035
dynstr_append(&ds_warning_messages, "Warning detected ");
1027
ds_warning_messages.append("Warning detected ");
1036
1028
if (cur_file && cur_file != file_stack)
1038
1030
len= snprintf(buff, sizeof(buff), "in included file %s ",
1039
cur_file->file_name);
1040
dynstr_append_mem(&ds_warning_messages,
1031
cur_file->file_name);
1032
ds_warning_messages.append(buff, len);
1043
1034
len= snprintf(buff, sizeof(buff), "at line %d: ",
1045
dynstr_append_mem(&ds_warning_messages,
1036
ds_warning_messages.append(buff, len);
1049
1039
len= vsnprintf(buff, sizeof(buff), fmt, args);
1050
dynstr_append_mem(&ds_warning_messages, buff, len);
1040
ds_warning_messages.append(buff, len);
1052
dynstr_append(&ds_warning_messages, "\n");
1042
ds_warning_messages.append("\n");
1165
1147
tool_path - the name of the tool to run
1166
ds_res - pointer to dynamic string where to store the result
1148
result - pointer to dynamic string where to store the result
1167
1149
... - variable number of arguments that will be properly
1168
quoted and appended after the tool's name
1150
quoted and appended after the tool's name
1172
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1154
static int run_tool(const char *tool_path, string * result, ...)
1175
1157
const char* arg;
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);
1162
append_os_quoted(&ds_cmdline, tool_path);
1163
ds_cmdline.append(" ");
1165
va_start(args, result);
1187
1167
while ((arg= va_arg(args, char *)))
1189
1169
/* Options should be os quoted */
1190
1170
if (strncmp(arg, "--", 2) == 0)
1191
dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1171
append_os_quoted(&ds_cmdline, arg, NullS);
1193
dynstr_append(&ds_cmdline, arg);
1194
dynstr_append(&ds_cmdline, " ");
1173
ds_cmdline.append(arg);
1174
ds_cmdline.append(" ");
1199
ret= run_command(ds_cmdline.str, ds_res);
1200
dynstr_free(&ds_cmdline);
1179
ret= run_command(ds_cmdline.c_str(), result);
1248
1224
Fallback to dump both files to result file and inform
1249
1225
about installing "diff"
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");
1231
"The two files differ but it was not possible to execute 'diff' in\n"
1232
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1233
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
1234
"To get a better report you should install 'diff' on your system, which you\n"
1235
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1238
ds_tmp.append(" --- ");
1239
ds_tmp.append(filename1);
1240
ds_tmp.append(" >>>\n");
1265
1241
cat_file(&ds_tmp, filename1);
1266
dynstr_append(&ds_tmp, "<<<\n --- ");
1267
dynstr_append(&ds_tmp, filename1);
1268
dynstr_append(&ds_tmp, " >>>\n");
1242
ds_tmp.append("<<<\n --- ");
1243
ds_tmp.append(filename1);
1244
ds_tmp.append(" >>>\n");
1269
1245
cat_file(&ds_tmp, filename2);
1270
dynstr_append(&ds_tmp, "<<<<\n");
1246
ds_tmp.append("<<<<\n");
1276
1252
/* Add the diff to output */
1277
dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1253
ds->append(ds_tmp.c_str(), ds_tmp.length());
1281
1257
/* Print diff directly to stdout */
1282
fprintf(stderr, "%s\n", ds_tmp.str);
1258
fprintf(stderr, "%s\n", ds_tmp.c_str());
1285
dynstr_free(&ds_tmp);
1290
1264
enum compare_files_result_enum {
1292
RESULT_CONTENT_MISMATCH= 1,
1293
RESULT_LENGTH_MISMATCH= 2
1266
RESULT_CONTENT_MISMATCH= 1,
1267
RESULT_LENGTH_MISMATCH= 2
1827
1801
/* Eval the query, thus replacing all environment variables */
1828
init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
1829
1802
do_eval(&ds_query, query, end, false);
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
if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1805
die("Error running query '%s': %d %s", ds_query.c_str(),
1806
drizzle_errno(drizzle), drizzle_error(drizzle));
1834
1807
if (!(res= drizzle_store_result(drizzle)))
1835
die("Query '%s' didn't return a result set", ds_query.str);
1836
dynstr_free(&ds_query);
1808
die("Query '%s' didn't return a result set", ds_query.c_str());
1838
1810
if ((row= drizzle_fetch_row(res)) && row[0])
1841
1813
Concatenate all fields in the first row with tab in between
1842
1814
and assign that string to the $variable
1844
DYNAMIC_STRING result;
1846
1818
uint32_t *lengths;
1848
init_dynamic_string(&result, "", 512, 512);
1849
1820
lengths= drizzle_fetch_lengths(res);
1850
1821
for (i= 0; i < drizzle_num_fields(res); i++)
1854
1825
/* Add column to tab separated string */
1855
dynstr_append_mem(&result, row[i], lengths[i]);
1826
result.append(row[i], lengths[i]);
1857
dynstr_append_mem(&result, "\t", 1);
1828
result.append("\t", 1);
1859
end= result.str + result.length-1;
1860
eval_expr(var, result.str, (const char**) &end);
1861
dynstr_free(&result);
1830
end= result.c_str() + result.length()-1;
1831
eval_expr(var, result.c_str(), (const char**) &end);
1864
1834
eval_expr(var, "", 0);
1916
1886
/* Convert row number to int */
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
if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1888
die("Invalid row number: '%s'", ds_row.c_str());
1921
1890
/* Remove any surrounding "'s from the query - if there is any */
1922
if (strip_surrounding(ds_query.str, '"', '"'))
1923
die("Mismatched \"'s around query '%s'", ds_query.str);
1891
// (Don't get me started on this)
1892
char * unstripped_query= strdup(ds_query.c_str());
1893
if (strip_surrounding(unstripped_query, '"', '"'))
1894
die("Mismatched \"'s around query '%s'", ds_query.c_str());
1895
ds_query= unstripped_query;
1925
1897
/* Run the query */
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
if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1899
die("Error running query '%s': %d %s", ds_query.c_str(),
1900
drizzle_errno(drizzle), drizzle_error(drizzle));
1929
1901
if (!(res= drizzle_store_result(drizzle)))
1930
die("Query '%s' didn't return a result set", ds_query.str);
1902
die("Query '%s' didn't return a result set", ds_query.c_str());
1933
1905
/* Find column number from the given column name */
2144
2107
Replace a substring
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
2111
ds_str The string to search and perform the replace in
2112
search_str The string to search for
2113
search_len Length of the string to search for
2114
replace_str The string to replace with
2115
replace_len Length of the string to replace with
2156
1 Could not find search_str in str
2119
1 Could not find search_str in str
2159
static int replace(DYNAMIC_STRING *ds_str,
2122
static int replace(string *ds_str,
2160
2123
const char *search_str, uint32_t search_len,
2161
2124
const char *replace_str, uint32_t replace_len)
2163
DYNAMIC_STRING ds_tmp;
2164
const char *start= strstr(ds_str->str, search_str);
2127
const char *start= strstr(ds_str->c_str(), search_str);
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);
2130
ds_tmp.append(ds_str->c_str(), start - ds_str->c_str());
2131
ds_tmp.append(replace_str, replace_len);
2132
ds_tmp.append(start + search_len);
2365
2302
static void do_system(struct st_command *command)
2367
DYNAMIC_STRING ds_cmd;
2370
2307
if (strlen(command->first_argument) == 0)
2371
2308
die("Missing arguments to system, nothing to do!");
2373
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
2375
2310
/* Eval the system command, thus replacing all environment variables */
2376
2311
do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2378
if (my_system(&ds_cmd))
2313
if (system(ds_cmd.c_str()))
2380
2315
if (command->abort_on_error)
2381
2316
die("system command '%s' failed", command->first_argument);
2383
2318
/* If ! abort_on_error, log message and continue */
2384
dynstr_append(&ds_res, "system command '");
2385
replace_dynstr_append(&ds_res, command->first_argument);
2386
dynstr_append(&ds_res, "' failed\n");
2319
ds_res.append("system command '");
2320
replace_append(&ds_res, command->first_argument);
2321
ds_res.append("' failed\n");
2389
2324
command->last_argument= command->end;
2390
dynstr_free(&ds_cmd);
2489
2420
/* Parse what mode to set */
2490
if (ds_mode.length != 4 ||
2491
str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
2421
if (ds_mode.length() != 4 ||
2422
str2int(ds_mode.c_str(), 8, 0, INT_MAX, &mode) == NullS)
2492
2423
die("You must write a 4 digit octal number for mode");
2494
handle_command_error(command, chmod(ds_file.str, mode));
2495
dynstr_free(&ds_mode);
2496
dynstr_free(&ds_file);
2425
handle_command_error(command, chmod(ds_file.c_str(), mode));
2675
2601
/* If no delimiter was provided, use EOF */
2676
if (ds_delimiter.length == 0)
2677
dynstr_set(&ds_delimiter, "EOF");
2602
if (ds_delimiter.length() == 0)
2603
ds_delimiter= "EOF";
2679
if (!append && access(ds_filename.str, F_OK) == 0)
2605
if (!append && access(ds_filename.c_str(), F_OK) == 0)
2681
2607
/* The file should not be overwritten */
2682
die("File already exist: '%s'", ds_filename.str);
2608
die("File already exist: '%s'", ds_filename.c_str());
2685
init_dynamic_string(&ds_content, "", 1024, 1024);
2686
2611
read_until_delimiter(&ds_content, &ds_delimiter);
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);
2612
str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2613
ds_content.length(), append);
2818
2740
sizeof(diff_file_args)/sizeof(struct command_arg),
2821
if ((error= compare_files(ds_filename.str, ds_filename2.str)))
2743
if ((error= compare_files(ds_filename.c_str(), ds_filename2.c_str())))
2823
2745
/* Compare of the two files failed, append them to output
2824
2746
so the failure can be analyzed
2826
show_diff(&ds_res, ds_filename.str, ds_filename2.str);
2748
show_diff(&ds_res, ds_filename.c_str(), ds_filename2.c_str());
2829
dynstr_free(&ds_filename);
2830
dynstr_free(&ds_filename2);
2831
2751
handle_command_error(command, error);
2902
2822
DRIZZLE *drizzle= &cur_con->drizzle;
2903
2823
/* static keyword to make the NetWare compiler happy. */
2904
static DYNAMIC_STRING ds_user, ds_passwd, ds_db;
2824
string ds_user, ds_passwd, ds_db;
2905
2825
const struct command_arg change_user_args[] = {
2906
2826
{ "user", ARG_STRING, false, &ds_user, "User to connect as" },
2907
2827
{ "password", ARG_STRING, false, &ds_passwd, "Password used when connecting" },
2915
2835
sizeof(change_user_args)/sizeof(struct command_arg),
2918
if (!ds_user.length)
2919
dynstr_set(&ds_user, drizzle->user);
2921
if (!ds_passwd.length)
2922
dynstr_set(&ds_passwd, drizzle->passwd);
2925
dynstr_set(&ds_db, drizzle->db);
2927
if (drizzle_change_user(drizzle, ds_user.str, ds_passwd.str, ds_db.str))
2838
if (!ds_user.length())
2839
ds_user= drizzle->user;
2841
if (!ds_passwd.length())
2842
ds_passwd= drizzle->passwd;
2844
if (!ds_db.length())
2847
if (drizzle_change_user(drizzle, ds_user.c_str(),
2848
ds_passwd.c_str(), ds_db.c_str()))
2928
2849
die("change user failed: %s", drizzle_error(drizzle));
2930
dynstr_free(&ds_user);
2931
dynstr_free(&ds_passwd);
2932
dynstr_free(&ds_db);
3653
3563
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
3654
const char *user, const char *pass, const char *db,
3564
const char *user, const char *pass, const char *db,
3657
3567
int failed_attempts= 0;
3658
3568
static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3661
3571
while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3662
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3572
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3719
3629
static int connect_n_handle_errors(struct st_command *command,
3720
DRIZZLE *con, const char* host,
3721
const char* user, const char* pass,
3722
const char* db, int port, const char* sock)
3630
DRIZZLE *con, const char* host,
3631
const char* user, const char* pass,
3632
const char* db, int port, const char* sock)
3728
3635
/* Only log if an error is expected */
3729
3636
if (!command->abort_on_error &&
3733
3640
Log the connect to result log
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);
3642
ds_res.append("connect(");
3643
replace_append(&ds_res, host);
3645
replace_append(&ds_res, user);
3647
replace_append(&ds_res, pass);
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);
3650
replace_append(&ds_res, db);
3652
replace_append_uint(&ds_res, port);
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);
3655
replace_append(&ds_res, sock);
3657
ds_res.append(delimiter);
3658
ds_res.append("\n");
3753
3660
if (!drizzle_connect(con, host, user, pass, db, port, 0,
3754
CLIENT_MULTI_STATEMENTS))
3661
CLIENT_MULTI_STATEMENTS))
3756
3663
var_set_errno(drizzle_errno(con));
3757
3664
handle_error(command, drizzle_errno(con), drizzle_error(con),
3758
drizzle_sqlstate(con), ds);
3665
drizzle_sqlstate(con), &ds_res);
3759
3666
return 0; /* Not connected */
3785
3692
<port> - server port
3786
3693
<sock> - server socket
3787
3694
<opts> - options to use for the connection
3788
* SSL - use SSL if available
3789
* COMPRESS - use compression if available
3695
* SSL - use SSL if available
3696
* COMPRESS - use compression if available
3793
3700
static void do_connect(struct st_command *command)
3795
3702
int con_port= opt_port;
3703
const char *con_options;
3797
3704
bool con_ssl= 0, con_compress= 0;
3798
3705
struct st_connection* con_slot;
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;
3707
string ds_connection_name;
3808
3715
const struct command_arg connect_args[] = {
3809
3716
{ "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3810
3717
{ "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3733
if (ds_port.length())
3828
con_port= atoi(ds_port.str);
3735
con_port= atoi(ds_port.c_str());
3829
3736
if (con_port == 0)
3830
die("Illegal argument for port: '%s'", ds_port.str);
3737
die("Illegal argument for port: '%s'", ds_port.c_str());
3741
if (!ds_sock.empty())
3837
3744
If the socket is specified just as a name without path
3838
3745
append tmpdir in front
3840
if (*ds_sock.str != FN_LIBCHAR)
3747
if (*ds_sock.c_str() != FN_LIBCHAR)
3842
3749
char buff[FN_REFLEN];
3843
fn_format(buff, ds_sock.str, TMPDIR, "", 0);
3844
dynstr_set(&ds_sock, buff);
3750
fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3849
/* No socket specified, use default */
3850
dynstr_set(&ds_sock, unix_sock);
3854
con_options= ds_options.str;
3756
con_options= ds_options.c_str();
3855
3757
while (*con_options)
3858
3760
/* Step past any spaces in beginning of option*/
3859
3761
while (*con_options && my_isspace(charset_info, *con_options))
3861
3763
/* Find end of this option */
3862
3764
end= con_options;
3863
3765
while (*end && !my_isspace(charset_info, *end))
3885
3789
(int) (sizeof(connections)/sizeof(struct st_connection)));
3888
#ifdef EMBEDDED_LIBRARY
3889
con_slot->query_done= 1;
3891
3792
if (!drizzle_create(&con_slot->drizzle))
3892
3793
die("Failed on drizzle_create()");
3893
3794
if (opt_compress || con_compress)
3894
3795
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NullS);
3895
3796
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
3896
3797
drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_NAME,
3897
charset_info->csname);
3798
charset_info->csname);
3898
3799
int opt_protocol= DRIZZLE_PROTOCOL_TCP;
3899
3800
drizzle_options(&con_slot->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
3900
3801
if (opt_charsets_dir)
3901
3802
drizzle_options(&con_slot->drizzle, DRIZZLE_SET_CHARSET_DIR,
3904
3805
/* Use default db name */
3905
if (ds_database.length == 0)
3906
dynstr_set(&ds_database, opt_db);
3806
if (ds_database.length() == 0)
3807
ds_database= opt_db;
3908
3809
/* Special database to allow one to connect without a database name */
3909
if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
3910
dynstr_set(&ds_database, "");
3810
if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
3912
3813
if (connect_n_handle_errors(command, &con_slot->drizzle,
3913
ds_host.str,ds_user.str,
3914
ds_password.str, ds_database.str,
3915
con_port, ds_sock.str))
3814
ds_host.c_str(),ds_user.c_str(),
3815
ds_password.c_str(), ds_database.c_str(),
3816
con_port, ds_sock.c_str()))
3917
if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3818
if (!(con_slot->name= strdup(ds_connection_name.c_str())))
3918
3819
die("Out of memory");
3919
3820
cur_con= con_slot;
3921
3822
if (con_slot == next_con)
3922
3823
next_con++; /* if we used the next_con slot, advance the pointer */
4269
4162
/* completed before we pass buf_end */
4270
4163
if ((charlen > 1) && (p + charlen) <= buf_end)
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)
4170
for (i= 1; i < charlen; i++)
4172
if (feof(cur_file->file))
4174
c= my_getc(cur_file->file);
4177
if (! my_ismbchar(charset_info, mb_start, p))
4179
/* It was not a multiline char, push back the characters */
4180
/* We leave first 'c', i.e. pretend it was a normal char */
4181
while (p > mb_start)
4297
die("The input buffer is too small for this query.x\n" \
4190
die("The input buffer is too small for this query.x\n" \
4298
4191
"check your query or increase MAX_QUERY and recompile");
4614
4507
static void print_version(void)
4616
4509
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4617
drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
4510
drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
4620
4513
static void usage(void)
4622
4515
print_version();
4623
printf("DRIZZLE AB, by Sasha, Matt, Monty & Jani\n");
4516
printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4624
4517
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4625
4518
printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
4626
4519
printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4824
4717
size - size of content witten to file
4827
void str_to_file(const char *fname, char *str, int size)
4720
void str_to_file(const char *fname, const char *str, int size)
4829
4722
str_to_file2(fname, str, size, false);
4833
void dump_result_to_log_file(char *buf, int size)
4726
void dump_result_to_log_file(const char *buf, int size)
4835
4728
char log_file[FN_REFLEN];
4836
4729
str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
4883
4776
if (!display_result_vertically)
4886
dynstr_append_mem(ds, "\t", 1);
4887
replace_dynstr_append_mem(ds, val, (int)len);
4780
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);
4784
ds->append(field->name);
4786
replace_append_mem(ds, val, (int)len);
4925
4819
Append metadata for fields to output
4928
static void append_metadata(DYNAMIC_STRING *ds,
4822
static void append_metadata(string *ds,
4929
4823
const DRIZZLE_FIELD *field,
4930
4824
uint num_fields)
4932
4826
const DRIZZLE_FIELD *field_end;
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");
4827
ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4828
"Column_alias\tType\tLength\tMax length\tIs_null\t"
4829
"Flags\tDecimals\tCharsetnr\n");
4937
4831
for (field_end= field+num_fields ;
4938
4832
field < field_end ;
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);
4835
ds->append(field->catalog,
4836
field->catalog_length);
4837
ds->append("\t", 1);
4838
ds->append(field->db, field->db_length);
4839
ds->append("\t", 1);
4840
ds->append(field->org_table,
4841
field->org_table_length);
4842
ds->append("\t", 1);
4843
ds->append(field->table,
4844
field->table_length);
4845
ds->append("\t", 1);
4846
ds->append(field->org_name,
4847
field->org_name_length);
4848
ds->append("\t", 1);
4849
ds->append(field->name, field->name_length);
4850
ds->append("\t", 1);
4851
replace_append_uint(ds, field->type);
4852
ds->append("\t", 1);
4853
replace_append_uint(ds, field->length);
4854
ds->append("\t", 1);
4855
replace_append_uint(ds, field->max_length);
4856
ds->append("\t", 1);
4857
ds->append((char*) (IS_NOT_NULL(field->flags) ?
4859
ds->append("\t", 1);
4860
replace_append_uint(ds, field->flags);
4861
ds->append("\t", 1);
4862
replace_append_uint(ds, field->decimals);
4863
ds->append("\t", 1);
4864
replace_append_uint(ds, field->charsetnr);
4865
ds->append("\n", 1);
5051
4944
Run query using DRIZZLE C API
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
4948
drizzle DRIZZLE handle
4949
command current command pointer
4950
flags flags indicating if we should SEND and/or REAP
4951
query query string to execute
4952
query_len length query string to execute
4953
ds output buffer where to store result form query
5063
4956
static void run_query_normal(struct st_connection *cn,
5064
4957
struct st_command *command,
5065
4958
int flags, char *query, int query_len,
5066
DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4959
string *ds, string *ds_warnings)
5068
4961
DRIZZLE_RES *res= 0;
5069
4962
DRIZZLE *drizzle= &cn->drizzle;
5072
4965
if (flags & QUERY_SEND_FLAG)
5077
4970
if (do_send_query(cn, query, query_len, flags))
5079
4972
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5080
drizzle_sqlstate(drizzle), ds);
4973
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*/
5092
4977
if (!(flags & QUERY_REAP_FLAG))
5149
5034
if (!disable_warnings && !drizzle_more_results(drizzle))
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);
5036
if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
5038
ds->append("Warnings:\n", 10);
5039
ds->append(ds_warnings->c_str(), ds_warnings->length());
5158
5043
if (!disable_info)
5159
append_info(ds, affected_rows, drizzle_info(drizzle));
5044
append_info(ds, affected_rows, drizzle_info(drizzle));
5247
5131
if (command->expected_errors.count == 1)
5249
5133
/* Only log error if there is one possible 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);
5134
ds->append("ERROR ", 6);
5135
replace_append(ds, err_sqlstate);
5136
ds->append(": ", 2);
5137
replace_append(ds, err_error);
5256
5140
/* Don't log error if we may not get an error */
5257
5141
else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5258
5142
(command->expected_errors.err[0].type == ERR_ERRNO &&
5259
5143
command->expected_errors.err[0].code.errnum != 0))
5260
dynstr_append(ds,"Got one of the listed errors\n");
5144
ds->append("Got one of the listed errors\n");
5380
5261
if (command->require_file[0])
5382
init_dynamic_string(&ds_result, "", 1024, 1024);
5383
5263
ds= &ds_result;
5389
5270
Log the query into the output buffer
5391
5272
if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5393
replace_dynstr_append_mem(ds, query, query_len);
5394
dynstr_append_mem(ds, delimiter, delimiter_length);
5395
dynstr_append_mem(ds, "\n", 1);
5274
replace_append_mem(ds, query, query_len);
5275
ds->append(delimiter, delimiter_length);
5398
5279
if (display_result_sorted)
5401
Collect the query output in a separate string
5402
that can be sorted before it's added to the
5403
global result string
5282
Collect the query output in a separate string
5283
that can be sorted before it's added to the
5284
global result string
5405
init_dynamic_string(&ds_sorted, "", 1024, 1024);
5406
5286
save_ds= ds; /* Remember original ds */
5407
5287
ds= &ds_sorted;
5540
5414
/* Milliseconds since start */
5541
5415
end= int64_t2str(timer, buf, 10);
5542
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5543
dynstr_append_mem(&ds_progress, "\t", 1);
5416
ds_progress.append(buf, (int)(end-buf));
5417
ds_progress.append("\t", 1);
5545
5419
/* Parser line number */
5546
5420
end= int10_to_str(line, buf, 10);
5547
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5548
dynstr_append_mem(&ds_progress, "\t", 1);
5421
ds_progress.append(buf, (int)(end-buf));
5422
ds_progress.append("\t", 1);
5551
dynstr_append(&ds_progress, cur_file->file_name);
5552
dynstr_append_mem(&ds_progress, ":", 1);
5425
ds_progress.append(cur_file->file_name);
5426
ds_progress.append(":", 1);
5554
5428
/* Line in file */
5555
5429
end= int10_to_str(cur_file->lineno, buf, 10);
5556
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5559
dynstr_append_mem(&ds_progress, "\n", 1);
5430
ds_progress.append(buf, (int)(end-buf));
5433
ds_progress.append("\n", 1);
5776
5645
/* Check for special property for this query */
5777
5646
display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5781
strmake(command->require_file, save_file, sizeof(save_file) - 1);
5784
run_query(cur_con, command, flags);
5650
strmake(command->require_file, save_file, sizeof(save_file) - 1);
5653
run_query(cur_con, command, flags);
5786
5655
command->last_argument= command->end;
5788
5657
/* Restore settings */
5789
display_result_vertically= old_display_result_vertically;
5658
display_result_vertically= old_display_result_vertically;
5794
5663
if (!*command->first_argument)
5804
5673
/* Remove "send" if this is first iteration */
5805
if (command->query == command->query_buf)
5806
command->query= command->first_argument;
5674
if (command->query == command->query_buf)
5675
command->query= command->first_argument;
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
5678
run_query() can execute a query partially, depending on the flags.
5679
QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5811
5680
the query and read the result some time later when reap instruction
5812
is given on this connection.
5681
is given on this connection.
5814
run_query(cur_con, command, QUERY_SEND_FLAG);
5683
run_query(cur_con, command, QUERY_SEND_FLAG);
5816
5685
command->last_argument= command->end;
5818
5687
case Q_REQUIRE:
5819
do_get_file_name(command, save_file, sizeof(save_file));
5688
do_get_file_name(command, save_file, sizeof(save_file));
5822
5691
do_get_errcodes(command);
5824
5693
case Q_REPLACE:
5825
do_get_replace(command);
5694
do_get_replace(command);
5827
5696
case Q_REPLACE_REGEX:
5828
5697
do_get_replace_regex(command);
5830
5699
case Q_REPLACE_COLUMN:
5831
do_get_replace_column(command);
5700
do_get_replace_column(command);
5833
5702
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5834
5703
case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5835
5704
case Q_SYNC_SLAVE_WITH_MASTER:
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);
5706
do_save_master_pos();
5707
if (*command->first_argument)
5708
select_connection(command);
5710
select_connection_name("slave");
5711
do_sync_with_master2(0);
5845
5714
case Q_COMMENT: /* Ignore row */
5846
5715
command->last_argument= command->end;
5849
(void) drizzle_ping(&cur_con->drizzle);
5718
(void) drizzle_ping(&cur_con->drizzle);
5855
5724
case Q_START_TIMER:
5856
/* Overwrite possible earlier start of timer */
5857
timer_start= timer_now();
5725
/* Overwrite possible earlier start of timer */
5726
timer_start= timer_now();
5859
5728
case Q_END_TIMER:
5860
/* End timer before ending drizzletest */
5729
/* End timer before ending drizzletest */
5863
5732
case Q_CHARACTER_SET:
5864
do_set_charset(command);
5733
do_set_charset(command);
5866
5735
case Q_DISABLE_RECONNECT:
5867
5736
set_reconnect(&cur_con->drizzle, 0);
5969
/* Recording - dump the output from test to result file */
5970
str_to_file(result_file_name, ds_res.str, ds_res.length);
5838
/* Recording - dump the output from test to result file */
5839
str_to_file(result_file_name, ds_res.c_str(), ds_res.length());
5974
/* Check that the output from test is equal to result file
5975
- detect missing result file
5976
- detect zero size result file
5843
/* Check that the output from test is equal to result file
5844
- detect missing result file
5845
- detect zero size result file
5978
check_result(&ds_res);
5847
check_result(&ds_res);
5983
5852
/* No result_file_name specified to compare with, print to stdout */
5984
printf("%s", ds_res.str);
5853
printf("%s", ds_res.c_str());
6234
6102
if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6236
6104
/* No match found */
6237
dynstr_append_mem(ds, start, from - start - 1);
6105
ds->append(start, from - start - 1);
6241
6109
/* Append part of original string before replace string */
6242
dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6110
ds->append(start, (from - rep_str->to_offset) - start);
6244
6112
/* Append replace string */
6245
dynstr_append_mem(ds, rep_str->replace_string,
6246
strlen(rep_str->replace_string));
6113
ds->append(rep_str->replace_string,
6114
strlen(rep_str->replace_string));
6248
6116
if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6705
6573
internal_set_bit(word_states,states);
6706
6574
if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6708
start_states->table_offset=i;
6709
start_states->found_offset=0;
6576
start_states->table_offset=i;
6577
start_states->found_offset=0;
6714
6582
internal_set_bit(word_states,states);
6715
6583
if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6716
internal_set_bit(start_states,states+1);
6584
internal_set_bit(start_states,states+1);
6718
internal_set_bit(start_states,states);
6586
internal_set_bit(start_states,states);
6720
6588
for (pos=from[i], len=0; *pos ; pos++)
6722
6590
if (*pos == '\\' && *(pos+1))
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;
6595
follow_ptr->chr = SPACE_CHAR;
6598
follow_ptr->chr = START_OF_LINE;
6601
follow_ptr->chr = END_OF_LINE;
6604
follow_ptr->chr = '\r';
6607
follow_ptr->chr = '\t';
6610
follow_ptr->chr = '\v';
6613
follow_ptr->chr = (uchar) *pos;
6750
follow_ptr->chr= (uchar) *pos;
6618
follow_ptr->chr= (uchar) *pos;
6751
6619
follow_ptr->table_offset=i;
6752
6620
follow_ptr->len= ++len;
6787
6655
used_chars[follow[i].chr]=1;
6788
6656
if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6789
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6657
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6793
6661
/* Mark word_chars used if \b is in state */
6794
6662
if (used_chars[SPACE_CHAR])
6795
6663
for (pos= word_end_chars ; *pos ; pos++)
6796
used_chars[(int) (uchar) *pos] = 1;
6664
used_chars[(int) (uchar) *pos] = 1;
6798
6666
/* Handle other used characters */
6799
6667
for (chr= 0 ; chr < 256 ; chr++)
6801
6669
if (! used_chars[chr])
6802
set->next[chr]= chr ? default_state : -1;
6670
set->next[chr]= chr ? default_state : -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;
6673
new_set=make_new_set(&sets);
6674
set=sets.set+set_nr; /* if realloc */
6675
new_set->table_offset=set->table_offset;
6676
new_set->found_len=set->found_len;
6677
new_set->found_offset=set->found_offset+1;
6812
for (i= UINT32_MAX ; (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= UINT32_MAX; (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);
6680
for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6682
if (!follow[i].chr || follow[i].chr == chr ||
6683
(follow[i].chr == SPACE_CHAR &&
6684
(is_word_end[chr] ||
6685
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6686
(follow[i].chr == END_OF_LINE && ! chr))
6688
if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6689
follow[i].len > found_end)
6690
found_end=follow[i].len;
6691
if (chr && follow[i].chr)
6692
internal_set_bit(new_set,i+1); /* To next set */
6694
internal_set_bit(new_set,i);
6699
new_set->found_len=0; /* Set for testing if first */
6701
for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6703
if ((follow[i].chr == SPACE_CHAR ||
6704
follow[i].chr == END_OF_LINE) && ! chr)
6708
if (follow[bit_nr-1].len < found_end ||
6709
(new_set->found_len &&
6710
(chr == 0 || !follow[bit_nr].chr)))
6711
internal_clear_bit(new_set,i);
6714
if (chr == 0 || !follow[bit_nr].chr)
6716
new_set->table_offset=follow[bit_nr].table_offset;
6717
if (chr || (follow[i].chr == SPACE_CHAR ||
6718
follow[i].chr == END_OF_LINE))
6719
new_set->found_offset=found_end; /* New match */
6720
new_set->found_len=found_end;
6727
set->next[chr] = find_found(found_set,
6728
new_set->table_offset,
6729
new_set->found_offset);
6730
free_last_set(&sets);
6733
set->next[chr] = find_set(&sets,new_set);
6736
set->next[chr] = find_set(&sets,new_set);
7114
6982
if (! pa->typelib.count)
7116
6984
if (!(pa->typelib.type_names=(const char **)
7117
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7118
(sizeof(char *)+sizeof(*pa->flag))*
7119
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6985
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
6986
(sizeof(char *)+sizeof(*pa->flag))*
6987
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
7121
6989
if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
7124
6992
my_free((char*) pa->typelib.type_names,MYF(0));
7127
6995
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7129
6997
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7131
6999
pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
7192
7060
/* Functions that uses replace and replace_regex */
7194
7062
/* Append the string to ds, with optional replace */
7195
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
7196
const char *val, int len)
7063
void replace_append_mem(string *ds,
7064
const char *val, int len)
7066
char *v= strdup(val);
7198
7068
if (glob_replace_regex)
7200
7070
/* Regex replace */
7201
if (!multi_reg_replace(glob_replace_regex, (char*)val))
7071
if (!multi_reg_replace(glob_replace_regex, v))
7203
val= glob_replace_regex->buf;
7073
v= glob_replace_regex->buf;
7208
7078
if (glob_replace)
7210
7080
/* Normal replace */
7211
replace_strings_append(glob_replace, ds, val, len);
7081
replace_strings_append(glob_replace, ds, v, len);
7214
dynstr_append_mem(ds, val, len);
7218
7090
/* Append zero-terminated string to ds, with optional replace */
7219
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7091
void replace_append(string *ds, const char *val)
7221
replace_dynstr_append_mem(ds, val, strlen(val));
7093
replace_append_mem(ds, val, strlen(val));
7224
7096
/* Append uint to ds, with optional replace */
7225
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7097
void replace_append_uint(string *ds, uint val)
7227
7099
char buff[22]; /* This should be enough for any int */
7228
7100
char *end= int64_t10_to_str(val, buff, 10);
7229
replace_dynstr_append_mem(ds, buff, end - buff);
7101
replace_append_mem(ds, buff, end - buff);
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;
7120
void append_sorted(string* ds, string *ds_input)
7122
priority_queue<string> lines;
7124
if (ds_input->empty())
7259
7125
return; /* No input */
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);
7127
unsigned long eol_pos= 0;
7129
eol_pos= ds_input->find_first_of('\n', 0);
7130
if (eol_pos == string::npos)
7131
return; // We should have at least one header here
7133
ds->append(ds_input->substr(0, eol_pos));
7135
unsigned long start_pos= eol_pos+1;
7269
7137
/* Insert line(s) in array */
7272
char* line_end= (char*)start;
7140
eol_pos= ds_input->find_first_of('\n', start_pos);
7274
7141
/* Find end of line */
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);
7142
lines.push(ds_input->substr(start_pos, eol_pos-start_pos));
7143
start_pos= eol_pos+1;
7145
} while ( eol_pos != string::npos);
7290
7147
/* Create new result */
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");
7148
while (!lines.empty()) {
7149
ds->append(lines.top());
7298
delete_dynamic(&lines);