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) 2000 MySQL AB
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 */
24
19
Tool used for executing a .test file
26
See the "DRIZZLE Test framework manual" for more information
27
http://dev.mysql.com/doc/drizzletest/en/index.html
21
See the "MySQL Test framework manual" for more information
22
http://dev.mysql.com/doc/mysqltest/en/index.html
29
24
Please keep the test framework tools identical in all versions!
189
187
struct st_connection
192
190
/* Used when creating views and sp, to avoid implicit commit */
193
DRIZZLE *util_drizzle;
196
194
struct st_connection connections[128];
197
195
struct st_connection* cur_con= NULL, *next_con, *connections_end;
200
List of commands in drizzletest
198
List of commands in mysqltest
201
199
Must match the "command_names" array
202
200
Add new commands before Q_UNKNOWN!
204
202
enum enum_commands {
205
203
Q_CONNECTION=1, Q_QUERY,
206
Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
208
Q_SOURCE, Q_DISCONNECT,
210
Q_WHILE, Q_END_BLOCK,
212
Q_REQUIRE, Q_SAVE_MASTER_POS,
204
Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
206
Q_SOURCE, Q_DISCONNECT,
208
Q_WHILE, Q_END_BLOCK,
210
Q_REQUIRE, Q_SAVE_MASTER_POS,
213
211
Q_SYNC_WITH_MASTER,
214
212
Q_SYNC_SLAVE_WITH_MASTER,
217
Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
215
Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
220
218
Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
221
219
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
371
369
TYPELIB command_typelib= {array_elements(command_names),"",
374
string ds_res, ds_progress, ds_warning_messages;
372
DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
376
374
char builtin_echo[FN_REFLEN];
378
376
void die(const char *fmt, ...)
379
__attribute__((format(printf, 1, 2)));
377
ATTRIBUTE_FORMAT(printf, 1, 2);
380
378
void abort_not_supported_test(const char *fmt, ...)
381
__attribute__((format(printf, 1, 2)));
379
ATTRIBUTE_FORMAT(printf, 1, 2);
382
380
void verbose_msg(const char *fmt, ...)
383
__attribute__((format(printf, 1, 2)));
381
ATTRIBUTE_FORMAT(printf, 1, 2);
384
382
void warning_msg(const char *fmt, ...)
385
__attribute__((format(printf, 1, 2)));
383
ATTRIBUTE_FORMAT(printf, 1, 2);
386
384
void log_msg(const char *fmt, ...)
387
__attribute__((format(printf, 1, 2)));
385
ATTRIBUTE_FORMAT(printf, 1, 2);
389
387
VAR* var_from_env(const char *, const char *);
390
388
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
395
393
void eval_expr(VAR* v, const char *p, const char** p_end);
396
394
bool match_delimiter(int c, const char *delim, uint length);
397
395
void dump_result_to_reject_file(char *buf, int size);
398
void dump_result_to_log_file(const char *buf, int size);
396
void dump_result_to_log_file(char *buf, int size);
399
397
void dump_warning_messages(void);
400
398
void dump_progress(void);
402
void do_eval(string *query_eval, const char *query,
400
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
403
401
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);
402
void str_to_file(const char *fname, char *str, int size);
403
void str_to_file2(const char *fname, char *str, int size, bool append);
407
405
/* For replace_column */
408
406
static char *replace_column[MAX_COLUMNS];
428
426
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);
429
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
431
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
432
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
433
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input);
437
435
void handle_error(struct st_command*,
438
436
unsigned int err_errno, const char *err_error,
439
const char *err_sqlstate, string *ds);
437
const char *err_sqlstate, DYNAMIC_STRING *ds);
440
438
void handle_no_error(struct st_command*);
443
#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,
440
#ifdef EMBEDDED_LIBRARY
442
/* attributes of the query thread */
443
pthread_attr_t cn_thd_attrib;
446
send_one_query executes query in separate thread, which is
447
necessary in embedded library to run 'send' in proper way.
448
This implementation doesn't handle errors returned
449
by mysql_send_query. It's technically possible, though
450
I don't see where it is needed.
452
pthread_handler_t send_one_query(void *arg)
454
struct st_connection *cn= (struct st_connection*)arg;
457
VOID(mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len));
460
pthread_mutex_lock(&cn->mutex);
462
VOID(pthread_cond_signal(&cn->cond));
463
pthread_mutex_unlock(&cn->mutex);
468
static int do_send_query(struct st_connection *cn, const char *q, int q_len,
473
if (flags & QUERY_REAP_FLAG)
474
return mysql_send_query(&cn->mysql, q, q_len);
476
if (pthread_mutex_init(&cn->mutex, NULL) ||
477
pthread_cond_init(&cn->cond, NULL))
478
die("Error in the thread library");
481
cn->cur_query_len= q_len;
483
if (pthread_create(&tid, &cn_thd_attrib, send_one_query, (void*)cn))
484
die("Cannot start new thread for query");
489
static void wait_query_thread_end(struct st_connection *con)
491
if (!con->query_done)
493
pthread_mutex_lock(&con->mutex);
494
while (!con->query_done)
495
pthread_cond_wait(&con->cond, &con->mutex);
496
pthread_mutex_unlock(&con->mutex);
500
#else /*EMBEDDED_LIBRARY*/
502
#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q, q_len)
504
#endif /*EMBEDDED_LIBRARY*/
506
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
446
507
const char *query_end, bool pass_through_escape_chars)
461
query_eval->append(p, 1);
522
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);
526
if (!(v= var_get(p, &p, 0, 0)))
527
die("Bad variable in eval");
528
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
475
query_eval->append(p, 1);
536
dynstr_append_mem(query_eval, p, 1);
477
538
else if (next_c == '\\' || next_c == '$' || next_c == '"')
479
540
/* Set escaped only if next char is \, " or $ */
482
543
if (pass_through_escape_chars)
484
545
/* The escape char should be added to the output string. */
485
query_eval->append(p, 1);
546
dynstr_append_mem(query_eval, p, 1);
489
query_eval->append(p, 1);
550
dynstr_append_mem(query_eval, p, 1);
493
query_eval->append(p, 1);
554
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
563
Run query and dump the result to stdout in vertical format
548
565
NOTE! This function should be safe to call when an error
553
drizzle - connection to use
570
mysql - connection to use
554
571
query - query to run
558
static void show_query(DRIZZLE *drizzle, const char* query)
575
static void show_query(MYSQL* mysql, const char* query)
566
if (drizzle_query(drizzle, query))
583
if (mysql_query(mysql, query))
568
585
log_msg("Error running query '%s': %d %s",
569
query, drizzle_errno(drizzle), drizzle_error(drizzle));
586
query, mysql_errno(mysql), mysql_error(mysql));
573
if ((res= drizzle_store_result(drizzle)) == NULL)
590
if ((res= mysql_store_result(mysql)) == NULL)
575
592
/* No result set returned */
582
599
unsigned int row_num= 0;
583
unsigned int num_fields= drizzle_num_fields(res);
584
const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
600
unsigned int num_fields= mysql_num_fields(res);
601
MYSQL_FIELD *fields= mysql_fetch_fields(res);
586
603
fprintf(stderr, "=== %s ===\n", query);
587
while ((row= drizzle_fetch_row(res)))
604
while ((row= mysql_fetch_row(res)))
589
uint32_t *lengths= drizzle_fetch_lengths(res);
606
uint32_t *lengths= mysql_fetch_lengths(res);
592
609
fprintf(stderr, "---- %d. ----\n", row_num);
618
635
show_warnings_before_error
619
drizzle - connection to use
636
mysql - connection to use
623
static void show_warnings_before_error(DRIZZLE *drizzle)
640
static void show_warnings_before_error(MYSQL* mysql)
626
643
const char* query= "SHOW WARNINGS";
632
if (drizzle_query(drizzle, query))
649
if (mysql_query(mysql, query))
634
651
log_msg("Error running query '%s': %d %s",
635
query, drizzle_errno(drizzle), drizzle_error(drizzle));
652
query, mysql_errno(mysql), mysql_error(mysql));
639
if ((res= drizzle_store_result(drizzle)) == NULL)
656
if ((res= mysql_store_result(mysql)) == NULL)
641
658
/* No result set returned */
645
if (drizzle_num_rows(res) <= 1)
662
if (mysql_num_rows(res) <= 1)
647
664
/* Don't display the last row, it's "last error" */
652
669
unsigned int row_num= 0;
653
unsigned int num_fields= drizzle_num_fields(res);
670
unsigned int num_fields= mysql_num_fields(res);
655
672
fprintf(stderr, "\nWarnings from just before the error:\n");
656
while ((row= drizzle_fetch_row(res)))
673
while ((row= mysql_fetch_row(res)))
659
uint32_t *lengths= drizzle_fetch_lengths(res);
676
uint32_t *lengths= mysql_fetch_lengths(res);
661
if (++row_num >= drizzle_num_rows(res))
678
if (++row_num >= mysql_num_rows(res))
663
680
/* Don't display the last row, it's "last error" */
836
855
hash_free(&var_hash);
838
vector<struct st_command *>::iterator iter;
839
for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
857
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);
859
struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
860
my_free((*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
861
my_free((*q),MYF(0));
849
863
for (i= 0; i < 10; i++)
851
865
if (var_reg[i].alloced_len)
852
free(var_reg[i].str_val);
866
my_free(var_reg[i].str_val, MYF(MY_WME));
854
868
while (embedded_server_arg_count > 1)
855
free(embedded_server_args[--embedded_server_arg_count]);
869
my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
870
delete_dynamic(&q_lines);
871
dynstr_free(&ds_res);
872
dynstr_free(&ds_progress);
873
dynstr_free(&ds_warning_messages);
857
874
free_all_replace();
875
my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
859
876
free_defaults(default_argv);
878
/* Only call mysql_server_end if mysql_server_init has been called */
879
if (server_initialized)
922
943
/* Show results from queries just before failure */
923
if (ds_res.length() && opt_tail_lines)
944
if (ds_res.length && opt_tail_lines)
925
946
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 )
947
char* show_from= ds_res.str + ds_res.length - 1;
948
while(show_from > ds_res.str && tail_lines > 0 )
930
951
if (*show_from == '\n')
933
954
fprintf(stderr, "\nThe result from queries just before the failure was:\n");
934
if (show_from > ds_res.c_str())
955
if (show_from > ds_res.str)
935
956
fprintf(stderr, "< snip >");
936
957
fprintf(stderr, "%s", show_from);
940
961
/* 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());
962
if (result_file_name && ds_res.length)
963
dump_result_to_log_file(ds_res.str, ds_res.length);
944
965
/* Dump warning messages */
945
if (result_file_name && ds_warning_messages.length())
966
if (result_file_name && ds_warning_messages.length)
946
967
dump_warning_messages();
1021
1042
va_start(args, fmt);
1022
ds_warning_messages.append("drizzletest: ");
1043
dynstr_append(&ds_warning_messages, "mysqltest: ");
1023
1044
if (start_lineno != 0)
1025
ds_warning_messages.append("Warning detected ");
1046
dynstr_append(&ds_warning_messages, "Warning detected ");
1026
1047
if (cur_file && cur_file != file_stack)
1028
1049
len= snprintf(buff, sizeof(buff), "in included file %s ",
1029
cur_file->file_name);
1030
ds_warning_messages.append(buff, len);
1050
cur_file->file_name);
1051
dynstr_append_mem(&ds_warning_messages,
1032
1054
len= snprintf(buff, sizeof(buff), "at line %d: ",
1034
ds_warning_messages.append(buff, len);
1056
dynstr_append_mem(&ds_warning_messages,
1037
1060
len= vsnprintf(buff, sizeof(buff), fmt, args);
1038
ds_warning_messages.append(buff, len);
1061
dynstr_append_mem(&ds_warning_messages, buff, len);
1040
ds_warning_messages.append("\n");
1063
dynstr_append(&ds_warning_messages, "\n");
1145
1176
tool_path - the name of the tool to run
1146
result - pointer to dynamic string where to store the result
1177
ds_res - pointer to dynamic string where to store the result
1147
1178
... - variable number of arguments that will be properly
1148
quoted and appended after the tool's name
1179
quoted and appended after the tool's name
1152
static int run_tool(const char *tool_path, string * result, ...)
1183
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1155
1186
const char* arg;
1160
append_os_quoted(&ds_cmdline, tool_path, NULL);
1161
ds_cmdline.append(" ");
1163
va_start(args, result);
1188
DYNAMIC_STRING ds_cmdline;
1190
if (init_dynamic_string(&ds_cmdline, "", FN_REFLEN, FN_REFLEN))
1191
die("Out of memory");
1193
dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
1194
dynstr_append(&ds_cmdline, " ");
1196
va_start(args, ds_res);
1165
1198
while ((arg= va_arg(args, char *)))
1167
1200
/* Options should be os quoted */
1168
1201
if (strncmp(arg, "--", 2) == 0)
1169
append_os_quoted(&ds_cmdline, arg, NULL);
1202
dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1171
ds_cmdline.append(arg);
1172
ds_cmdline.append(" ");
1204
dynstr_append(&ds_cmdline, arg);
1205
dynstr_append(&ds_cmdline, " ");
1177
ret= run_command(ds_cmdline.c_str(), result);
1210
ret= run_command(ds_cmdline.str, ds_res);
1211
dynstr_free(&ds_cmdline);
1222
1259
Fallback to dump both files to result file and inform
1223
1260
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");
1262
dynstr_set(&ds_tmp, "");
1264
dynstr_append(&ds_tmp,
1266
"The two files differ but it was not possible to execute 'diff' in\n"
1267
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1268
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
1269
"To get a better report you should install 'diff' on your system, which you\n"
1270
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1273
dynstr_append(&ds_tmp, " --- ");
1274
dynstr_append(&ds_tmp, filename1);
1275
dynstr_append(&ds_tmp, " >>>\n");
1239
1276
cat_file(&ds_tmp, filename1);
1240
ds_tmp.append("<<<\n --- ");
1241
ds_tmp.append(filename1);
1242
ds_tmp.append(" >>>\n");
1277
dynstr_append(&ds_tmp, "<<<\n --- ");
1278
dynstr_append(&ds_tmp, filename1);
1279
dynstr_append(&ds_tmp, " >>>\n");
1243
1280
cat_file(&ds_tmp, filename2);
1244
ds_tmp.append("<<<<\n");
1281
dynstr_append(&ds_tmp, "<<<<\n");
1250
1287
/* Add the diff to output */
1251
ds->append(ds_tmp.c_str(), ds_tmp.length());
1288
dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1255
1292
/* Print diff directly to stdout */
1256
fprintf(stderr, "%s\n", ds_tmp.c_str());
1293
fprintf(stderr, "%s\n", ds_tmp.str);
1296
dynstr_free(&ds_tmp);
1262
1301
enum compare_files_result_enum {
1264
RESULT_CONTENT_MISMATCH= 1,
1265
RESULT_LENGTH_MISMATCH= 2
1303
RESULT_CONTENT_MISMATCH= 1,
1304
RESULT_LENGTH_MISMATCH= 2
1799
1838
/* Eval the query, thus replacing all environment variables */
1839
init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
1800
1840
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));
1805
if (!(res= drizzle_store_result(drizzle)))
1806
die("Query '%s' didn't return a result set", ds_query.c_str());
1842
if (mysql_real_query(mysql, ds_query.str, ds_query.length))
1843
die("Error running query '%s': %d %s", ds_query.str,
1844
mysql_errno(mysql), mysql_error(mysql));
1845
if (!(res= mysql_store_result(mysql)))
1846
die("Query '%s' didn't return a result set", ds_query.str);
1847
dynstr_free(&ds_query);
1808
if ((row= drizzle_fetch_row(res)) && row[0])
1849
if ((row= mysql_fetch_row(res)) && row[0])
1811
1852
Concatenate all fields in the first row with tab in between
1812
1853
and assign that string to the $variable
1855
DYNAMIC_STRING result;
1816
1857
uint32_t *lengths;
1818
lengths= drizzle_fetch_lengths(res);
1819
for (i= 0; i < drizzle_num_fields(res); i++)
1859
init_dynamic_string(&result, "", 512, 512);
1860
lengths= mysql_fetch_lengths(res);
1861
for (i= 0; i < mysql_num_fields(res); i++)
1823
1865
/* Add column to tab separated string */
1824
result.append(row[i], lengths[i]);
1866
dynstr_append_mem(&result, row[i], lengths[i]);
1826
result.append("\t", 1);
1868
dynstr_append_mem(&result, "\t", 1);
1828
end= result.c_str() + result.length()-1;
1829
eval_expr(var, result.c_str(), (const char**) &end);
1870
end= result.str + result.length-1;
1871
eval_expr(var, result.str, (const char**) &end);
1872
dynstr_free(&result);
1832
1875
eval_expr(var, "", 0);
1834
drizzle_free_result(res);
1877
mysql_free_result(res);
1884
1927
/* 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());
1928
if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
1929
die("Invalid row number: '%s'", ds_row.str);
1930
dynstr_free(&ds_row);
1888
1932
/* 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;
1933
if (strip_surrounding(ds_query.str, '"', '"'))
1934
die("Mismatched \"'s around query '%s'", ds_query.str);
1895
1936
/* 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));
1899
if (!(res= drizzle_store_result(drizzle)))
1900
die("Query '%s' didn't return a result set", ds_query.c_str());
1937
if (mysql_real_query(mysql, ds_query.str, ds_query.length))
1938
die("Error running query '%s': %d %s", ds_query.str,
1939
mysql_errno(mysql), mysql_error(mysql));
1940
if (!(res= mysql_store_result(mysql)))
1941
die("Query '%s' didn't return a result set", ds_query.str);
1903
1944
/* Find column number from the given column name */
1905
uint num_fields= drizzle_num_fields(res);
1906
const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
1946
uint num_fields= mysql_num_fields(res);
1947
MYSQL_FIELD *fields= mysql_fetch_fields(res);
1908
1949
for (i= 0; i < num_fields; i++)
1910
if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
1911
strlen(fields[i].name) == ds_col.length())
1951
if (strcmp(fields[i].name, ds_col.str) == 0 &&
1952
strlen(fields[i].name) == ds_col.length)
2105
2155
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
2159
ds_str The string to search and perform the replace in
2160
search_str The string to search for
2161
search_len Length of the string to search for
2162
replace_str The string to replace with
2163
replace_len Length of the string to replace with
2117
1 Could not find search_str in str
2167
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)
2170
static int replace(DYNAMIC_STRING *ds_str,
2171
const char *search_str, ulong search_len,
2172
const char *replace_str, ulong replace_len)
2125
const char *start= strstr(ds_str->c_str(), search_str);
2174
DYNAMIC_STRING ds_tmp;
2175
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);
2178
init_dynamic_string(&ds_tmp, "",
2179
ds_str->length + replace_len, 256);
2180
dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
2181
dynstr_append_mem(&ds_tmp, replace_str, replace_len);
2182
dynstr_append(&ds_tmp, start + search_len);
2183
dynstr_set(ds_str, ds_tmp.str);
2184
dynstr_free(&ds_tmp);
2300
2376
static void do_system(struct st_command *command)
2378
DYNAMIC_STRING ds_cmd;
2305
2381
if (strlen(command->first_argument) == 0)
2306
2382
die("Missing arguments to system, nothing to do!");
2384
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
2308
2386
/* Eval the system command, thus replacing all environment variables */
2309
2387
do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2311
if (system(ds_cmd.c_str()))
2389
if (my_system(&ds_cmd))
2313
2391
if (command->abort_on_error)
2314
2392
die("system command '%s' failed", command->first_argument);
2316
2394
/* 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");
2395
dynstr_append(&ds_res, "system command '");
2396
replace_dynstr_append(&ds_res, command->first_argument);
2397
dynstr_append(&ds_res, "' failed\n");
2322
2400
command->last_argument= command->end;
2401
dynstr_free(&ds_cmd);
2599
2686
/* If no delimiter was provided, use EOF */
2600
if (ds_delimiter.length() == 0)
2601
ds_delimiter= "EOF";
2687
if (ds_delimiter.length == 0)
2688
dynstr_set(&ds_delimiter, "EOF");
2603
if (!append && access(ds_filename.c_str(), F_OK) == 0)
2690
if (!append && access(ds_filename.str, F_OK) == 0)
2605
2692
/* The file should not be overwritten */
2606
die("File already exist: '%s'", ds_filename.c_str());
2693
die("File already exist: '%s'", ds_filename.str);
2696
init_dynamic_string(&ds_content, "", 1024, 1024);
2609
2697
read_until_delimiter(&ds_content, &ds_delimiter);
2610
str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2611
ds_content.length(), append);
2698
str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
2699
dynstr_free(&ds_content);
2700
dynstr_free(&ds_filename);
2701
dynstr_free(&ds_delimiter);
2893
2988
/* If no delimiter was provided, use EOF */
2894
if (ds_delimiter.length() == 0)
2895
ds_delimiter= "EOF";
2989
if (ds_delimiter.length == 0)
2990
dynstr_set(&ds_delimiter, "EOF");
2992
init_dynamic_string(&ds_script, "", 1024, 1024);
2897
2993
read_until_delimiter(&ds_script, &ds_delimiter);
2899
2995
/* Create temporary file name */
2900
2996
if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
2901
"tmp", O_CREAT | O_RDWR,
2997
"tmp", O_CREAT | O_SHARE | O_RDWR,
2902
2998
MYF(MY_WME))) < 0)
2903
2999
die("Failed to create temporary file for perl command");
2904
3000
my_close(fd, MYF(0));
2906
str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
3002
str_to_file(temp_file_path, ds_script.str, ds_script.length);
2908
3004
/* Format the "perl <filename>" command */
2909
3005
snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
3007
3107
die("Calling 'sync_with_master' without calling 'save_master_pos'");
3009
3109
sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3010
master_pos.pos + offset);
3110
master_pos.pos + offset);
3012
3112
wait_for_position:
3014
if (drizzle_query(drizzle, query_buf))
3015
die("failed in '%s': %d: %s", query_buf, drizzle_errno(drizzle),
3016
drizzle_error(drizzle));
3114
if (mysql_query(mysql, query_buf))
3115
die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
3116
mysql_error(mysql));
3018
if (!(res= drizzle_store_result(drizzle)))
3019
die("drizzle_store_result() returned NULL for '%s'", query_buf);
3020
if (!(row= drizzle_fetch_row(res)))
3118
if (!(res= mysql_store_result(mysql)))
3119
die("mysql_store_result() returned NULL for '%s'", query_buf);
3120
if (!(row= mysql_fetch_row(res)))
3022
drizzle_free_result(res);
3122
mysql_free_result(res);
3023
3123
die("empty result in %s", query_buf);
3066
3166
when ndb binlog is on, this call will wait until last updated epoch
3067
(locally in the drizzled) has been received into the binlog
3167
(locally in the mysqld) has been received into the binlog
3069
3169
static int do_save_master_pos(void)
3073
DRIZZLE *drizzle= &cur_con->drizzle;
3173
MYSQL *mysql = &cur_con->mysql;
3074
3174
const char *query;
3077
if (drizzle_query(drizzle, query= "show master status"))
3177
if (mysql_query(mysql, query= "show master status"))
3078
3178
die("failed in 'show master status': %d %s",
3079
drizzle_errno(drizzle), drizzle_error(drizzle));
3179
mysql_errno(mysql), mysql_error(mysql));
3081
if (!(res = drizzle_store_result(drizzle)))
3082
die("drizzle_store_result() retuned NULL for '%s'", query);
3083
if (!(row = drizzle_fetch_row(res)))
3181
if (!(res = mysql_store_result(mysql)))
3182
die("mysql_store_result() retuned NULL for '%s'", query);
3183
if (!(row = mysql_fetch_row(res)))
3084
3184
die("empty result in show master status");
3085
my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
3185
strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
3086
3186
master_pos.pos = strtoul(row[1], (char**) 0, 10);
3087
drizzle_free_result(res);
3187
mysql_free_result(res);
3560
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
3561
const char *user, const char *pass, const char *db,
3689
static void safe_connect(MYSQL* mysql, const char *name, const char *host,
3690
const char *user, const char *pass, const char *db,
3564
3693
int failed_attempts= 0;
3565
static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3568
while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3569
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3694
static ulong connection_retry_sleep= 100000; /* Microseconds */
3697
while(!mysql_real_connect(mysql, host, user, pass, db, port, NULL,
3698
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3576
3705
on protocol/connection type
3579
if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
3580
drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
3708
if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
3709
mysql_errno(mysql) == CR_CONNECTION_ERROR) &&
3581
3710
failed_attempts < opt_max_connect_retries)
3583
3712
verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3584
opt_max_connect_retries, drizzle_errno(drizzle),
3585
drizzle_error(drizzle));
3713
opt_max_connect_retries, mysql_errno(mysql),
3714
mysql_error(mysql));
3586
3715
my_sleep(connection_retry_sleep);
3590
3719
if (failed_attempts > 0)
3591
3720
die("Could not open connection '%s' after %d attempts: %d %s", name,
3592
failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
3721
failed_attempts, mysql_errno(mysql), mysql_error(mysql));
3594
3723
die("Could not open connection '%s': %d %s", name,
3595
drizzle_errno(drizzle), drizzle_error(drizzle));
3724
mysql_errno(mysql), mysql_error(mysql));
3597
3726
failed_attempts++;
3637
3769
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);
3771
dynstr_append_mem(ds, "connect(", 8);
3772
replace_dynstr_append(ds, host);
3773
dynstr_append_mem(ds, ",", 1);
3774
replace_dynstr_append(ds, user);
3775
dynstr_append_mem(ds, ",", 1);
3776
replace_dynstr_append(ds, pass);
3777
dynstr_append_mem(ds, ",", 1);
3647
replace_append(&ds_res, db);
3649
replace_append_uint(&ds_res, port);
3779
replace_dynstr_append(ds, db);
3780
dynstr_append_mem(ds, ",", 1);
3781
replace_dynstr_append_uint(ds, port);
3782
dynstr_append_mem(ds, ",", 1);
3652
replace_append(&ds_res, sock);
3654
ds_res.append(delimiter);
3655
ds_res.append("\n");
3784
replace_dynstr_append(ds, sock);
3785
dynstr_append_mem(ds, ")", 1);
3786
dynstr_append_mem(ds, delimiter, delimiter_length);
3787
dynstr_append_mem(ds, "\n", 1);
3657
if (!drizzle_connect(con, host, user, pass, db, port, 0,
3658
CLIENT_MULTI_STATEMENTS))
3789
if (!mysql_real_connect(con, host, user, pass, db, port, 0,
3790
CLIENT_MULTI_STATEMENTS))
3660
var_set_errno(drizzle_errno(con));
3661
handle_error(command, drizzle_errno(con), drizzle_error(con),
3662
drizzle_sqlstate(con), &ds_res);
3792
var_set_errno(mysql_errno(con));
3793
handle_error(command, mysql_errno(con), mysql_error(con),
3794
mysql_sqlstate(con), ds);
3663
3795
return 0; /* Not connected */
3689
3821
<port> - server port
3690
3822
<sock> - server socket
3691
3823
<opts> - options to use for the connection
3692
* SSL - use SSL if available
3693
* COMPRESS - use compression if available
3824
* SSL - use SSL if available
3825
* COMPRESS - use compression if available
3697
3829
static void do_connect(struct st_command *command)
3699
3831
int con_port= opt_port;
3700
const char *con_options;
3701
3833
bool con_ssl= 0, con_compress= 0;
3702
3834
struct st_connection* con_slot;
3704
string ds_connection_name;
3836
static DYNAMIC_STRING ds_connection_name;
3837
static DYNAMIC_STRING ds_host;
3838
static DYNAMIC_STRING ds_user;
3839
static DYNAMIC_STRING ds_password;
3840
static DYNAMIC_STRING ds_database;
3841
static DYNAMIC_STRING ds_port;
3842
static DYNAMIC_STRING ds_sock;
3843
static DYNAMIC_STRING ds_options;
3712
3844
const struct command_arg connect_args[] = {
3713
3845
{ "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3714
3846
{ "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3730
if (ds_port.length())
3732
con_port= atoi(ds_port.c_str());
3864
con_port= atoi(ds_port.str);
3733
3865
if (con_port == 0)
3734
die("Illegal argument for port: '%s'", ds_port.c_str());
3866
die("Illegal argument for port: '%s'", ds_port.str);
3738
if (!ds_sock.empty())
3741
3873
If the socket is specified just as a name without path
3742
3874
append tmpdir in front
3744
if (*ds_sock.c_str() != FN_LIBCHAR)
3876
if (*ds_sock.str != FN_LIBCHAR)
3746
3878
char buff[FN_REFLEN];
3747
fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3879
fn_format(buff, ds_sock.str, TMPDIR, "", 0);
3880
dynstr_set(&ds_sock, buff);
3885
/* No socket specified, use default */
3886
dynstr_set(&ds_sock, unix_sock);
3753
con_options= ds_options.c_str();
3890
con_options= ds_options.str;
3754
3891
while (*con_options)
3757
3894
/* Step past any spaces in beginning of option*/
3758
3895
while (*con_options && my_isspace(charset_info, *con_options))
3760
3897
/* Find end of this option */
3761
3898
end= con_options;
3762
3899
while (*end && !my_isspace(charset_info, *end))
3786
3921
(int) (sizeof(connections)/sizeof(struct st_connection)));
3789
if (!drizzle_create(&con_slot->drizzle))
3790
die("Failed on drizzle_create()");
3924
#ifdef EMBEDDED_LIBRARY
3925
con_slot->query_done= 1;
3927
if (!mysql_init(&con_slot->mysql))
3928
die("Failed on mysql_init()");
3791
3929
if (opt_compress || con_compress)
3792
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NULL);
3793
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
3930
mysql_options(&con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
3931
mysql_options(&con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
3932
mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_NAME,
3933
charset_info->csname);
3934
int opt_protocol= MYSQL_PROTOCOL_TCP;
3935
mysql_options(&con_slot->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
3936
if (opt_charsets_dir)
3937
mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
3795
3940
/* Use default db name */
3796
if (ds_database.length() == 0)
3797
ds_database= opt_db;
3941
if (ds_database.length == 0)
3942
dynstr_set(&ds_database, opt_db);
3799
3944
/* Special database to allow one to connect without a database name */
3800
if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
3945
if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
3946
dynstr_set(&ds_database, "");
3803
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()))
3948
if (connect_n_handle_errors(command, &con_slot->mysql,
3949
ds_host.str,ds_user.str,
3950
ds_password.str, ds_database.str,
3951
con_port, ds_sock.str))
3808
if (!(con_slot->name= strdup(ds_connection_name.c_str())))
3953
if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3809
3954
die("Out of memory");
3810
3955
cur_con= con_slot;
3812
3957
if (con_slot == next_con)
3813
3958
next_con++; /* if we used the next_con slot, advance the pointer */
3816
/* Update $drizzle_get_server_version to that of current connection */
3817
var_set_drizzle_get_server_version(&cur_con->drizzle);
3961
/* Update $mysql_get_server_version to that of current connection */
3962
var_set_mysql_get_server_version(&cur_con->mysql);
3964
dynstr_free(&ds_connection_name);
3965
dynstr_free(&ds_host);
3966
dynstr_free(&ds_user);
3967
dynstr_free(&ds_password);
3968
dynstr_free(&ds_database);
3969
dynstr_free(&ds_port);
3970
dynstr_free(&ds_sock);
3971
dynstr_free(&ds_options);
4063
4216
if (end_of_query(c))
4068
4221
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))))
4222
(!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
4223
(uchar*) buf, min(5, p - buf), 0) ||
4224
!my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
4225
(uchar*) buf, min(2, p - buf), 0))))
4074
4227
/* Only if and while commands can be terminated by { */
4079
4232
else if (c == '\'' || c == '"' || c == '`')
4152
4305
/* completed before we pass buf_end */
4153
4306
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)
4313
for (i= 1; i < charlen; i++)
4315
if (feof(cur_file->file))
4317
c= my_getc(cur_file->file);
4320
if (! my_ismbchar(charset_info, mb_start, p))
4322
/* It was not a multiline char, push back the characters */
4323
/* We leave first 'c', i.e. pretend it was a normal char */
4324
while (p > mb_start)
4180
die("The input buffer is too small for this query.x\n" \
4333
die("The input buffer is too small for this query.x\n" \
4181
4334
"check your query or increase MAX_QUERY and recompile");
4454
4607
{"password", 'p', "Password to use when connecting to server.",
4455
4608
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4456
4609
{"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) ").",
4610
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
4611
#if MYSQL_PORT_DEFAULT == 0
4614
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
4459
4615
(char**) &opt_port,
4460
4616
(char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4461
4617
{"quiet", 's', "Suppress all normal output.", (char**) &silent,
4532
4693
if (!embedded_server_arg_count)
4534
4695
embedded_server_arg_count=1;
4535
embedded_server_args[0]= (char*) ""; /* Progname */
4696
embedded_server_args[0]= (char*) ""; /* Progname */
4537
if (!(file=my_fopen(buff, O_RDONLY, MYF(MY_WME))))
4698
if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4538
4699
die("Failed to open file '%s'", buff);
4540
4701
while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4541
(str=fgets(argument,sizeof(argument), file)))
4702
(str=fgets(argument,sizeof(argument), file)))
4543
*(strchr(str, '\0')-1)=0; /* Remove end newline */
4704
*(strend(str)-1)=0; /* Remove end newline */
4544
4705
if (!(embedded_server_args[embedded_server_arg_count]=
4545
(char*) my_strdup(str,MYF(MY_WME))))
4706
(char*) my_strdup(str,MYF(MY_WME))))
4547
4708
my_fclose(file,MYF(0));
4548
4709
die("Out of memory");
4588
4749
static char buff[FN_REFLEN];
4589
4750
if (!test_if_hard_path(argument))
4591
strxmov(buff, opt_basedir, argument, NULL);
4752
strxmov(buff, opt_basedir, argument, NullS);
4592
4753
argument= buff;
4594
4755
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4595
4756
timer_file= buff;
4596
unlink(timer_file); /* Ignore error, may not exist */
4757
unlink(timer_file); /* Ignore error, may not exist */
4763
my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
4603
4764
opt_pass= my_strdup(argument, MYF(MY_FAE));
4604
while (*argument) *argument++= 'x'; /* Destroy argument */
4765
while (*argument) *argument++= 'x'; /* Destroy argument */
4605
4766
tty_password= 0;
4608
4769
tty_password= 1;
4611
my_stpncpy(TMPDIR, argument, sizeof(TMPDIR));
4772
strnmov(TMPDIR, argument, sizeof(TMPDIR));
4614
4775
if (!embedded_server_arg_count)
4784
4945
Values may be converted with 'replace_column'
4787
static void append_result(string *ds, DRIZZLE_RES *res)
4948
static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
4790
uint32_t num_fields= drizzle_num_fields(res);
4791
const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
4951
uint32_t num_fields= mysql_num_fields(res);
4952
MYSQL_FIELD *fields= mysql_fetch_fields(res);
4792
4953
uint32_t *lengths;
4794
while ((row = drizzle_fetch_row(res)))
4955
while ((row = mysql_fetch_row(res)))
4797
lengths = drizzle_fetch_lengths(res);
4958
lengths = mysql_fetch_lengths(res);
4798
4959
for (i = 0; i < num_fields; i++)
4799
4960
append_field(ds, i, &fields[i],
4800
4961
(const char*)row[i], lengths[i], !row[i]);
4801
4962
if (!display_result_vertically)
4963
dynstr_append_mem(ds, "\n", 1);
4809
4969
Append metadata for fields to output
4812
static void append_metadata(string *ds,
4813
const DRIZZLE_FIELD *field,
4972
static void append_metadata(DYNAMIC_STRING *ds,
4814
4974
uint num_fields)
4816
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");
4976
MYSQL_FIELD *field_end;
4977
dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4978
"Column_alias\tType\tLength\tMax length\tIs_null\t"
4979
"Flags\tDecimals\tCharsetnr\n");
4821
4981
for (field_end= field+num_fields ;
4822
4982
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);
4985
dynstr_append_mem(ds, field->catalog,
4986
field->catalog_length);
4987
dynstr_append_mem(ds, "\t", 1);
4988
dynstr_append_mem(ds, field->db, field->db_length);
4989
dynstr_append_mem(ds, "\t", 1);
4990
dynstr_append_mem(ds, field->org_table,
4991
field->org_table_length);
4992
dynstr_append_mem(ds, "\t", 1);
4993
dynstr_append_mem(ds, field->table,
4994
field->table_length);
4995
dynstr_append_mem(ds, "\t", 1);
4996
dynstr_append_mem(ds, field->org_name,
4997
field->org_name_length);
4998
dynstr_append_mem(ds, "\t", 1);
4999
dynstr_append_mem(ds, field->name, field->name_length);
5000
dynstr_append_mem(ds, "\t", 1);
5001
replace_dynstr_append_uint(ds, field->type);
5002
dynstr_append_mem(ds, "\t", 1);
5003
replace_dynstr_append_uint(ds, field->length);
5004
dynstr_append_mem(ds, "\t", 1);
5005
replace_dynstr_append_uint(ds, field->max_length);
5006
dynstr_append_mem(ds, "\t", 1);
5007
dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
5009
dynstr_append_mem(ds, "\t", 1);
5010
replace_dynstr_append_uint(ds, field->flags);
5011
dynstr_append_mem(ds, "\t", 1);
5012
replace_dynstr_append_uint(ds, field->decimals);
5013
dynstr_append_mem(ds, "\t", 1);
5014
replace_dynstr_append_uint(ds, field->charsetnr);
5015
dynstr_append_mem(ds, "\n", 1);
4915
5075
through PS API we should not issue SHOW WARNINGS until
4916
5076
we have not read all results...
4918
assert(!drizzle_more_results(drizzle));
4920
if (drizzle_real_query(drizzle, "SHOW WARNINGS", 13))
4921
die("Error running query \"SHOW WARNINGS\": %s", drizzle_error(drizzle));
4923
if (!(warn_res= drizzle_store_result(drizzle)))
5078
assert(!mysql_more_results(mysql));
5080
if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
5081
die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql));
5083
if (!(warn_res= mysql_store_result(mysql)))
4924
5084
die("Warning count is %u but didn't get any warnings",
4927
5087
append_result(ds, warn_res);
5088
mysql_free_result(warn_res);
4934
Run query using DRIZZLE C API
5095
Run query using MySQL 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
5100
command current command pointer
5101
flags flags indicating if we should SEND and/or REAP
5102
query query string to execute
5103
query_len length query string to execute
5104
ds output buffer where to store result form query
4946
5107
static void run_query_normal(struct st_connection *cn,
4947
5108
struct st_command *command,
4948
5109
int flags, char *query, int query_len,
4949
string *ds, string *ds_warnings)
5110
DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4951
DRIZZLE_RES *res= 0;
4952
DRIZZLE *drizzle= &cn->drizzle;
5113
MYSQL *mysql= &cn->mysql;
4953
5114
int err= 0, counter= 0;
4955
5116
if (flags & QUERY_SEND_FLAG)
4960
5121
if (do_send_query(cn, query, query_len, flags))
4962
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4963
drizzle_sqlstate(drizzle), ds);
5123
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
5124
mysql_sqlstate(mysql), ds);
5128
#ifdef EMBEDDED_LIBRARY
5130
Here we handle 'reap' command, so we need to check if the
5131
query's thread was finished and probably wait
5133
else if (flags & QUERY_REAP_FLAG)
5134
wait_query_thread_end(cn);
5135
#endif /*EMBEDDED_LIBRARY*/
4967
5136
if (!(flags & QUERY_REAP_FLAG))
4973
When on first result set, call drizzle_read_query_result to retrieve
5142
When on first result set, call mysql_read_query_result to retrieve
4974
5143
answer to the query sent earlier
4976
if ((counter==0) && drizzle_read_query_result(drizzle))
5145
if ((counter==0) && mysql_read_query_result(mysql))
4978
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4979
drizzle_sqlstate(drizzle), ds);
5147
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
5148
mysql_sqlstate(mysql), ds);
5000
const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
5001
uint num_fields= drizzle_num_fields(res);
5169
MYSQL_FIELD *fields= mysql_fetch_fields(res);
5170
uint num_fields= mysql_num_fields(res);
5003
if (display_metadata)
5172
if (display_metadata)
5004
5173
append_metadata(ds, fields, num_fields);
5006
if (!display_result_vertically)
5007
append_table_headings(ds, fields, num_fields);
5175
if (!display_result_vertically)
5176
append_table_headings(ds, fields, num_fields);
5009
append_result(ds, res);
5178
append_result(ds, res);
5013
Need to call drizzle_affected_rows() before the "new"
5182
Need to call mysql_affected_rows() before the "new"
5014
5183
query to find the warnings
5016
5185
if (!disable_info)
5017
affected_rows= drizzle_affected_rows(drizzle);
5186
affected_rows= mysql_affected_rows(mysql);
5020
5189
Add all warnings to the result. We can't do this if we are in
5021
5190
the middle of processing results from multi-statement, because
5022
5191
this will break protocol.
5024
if (!disable_warnings && !drizzle_more_results(drizzle))
5193
if (!disable_warnings && !mysql_more_results(mysql))
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());
5195
if (append_warnings(ds_warnings, mysql) || ds_warnings->length)
5197
dynstr_append_mem(ds, "Warnings:\n", 10);
5198
dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
5033
5202
if (!disable_info)
5034
append_info(ds, affected_rows, drizzle_info(drizzle));
5203
append_info(ds, affected_rows, mysql_info(mysql));
5039
drizzle_free_result(res);
5208
mysql_free_result(res);
5043
} while (!(err= drizzle_next_result(drizzle)));
5212
} while (!(err= mysql_next_result(mysql)));
5046
/* We got an error from drizzle_next_result, maybe expected */
5047
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5048
drizzle_sqlstate(drizzle), ds);
5215
/* We got an error from mysql_next_result, maybe expected */
5216
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
5217
mysql_sqlstate(mysql), ds);
5051
5220
assert(err == -1); /* Successful and there are no more results */
5121
5291
if (command->expected_errors.count == 1)
5123
5293
/* 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);
5294
dynstr_append_mem(ds, "ERROR ", 6);
5295
replace_dynstr_append(ds, err_sqlstate);
5296
dynstr_append_mem(ds, ": ", 2);
5297
replace_dynstr_append(ds, err_error);
5298
dynstr_append_mem(ds,"\n",1);
5130
5300
/* Don't log error if we may not get an error */
5131
5301
else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5132
5302
(command->expected_errors.err[0].type == ERR_ERRNO &&
5133
5303
command->expected_errors.err[0].code.errnum != 0))
5134
ds->append("Got one of the listed errors\n");
5304
dynstr_append(ds,"Got one of the listed errors\n");
5205
drizzle DRIZZLE handle
5206
command currrent command pointer
5376
command currrent command pointer
5208
5378
flags control the phased/stages of query execution to be performed
5209
5379
if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
5210
5380
is on the result will be read - for regular query, both bits must be on
5213
static void run_query(struct st_connection *cn,
5383
static void run_query(struct st_connection *cn,
5214
5384
struct st_command *command,
5218
string *save_ds= NULL;
5388
DYNAMIC_STRING *save_ds= NULL;
5389
DYNAMIC_STRING ds_result;
5390
DYNAMIC_STRING ds_sorted;
5391
DYNAMIC_STRING ds_warnings;
5392
DYNAMIC_STRING eval_query;
5397
init_dynamic_string(&ds_warnings, NULL, 0, 256);
5227
5399
/* Scan for warning before sending to server */
5228
5400
scan_command_for_warnings(command);
5251
5424
if (command->require_file[0])
5426
init_dynamic_string(&ds_result, "", 1024, 1024);
5253
5427
ds= &ds_result;
5260
5433
Log the query into the output buffer
5262
5435
if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5264
replace_append_mem(ds, query, query_len);
5265
ds->append(delimiter, delimiter_length);
5437
replace_dynstr_append_mem(ds, query, query_len);
5438
dynstr_append_mem(ds, delimiter, delimiter_length);
5439
dynstr_append_mem(ds, "\n", 1);
5269
5442
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
5445
Collect the query output in a separate string
5446
that can be sorted before it's added to the
5447
global result string
5449
init_dynamic_string(&ds_sorted, "", 1024, 1024);
5276
5450
save_ds= ds; /* Remember original ds */
5277
5451
ds= &ds_sorted;
5404
5584
/* Milliseconds since start */
5405
5585
end= int64_t2str(timer, buf, 10);
5406
ds_progress.append(buf, (int)(end-buf));
5407
ds_progress.append("\t", 1);
5586
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5587
dynstr_append_mem(&ds_progress, "\t", 1);
5409
5589
/* Parser line number */
5410
5590
end= int10_to_str(line, buf, 10);
5411
ds_progress.append(buf, (int)(end-buf));
5412
ds_progress.append("\t", 1);
5591
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5592
dynstr_append_mem(&ds_progress, "\t", 1);
5415
ds_progress.append(cur_file->file_name);
5416
ds_progress.append(":", 1);
5595
dynstr_append(&ds_progress, cur_file->file_name);
5596
dynstr_append_mem(&ds_progress, ":", 1);
5418
5598
/* Line in file */
5419
5599
end= int10_to_str(cur_file->lineno, buf, 10);
5420
ds_progress.append(buf, (int)(end-buf));
5423
ds_progress.append("\n", 1);
5600
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5603
dynstr_append_mem(&ds_progress, "\n", 1);
5487
5678
cur_file->lineno= 1;
5489
5680
cur_con= connections;
5490
if (!( drizzle_create(&cur_con->drizzle)))
5491
die("Failed in drizzle_create()");
5681
if (!( mysql_init(&cur_con->mysql)))
5682
die("Failed in mysql_init()");
5492
5683
if (opt_compress)
5493
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
5494
drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
5684
mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS);
5685
mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
5686
mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME,
5687
charset_info->csname);
5688
int opt_protocol= MYSQL_PROTOCOL_TCP;
5689
mysql_options(&cur_con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
5690
if (opt_charsets_dir)
5691
mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR,
5496
5694
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5497
5695
die("Out of memory");
5499
safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
5697
safe_connect(&cur_con->mysql, cur_con->name, opt_host, opt_user, opt_pass,
5500
5698
opt_db, opt_port);
5502
5700
/* Use all time until exit if no explicit 'start_timer' */
5503
5701
timer_start= timer_now();
5506
Initialize $drizzle_errno with -1, so we can
5704
Initialize $mysql_errno with -1, so we can
5507
5705
- distinguish it from valid values ( >= 0 ) and
5508
5706
- detect if there was never a command sent to the server
5510
5708
var_set_errno(-1);
5512
/* Update $drizzle_get_server_version to that of current connection */
5513
var_set_drizzle_get_server_version(&cur_con->drizzle);
5710
/* Update $mysql_get_server_version to that of current connection */
5711
var_set_mysql_get_server_version(&cur_con->mysql);
5515
5713
if (opt_include)
5656
5852
/* Remove "send" if this is first iteration */
5657
if (command->query == command->query_buf)
5658
command->query= command->first_argument;
5853
if (command->query == command->query_buf)
5854
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
5857
run_query() can execute a query partially, depending on the flags.
5858
QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5663
5859
the query and read the result some time later when reap instruction
5664
is given on this connection.
5860
is given on this connection.
5666
run_query(cur_con, command, QUERY_SEND_FLAG);
5862
run_query(cur_con, command, QUERY_SEND_FLAG);
5668
5864
command->last_argument= command->end;
5670
5866
case Q_REQUIRE:
5671
do_get_file_name(command, save_file, sizeof(save_file));
5867
do_get_file_name(command, save_file, sizeof(save_file));
5674
5870
do_get_errcodes(command);
5676
5872
case Q_REPLACE:
5677
do_get_replace(command);
5873
do_get_replace(command);
5679
5875
case Q_REPLACE_REGEX:
5680
5876
do_get_replace_regex(command);
5682
5878
case Q_REPLACE_COLUMN:
5683
do_get_replace_column(command);
5879
do_get_replace_column(command);
5685
5881
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5686
5882
case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5687
5883
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);
5885
do_save_master_pos();
5886
if (*command->first_argument)
5887
select_connection(command);
5889
select_connection_name("slave");
5890
do_sync_with_master2(0);
5697
case Q_COMMENT: /* Ignore row */
5893
case Q_COMMENT: /* Ignore row */
5698
5894
command->last_argument= command->end;
5701
(void) drizzle_ping(&cur_con->drizzle);
5897
(void) mysql_ping(&cur_con->mysql);
5707
5903
case Q_START_TIMER:
5708
/* Overwrite possible earlier start of timer */
5709
timer_start= timer_now();
5904
/* Overwrite possible earlier start of timer */
5905
timer_start= timer_now();
5711
5907
case Q_END_TIMER:
5712
/* End timer before ending drizzletest */
5908
/* End timer before ending mysqltest */
5715
5911
case Q_CHARACTER_SET:
5716
do_set_charset(command);
5912
do_set_charset(command);
5718
5914
case Q_DISABLE_RECONNECT:
5719
set_reconnect(&cur_con->drizzle, 0);
5915
set_reconnect(&cur_con->mysql, 0);
5721
5917
case Q_ENABLE_RECONNECT:
5722
set_reconnect(&cur_con->drizzle, 1);
5918
set_reconnect(&cur_con->mysql, 1);
5724
5920
case Q_DISABLE_PARSING:
5725
5921
if (parsing_disabled == 0)
5972
6168
/* Definitions for replace result */
5974
typedef struct st_pointer_array { /* when using array-strings */
5975
TYPELIB typelib; /* Pointer to strings */
5976
unsigned char *str; /* Strings is here */
5977
uint8_t *flag; /* Flag about each var. */
5978
uint array_allocs,max_count,length,max_length;
6170
typedef struct st_pointer_array { /* when using array-strings */
6171
TYPELIB typelib; /* Pointer to strings */
6172
uchar *str; /* Strings is here */
6173
int7 *flag; /* Flag about each var. */
6174
uint array_allocs,max_count,length,max_length;
5979
6175
} POINTER_ARRAY;
5981
6177
struct st_replace;
5982
6178
struct st_replace *init_replace(char * *from, char * *to, uint count,
5983
char * word_end_chars);
6179
char * word_end_chars);
5984
6180
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5985
void replace_strings_append(struct st_replace *rep, string* ds,
6181
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5986
6182
const char *from, int len);
5987
6183
void free_pointer_array(POINTER_ARRAY *pa);
6080
6277
/* Loop through states */
6081
6278
while (!rep_pos->found)
6082
rep_pos= rep_pos->next[(unsigned char) *from++];
6279
rep_pos= rep_pos->next[(uchar) *from++];
6084
6281
/* Does this state contain a string to be replaced */
6085
6282
if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6087
6284
/* No match found */
6088
ds->append(start, from - start - 1);
6285
dynstr_append_mem(ds, start, from - start - 1);
6092
6289
/* Append part of original string before replace string */
6093
ds->append(start, (from - rep_str->to_offset) - start);
6290
dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6095
6292
/* Append replace string */
6096
ds->append(rep_str->replace_string,
6097
strlen(rep_str->replace_string));
6293
dynstr_append_mem(ds, rep_str->replace_string,
6294
strlen(rep_str->replace_string));
6099
6296
if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6416
6613
#define LAST_CHAR_CODE 259
6418
6615
typedef struct st_rep_set {
6419
uint *bits; /* Pointer to used sets */
6420
short next[LAST_CHAR_CODE]; /* Pointer to next sets */
6421
uint found_len; /* Best match to date */
6424
uint size_of_bits; /* For convinience */
6616
uint *bits; /* Pointer to used sets */
6617
short next[LAST_CHAR_CODE]; /* Pointer to next sets */
6618
uint found_len; /* Best match to date */
6621
uint size_of_bits; /* For convinience */
6427
6624
typedef struct st_rep_sets {
6428
uint count; /* Number of sets */
6429
uint extra; /* Extra sets in buffer */
6430
uint invisible; /* Sets not chown */
6432
REP_SET *set,*set_buffer;
6625
uint count; /* Number of sets */
6626
uint extra; /* Extra sets in buffer */
6627
uint invisible; /* Sets not chown */
6629
REP_SET *set,*set_buffer;
6436
6633
typedef struct st_found_set {
6513
6710
if (len > max_length)
6514
6711
max_length=len;
6516
memset(is_word_end, 0, sizeof(is_word_end));
6713
bzero((char*) is_word_end,sizeof(is_word_end));
6517
6714
for (i=0 ; word_end_chars[i] ; i++)
6518
is_word_end[(unsigned char) word_end_chars[i]]=1;
6715
is_word_end[(uchar) word_end_chars[i]]=1;
6520
6717
if (init_sets(&sets,states))
6523
6720
if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
6526
6723
free_sets(&sets);
6529
make_new_set(&sets); /* Set starting set */
6530
make_sets_invisible(&sets); /* Hide previus sets */
6726
VOID(make_new_set(&sets)); /* Set starting set */
6727
make_sets_invisible(&sets); /* Hide previus sets */
6532
word_states=make_new_set(&sets); /* Start of new word */
6533
start_states=make_new_set(&sets); /* This is first state */
6729
word_states=make_new_set(&sets); /* Start of new word */
6730
start_states=make_new_set(&sets); /* This is first state */
6534
6731
if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6536
6733
free_sets(&sets);
6734
my_free(found_set,MYF(0));
6546
6743
internal_set_bit(start_states,states+1);
6547
6744
if (!from[i][2])
6549
start_states->table_offset=i;
6550
start_states->found_offset=1;
6746
start_states->table_offset=i;
6747
start_states->found_offset=1;
6553
6750
else if (from[i][0] == '\\' && from[i][1] == '$')
6555
6752
internal_set_bit(start_states,states);
6556
6753
internal_set_bit(word_states,states);
6557
if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6754
if (!from[i][2] && start_states->table_offset == (uint) ~0)
6559
start_states->table_offset=i;
6560
start_states->found_offset=0;
6756
start_states->table_offset=i;
6757
start_states->found_offset=0;
6565
6762
internal_set_bit(word_states,states);
6566
6763
if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6567
internal_set_bit(start_states,states+1);
6764
internal_set_bit(start_states,states+1);
6569
internal_set_bit(start_states,states);
6766
internal_set_bit(start_states,states);
6571
6768
for (pos=from[i], len=0; *pos ; pos++)
6573
6770
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;
6775
follow_ptr->chr = SPACE_CHAR;
6778
follow_ptr->chr = START_OF_LINE;
6781
follow_ptr->chr = END_OF_LINE;
6784
follow_ptr->chr = '\r';
6787
follow_ptr->chr = '\t';
6790
follow_ptr->chr = '\v';
6793
follow_ptr->chr = (uchar) *pos;
6601
follow_ptr->chr= (unsigned char) *pos;
6798
follow_ptr->chr= (uchar) *pos;
6602
6799
follow_ptr->table_offset=i;
6603
6800
follow_ptr->len= ++len;
6614
6811
for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6616
6813
set=sets.set+set_nr;
6617
default_state= 0; /* Start from beginning */
6814
default_state= 0; /* Start from beginning */
6619
6816
/* If end of found-string not found or start-set with current set */
6621
for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6818
for (i= (uint) ~0; (i=get_next_bit(set,i)) ;)
6623
6820
if (!follow[i].chr)
6625
if (! default_state)
6626
default_state= find_found(found_set,set->table_offset,
6627
set->found_offset+1);
6822
if (! default_state)
6823
default_state= find_found(found_set,set->table_offset,
6824
set->found_offset+1);
6630
copy_bits(sets.set+used_sets,set); /* Save set for changes */
6827
copy_bits(sets.set+used_sets,set); /* Save set for changes */
6631
6828
if (!default_state)
6632
or_bits(sets.set+used_sets,sets.set); /* Can restart from start */
6829
or_bits(sets.set+used_sets,sets.set); /* Can restart from start */
6634
6831
/* Find all chars that follows current sets */
6635
memset(used_chars, 0, sizeof(used_chars));
6636
for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6832
bzero((char*) used_chars,sizeof(used_chars));
6833
for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6638
6835
used_chars[follow[i].chr]=1;
6639
6836
if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6640
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6837
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6644
6841
/* Mark word_chars used if \b is in state */
6645
6842
if (used_chars[SPACE_CHAR])
6646
6843
for (pos= word_end_chars ; *pos ; pos++)
6647
used_chars[(int) (unsigned char) *pos] = 1;
6844
used_chars[(int) (uchar) *pos] = 1;
6649
6846
/* Handle other used characters */
6650
6847
for (chr= 0 ; chr < 256 ; chr++)
6652
6849
if (! used_chars[chr])
6653
set->next[chr]= chr ? default_state : -1;
6850
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;
6853
new_set=make_new_set(&sets);
6854
set=sets.set+set_nr; /* if realloc */
6855
new_set->table_offset=set->table_offset;
6856
new_set->found_len=set->found_len;
6857
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);
6860
for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6862
if (!follow[i].chr || follow[i].chr == chr ||
6863
(follow[i].chr == SPACE_CHAR &&
6864
(is_word_end[chr] ||
6865
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6866
(follow[i].chr == END_OF_LINE && ! chr))
6868
if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6869
follow[i].len > found_end)
6870
found_end=follow[i].len;
6871
if (chr && follow[i].chr)
6872
internal_set_bit(new_set,i+1); /* To next set */
6874
internal_set_bit(new_set,i);
6879
new_set->found_len=0; /* Set for testing if first */
6881
for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
6883
if ((follow[i].chr == SPACE_CHAR ||
6884
follow[i].chr == END_OF_LINE) && ! chr)
6888
if (follow[bit_nr-1].len < found_end ||
6889
(new_set->found_len &&
6890
(chr == 0 || !follow[bit_nr].chr)))
6891
internal_clear_bit(new_set,i);
6894
if (chr == 0 || !follow[bit_nr].chr)
6896
new_set->table_offset=follow[bit_nr].table_offset;
6897
if (chr || (follow[i].chr == SPACE_CHAR ||
6898
follow[i].chr == END_OF_LINE))
6899
new_set->found_offset=found_end; /* New match */
6900
new_set->found_len=found_end;
6907
set->next[chr] = find_found(found_set,
6908
new_set->table_offset,
6909
new_set->found_offset);
6910
free_last_set(&sets);
6913
set->next[chr] = find_set(&sets,new_set);
6916
set->next[chr] = find_set(&sets,new_set);
6734
6931
for (i=0 ; i < count ; i++)
6736
6933
to_array[i]=to_pos;
6737
to_pos=my_stpcpy(to_pos,to[i])+1;
6934
to_pos=strmov(to_pos,to[i])+1;
6739
6936
rep_str[0].found=1;
6740
6937
rep_str[0].replace_string=0;
6741
6938
for (i=1 ; i <= found_sets ; i++)
6743
6940
pos=from[found_set[i-1].table_offset];
6744
rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
6941
rep_str[i].found= !bcmp((const uchar*) pos,
6942
(const uchar*) "\\^", 3) ? 2 : 1;
6745
6943
rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
6746
6944
rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
6747
6945
rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6750
6948
for (i=0 ; i < sets.count ; i++)
6752
6950
for (j=0 ; j < 256 ; j++)
6753
if (sets.set[i].next[j] >= 0)
6754
replace[i].next[j]=replace+sets.set[i].next[j];
6756
replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6951
if (sets.set[i].next[j] >= 0)
6952
replace[i].next[j]=replace+sets.set[i].next[j];
6954
replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6957
my_free(follow,MYF(0));
6760
6958
free_sets(&sets);
6959
my_free(found_set,MYF(0));
6762
6960
return(replace);
6766
6964
int init_sets(REP_SETS *sets,uint states)
6768
memset(sets, 0, sizeof(*sets));
6966
bzero((char*) sets,sizeof(*sets));
6769
6967
sets->size_of_bits=((states+7)/8);
6770
6968
if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
6773
6971
if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
6774
SET_MALLOC_HUNC,MYF(MY_WME))))
6972
SET_MALLOC_HUNC,MYF(MY_WME))))
6974
my_free(sets->set,MYF(0));
6798
6996
set=sets->set+ sets->count++;
6799
memset(set->bits, 0, sizeof(uint)*sets->size_of_bits);
6800
memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
6997
bzero((char*) set->bits,sizeof(uint)*sets->size_of_bits);
6998
bzero((char*) &set->next[0],sizeof(set->next[0])*LAST_CHAR_CODE);
6801
6999
set->found_offset=0;
6802
7000
set->found_len=0;
6803
set->table_offset= UINT32_MAX;
7001
set->table_offset= (uint) ~0;
6804
7002
set->size_of_bits=sets->size_of_bits;
6807
7005
count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6808
if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
7006
if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6809
7007
sizeof(REP_SET)*count,
6812
7010
sets->set_buffer=set;
6813
7011
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,
7012
if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
7013
(sizeof(uint)*sets->size_of_bits)*count,
6818
7016
sets->bit_buffer=bit_buffer;
6819
7017
for (i=0 ; i < count ; i++)
6926
7125
for (i=0 ; (uint) i < found_sets ; i++)
6927
7126
if (found_set[i].table_offset == table_offset &&
6928
found_set[i].found_offset == found_offset)
7127
found_set[i].found_offset == found_offset)
6930
7129
found_set[i].table_offset=table_offset;
6931
7130
found_set[i].found_offset=found_offset;
6933
return -i-2; /* return new postion */
7132
return -i-2; /* return new postion */
6936
7135
/* Return 1 if regexp starts with \b or ends with \b*/
6938
7137
uint start_at_word(char * pos)
6940
return (((!memcmp(pos, "\\b",2) && pos[2]) ||
6941
!memcmp(pos, "\\^", 2)) ? 1 : 0);
7139
return (((!bcmp((const uchar*) pos, (const uchar*) "\\b",2) && pos[2]) ||
7140
!bcmp((const uchar*) pos, (const uchar*) "\\^", 2)) ? 1 : 0);
6944
7143
uint end_of_word(char * pos)
6946
char * end= strchr(pos, '\0');
6947
return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
6948
(end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7145
char * end=strend(pos);
7146
return ((end > pos+2 && !bcmp((const uchar*) end-2,
7147
(const uchar*) "\\b", 2)) ||
7148
(end >= pos+2 && !bcmp((const uchar*) end-2,
7149
(const uchar*) "\\$",2))) ? 1 : 0;
6951
7152
/****************************************************************************
6952
7153
* Handle replacement of strings
6953
7154
****************************************************************************/
6955
#define PC_MALLOC 256 /* Bytes for pointers */
6956
#define PS_MALLOC 512 /* Bytes for data */
7156
#define PC_MALLOC 256 /* Bytes for pointers */
7157
#define PS_MALLOC 512 /* Bytes for data */
6958
7159
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6960
7161
uint i,length,old_count;
6961
unsigned char *new_pos;
6962
7163
const char **new_array;
6965
7166
if (! pa->typelib.count)
6967
7168
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))))
7169
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7170
(sizeof(char *)+sizeof(*pa->flag))*
7171
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6972
if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
7173
if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
6975
free((char*) pa->typelib.type_names);
7176
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);
7179
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7181
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6982
7183
pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6983
7184
pa->array_allocs=1;
7005
7206
pa->array_allocs++;
7006
7207
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)),
7208
if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
7210
(sizeof(uchar*)+sizeof(*pa->flag))*
7211
(sizeof(uchar*)+sizeof(*pa->flag)),
7013
7214
pa->typelib.type_names=new_array;
7014
7215
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);
7017
memcpy(pa->flag, pa->typelib.type_names+old_count,
7018
old_count*sizeof(*pa->flag));
7216
pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
7217
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7218
memcpy((uchar*) pa->flag,(char *) (pa->typelib.type_names+old_count),
7219
old_count*sizeof(*pa->flag));
7020
pa->flag[pa->typelib.count]=0; /* Reset flag */
7221
pa->flag[pa->typelib.count]=0; /* Reset flag */
7021
7222
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);
7223
pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
7224
VOID(strmov((char*) pa->str+pa->length,name));
7024
7225
pa->length+=length;
7026
7227
} /* insert_pointer_name */
7043
7244
/* Functions that uses replace and replace_regex */
7045
7246
/* Append the string to ds, with optional replace */
7046
void replace_append_mem(string *ds,
7047
const char *val, int len)
7247
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
7248
const char *val, int len)
7049
char *v= strdup(val);
7051
7250
if (glob_replace_regex)
7053
7252
/* Regex replace */
7054
if (!multi_reg_replace(glob_replace_regex, v))
7253
if (!multi_reg_replace(glob_replace_regex, (char*)val))
7056
v= glob_replace_regex->buf;
7255
val= glob_replace_regex->buf;
7061
7260
if (glob_replace)
7063
7262
/* Normal replace */
7064
replace_strings_append(glob_replace, ds, v, len);
7263
replace_strings_append(glob_replace, ds, val, len);
7266
dynstr_append_mem(ds, val, len);
7073
7270
/* Append zero-terminated string to ds, with optional replace */
7074
void replace_append(string *ds, const char *val)
7271
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7076
replace_append_mem(ds, val, strlen(val));
7273
replace_dynstr_append_mem(ds, val, strlen(val));
7079
7276
/* Append uint to ds, with optional replace */
7080
void replace_append_uint(string *ds, uint val)
7277
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7082
7279
char buff[22]; /* This should be enough for any int */
7083
7280
char *end= int64_t10_to_str(val, buff, 10);
7084
replace_append_mem(ds, buff, end - buff);
7281
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())
7298
static int comp_lines(const char **a, const char **b)
7300
return (strcmp(*a,*b));
7303
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
7306
char *start= ds_input->str;
7307
DYNAMIC_ARRAY lines;
7108
7311
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;
7313
my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
7315
/* First line is result header, skip past it */
7316
while (*start && *start != '\n')
7318
start++; /* Skip past \n */
7319
dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
7120
7321
/* Insert line(s) in array */
7324
char* line_end= (char*)start;
7123
eol_pos= ds_input->find_first_of('\n', start_pos);
7124
7326
/* 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);
7327
while (*line_end && *line_end != '\n')
7331
/* Insert pointer to the line in array */
7332
if (insert_dynamic(&lines, (uchar*) &start))
7333
die("Out of memory inserting lines to sort");
7339
qsort(lines.buffer, lines.elements,
7340
sizeof(char**), (qsort_cmp)comp_lines);
7130
7342
/* Create new result */
7131
while (!lines.empty()) {
7132
ds->append(lines.top());
7343
for (i= 0; i < lines.elements ; i++)
7345
const char **line= dynamic_element(&lines, i, const char**);
7346
dynstr_append(ds, *line);
7347
dynstr_append(ds, "\n");
7350
delete_dynamic(&lines);