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!
188
187
struct st_connection
191
190
/* Used when creating views and sp, to avoid implicit commit */
192
DRIZZLE *util_drizzle;
195
194
struct st_connection connections[128];
196
195
struct st_connection* cur_con= NULL, *next_con, *connections_end;
199
List of commands in drizzletest
198
List of commands in mysqltest
200
199
Must match the "command_names" array
201
200
Add new commands before Q_UNKNOWN!
203
202
enum enum_commands {
204
203
Q_CONNECTION=1, Q_QUERY,
205
Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
207
Q_SOURCE, Q_DISCONNECT,
209
Q_WHILE, Q_END_BLOCK,
211
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,
212
211
Q_SYNC_WITH_MASTER,
213
212
Q_SYNC_SLAVE_WITH_MASTER,
216
Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
215
Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
219
218
Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
220
219
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
370
369
TYPELIB command_typelib= {array_elements(command_names),"",
373
string ds_res, ds_progress, ds_warning_messages;
372
DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
375
374
char builtin_echo[FN_REFLEN];
377
376
void die(const char *fmt, ...)
378
__attribute__((format(printf, 1, 2)));
377
ATTRIBUTE_FORMAT(printf, 1, 2);
379
378
void abort_not_supported_test(const char *fmt, ...)
380
__attribute__((format(printf, 1, 2)));
379
ATTRIBUTE_FORMAT(printf, 1, 2);
381
380
void verbose_msg(const char *fmt, ...)
382
__attribute__((format(printf, 1, 2)));
381
ATTRIBUTE_FORMAT(printf, 1, 2);
383
382
void warning_msg(const char *fmt, ...)
384
__attribute__((format(printf, 1, 2)));
383
ATTRIBUTE_FORMAT(printf, 1, 2);
385
384
void log_msg(const char *fmt, ...)
386
__attribute__((format(printf, 1, 2)));
385
ATTRIBUTE_FORMAT(printf, 1, 2);
388
387
VAR* var_from_env(const char *, const char *);
389
388
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
394
393
void eval_expr(VAR* v, const char *p, const char** p_end);
395
394
bool match_delimiter(int c, const char *delim, uint length);
396
395
void dump_result_to_reject_file(char *buf, int size);
397
void dump_result_to_log_file(const char *buf, int size);
396
void dump_result_to_log_file(char *buf, int size);
398
397
void dump_warning_messages(void);
399
398
void dump_progress(void);
401
void do_eval(string *query_eval, const char *query,
400
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
402
401
const char *query_end, bool pass_through_escape_chars);
403
void str_to_file(const char *fname, const char *str, int size);
404
void str_to_file2(const char *fname, const char *str, int size, bool append);
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);
406
405
/* For replace_column */
407
406
static char *replace_column[MAX_COLUMNS];
427
426
free_replace_column();
430
void replace_append_mem(string *ds, const char *val,
432
void replace_append(string *ds, const char *val);
433
void replace_append_uint(string *ds, uint val);
434
void append_sorted(string* ds, string* ds_input);
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);
436
435
void handle_error(struct st_command*,
437
436
unsigned int err_errno, const char *err_error,
438
const char *err_sqlstate, string *ds);
437
const char *err_sqlstate, DYNAMIC_STRING *ds);
439
438
void handle_no_error(struct st_command*);
442
#define do_send_query(cn,q,q_len,flags) drizzle_send_query(&cn->drizzle, q, q_len)
444
void do_eval(string *query_eval, const char *query,
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,
445
507
const char *query_end, bool pass_through_escape_chars)
460
query_eval->append(p, 1);
522
dynstr_append_mem(query_eval, p, 1);
464
if (!(v= var_get(p, &p, 0, 0)))
465
die("Bad variable in eval");
466
query_eval->append(v->str_val, v->str_val_len);
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);
474
query_eval->append(p, 1);
536
dynstr_append_mem(query_eval, p, 1);
476
538
else if (next_c == '\\' || next_c == '$' || next_c == '"')
478
540
/* Set escaped only if next char is \, " or $ */
481
543
if (pass_through_escape_chars)
483
545
/* The escape char should be added to the output string. */
484
query_eval->append(p, 1);
546
dynstr_append_mem(query_eval, p, 1);
488
query_eval->append(p, 1);
550
dynstr_append_mem(query_eval, p, 1);
492
query_eval->append(p, 1);
554
dynstr_append_mem(query_eval, p, 1);
501
Concatenates any number of strings, escapes any OS quote in the result then
502
surround the whole affair in another set of quotes which is finally appended
503
to specified string. This function is especially useful when
504
building strings to be executed with the system() function.
506
@param str string which will have addtional strings appended.
507
@param append string to be appended.
508
@param ... Optional. Additional string(s) to be appended.
510
@note The final argument in the list must be NULL even if no additional
514
void append_os_quoted(string *str, const char *append, ...)
516
const char *quote_str= "\'";
517
const uint quote_len= 1;
521
str->append(quote_str, quote_len); /* Leading quote */
522
va_start(dirty_text, append);
523
while (append != NULL)
525
const char *cur_pos= append;
526
const char *next_pos= cur_pos;
528
/* Search for quote in each string and replace with escaped quote */
529
while((next_pos= strrchr(cur_pos, quote_str[0])) != NULL)
531
str->append(cur_pos, next_pos - cur_pos);
532
str->append("\\", 1);
533
str->append(quote_str, quote_len);
534
cur_pos= next_pos + 1;
536
str->append(cur_pos, next_pos - cur_pos);
537
append= va_arg(dirty_text, char *);
540
str->append(quote_str, quote_len); /* Trailing quote */
545
563
Run query and dump the result to stdout in vertical format
547
565
NOTE! This function should be safe to call when an error
552
drizzle - connection to use
570
mysql - connection to use
553
571
query - query to run
557
static void show_query(DRIZZLE *drizzle, const char* query)
575
static void show_query(MYSQL* mysql, const char* query)
565
if (drizzle_query(drizzle, query))
583
if (mysql_query(mysql, query))
567
585
log_msg("Error running query '%s': %d %s",
568
query, drizzle_errno(drizzle), drizzle_error(drizzle));
586
query, mysql_errno(mysql), mysql_error(mysql));
572
if ((res= drizzle_store_result(drizzle)) == NULL)
590
if ((res= mysql_store_result(mysql)) == NULL)
574
592
/* No result set returned */
581
599
unsigned int row_num= 0;
582
unsigned int num_fields= drizzle_num_fields(res);
583
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);
585
603
fprintf(stderr, "=== %s ===\n", query);
586
while ((row= drizzle_fetch_row(res)))
604
while ((row= mysql_fetch_row(res)))
588
uint32_t *lengths= drizzle_fetch_lengths(res);
606
uint32_t *lengths= mysql_fetch_lengths(res);
591
609
fprintf(stderr, "---- %d. ----\n", row_num);
617
635
show_warnings_before_error
618
drizzle - connection to use
636
mysql - connection to use
622
static void show_warnings_before_error(DRIZZLE *drizzle)
640
static void show_warnings_before_error(MYSQL* mysql)
625
643
const char* query= "SHOW WARNINGS";
631
if (drizzle_query(drizzle, query))
649
if (mysql_query(mysql, query))
633
651
log_msg("Error running query '%s': %d %s",
634
query, drizzle_errno(drizzle), drizzle_error(drizzle));
652
query, mysql_errno(mysql), mysql_error(mysql));
638
if ((res= drizzle_store_result(drizzle)) == NULL)
656
if ((res= mysql_store_result(mysql)) == NULL)
640
658
/* No result set returned */
644
if (drizzle_num_rows(res) <= 1)
662
if (mysql_num_rows(res) <= 1)
646
664
/* Don't display the last row, it's "last error" */
651
669
unsigned int row_num= 0;
652
unsigned int num_fields= drizzle_num_fields(res);
670
unsigned int num_fields= mysql_num_fields(res);
654
672
fprintf(stderr, "\nWarnings from just before the error:\n");
655
while ((row= drizzle_fetch_row(res)))
673
while ((row= mysql_fetch_row(res)))
658
uint32_t *lengths= drizzle_fetch_lengths(res);
676
uint32_t *lengths= mysql_fetch_lengths(res);
660
if (++row_num >= drizzle_num_rows(res))
678
if (++row_num >= mysql_num_rows(res))
662
680
/* Don't display the last row, it's "last error" */
835
855
hash_free(&var_hash);
837
vector<struct st_command *>::iterator iter;
838
for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
857
for (i= 0 ; i < q_lines.elements ; i++)
840
struct st_command * q_line= *(iter.base());
841
if (q_line->query_buf != NULL)
843
free(q_line->query_buf);
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));
848
863
for (i= 0; i < 10; i++)
850
865
if (var_reg[i].alloced_len)
851
free(var_reg[i].str_val);
866
my_free(var_reg[i].str_val, MYF(MY_WME));
853
868
while (embedded_server_arg_count > 1)
854
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);
856
874
free_all_replace();
875
my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
858
876
free_defaults(default_argv);
878
/* Only call mysql_server_end if mysql_server_init has been called */
879
if (server_initialized)
921
943
/* Show results from queries just before failure */
922
if (ds_res.length() && opt_tail_lines)
944
if (ds_res.length && opt_tail_lines)
924
946
int tail_lines= opt_tail_lines;
925
const char* show_from= ds_res.c_str() + ds_res.length() - 1;
926
while(show_from > ds_res.c_str() && tail_lines > 0 )
947
char* show_from= ds_res.str + ds_res.length - 1;
948
while(show_from > ds_res.str && tail_lines > 0 )
929
951
if (*show_from == '\n')
932
954
fprintf(stderr, "\nThe result from queries just before the failure was:\n");
933
if (show_from > ds_res.c_str())
955
if (show_from > ds_res.str)
934
956
fprintf(stderr, "< snip >");
935
957
fprintf(stderr, "%s", show_from);
939
961
/* Dump the result that has been accumulated so far to .log file */
940
if (result_file_name && ds_res.length())
941
dump_result_to_log_file(ds_res.c_str(), ds_res.length());
962
if (result_file_name && ds_res.length)
963
dump_result_to_log_file(ds_res.str, ds_res.length);
943
965
/* Dump warning messages */
944
if (result_file_name && ds_warning_messages.length())
966
if (result_file_name && ds_warning_messages.length)
945
967
dump_warning_messages();
1020
1042
va_start(args, fmt);
1021
ds_warning_messages.append("drizzletest: ");
1043
dynstr_append(&ds_warning_messages, "mysqltest: ");
1022
1044
if (start_lineno != 0)
1024
ds_warning_messages.append("Warning detected ");
1046
dynstr_append(&ds_warning_messages, "Warning detected ");
1025
1047
if (cur_file && cur_file != file_stack)
1027
1049
len= snprintf(buff, sizeof(buff), "in included file %s ",
1028
cur_file->file_name);
1029
ds_warning_messages.append(buff, len);
1050
cur_file->file_name);
1051
dynstr_append_mem(&ds_warning_messages,
1031
1054
len= snprintf(buff, sizeof(buff), "at line %d: ",
1033
ds_warning_messages.append(buff, len);
1056
dynstr_append_mem(&ds_warning_messages,
1036
1060
len= vsnprintf(buff, sizeof(buff), fmt, args);
1037
ds_warning_messages.append(buff, len);
1061
dynstr_append_mem(&ds_warning_messages, buff, len);
1039
ds_warning_messages.append("\n");
1063
dynstr_append(&ds_warning_messages, "\n");
1144
1176
tool_path - the name of the tool to run
1145
result - pointer to dynamic string where to store the result
1177
ds_res - pointer to dynamic string where to store the result
1146
1178
... - variable number of arguments that will be properly
1147
quoted and appended after the tool's name
1179
quoted and appended after the tool's name
1151
static int run_tool(const char *tool_path, string * result, ...)
1183
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
1154
1186
const char* arg;
1159
append_os_quoted(&ds_cmdline, tool_path);
1160
ds_cmdline.append(" ");
1162
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);
1164
1198
while ((arg= va_arg(args, char *)))
1166
1200
/* Options should be os quoted */
1167
1201
if (strncmp(arg, "--", 2) == 0)
1168
append_os_quoted(&ds_cmdline, arg, NULL);
1202
dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1170
ds_cmdline.append(arg);
1171
ds_cmdline.append(" ");
1204
dynstr_append(&ds_cmdline, arg);
1205
dynstr_append(&ds_cmdline, " ");
1176
ret= run_command(ds_cmdline.c_str(), result);
1210
ret= run_command(ds_cmdline.str, ds_res);
1211
dynstr_free(&ds_cmdline);
1221
1259
Fallback to dump both files to result file and inform
1222
1260
about installing "diff"
1228
"The two files differ but it was not possible to execute 'diff' in\n"
1229
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1230
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
1231
"To get a better report you should install 'diff' on your system, which you\n"
1232
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1235
ds_tmp.append(" --- ");
1236
ds_tmp.append(filename1);
1237
ds_tmp.append(" >>>\n");
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");
1238
1276
cat_file(&ds_tmp, filename1);
1239
ds_tmp.append("<<<\n --- ");
1240
ds_tmp.append(filename1);
1241
ds_tmp.append(" >>>\n");
1277
dynstr_append(&ds_tmp, "<<<\n --- ");
1278
dynstr_append(&ds_tmp, filename1);
1279
dynstr_append(&ds_tmp, " >>>\n");
1242
1280
cat_file(&ds_tmp, filename2);
1243
ds_tmp.append("<<<<\n");
1281
dynstr_append(&ds_tmp, "<<<<\n");
1249
1287
/* Add the diff to output */
1250
ds->append(ds_tmp.c_str(), ds_tmp.length());
1288
dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1254
1292
/* Print diff directly to stdout */
1255
fprintf(stderr, "%s\n", ds_tmp.c_str());
1293
fprintf(stderr, "%s\n", ds_tmp.str);
1296
dynstr_free(&ds_tmp);
1261
1301
enum compare_files_result_enum {
1263
RESULT_CONTENT_MISMATCH= 1,
1264
RESULT_LENGTH_MISMATCH= 2
1303
RESULT_CONTENT_MISMATCH= 1,
1304
RESULT_LENGTH_MISMATCH= 2
1798
1838
/* Eval the query, thus replacing all environment variables */
1839
init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
1799
1840
do_eval(&ds_query, query, end, false);
1801
if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1802
die("Error running query '%s': %d %s", ds_query.c_str(),
1803
drizzle_errno(drizzle), drizzle_error(drizzle));
1804
if (!(res= drizzle_store_result(drizzle)))
1805
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);
1807
if ((row= drizzle_fetch_row(res)) && row[0])
1849
if ((row= mysql_fetch_row(res)) && row[0])
1810
1852
Concatenate all fields in the first row with tab in between
1811
1853
and assign that string to the $variable
1855
DYNAMIC_STRING result;
1815
1857
uint32_t *lengths;
1817
lengths= drizzle_fetch_lengths(res);
1818
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++)
1822
1865
/* Add column to tab separated string */
1823
result.append(row[i], lengths[i]);
1866
dynstr_append_mem(&result, row[i], lengths[i]);
1825
result.append("\t", 1);
1868
dynstr_append_mem(&result, "\t", 1);
1827
end= result.c_str() + result.length()-1;
1828
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);
1831
1875
eval_expr(var, "", 0);
1833
drizzle_free_result(res);
1877
mysql_free_result(res);
1883
1927
/* Convert row number to int */
1884
if (!str2int(ds_row.c_str(), 10, (long) 0, (long) INT_MAX, &row_no))
1885
die("Invalid row number: '%s'", ds_row.c_str());
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);
1887
1932
/* Remove any surrounding "'s from the query - if there is any */
1888
// (Don't get me started on this)
1889
char * unstripped_query= strdup(ds_query.c_str());
1890
if (strip_surrounding(unstripped_query, '"', '"'))
1891
die("Mismatched \"'s around query '%s'", ds_query.c_str());
1892
ds_query= unstripped_query;
1933
if (strip_surrounding(ds_query.str, '"', '"'))
1934
die("Mismatched \"'s around query '%s'", ds_query.str);
1894
1936
/* Run the query */
1895
if (drizzle_real_query(drizzle, ds_query.c_str(), ds_query.length()))
1896
die("Error running query '%s': %d %s", ds_query.c_str(),
1897
drizzle_errno(drizzle), drizzle_error(drizzle));
1898
if (!(res= drizzle_store_result(drizzle)))
1899
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);
1902
1944
/* Find column number from the given column name */
1904
uint num_fields= drizzle_num_fields(res);
1905
const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
1946
uint num_fields= mysql_num_fields(res);
1947
MYSQL_FIELD *fields= mysql_fetch_fields(res);
1907
1949
for (i= 0; i < num_fields; i++)
1909
if (strcmp(fields[i].name, ds_col.c_str()) == 0 &&
1910
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)
2104
2155
Replace a substring
2108
ds_str The string to search and perform the replace in
2109
search_str The string to search for
2110
search_len Length of the string to search for
2111
replace_str The string to replace with
2112
replace_len Length of the string to replace with
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
2116
1 Could not find search_str in str
2167
1 Could not find search_str in str
2119
static int replace(string *ds_str,
2120
const char *search_str, uint32_t search_len,
2121
const char *replace_str, uint32_t replace_len)
2170
static int replace(DYNAMIC_STRING *ds_str,
2171
const char *search_str, ulong search_len,
2172
const char *replace_str, ulong replace_len)
2124
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);
2127
ds_tmp.append(ds_str->c_str(), start - ds_str->c_str());
2128
ds_tmp.append(replace_str, replace_len);
2129
ds_tmp.append(start + search_len);
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);
2299
2376
static void do_system(struct st_command *command)
2378
DYNAMIC_STRING ds_cmd;
2304
2381
if (strlen(command->first_argument) == 0)
2305
2382
die("Missing arguments to system, nothing to do!");
2384
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
2307
2386
/* Eval the system command, thus replacing all environment variables */
2308
2387
do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
2310
if (system(ds_cmd.c_str()))
2389
if (my_system(&ds_cmd))
2312
2391
if (command->abort_on_error)
2313
2392
die("system command '%s' failed", command->first_argument);
2315
2394
/* If ! abort_on_error, log message and continue */
2316
ds_res.append("system command '");
2317
replace_append(&ds_res, command->first_argument);
2318
ds_res.append("' failed\n");
2395
dynstr_append(&ds_res, "system command '");
2396
replace_dynstr_append(&ds_res, command->first_argument);
2397
dynstr_append(&ds_res, "' failed\n");
2321
2400
command->last_argument= command->end;
2401
dynstr_free(&ds_cmd);
2598
2686
/* If no delimiter was provided, use EOF */
2599
if (ds_delimiter.length() == 0)
2600
ds_delimiter= "EOF";
2687
if (ds_delimiter.length == 0)
2688
dynstr_set(&ds_delimiter, "EOF");
2602
if (!append && access(ds_filename.c_str(), F_OK) == 0)
2690
if (!append && access(ds_filename.str, F_OK) == 0)
2604
2692
/* The file should not be overwritten */
2605
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);
2608
2697
read_until_delimiter(&ds_content, &ds_delimiter);
2609
str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2610
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);
3006
3107
die("Calling 'sync_with_master' without calling 'save_master_pos'");
3008
3109
sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
3009
master_pos.pos + offset);
3110
master_pos.pos + offset);
3011
3112
wait_for_position:
3013
if (drizzle_query(drizzle, query_buf))
3014
die("failed in '%s': %d: %s", query_buf, drizzle_errno(drizzle),
3015
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));
3017
if (!(res= drizzle_store_result(drizzle)))
3018
die("drizzle_store_result() returned NULL for '%s'", query_buf);
3019
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)))
3021
drizzle_free_result(res);
3122
mysql_free_result(res);
3022
3123
die("empty result in %s", query_buf);
3065
3166
when ndb binlog is on, this call will wait until last updated epoch
3066
(locally in the drizzled) has been received into the binlog
3167
(locally in the mysqld) has been received into the binlog
3068
3169
static int do_save_master_pos(void)
3072
DRIZZLE *drizzle= &cur_con->drizzle;
3173
MYSQL *mysql = &cur_con->mysql;
3073
3174
const char *query;
3076
if (drizzle_query(drizzle, query= "show master status"))
3177
if (mysql_query(mysql, query= "show master status"))
3077
3178
die("failed in 'show master status': %d %s",
3078
drizzle_errno(drizzle), drizzle_error(drizzle));
3179
mysql_errno(mysql), mysql_error(mysql));
3080
if (!(res = drizzle_store_result(drizzle)))
3081
die("drizzle_store_result() retuned NULL for '%s'", query);
3082
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)))
3083
3184
die("empty result in show master status");
3084
my_stpncpy(master_pos.file, row[0], sizeof(master_pos.file)-1);
3185
strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
3085
3186
master_pos.pos = strtoul(row[1], (char**) 0, 10);
3086
drizzle_free_result(res);
3187
mysql_free_result(res);
3559
static void safe_connect(DRIZZLE *drizzle, const char *name, const char *host,
3560
const char *user, const char *pass, const char *db,
3678
static void safe_connect(MYSQL* mysql, const char *name, const char *host,
3679
const char *user, const char *pass, const char *db,
3563
3682
int failed_attempts= 0;
3564
static uint32_t connection_retry_sleep= 100000; /* Microseconds */
3567
while(!drizzle_connect(drizzle, host, user, pass, db, port, NULL,
3568
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3683
static ulong connection_retry_sleep= 100000; /* Microseconds */
3686
while(!mysql_real_connect(mysql, host, user, pass, db, port, NULL,
3687
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
3575
3694
on protocol/connection type
3578
if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
3579
drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
3697
if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
3698
mysql_errno(mysql) == CR_CONNECTION_ERROR) &&
3580
3699
failed_attempts < opt_max_connect_retries)
3582
3701
verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3583
opt_max_connect_retries, drizzle_errno(drizzle),
3584
drizzle_error(drizzle));
3702
opt_max_connect_retries, mysql_errno(mysql),
3703
mysql_error(mysql));
3585
3704
my_sleep(connection_retry_sleep);
3589
3708
if (failed_attempts > 0)
3590
3709
die("Could not open connection '%s' after %d attempts: %d %s", name,
3591
failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
3710
failed_attempts, mysql_errno(mysql), mysql_error(mysql));
3593
3712
die("Could not open connection '%s': %d %s", name,
3594
drizzle_errno(drizzle), drizzle_error(drizzle));
3713
mysql_errno(mysql), mysql_error(mysql));
3596
3715
failed_attempts++;
3636
3758
Log the connect to result log
3638
ds_res.append("connect(");
3639
replace_append(&ds_res, host);
3641
replace_append(&ds_res, user);
3643
replace_append(&ds_res, pass);
3760
dynstr_append_mem(ds, "connect(", 8);
3761
replace_dynstr_append(ds, host);
3762
dynstr_append_mem(ds, ",", 1);
3763
replace_dynstr_append(ds, user);
3764
dynstr_append_mem(ds, ",", 1);
3765
replace_dynstr_append(ds, pass);
3766
dynstr_append_mem(ds, ",", 1);
3646
replace_append(&ds_res, db);
3648
replace_append_uint(&ds_res, port);
3768
replace_dynstr_append(ds, db);
3769
dynstr_append_mem(ds, ",", 1);
3770
replace_dynstr_append_uint(ds, port);
3771
dynstr_append_mem(ds, ",", 1);
3651
replace_append(&ds_res, sock);
3653
ds_res.append(delimiter);
3654
ds_res.append("\n");
3773
replace_dynstr_append(ds, sock);
3774
dynstr_append_mem(ds, ")", 1);
3775
dynstr_append_mem(ds, delimiter, delimiter_length);
3776
dynstr_append_mem(ds, "\n", 1);
3656
if (!drizzle_connect(con, host, user, pass, db, port, 0,
3657
CLIENT_MULTI_STATEMENTS))
3778
if (!mysql_real_connect(con, host, user, pass, db, port, 0,
3779
CLIENT_MULTI_STATEMENTS))
3659
var_set_errno(drizzle_errno(con));
3660
handle_error(command, drizzle_errno(con), drizzle_error(con),
3661
drizzle_sqlstate(con), &ds_res);
3781
var_set_errno(mysql_errno(con));
3782
handle_error(command, mysql_errno(con), mysql_error(con),
3783
mysql_sqlstate(con), ds);
3662
3784
return 0; /* Not connected */
3688
3810
<port> - server port
3689
3811
<sock> - server socket
3690
3812
<opts> - options to use for the connection
3691
* SSL - use SSL if available
3692
* COMPRESS - use compression if available
3813
* SSL - use SSL if available
3814
* COMPRESS - use compression if available
3696
3818
static void do_connect(struct st_command *command)
3698
3820
int con_port= opt_port;
3699
const char *con_options;
3700
3822
bool con_ssl= 0, con_compress= 0;
3701
3823
struct st_connection* con_slot;
3703
string ds_connection_name;
3825
static DYNAMIC_STRING ds_connection_name;
3826
static DYNAMIC_STRING ds_host;
3827
static DYNAMIC_STRING ds_user;
3828
static DYNAMIC_STRING ds_password;
3829
static DYNAMIC_STRING ds_database;
3830
static DYNAMIC_STRING ds_port;
3831
static DYNAMIC_STRING ds_sock;
3832
static DYNAMIC_STRING ds_options;
3711
3833
const struct command_arg connect_args[] = {
3712
3834
{ "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3713
3835
{ "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3729
if (ds_port.length())
3731
con_port= atoi(ds_port.c_str());
3853
con_port= atoi(ds_port.str);
3732
3854
if (con_port == 0)
3733
die("Illegal argument for port: '%s'", ds_port.c_str());
3855
die("Illegal argument for port: '%s'", ds_port.str);
3737
if (!ds_sock.empty())
3740
3862
If the socket is specified just as a name without path
3741
3863
append tmpdir in front
3743
if (*ds_sock.c_str() != FN_LIBCHAR)
3865
if (*ds_sock.str != FN_LIBCHAR)
3745
3867
char buff[FN_REFLEN];
3746
fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3868
fn_format(buff, ds_sock.str, TMPDIR, "", 0);
3869
dynstr_set(&ds_sock, buff);
3874
/* No socket specified, use default */
3875
dynstr_set(&ds_sock, unix_sock);
3752
con_options= ds_options.c_str();
3879
con_options= ds_options.str;
3753
3880
while (*con_options)
3756
3883
/* Step past any spaces in beginning of option*/
3757
3884
while (*con_options && my_isspace(charset_info, *con_options))
3759
3886
/* Find end of this option */
3760
3887
end= con_options;
3761
3888
while (*end && !my_isspace(charset_info, *end))
3785
3910
(int) (sizeof(connections)/sizeof(struct st_connection)));
3788
if (!drizzle_create(&con_slot->drizzle))
3789
die("Failed on drizzle_create()");
3913
#ifdef EMBEDDED_LIBRARY
3914
con_slot->query_done= 1;
3916
if (!mysql_init(&con_slot->mysql))
3917
die("Failed on mysql_init()");
3790
3918
if (opt_compress || con_compress)
3791
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_COMPRESS, NULL);
3792
drizzle_options(&con_slot->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
3919
mysql_options(&con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
3920
mysql_options(&con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
3921
mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_NAME,
3922
charset_info->csname);
3923
int opt_protocol= MYSQL_PROTOCOL_TCP;
3924
mysql_options(&con_slot->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
3925
if (opt_charsets_dir)
3926
mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
3794
3929
/* Use default db name */
3795
if (ds_database.length() == 0)
3796
ds_database= opt_db;
3930
if (ds_database.length == 0)
3931
dynstr_set(&ds_database, opt_db);
3798
3933
/* Special database to allow one to connect without a database name */
3799
if (ds_database.length() && !strcmp(ds_database.c_str(),"*NO-ONE*"))
3934
if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
3935
dynstr_set(&ds_database, "");
3802
if (connect_n_handle_errors(command, &con_slot->drizzle,
3803
ds_host.c_str(),ds_user.c_str(),
3804
ds_password.c_str(), ds_database.c_str(),
3805
con_port, ds_sock.c_str()))
3937
if (connect_n_handle_errors(command, &con_slot->mysql,
3938
ds_host.str,ds_user.str,
3939
ds_password.str, ds_database.str,
3940
con_port, ds_sock.str))
3807
if (!(con_slot->name= strdup(ds_connection_name.c_str())))
3942
if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3808
3943
die("Out of memory");
3809
3944
cur_con= con_slot;
3811
3946
if (con_slot == next_con)
3812
3947
next_con++; /* if we used the next_con slot, advance the pointer */
3815
/* Update $drizzle_get_server_version to that of current connection */
3816
var_set_drizzle_get_server_version(&cur_con->drizzle);
3950
/* Update $mysql_get_server_version to that of current connection */
3951
var_set_mysql_get_server_version(&cur_con->mysql);
3953
dynstr_free(&ds_connection_name);
3954
dynstr_free(&ds_host);
3955
dynstr_free(&ds_user);
3956
dynstr_free(&ds_password);
3957
dynstr_free(&ds_database);
3958
dynstr_free(&ds_port);
3959
dynstr_free(&ds_sock);
3960
dynstr_free(&ds_options);
4062
4205
if (end_of_query(c))
4067
4210
else if ((c == '{' &&
4068
(!my_strnncoll_simple(charset_info, (const unsigned char*) "while", 5,
4069
(unsigned char*) buf, cmin((long)5, p - buf), 0) ||
4070
!my_strnncoll_simple(charset_info, (const unsigned char*) "if", 2,
4071
(unsigned char*) buf, cmin((long)2, p - buf), 0))))
4211
(!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
4212
(uchar*) buf, min(5, p - buf), 0) ||
4213
!my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
4214
(uchar*) buf, min(2, p - buf), 0))))
4073
4216
/* Only if and while commands can be terminated by { */
4078
4221
else if (c == '\'' || c == '"' || c == '`')
4151
4294
/* completed before we pass buf_end */
4152
4295
if ((charlen > 1) && (p + charlen) <= buf_end)
4159
for (i= 1; i < charlen; i++)
4161
if (feof(cur_file->file))
4163
c= my_getc(cur_file->file);
4166
if (! my_ismbchar(charset_info, mb_start, p))
4168
/* It was not a multiline char, push back the characters */
4169
/* We leave first 'c', i.e. pretend it was a normal char */
4170
while (p > mb_start)
4302
for (i= 1; i < charlen; i++)
4304
if (feof(cur_file->file))
4306
c= my_getc(cur_file->file);
4309
if (! my_ismbchar(charset_info, mb_start, p))
4311
/* It was not a multiline char, push back the characters */
4312
/* We leave first 'c', i.e. pretend it was a normal char */
4313
while (p > mb_start)
4179
die("The input buffer is too small for this query.x\n" \
4322
die("The input buffer is too small for this query.x\n" \
4180
4323
"check your query or increase MAX_QUERY and recompile");
4453
4596
{"password", 'p', "Password to use when connecting to server.",
4454
4597
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4455
4598
{"port", 'P', "Port number to use for connection or 0 for default to, in "
4456
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
4457
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
4599
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
4600
#if MYSQL_PORT_DEFAULT == 0
4603
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
4458
4604
(char**) &opt_port,
4459
4605
(char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4460
4606
{"quiet", 's', "Suppress all normal output.", (char**) &silent,
4531
4682
if (!embedded_server_arg_count)
4533
4684
embedded_server_arg_count=1;
4534
embedded_server_args[0]= (char*) ""; /* Progname */
4685
embedded_server_args[0]= (char*) ""; /* Progname */
4536
4687
if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4537
4688
die("Failed to open file '%s'", buff);
4539
4690
while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4540
(str=fgets(argument,sizeof(argument), file)))
4691
(str=fgets(argument,sizeof(argument), file)))
4542
*(strchr(str, '\0')-1)=0; /* Remove end newline */
4693
*(strend(str)-1)=0; /* Remove end newline */
4543
4694
if (!(embedded_server_args[embedded_server_arg_count]=
4544
(char*) my_strdup(str,MYF(MY_WME))))
4695
(char*) my_strdup(str,MYF(MY_WME))))
4546
4697
my_fclose(file,MYF(0));
4547
4698
die("Out of memory");
4587
4738
static char buff[FN_REFLEN];
4588
4739
if (!test_if_hard_path(argument))
4590
strxmov(buff, opt_basedir, argument, NULL);
4741
strxmov(buff, opt_basedir, argument, NullS);
4591
4742
argument= buff;
4593
4744
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4594
4745
timer_file= buff;
4595
unlink(timer_file); /* Ignore error, may not exist */
4746
unlink(timer_file); /* Ignore error, may not exist */
4752
my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
4602
4753
opt_pass= my_strdup(argument, MYF(MY_FAE));
4603
while (*argument) *argument++= 'x'; /* Destroy argument */
4754
while (*argument) *argument++= 'x'; /* Destroy argument */
4604
4755
tty_password= 0;
4607
4758
tty_password= 1;
4610
my_stpncpy(TMPDIR, argument, sizeof(TMPDIR));
4761
strnmov(TMPDIR, argument, sizeof(TMPDIR));
4613
4764
if (!embedded_server_arg_count)
4783
4934
Values may be converted with 'replace_column'
4786
static void append_result(string *ds, DRIZZLE_RES *res)
4937
static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
4789
uint32_t num_fields= drizzle_num_fields(res);
4790
const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
4940
uint32_t num_fields= mysql_num_fields(res);
4941
MYSQL_FIELD *fields= mysql_fetch_fields(res);
4791
4942
uint32_t *lengths;
4793
while ((row = drizzle_fetch_row(res)))
4944
while ((row = mysql_fetch_row(res)))
4796
lengths = drizzle_fetch_lengths(res);
4947
lengths = mysql_fetch_lengths(res);
4797
4948
for (i = 0; i < num_fields; i++)
4798
4949
append_field(ds, i, &fields[i],
4799
4950
(const char*)row[i], lengths[i], !row[i]);
4800
4951
if (!display_result_vertically)
4952
dynstr_append_mem(ds, "\n", 1);
4808
4958
Append metadata for fields to output
4811
static void append_metadata(string *ds,
4812
const DRIZZLE_FIELD *field,
4961
static void append_metadata(DYNAMIC_STRING *ds,
4813
4963
uint num_fields)
4815
const DRIZZLE_FIELD *field_end;
4816
ds->append("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4817
"Column_alias\tType\tLength\tMax length\tIs_null\t"
4818
"Flags\tDecimals\tCharsetnr\n");
4965
MYSQL_FIELD *field_end;
4966
dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
4967
"Column_alias\tType\tLength\tMax length\tIs_null\t"
4968
"Flags\tDecimals\tCharsetnr\n");
4820
4970
for (field_end= field+num_fields ;
4821
4971
field < field_end ;
4824
ds->append(field->catalog,
4825
field->catalog_length);
4826
ds->append("\t", 1);
4827
ds->append(field->db, field->db_length);
4828
ds->append("\t", 1);
4829
ds->append(field->org_table,
4830
field->org_table_length);
4831
ds->append("\t", 1);
4832
ds->append(field->table,
4833
field->table_length);
4834
ds->append("\t", 1);
4835
ds->append(field->org_name,
4836
field->org_name_length);
4837
ds->append("\t", 1);
4838
ds->append(field->name, field->name_length);
4839
ds->append("\t", 1);
4840
replace_append_uint(ds, field->type);
4841
ds->append("\t", 1);
4842
replace_append_uint(ds, field->length);
4843
ds->append("\t", 1);
4844
replace_append_uint(ds, field->max_length);
4845
ds->append("\t", 1);
4846
ds->append((char*) ((field->flags & NOT_NULL_FLAG) ?
4848
ds->append("\t", 1);
4849
replace_append_uint(ds, field->flags);
4850
ds->append("\t", 1);
4851
replace_append_uint(ds, field->decimals);
4852
ds->append("\t", 1);
4853
replace_append_uint(ds, field->charsetnr);
4854
ds->append("\n", 1);
4974
dynstr_append_mem(ds, field->catalog,
4975
field->catalog_length);
4976
dynstr_append_mem(ds, "\t", 1);
4977
dynstr_append_mem(ds, field->db, field->db_length);
4978
dynstr_append_mem(ds, "\t", 1);
4979
dynstr_append_mem(ds, field->org_table,
4980
field->org_table_length);
4981
dynstr_append_mem(ds, "\t", 1);
4982
dynstr_append_mem(ds, field->table,
4983
field->table_length);
4984
dynstr_append_mem(ds, "\t", 1);
4985
dynstr_append_mem(ds, field->org_name,
4986
field->org_name_length);
4987
dynstr_append_mem(ds, "\t", 1);
4988
dynstr_append_mem(ds, field->name, field->name_length);
4989
dynstr_append_mem(ds, "\t", 1);
4990
replace_dynstr_append_uint(ds, field->type);
4991
dynstr_append_mem(ds, "\t", 1);
4992
replace_dynstr_append_uint(ds, field->length);
4993
dynstr_append_mem(ds, "\t", 1);
4994
replace_dynstr_append_uint(ds, field->max_length);
4995
dynstr_append_mem(ds, "\t", 1);
4996
dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
4998
dynstr_append_mem(ds, "\t", 1);
4999
replace_dynstr_append_uint(ds, field->flags);
5000
dynstr_append_mem(ds, "\t", 1);
5001
replace_dynstr_append_uint(ds, field->decimals);
5002
dynstr_append_mem(ds, "\t", 1);
5003
replace_dynstr_append_uint(ds, field->charsetnr);
5004
dynstr_append_mem(ds, "\n", 1);
4914
5064
through PS API we should not issue SHOW WARNINGS until
4915
5065
we have not read all results...
4917
assert(!drizzle_more_results(drizzle));
4919
if (drizzle_real_query(drizzle, "SHOW WARNINGS", 13))
4920
die("Error running query \"SHOW WARNINGS\": %s", drizzle_error(drizzle));
4922
if (!(warn_res= drizzle_store_result(drizzle)))
5067
assert(!mysql_more_results(mysql));
5069
if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
5070
die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql));
5072
if (!(warn_res= mysql_store_result(mysql)))
4923
5073
die("Warning count is %u but didn't get any warnings",
4926
5076
append_result(ds, warn_res);
5077
mysql_free_result(warn_res);
4933
Run query using DRIZZLE C API
5084
Run query using MySQL C API
4937
drizzle DRIZZLE handle
4938
command current command pointer
4939
flags flags indicating if we should SEND and/or REAP
4940
query query string to execute
4941
query_len length query string to execute
4942
ds output buffer where to store result form query
5089
command current command pointer
5090
flags flags indicating if we should SEND and/or REAP
5091
query query string to execute
5092
query_len length query string to execute
5093
ds output buffer where to store result form query
4945
5096
static void run_query_normal(struct st_connection *cn,
4946
5097
struct st_command *command,
4947
5098
int flags, char *query, int query_len,
4948
string *ds, string *ds_warnings)
5099
DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4950
DRIZZLE_RES *res= 0;
4951
DRIZZLE *drizzle= &cn->drizzle;
5102
MYSQL *mysql= &cn->mysql;
4952
5103
int err= 0, counter= 0;
4954
5105
if (flags & QUERY_SEND_FLAG)
4959
5110
if (do_send_query(cn, query, query_len, flags))
4961
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4962
drizzle_sqlstate(drizzle), ds);
5112
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
5113
mysql_sqlstate(mysql), ds);
5117
#ifdef EMBEDDED_LIBRARY
5119
Here we handle 'reap' command, so we need to check if the
5120
query's thread was finished and probably wait
5122
else if (flags & QUERY_REAP_FLAG)
5123
wait_query_thread_end(cn);
5124
#endif /*EMBEDDED_LIBRARY*/
4966
5125
if (!(flags & QUERY_REAP_FLAG))
4972
When on first result set, call drizzle_read_query_result to retrieve
5131
When on first result set, call mysql_read_query_result to retrieve
4973
5132
answer to the query sent earlier
4975
if ((counter==0) && drizzle_read_query_result(drizzle))
5134
if ((counter==0) && mysql_read_query_result(mysql))
4977
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4978
drizzle_sqlstate(drizzle), ds);
5136
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
5137
mysql_sqlstate(mysql), ds);
4999
const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
5000
uint num_fields= drizzle_num_fields(res);
5158
MYSQL_FIELD *fields= mysql_fetch_fields(res);
5159
uint num_fields= mysql_num_fields(res);
5002
if (display_metadata)
5161
if (display_metadata)
5003
5162
append_metadata(ds, fields, num_fields);
5005
if (!display_result_vertically)
5006
append_table_headings(ds, fields, num_fields);
5164
if (!display_result_vertically)
5165
append_table_headings(ds, fields, num_fields);
5008
append_result(ds, res);
5167
append_result(ds, res);
5012
Need to call drizzle_affected_rows() before the "new"
5171
Need to call mysql_affected_rows() before the "new"
5013
5172
query to find the warnings
5015
5174
if (!disable_info)
5016
affected_rows= drizzle_affected_rows(drizzle);
5175
affected_rows= mysql_affected_rows(mysql);
5019
5178
Add all warnings to the result. We can't do this if we are in
5020
5179
the middle of processing results from multi-statement, because
5021
5180
this will break protocol.
5023
if (!disable_warnings && !drizzle_more_results(drizzle))
5182
if (!disable_warnings && !mysql_more_results(mysql))
5025
if (append_warnings(ds_warnings, drizzle) || ds_warnings->length())
5027
ds->append("Warnings:\n", 10);
5028
ds->append(ds_warnings->c_str(), ds_warnings->length());
5184
if (append_warnings(ds_warnings, mysql) || ds_warnings->length)
5186
dynstr_append_mem(ds, "Warnings:\n", 10);
5187
dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
5032
5191
if (!disable_info)
5033
append_info(ds, affected_rows, drizzle_info(drizzle));
5192
append_info(ds, affected_rows, mysql_info(mysql));
5038
drizzle_free_result(res);
5197
mysql_free_result(res);
5042
} while (!(err= drizzle_next_result(drizzle)));
5201
} while (!(err= mysql_next_result(mysql)));
5045
/* We got an error from drizzle_next_result, maybe expected */
5046
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5047
drizzle_sqlstate(drizzle), ds);
5204
/* We got an error from mysql_next_result, maybe expected */
5205
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
5206
mysql_sqlstate(mysql), ds);
5050
5209
assert(err == -1); /* Successful and there are no more results */
5120
5280
if (command->expected_errors.count == 1)
5122
5282
/* Only log error if there is one possible error */
5123
ds->append("ERROR ", 6);
5124
replace_append(ds, err_sqlstate);
5125
ds->append(": ", 2);
5126
replace_append(ds, err_error);
5283
dynstr_append_mem(ds, "ERROR ", 6);
5284
replace_dynstr_append(ds, err_sqlstate);
5285
dynstr_append_mem(ds, ": ", 2);
5286
replace_dynstr_append(ds, err_error);
5287
dynstr_append_mem(ds,"\n",1);
5129
5289
/* Don't log error if we may not get an error */
5130
5290
else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5131
5291
(command->expected_errors.err[0].type == ERR_ERRNO &&
5132
5292
command->expected_errors.err[0].code.errnum != 0))
5133
ds->append("Got one of the listed errors\n");
5293
dynstr_append(ds,"Got one of the listed errors\n");
5204
drizzle DRIZZLE handle
5205
command currrent command pointer
5365
command currrent command pointer
5207
5367
flags control the phased/stages of query execution to be performed
5208
5368
if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
5209
5369
is on the result will be read - for regular query, both bits must be on
5212
static void run_query(struct st_connection *cn,
5372
static void run_query(struct st_connection *cn,
5213
5373
struct st_command *command,
5217
string *save_ds= NULL;
5377
DYNAMIC_STRING *save_ds= NULL;
5378
DYNAMIC_STRING ds_result;
5379
DYNAMIC_STRING ds_sorted;
5380
DYNAMIC_STRING ds_warnings;
5381
DYNAMIC_STRING eval_query;
5386
init_dynamic_string(&ds_warnings, NULL, 0, 256);
5226
5388
/* Scan for warning before sending to server */
5227
5389
scan_command_for_warnings(command);
5250
5413
if (command->require_file[0])
5415
init_dynamic_string(&ds_result, "", 1024, 1024);
5252
5416
ds= &ds_result;
5259
5422
Log the query into the output buffer
5261
5424
if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5263
replace_append_mem(ds, query, query_len);
5264
ds->append(delimiter, delimiter_length);
5426
replace_dynstr_append_mem(ds, query, query_len);
5427
dynstr_append_mem(ds, delimiter, delimiter_length);
5428
dynstr_append_mem(ds, "\n", 1);
5268
5431
if (display_result_sorted)
5271
Collect the query output in a separate string
5272
that can be sorted before it's added to the
5273
global result string
5434
Collect the query output in a separate string
5435
that can be sorted before it's added to the
5436
global result string
5438
init_dynamic_string(&ds_sorted, "", 1024, 1024);
5275
5439
save_ds= ds; /* Remember original ds */
5276
5440
ds= &ds_sorted;
5403
5573
/* Milliseconds since start */
5404
5574
end= int64_t2str(timer, buf, 10);
5405
ds_progress.append(buf, (int)(end-buf));
5406
ds_progress.append("\t", 1);
5575
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5576
dynstr_append_mem(&ds_progress, "\t", 1);
5408
5578
/* Parser line number */
5409
5579
end= int10_to_str(line, buf, 10);
5410
ds_progress.append(buf, (int)(end-buf));
5411
ds_progress.append("\t", 1);
5580
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5581
dynstr_append_mem(&ds_progress, "\t", 1);
5414
ds_progress.append(cur_file->file_name);
5415
ds_progress.append(":", 1);
5584
dynstr_append(&ds_progress, cur_file->file_name);
5585
dynstr_append_mem(&ds_progress, ":", 1);
5417
5587
/* Line in file */
5418
5588
end= int10_to_str(cur_file->lineno, buf, 10);
5419
ds_progress.append(buf, (int)(end-buf));
5422
ds_progress.append("\n", 1);
5589
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5592
dynstr_append_mem(&ds_progress, "\n", 1);
5486
5667
cur_file->lineno= 1;
5488
5669
cur_con= connections;
5489
if (!( drizzle_create(&cur_con->drizzle)))
5490
die("Failed in drizzle_create()");
5670
if (!( mysql_init(&cur_con->mysql)))
5671
die("Failed in mysql_init()");
5491
5672
if (opt_compress)
5492
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
5493
drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
5673
mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS);
5674
mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
5675
mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME,
5676
charset_info->csname);
5677
int opt_protocol= MYSQL_PROTOCOL_TCP;
5678
mysql_options(&cur_con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
5679
if (opt_charsets_dir)
5680
mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR,
5495
5683
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5496
5684
die("Out of memory");
5498
safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
5686
safe_connect(&cur_con->mysql, cur_con->name, opt_host, opt_user, opt_pass,
5499
5687
opt_db, opt_port);
5501
5689
/* Use all time until exit if no explicit 'start_timer' */
5502
5690
timer_start= timer_now();
5505
Initialize $drizzle_errno with -1, so we can
5693
Initialize $mysql_errno with -1, so we can
5506
5694
- distinguish it from valid values ( >= 0 ) and
5507
5695
- detect if there was never a command sent to the server
5509
5697
var_set_errno(-1);
5511
/* Update $drizzle_get_server_version to that of current connection */
5512
var_set_drizzle_get_server_version(&cur_con->drizzle);
5699
/* Update $mysql_get_server_version to that of current connection */
5700
var_set_mysql_get_server_version(&cur_con->mysql);
5514
5702
if (opt_include)
5655
5841
/* Remove "send" if this is first iteration */
5656
if (command->query == command->query_buf)
5657
command->query= command->first_argument;
5842
if (command->query == command->query_buf)
5843
command->query= command->first_argument;
5660
run_query() can execute a query partially, depending on the flags.
5661
QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5846
run_query() can execute a query partially, depending on the flags.
5847
QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
5662
5848
the query and read the result some time later when reap instruction
5663
is given on this connection.
5849
is given on this connection.
5665
run_query(cur_con, command, QUERY_SEND_FLAG);
5851
run_query(cur_con, command, QUERY_SEND_FLAG);
5667
5853
command->last_argument= command->end;
5669
5855
case Q_REQUIRE:
5670
do_get_file_name(command, save_file, sizeof(save_file));
5856
do_get_file_name(command, save_file, sizeof(save_file));
5673
5859
do_get_errcodes(command);
5675
5861
case Q_REPLACE:
5676
do_get_replace(command);
5862
do_get_replace(command);
5678
5864
case Q_REPLACE_REGEX:
5679
5865
do_get_replace_regex(command);
5681
5867
case Q_REPLACE_COLUMN:
5682
do_get_replace_column(command);
5868
do_get_replace_column(command);
5684
5870
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5685
5871
case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5686
5872
case Q_SYNC_SLAVE_WITH_MASTER:
5688
do_save_master_pos();
5689
if (*command->first_argument)
5690
select_connection(command);
5692
select_connection_name("slave");
5693
do_sync_with_master2(0);
5874
do_save_master_pos();
5875
if (*command->first_argument)
5876
select_connection(command);
5878
select_connection_name("slave");
5879
do_sync_with_master2(0);
5696
case Q_COMMENT: /* Ignore row */
5882
case Q_COMMENT: /* Ignore row */
5697
5883
command->last_argument= command->end;
5700
(void) drizzle_ping(&cur_con->drizzle);
5886
(void) mysql_ping(&cur_con->mysql);
5706
5892
case Q_START_TIMER:
5707
/* Overwrite possible earlier start of timer */
5708
timer_start= timer_now();
5893
/* Overwrite possible earlier start of timer */
5894
timer_start= timer_now();
5710
5896
case Q_END_TIMER:
5711
/* End timer before ending drizzletest */
5897
/* End timer before ending mysqltest */
5714
5900
case Q_CHARACTER_SET:
5715
do_set_charset(command);
5901
do_set_charset(command);
5717
5903
case Q_DISABLE_RECONNECT:
5718
set_reconnect(&cur_con->drizzle, 0);
5904
set_reconnect(&cur_con->mysql, 0);
5720
5906
case Q_ENABLE_RECONNECT:
5721
set_reconnect(&cur_con->drizzle, 1);
5907
set_reconnect(&cur_con->mysql, 1);
5723
5909
case Q_DISABLE_PARSING:
5724
5910
if (parsing_disabled == 0)
5971
6157
/* Definitions for replace result */
5973
typedef struct st_pointer_array { /* when using array-strings */
5974
TYPELIB typelib; /* Pointer to strings */
5975
unsigned char *str; /* Strings is here */
5976
uint8_t *flag; /* Flag about each var. */
5977
uint array_allocs,max_count,length,max_length;
6159
typedef struct st_pointer_array { /* when using array-strings */
6160
TYPELIB typelib; /* Pointer to strings */
6161
uchar *str; /* Strings is here */
6162
int7 *flag; /* Flag about each var. */
6163
uint array_allocs,max_count,length,max_length;
5978
6164
} POINTER_ARRAY;
5980
6166
struct st_replace;
5981
6167
struct st_replace *init_replace(char * *from, char * *to, uint count,
5982
char * word_end_chars);
6168
char * word_end_chars);
5983
6169
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5984
void replace_strings_append(struct st_replace *rep, string* ds,
6170
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5985
6171
const char *from, int len);
5986
6172
void free_pointer_array(POINTER_ARRAY *pa);
6079
6266
/* Loop through states */
6080
6267
while (!rep_pos->found)
6081
rep_pos= rep_pos->next[(unsigned char) *from++];
6268
rep_pos= rep_pos->next[(uchar) *from++];
6083
6270
/* Does this state contain a string to be replaced */
6084
6271
if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6086
6273
/* No match found */
6087
ds->append(start, from - start - 1);
6274
dynstr_append_mem(ds, start, from - start - 1);
6091
6278
/* Append part of original string before replace string */
6092
ds->append(start, (from - rep_str->to_offset) - start);
6279
dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6094
6281
/* Append replace string */
6095
ds->append(rep_str->replace_string,
6096
strlen(rep_str->replace_string));
6282
dynstr_append_mem(ds, rep_str->replace_string,
6283
strlen(rep_str->replace_string));
6098
6285
if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6415
6602
#define LAST_CHAR_CODE 259
6417
6604
typedef struct st_rep_set {
6418
uint *bits; /* Pointer to used sets */
6419
short next[LAST_CHAR_CODE]; /* Pointer to next sets */
6420
uint found_len; /* Best match to date */
6423
uint size_of_bits; /* For convinience */
6605
uint *bits; /* Pointer to used sets */
6606
short next[LAST_CHAR_CODE]; /* Pointer to next sets */
6607
uint found_len; /* Best match to date */
6610
uint size_of_bits; /* For convinience */
6426
6613
typedef struct st_rep_sets {
6427
uint count; /* Number of sets */
6428
uint extra; /* Extra sets in buffer */
6429
uint invisible; /* Sets not chown */
6431
REP_SET *set,*set_buffer;
6614
uint count; /* Number of sets */
6615
uint extra; /* Extra sets in buffer */
6616
uint invisible; /* Sets not chown */
6618
REP_SET *set,*set_buffer;
6435
6622
typedef struct st_found_set {
6512
6699
if (len > max_length)
6513
6700
max_length=len;
6515
memset(is_word_end, 0, sizeof(is_word_end));
6702
bzero((char*) is_word_end,sizeof(is_word_end));
6516
6703
for (i=0 ; word_end_chars[i] ; i++)
6517
is_word_end[(unsigned char) word_end_chars[i]]=1;
6704
is_word_end[(uchar) word_end_chars[i]]=1;
6519
6706
if (init_sets(&sets,states))
6522
6709
if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
6525
6712
free_sets(&sets);
6528
make_new_set(&sets); /* Set starting set */
6529
make_sets_invisible(&sets); /* Hide previus sets */
6715
VOID(make_new_set(&sets)); /* Set starting set */
6716
make_sets_invisible(&sets); /* Hide previus sets */
6531
word_states=make_new_set(&sets); /* Start of new word */
6532
start_states=make_new_set(&sets); /* This is first state */
6718
word_states=make_new_set(&sets); /* Start of new word */
6719
start_states=make_new_set(&sets); /* This is first state */
6533
6720
if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6535
6722
free_sets(&sets);
6723
my_free(found_set,MYF(0));
6545
6732
internal_set_bit(start_states,states+1);
6546
6733
if (!from[i][2])
6548
start_states->table_offset=i;
6549
start_states->found_offset=1;
6735
start_states->table_offset=i;
6736
start_states->found_offset=1;
6552
6739
else if (from[i][0] == '\\' && from[i][1] == '$')
6554
6741
internal_set_bit(start_states,states);
6555
6742
internal_set_bit(word_states,states);
6556
if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6743
if (!from[i][2] && start_states->table_offset == (uint) ~0)
6558
start_states->table_offset=i;
6559
start_states->found_offset=0;
6745
start_states->table_offset=i;
6746
start_states->found_offset=0;
6564
6751
internal_set_bit(word_states,states);
6565
6752
if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6566
internal_set_bit(start_states,states+1);
6753
internal_set_bit(start_states,states+1);
6568
internal_set_bit(start_states,states);
6755
internal_set_bit(start_states,states);
6570
6757
for (pos=from[i], len=0; *pos ; pos++)
6572
6759
if (*pos == '\\' && *(pos+1))
6577
follow_ptr->chr = SPACE_CHAR;
6580
follow_ptr->chr = START_OF_LINE;
6583
follow_ptr->chr = END_OF_LINE;
6586
follow_ptr->chr = '\r';
6589
follow_ptr->chr = '\t';
6592
follow_ptr->chr = '\v';
6595
follow_ptr->chr = (unsigned char) *pos;
6764
follow_ptr->chr = SPACE_CHAR;
6767
follow_ptr->chr = START_OF_LINE;
6770
follow_ptr->chr = END_OF_LINE;
6773
follow_ptr->chr = '\r';
6776
follow_ptr->chr = '\t';
6779
follow_ptr->chr = '\v';
6782
follow_ptr->chr = (uchar) *pos;
6600
follow_ptr->chr= (unsigned char) *pos;
6787
follow_ptr->chr= (uchar) *pos;
6601
6788
follow_ptr->table_offset=i;
6602
6789
follow_ptr->len= ++len;
6613
6800
for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6615
6802
set=sets.set+set_nr;
6616
default_state= 0; /* Start from beginning */
6803
default_state= 0; /* Start from beginning */
6618
6805
/* If end of found-string not found or start-set with current set */
6620
for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6807
for (i= (uint) ~0; (i=get_next_bit(set,i)) ;)
6622
6809
if (!follow[i].chr)
6624
if (! default_state)
6625
default_state= find_found(found_set,set->table_offset,
6626
set->found_offset+1);
6811
if (! default_state)
6812
default_state= find_found(found_set,set->table_offset,
6813
set->found_offset+1);
6629
copy_bits(sets.set+used_sets,set); /* Save set for changes */
6816
copy_bits(sets.set+used_sets,set); /* Save set for changes */
6630
6817
if (!default_state)
6631
or_bits(sets.set+used_sets,sets.set); /* Can restart from start */
6818
or_bits(sets.set+used_sets,sets.set); /* Can restart from start */
6633
6820
/* Find all chars that follows current sets */
6634
memset(used_chars, 0, sizeof(used_chars));
6635
for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6821
bzero((char*) used_chars,sizeof(used_chars));
6822
for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6637
6824
used_chars[follow[i].chr]=1;
6638
6825
if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6639
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6826
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6643
6830
/* Mark word_chars used if \b is in state */
6644
6831
if (used_chars[SPACE_CHAR])
6645
6832
for (pos= word_end_chars ; *pos ; pos++)
6646
used_chars[(int) (unsigned char) *pos] = 1;
6833
used_chars[(int) (uchar) *pos] = 1;
6648
6835
/* Handle other used characters */
6649
6836
for (chr= 0 ; chr < 256 ; chr++)
6651
6838
if (! used_chars[chr])
6652
set->next[chr]= chr ? default_state : -1;
6839
set->next[chr]= chr ? default_state : -1;
6655
new_set=make_new_set(&sets);
6656
set=sets.set+set_nr; /* if realloc */
6657
new_set->table_offset=set->table_offset;
6658
new_set->found_len=set->found_len;
6659
new_set->found_offset=set->found_offset+1;
6842
new_set=make_new_set(&sets);
6843
set=sets.set+set_nr; /* if realloc */
6844
new_set->table_offset=set->table_offset;
6845
new_set->found_len=set->found_len;
6846
new_set->found_offset=set->found_offset+1;
6662
for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6664
if (!follow[i].chr || follow[i].chr == chr ||
6665
(follow[i].chr == SPACE_CHAR &&
6666
(is_word_end[chr] ||
6667
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6668
(follow[i].chr == END_OF_LINE && ! chr))
6670
if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6671
follow[i].len > found_end)
6672
found_end=follow[i].len;
6673
if (chr && follow[i].chr)
6674
internal_set_bit(new_set,i+1); /* To next set */
6676
internal_set_bit(new_set,i);
6681
new_set->found_len=0; /* Set for testing if first */
6683
for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6685
if ((follow[i].chr == SPACE_CHAR ||
6686
follow[i].chr == END_OF_LINE) && ! chr)
6690
if (follow[bit_nr-1].len < found_end ||
6691
(new_set->found_len &&
6692
(chr == 0 || !follow[bit_nr].chr)))
6693
internal_clear_bit(new_set,i);
6696
if (chr == 0 || !follow[bit_nr].chr)
6698
new_set->table_offset=follow[bit_nr].table_offset;
6699
if (chr || (follow[i].chr == SPACE_CHAR ||
6700
follow[i].chr == END_OF_LINE))
6701
new_set->found_offset=found_end; /* New match */
6702
new_set->found_len=found_end;
6709
set->next[chr] = find_found(found_set,
6710
new_set->table_offset,
6711
new_set->found_offset);
6712
free_last_set(&sets);
6715
set->next[chr] = find_set(&sets,new_set);
6718
set->next[chr] = find_set(&sets,new_set);
6849
for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6851
if (!follow[i].chr || follow[i].chr == chr ||
6852
(follow[i].chr == SPACE_CHAR &&
6853
(is_word_end[chr] ||
6854
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
6855
(follow[i].chr == END_OF_LINE && ! chr))
6857
if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
6858
follow[i].len > found_end)
6859
found_end=follow[i].len;
6860
if (chr && follow[i].chr)
6861
internal_set_bit(new_set,i+1); /* To next set */
6863
internal_set_bit(new_set,i);
6868
new_set->found_len=0; /* Set for testing if first */
6870
for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
6872
if ((follow[i].chr == SPACE_CHAR ||
6873
follow[i].chr == END_OF_LINE) && ! chr)
6877
if (follow[bit_nr-1].len < found_end ||
6878
(new_set->found_len &&
6879
(chr == 0 || !follow[bit_nr].chr)))
6880
internal_clear_bit(new_set,i);
6883
if (chr == 0 || !follow[bit_nr].chr)
6885
new_set->table_offset=follow[bit_nr].table_offset;
6886
if (chr || (follow[i].chr == SPACE_CHAR ||
6887
follow[i].chr == END_OF_LINE))
6888
new_set->found_offset=found_end; /* New match */
6889
new_set->found_len=found_end;
6896
set->next[chr] = find_found(found_set,
6897
new_set->table_offset,
6898
new_set->found_offset);
6899
free_last_set(&sets);
6902
set->next[chr] = find_set(&sets,new_set);
6905
set->next[chr] = find_set(&sets,new_set);
6733
6920
for (i=0 ; i < count ; i++)
6735
6922
to_array[i]=to_pos;
6736
to_pos=my_stpcpy(to_pos,to[i])+1;
6923
to_pos=strmov(to_pos,to[i])+1;
6738
6925
rep_str[0].found=1;
6739
6926
rep_str[0].replace_string=0;
6740
6927
for (i=1 ; i <= found_sets ; i++)
6742
6929
pos=from[found_set[i-1].table_offset];
6743
rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
6930
rep_str[i].found= !bcmp((const uchar*) pos,
6931
(const uchar*) "\\^", 3) ? 2 : 1;
6744
6932
rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
6745
6933
rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
6746
6934
rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6749
6937
for (i=0 ; i < sets.count ; i++)
6751
6939
for (j=0 ; j < 256 ; j++)
6752
if (sets.set[i].next[j] >= 0)
6753
replace[i].next[j]=replace+sets.set[i].next[j];
6755
replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6940
if (sets.set[i].next[j] >= 0)
6941
replace[i].next[j]=replace+sets.set[i].next[j];
6943
replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
6946
my_free(follow,MYF(0));
6759
6947
free_sets(&sets);
6948
my_free(found_set,MYF(0));
6761
6949
return(replace);
6765
6953
int init_sets(REP_SETS *sets,uint states)
6767
memset(sets, 0, sizeof(*sets));
6955
bzero((char*) sets,sizeof(*sets));
6768
6956
sets->size_of_bits=((states+7)/8);
6769
6957
if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
6772
6960
if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
6773
SET_MALLOC_HUNC,MYF(MY_WME))))
6961
SET_MALLOC_HUNC,MYF(MY_WME))))
6963
my_free(sets->set,MYF(0));
6797
6985
set=sets->set+ sets->count++;
6798
memset(set->bits, 0, sizeof(uint)*sets->size_of_bits);
6799
memset(&set->next[0], 0, sizeof(set->next[0])*LAST_CHAR_CODE);
6986
bzero((char*) set->bits,sizeof(uint)*sets->size_of_bits);
6987
bzero((char*) &set->next[0],sizeof(set->next[0])*LAST_CHAR_CODE);
6800
6988
set->found_offset=0;
6801
6989
set->found_len=0;
6802
set->table_offset= UINT32_MAX;
6990
set->table_offset= (uint) ~0;
6803
6991
set->size_of_bits=sets->size_of_bits;
6806
6994
count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6807
if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
6995
if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6808
6996
sizeof(REP_SET)*count,
6811
6999
sets->set_buffer=set;
6812
7000
sets->set=set+sets->invisible;
6813
if (!(bit_buffer=(uint*) my_realloc((unsigned char*) sets->bit_buffer,
6814
(sizeof(uint)*sets->size_of_bits)*count,
7001
if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
7002
(sizeof(uint)*sets->size_of_bits)*count,
6817
7005
sets->bit_buffer=bit_buffer;
6818
7006
for (i=0 ; i < count ; i++)
6925
7114
for (i=0 ; (uint) i < found_sets ; i++)
6926
7115
if (found_set[i].table_offset == table_offset &&
6927
found_set[i].found_offset == found_offset)
7116
found_set[i].found_offset == found_offset)
6929
7118
found_set[i].table_offset=table_offset;
6930
7119
found_set[i].found_offset=found_offset;
6932
return -i-2; /* return new postion */
7121
return -i-2; /* return new postion */
6935
7124
/* Return 1 if regexp starts with \b or ends with \b*/
6937
7126
uint start_at_word(char * pos)
6939
return (((!memcmp(pos, "\\b",2) && pos[2]) ||
6940
!memcmp(pos, "\\^", 2)) ? 1 : 0);
7128
return (((!bcmp((const uchar*) pos, (const uchar*) "\\b",2) && pos[2]) ||
7129
!bcmp((const uchar*) pos, (const uchar*) "\\^", 2)) ? 1 : 0);
6943
7132
uint end_of_word(char * pos)
6945
char * end= strchr(pos, '\0');
6946
return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
6947
(end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7134
char * end=strend(pos);
7135
return ((end > pos+2 && !bcmp((const uchar*) end-2,
7136
(const uchar*) "\\b", 2)) ||
7137
(end >= pos+2 && !bcmp((const uchar*) end-2,
7138
(const uchar*) "\\$",2))) ? 1 : 0;
6950
7141
/****************************************************************************
6951
7142
* Handle replacement of strings
6952
7143
****************************************************************************/
6954
#define PC_MALLOC 256 /* Bytes for pointers */
6955
#define PS_MALLOC 512 /* Bytes for data */
7145
#define PC_MALLOC 256 /* Bytes for pointers */
7146
#define PS_MALLOC 512 /* Bytes for data */
6957
7148
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6959
7150
uint i,length,old_count;
6960
unsigned char *new_pos;
6961
7152
const char **new_array;
6964
7155
if (! pa->typelib.count)
6966
7157
if (!(pa->typelib.type_names=(const char **)
6967
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
6968
(sizeof(char *)+sizeof(*pa->flag))*
6969
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
7158
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7159
(sizeof(char *)+sizeof(*pa->flag))*
7160
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6971
if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
7162
if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
6974
free((char*) pa->typelib.type_names);
7165
my_free((char*) pa->typelib.type_names,MYF(0));
6977
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(unsigned char*)+
6979
pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
7168
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7170
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6981
7172
pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6982
7173
pa->array_allocs=1;
7004
7195
pa->array_allocs++;
7005
7196
len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
7006
if (!(new_array=(const char **) my_realloc((unsigned char*) pa->typelib.type_names,
7008
(sizeof(unsigned char*)+sizeof(*pa->flag))*
7009
(sizeof(unsigned char*)+sizeof(*pa->flag)),
7197
if (!(new_array=(const char **) my_realloc((uchar*) pa->typelib.type_names,
7199
(sizeof(uchar*)+sizeof(*pa->flag))*
7200
(sizeof(uchar*)+sizeof(*pa->flag)),
7012
7203
pa->typelib.type_names=new_array;
7013
7204
old_count=pa->max_count;
7014
pa->max_count=len/(sizeof(unsigned char*) + sizeof(*pa->flag));
7015
pa->flag= (uint8_t*) (pa->typelib.type_names+pa->max_count);
7016
memcpy(pa->flag, pa->typelib.type_names+old_count,
7017
old_count*sizeof(*pa->flag));
7205
pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
7206
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
7207
memcpy((uchar*) pa->flag,(char *) (pa->typelib.type_names+old_count),
7208
old_count*sizeof(*pa->flag));
7019
pa->flag[pa->typelib.count]=0; /* Reset flag */
7210
pa->flag[pa->typelib.count]=0; /* Reset flag */
7020
7211
pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
7021
pa->typelib.type_names[pa->typelib.count]= NULL; /* Put end-mark */
7022
my_stpcpy((char*) pa->str+pa->length,name);
7212
pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
7213
VOID(strmov((char*) pa->str+pa->length,name));
7023
7214
pa->length+=length;
7025
7216
} /* insert_pointer_name */
7042
7233
/* Functions that uses replace and replace_regex */
7044
7235
/* Append the string to ds, with optional replace */
7045
void replace_append_mem(string *ds,
7046
const char *val, int len)
7236
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
7237
const char *val, int len)
7048
char *v= strdup(val);
7050
7239
if (glob_replace_regex)
7052
7241
/* Regex replace */
7053
if (!multi_reg_replace(glob_replace_regex, v))
7242
if (!multi_reg_replace(glob_replace_regex, (char*)val))
7055
v= glob_replace_regex->buf;
7244
val= glob_replace_regex->buf;
7060
7249
if (glob_replace)
7062
7251
/* Normal replace */
7063
replace_strings_append(glob_replace, ds, v, len);
7252
replace_strings_append(glob_replace, ds, val, len);
7255
dynstr_append_mem(ds, val, len);
7072
7259
/* Append zero-terminated string to ds, with optional replace */
7073
void replace_append(string *ds, const char *val)
7260
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7075
replace_append_mem(ds, val, strlen(val));
7262
replace_dynstr_append_mem(ds, val, strlen(val));
7078
7265
/* Append uint to ds, with optional replace */
7079
void replace_append_uint(string *ds, uint val)
7266
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7081
7268
char buff[22]; /* This should be enough for any int */
7082
7269
char *end= int64_t10_to_str(val, buff, 10);
7083
replace_append_mem(ds, buff, end - buff);
7270
replace_dynstr_append_mem(ds, buff, end - buff);
7102
void append_sorted(string* ds, string *ds_input)
7104
priority_queue<string> lines;
7106
if (ds_input->empty())
7287
static int comp_lines(const char **a, const char **b)
7289
return (strcmp(*a,*b));
7292
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input)
7295
char *start= ds_input->str;
7296
DYNAMIC_ARRAY lines;
7107
7300
return; /* No input */
7109
unsigned long eol_pos= 0;
7111
eol_pos= ds_input->find_first_of('\n', 0);
7112
if (eol_pos == string::npos)
7113
return; // We should have at least one header here
7115
ds->append(ds_input->substr(0, eol_pos));
7117
unsigned long start_pos= eol_pos+1;
7302
my_init_dynamic_array(&lines, sizeof(const char*), 32, 32);
7304
/* First line is result header, skip past it */
7305
while (*start && *start != '\n')
7307
start++; /* Skip past \n */
7308
dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
7119
7310
/* Insert line(s) in array */
7313
char* line_end= (char*)start;
7122
eol_pos= ds_input->find_first_of('\n', start_pos);
7123
7315
/* Find end of line */
7124
lines.push(ds_input->substr(start_pos, eol_pos-start_pos));
7125
start_pos= eol_pos+1;
7127
} while ( eol_pos != string::npos);
7316
while (*line_end && *line_end != '\n')
7320
/* Insert pointer to the line in array */
7321
if (insert_dynamic(&lines, (uchar*) &start))
7322
die("Out of memory inserting lines to sort");
7328
qsort(lines.buffer, lines.elements,
7329
sizeof(char**), (qsort_cmp)comp_lines);
7129
7331
/* Create new result */
7130
while (!lines.empty()) {
7131
ds->append(lines.top());
7332
for (i= 0; i < lines.elements ; i++)
7334
const char **line= dynamic_element(&lines, i, const char**);
7335
dynstr_append(ds, *line);
7336
dynstr_append(ds, "\n");
7339
delete_dynamic(&lines);