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,
3689
static void safe_connect(MYSQL* mysql, const char *name, const char *host,
3690
const char *user, const char *pass, const char *db,
3563
3693
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))
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))
3575
3705
on protocol/connection type
3578
if ((drizzle_errno(drizzle) == CR_CONN_HOST_ERROR ||
3579
drizzle_errno(drizzle) == CR_CONNECTION_ERROR) &&
3708
if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
3709
mysql_errno(mysql) == CR_CONNECTION_ERROR) &&
3580
3710
failed_attempts < opt_max_connect_retries)
3582
3712
verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts,
3583
opt_max_connect_retries, drizzle_errno(drizzle),
3584
drizzle_error(drizzle));
3713
opt_max_connect_retries, mysql_errno(mysql),
3714
mysql_error(mysql));
3585
3715
my_sleep(connection_retry_sleep);
3589
3719
if (failed_attempts > 0)
3590
3720
die("Could not open connection '%s' after %d attempts: %d %s", name,
3591
failed_attempts, drizzle_errno(drizzle), drizzle_error(drizzle));
3721
failed_attempts, mysql_errno(mysql), mysql_error(mysql));
3593
3723
die("Could not open connection '%s': %d %s", name,
3594
drizzle_errno(drizzle), drizzle_error(drizzle));
3724
mysql_errno(mysql), mysql_error(mysql));
3596
3726
failed_attempts++;
3636
3769
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);
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);
3646
replace_append(&ds_res, db);
3648
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);
3651
replace_append(&ds_res, sock);
3653
ds_res.append(delimiter);
3654
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);
3656
if (!drizzle_connect(con, host, user, pass, db, port, 0,
3657
CLIENT_MULTI_STATEMENTS))
3789
if (!mysql_real_connect(con, host, user, pass, db, port, 0,
3790
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);
3792
var_set_errno(mysql_errno(con));
3793
handle_error(command, mysql_errno(con), mysql_error(con),
3794
mysql_sqlstate(con), ds);
3662
3795
return 0; /* Not connected */
3688
3821
<port> - server port
3689
3822
<sock> - server socket
3690
3823
<opts> - options to use for the connection
3691
* SSL - use SSL if available
3692
* COMPRESS - use compression if available
3824
* SSL - use SSL if available
3825
* COMPRESS - use compression if available
3696
3829
static void do_connect(struct st_command *command)
3698
3831
int con_port= opt_port;
3699
const char *con_options;
3700
3833
bool con_ssl= 0, con_compress= 0;
3701
3834
struct st_connection* con_slot;
3703
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;
3711
3844
const struct command_arg connect_args[] = {
3712
3845
{ "connection name", ARG_STRING, true, &ds_connection_name, "Name of the connection" },
3713
3846
{ "host", ARG_STRING, true, &ds_host, "Host to connect to" },
3729
if (ds_port.length())
3731
con_port= atoi(ds_port.c_str());
3864
con_port= atoi(ds_port.str);
3732
3865
if (con_port == 0)
3733
die("Illegal argument for port: '%s'", ds_port.c_str());
3866
die("Illegal argument for port: '%s'", ds_port.str);
3737
if (!ds_sock.empty())
3740
3873
If the socket is specified just as a name without path
3741
3874
append tmpdir in front
3743
if (*ds_sock.c_str() != FN_LIBCHAR)
3876
if (*ds_sock.str != FN_LIBCHAR)
3745
3878
char buff[FN_REFLEN];
3746
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);
3752
con_options= ds_options.c_str();
3890
con_options= ds_options.str;
3753
3891
while (*con_options)
3756
3894
/* Step past any spaces in beginning of option*/
3757
3895
while (*con_options && my_isspace(charset_info, *con_options))
3759
3897
/* Find end of this option */
3760
3898
end= con_options;
3761
3899
while (*end && !my_isspace(charset_info, *end))
3785
3921
(int) (sizeof(connections)/sizeof(struct st_connection)));
3788
if (!drizzle_create(&con_slot->drizzle))
3789
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()");
3790
3929
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);
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,
3794
3940
/* Use default db name */
3795
if (ds_database.length() == 0)
3796
ds_database= opt_db;
3941
if (ds_database.length == 0)
3942
dynstr_set(&ds_database, opt_db);
3798
3944
/* Special database to allow one to connect without a database name */
3799
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, "");
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()))
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))
3807
if (!(con_slot->name= strdup(ds_connection_name.c_str())))
3953
if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
3808
3954
die("Out of memory");
3809
3955
cur_con= con_slot;
3811
3957
if (con_slot == next_con)
3812
3958
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);
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);
4062
4216
if (end_of_query(c))
4067
4221
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))))
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))))
4073
4227
/* Only if and while commands can be terminated by { */
4078
4232
else if (c == '\'' || c == '"' || c == '`')
4151
4305
/* completed before we pass buf_end */
4152
4306
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)
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)
4179
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" \
4180
4334
"check your query or increase MAX_QUERY and recompile");
4453
4607
{"password", 'p', "Password to use when connecting to server.",
4454
4608
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4455
4609
{"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) ").",
4610
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
4611
#if MYSQL_PORT_DEFAULT == 0
4614
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
4458
4615
(char**) &opt_port,
4459
4616
(char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4460
4617
{"quiet", 's', "Suppress all normal output.", (char**) &silent,
4531
4693
if (!embedded_server_arg_count)
4533
4695
embedded_server_arg_count=1;
4534
embedded_server_args[0]= (char*) ""; /* Progname */
4696
embedded_server_args[0]= (char*) ""; /* Progname */
4536
4698
if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4537
4699
die("Failed to open file '%s'", buff);
4539
4701
while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4540
(str=fgets(argument,sizeof(argument), file)))
4702
(str=fgets(argument,sizeof(argument), file)))
4542
*(strchr(str, '\0')-1)=0; /* Remove end newline */
4704
*(strend(str)-1)=0; /* Remove end newline */
4543
4705
if (!(embedded_server_args[embedded_server_arg_count]=
4544
(char*) my_strdup(str,MYF(MY_WME))))
4706
(char*) my_strdup(str,MYF(MY_WME))))
4546
4708
my_fclose(file,MYF(0));
4547
4709
die("Out of memory");
4587
4749
static char buff[FN_REFLEN];
4588
4750
if (!test_if_hard_path(argument))
4590
strxmov(buff, opt_basedir, argument, NULL);
4752
strxmov(buff, opt_basedir, argument, NullS);
4591
4753
argument= buff;
4593
4755
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4594
4756
timer_file= buff;
4595
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));
4602
4764
opt_pass= my_strdup(argument, MYF(MY_FAE));
4603
while (*argument) *argument++= 'x'; /* Destroy argument */
4765
while (*argument) *argument++= 'x'; /* Destroy argument */
4604
4766
tty_password= 0;
4607
4769
tty_password= 1;
4610
my_stpncpy(TMPDIR, argument, sizeof(TMPDIR));
4772
strnmov(TMPDIR, argument, sizeof(TMPDIR));
4613
4775
if (!embedded_server_arg_count)
4783
4945
Values may be converted with 'replace_column'
4786
static void append_result(string *ds, DRIZZLE_RES *res)
4948
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);
4951
uint32_t num_fields= mysql_num_fields(res);
4952
MYSQL_FIELD *fields= mysql_fetch_fields(res);
4791
4953
uint32_t *lengths;
4793
while ((row = drizzle_fetch_row(res)))
4955
while ((row = mysql_fetch_row(res)))
4796
lengths = drizzle_fetch_lengths(res);
4958
lengths = mysql_fetch_lengths(res);
4797
4959
for (i = 0; i < num_fields; i++)
4798
4960
append_field(ds, i, &fields[i],
4799
4961
(const char*)row[i], lengths[i], !row[i]);
4800
4962
if (!display_result_vertically)
4963
dynstr_append_mem(ds, "\n", 1);
4808
4969
Append metadata for fields to output
4811
static void append_metadata(string *ds,
4812
const DRIZZLE_FIELD *field,
4972
static void append_metadata(DYNAMIC_STRING *ds,
4813
4974
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");
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");
4820
4981
for (field_end= field+num_fields ;
4821
4982
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);
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);
4914
5075
through PS API we should not issue SHOW WARNINGS until
4915
5076
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)))
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)))
4923
5084
die("Warning count is %u but didn't get any warnings",
4926
5087
append_result(ds, warn_res);
5088
mysql_free_result(warn_res);
4933
Run query using DRIZZLE C API
5095
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
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
4945
5107
static void run_query_normal(struct st_connection *cn,
4946
5108
struct st_command *command,
4947
5109
int flags, char *query, int query_len,
4948
string *ds, string *ds_warnings)
5110
DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
4950
DRIZZLE_RES *res= 0;
4951
DRIZZLE *drizzle= &cn->drizzle;
5113
MYSQL *mysql= &cn->mysql;
4952
5114
int err= 0, counter= 0;
4954
5116
if (flags & QUERY_SEND_FLAG)
4959
5121
if (do_send_query(cn, query, query_len, flags))
4961
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4962
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*/
4966
5136
if (!(flags & QUERY_REAP_FLAG))
4972
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
4973
5143
answer to the query sent earlier
4975
if ((counter==0) && drizzle_read_query_result(drizzle))
5145
if ((counter==0) && mysql_read_query_result(mysql))
4977
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4978
drizzle_sqlstate(drizzle), ds);
5147
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
5148
mysql_sqlstate(mysql), ds);
4999
const DRIZZLE_FIELD *fields= drizzle_fetch_fields(res);
5000
uint num_fields= drizzle_num_fields(res);
5169
MYSQL_FIELD *fields= mysql_fetch_fields(res);
5170
uint num_fields= mysql_num_fields(res);
5002
if (display_metadata)
5172
if (display_metadata)
5003
5173
append_metadata(ds, fields, num_fields);
5005
if (!display_result_vertically)
5006
append_table_headings(ds, fields, num_fields);
5175
if (!display_result_vertically)
5176
append_table_headings(ds, fields, num_fields);
5008
append_result(ds, res);
5178
append_result(ds, res);
5012
Need to call drizzle_affected_rows() before the "new"
5182
Need to call mysql_affected_rows() before the "new"
5013
5183
query to find the warnings
5015
5185
if (!disable_info)
5016
affected_rows= drizzle_affected_rows(drizzle);
5186
affected_rows= mysql_affected_rows(mysql);
5019
5189
Add all warnings to the result. We can't do this if we are in
5020
5190
the middle of processing results from multi-statement, because
5021
5191
this will break protocol.
5023
if (!disable_warnings && !drizzle_more_results(drizzle))
5193
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());
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);
5032
5202
if (!disable_info)
5033
append_info(ds, affected_rows, drizzle_info(drizzle));
5203
append_info(ds, affected_rows, mysql_info(mysql));
5038
drizzle_free_result(res);
5208
mysql_free_result(res);
5042
} while (!(err= drizzle_next_result(drizzle)));
5212
} 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);
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);
5050
5220
assert(err == -1); /* Successful and there are no more results */
5120
5291
if (command->expected_errors.count == 1)
5122
5293
/* 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);
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);
5129
5300
/* Don't log error if we may not get an error */
5130
5301
else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
5131
5302
(command->expected_errors.err[0].type == ERR_ERRNO &&
5132
5303
command->expected_errors.err[0].code.errnum != 0))
5133
ds->append("Got one of the listed errors\n");
5304
dynstr_append(ds,"Got one of the listed errors\n");
5204
drizzle DRIZZLE handle
5205
command currrent command pointer
5376
command currrent command pointer
5207
5378
flags control the phased/stages of query execution to be performed
5208
5379
if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
5209
5380
is on the result will be read - for regular query, both bits must be on
5212
static void run_query(struct st_connection *cn,
5383
static void run_query(struct st_connection *cn,
5213
5384
struct st_command *command,
5217
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);
5226
5399
/* Scan for warning before sending to server */
5227
5400
scan_command_for_warnings(command);
5250
5424
if (command->require_file[0])
5426
init_dynamic_string(&ds_result, "", 1024, 1024);
5252
5427
ds= &ds_result;
5259
5433
Log the query into the output buffer
5261
5435
if (!disable_query_log && (flags & QUERY_SEND_FLAG))
5263
replace_append_mem(ds, query, query_len);
5264
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);
5268
5442
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
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);
5275
5450
save_ds= ds; /* Remember original ds */
5276
5451
ds= &ds_sorted;
5403
5584
/* Milliseconds since start */
5404
5585
end= int64_t2str(timer, buf, 10);
5405
ds_progress.append(buf, (int)(end-buf));
5406
ds_progress.append("\t", 1);
5586
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5587
dynstr_append_mem(&ds_progress, "\t", 1);
5408
5589
/* Parser line number */
5409
5590
end= int10_to_str(line, buf, 10);
5410
ds_progress.append(buf, (int)(end-buf));
5411
ds_progress.append("\t", 1);
5591
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5592
dynstr_append_mem(&ds_progress, "\t", 1);
5414
ds_progress.append(cur_file->file_name);
5415
ds_progress.append(":", 1);
5595
dynstr_append(&ds_progress, cur_file->file_name);
5596
dynstr_append_mem(&ds_progress, ":", 1);
5417
5598
/* Line in file */
5418
5599
end= int10_to_str(cur_file->lineno, buf, 10);
5419
ds_progress.append(buf, (int)(end-buf));
5422
ds_progress.append("\n", 1);
5600
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
5603
dynstr_append_mem(&ds_progress, "\n", 1);
5486
5678
cur_file->lineno= 1;
5488
5680
cur_con= connections;
5489
if (!( drizzle_create(&cur_con->drizzle)))
5490
die("Failed in drizzle_create()");
5681
if (!( mysql_init(&cur_con->mysql)))
5682
die("Failed in mysql_init()");
5491
5683
if (opt_compress)
5492
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NULL);
5493
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,
5495
5694
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5496
5695
die("Out of memory");
5498
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,
5499
5698
opt_db, opt_port);
5501
5700
/* Use all time until exit if no explicit 'start_timer' */
5502
5701
timer_start= timer_now();
5505
Initialize $drizzle_errno with -1, so we can
5704
Initialize $mysql_errno with -1, so we can
5506
5705
- distinguish it from valid values ( >= 0 ) and
5507
5706
- detect if there was never a command sent to the server
5509
5708
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);
5710
/* Update $mysql_get_server_version to that of current connection */
5711
var_set_mysql_get_server_version(&cur_con->mysql);
5514
5713
if (opt_include)
5655
5852
/* Remove "send" if this is first iteration */
5656
if (command->query == command->query_buf)
5657
command->query= command->first_argument;
5853
if (command->query == command->query_buf)
5854
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
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
5662
5859
the query and read the result some time later when reap instruction
5663
is given on this connection.
5860
is given on this connection.
5665
run_query(cur_con, command, QUERY_SEND_FLAG);
5862
run_query(cur_con, command, QUERY_SEND_FLAG);
5667
5864
command->last_argument= command->end;
5669
5866
case Q_REQUIRE:
5670
do_get_file_name(command, save_file, sizeof(save_file));
5867
do_get_file_name(command, save_file, sizeof(save_file));
5673
5870
do_get_errcodes(command);
5675
5872
case Q_REPLACE:
5676
do_get_replace(command);
5873
do_get_replace(command);
5678
5875
case Q_REPLACE_REGEX:
5679
5876
do_get_replace_regex(command);
5681
5878
case Q_REPLACE_COLUMN:
5682
do_get_replace_column(command);
5879
do_get_replace_column(command);
5684
5881
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
5685
5882
case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
5686
5883
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);
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);
5696
case Q_COMMENT: /* Ignore row */
5893
case Q_COMMENT: /* Ignore row */
5697
5894
command->last_argument= command->end;
5700
(void) drizzle_ping(&cur_con->drizzle);
5897
(void) mysql_ping(&cur_con->mysql);
5706
5903
case Q_START_TIMER:
5707
/* Overwrite possible earlier start of timer */
5708
timer_start= timer_now();
5904
/* Overwrite possible earlier start of timer */
5905
timer_start= timer_now();
5710
5907
case Q_END_TIMER:
5711
/* End timer before ending drizzletest */
5908
/* End timer before ending mysqltest */
5714
5911
case Q_CHARACTER_SET:
5715
do_set_charset(command);
5912
do_set_charset(command);
5717
5914
case Q_DISABLE_RECONNECT:
5718
set_reconnect(&cur_con->drizzle, 0);
5915
set_reconnect(&cur_con->mysql, 0);
5720
5917
case Q_ENABLE_RECONNECT:
5721
set_reconnect(&cur_con->drizzle, 1);
5918
set_reconnect(&cur_con->mysql, 1);
5723
5920
case Q_DISABLE_PARSING:
5724
5921
if (parsing_disabled == 0)
5971
6168
/* 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;
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;
5978
6175
} POINTER_ARRAY;
5980
6177
struct st_replace;
5981
6178
struct st_replace *init_replace(char * *from, char * *to, uint count,
5982
char * word_end_chars);
6179
char * word_end_chars);
5983
6180
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
5984
void replace_strings_append(struct st_replace *rep, string* ds,
6181
void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
5985
6182
const char *from, int len);
5986
6183
void free_pointer_array(POINTER_ARRAY *pa);
6079
6277
/* Loop through states */
6080
6278
while (!rep_pos->found)
6081
rep_pos= rep_pos->next[(unsigned char) *from++];
6279
rep_pos= rep_pos->next[(uchar) *from++];
6083
6281
/* Does this state contain a string to be replaced */
6084
6282
if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
6086
6284
/* No match found */
6087
ds->append(start, from - start - 1);
6285
dynstr_append_mem(ds, start, from - start - 1);
6091
6289
/* Append part of original string before replace string */
6092
ds->append(start, (from - rep_str->to_offset) - start);
6290
dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
6094
6292
/* Append replace string */
6095
ds->append(rep_str->replace_string,
6096
strlen(rep_str->replace_string));
6293
dynstr_append_mem(ds, rep_str->replace_string,
6294
strlen(rep_str->replace_string));
6098
6296
if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
6415
6613
#define LAST_CHAR_CODE 259
6417
6615
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 */
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 */
6426
6624
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;
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;
6435
6633
typedef struct st_found_set {
6512
6710
if (len > max_length)
6513
6711
max_length=len;
6515
memset(is_word_end, 0, sizeof(is_word_end));
6713
bzero((char*) is_word_end,sizeof(is_word_end));
6516
6714
for (i=0 ; word_end_chars[i] ; i++)
6517
is_word_end[(unsigned char) word_end_chars[i]]=1;
6715
is_word_end[(uchar) word_end_chars[i]]=1;
6519
6717
if (init_sets(&sets,states))
6522
6720
if (!(found_set= (FOUND_SET*) my_malloc(sizeof(FOUND_SET)*max_length*count,
6525
6723
free_sets(&sets);
6528
make_new_set(&sets); /* Set starting set */
6529
make_sets_invisible(&sets); /* Hide previus sets */
6726
VOID(make_new_set(&sets)); /* Set starting set */
6727
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 */
6729
word_states=make_new_set(&sets); /* Start of new word */
6730
start_states=make_new_set(&sets); /* This is first state */
6533
6731
if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
6535
6733
free_sets(&sets);
6734
my_free(found_set,MYF(0));
6545
6743
internal_set_bit(start_states,states+1);
6546
6744
if (!from[i][2])
6548
start_states->table_offset=i;
6549
start_states->found_offset=1;
6746
start_states->table_offset=i;
6747
start_states->found_offset=1;
6552
6750
else if (from[i][0] == '\\' && from[i][1] == '$')
6554
6752
internal_set_bit(start_states,states);
6555
6753
internal_set_bit(word_states,states);
6556
if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6754
if (!from[i][2] && start_states->table_offset == (uint) ~0)
6558
start_states->table_offset=i;
6559
start_states->found_offset=0;
6756
start_states->table_offset=i;
6757
start_states->found_offset=0;
6564
6762
internal_set_bit(word_states,states);
6565
6763
if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6566
internal_set_bit(start_states,states+1);
6764
internal_set_bit(start_states,states+1);
6568
internal_set_bit(start_states,states);
6766
internal_set_bit(start_states,states);
6570
6768
for (pos=from[i], len=0; *pos ; pos++)
6572
6770
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;
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;
6600
follow_ptr->chr= (unsigned char) *pos;
6798
follow_ptr->chr= (uchar) *pos;
6601
6799
follow_ptr->table_offset=i;
6602
6800
follow_ptr->len= ++len;
6613
6811
for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6615
6813
set=sets.set+set_nr;
6616
default_state= 0; /* Start from beginning */
6814
default_state= 0; /* Start from beginning */
6618
6816
/* If end of found-string not found or start-set with current set */
6620
for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6818
for (i= (uint) ~0; (i=get_next_bit(set,i)) ;)
6622
6820
if (!follow[i].chr)
6624
if (! default_state)
6625
default_state= find_found(found_set,set->table_offset,
6626
set->found_offset+1);
6822
if (! default_state)
6823
default_state= find_found(found_set,set->table_offset,
6824
set->found_offset+1);
6629
copy_bits(sets.set+used_sets,set); /* Save set for changes */
6827
copy_bits(sets.set+used_sets,set); /* Save set for changes */
6630
6828
if (!default_state)
6631
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 */
6633
6831
/* 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)) ;)
6832
bzero((char*) used_chars,sizeof(used_chars));
6833
for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
6637
6835
used_chars[follow[i].chr]=1;
6638
6836
if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6639
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6837
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
6643
6841
/* Mark word_chars used if \b is in state */
6644
6842
if (used_chars[SPACE_CHAR])
6645
6843
for (pos= word_end_chars ; *pos ; pos++)
6646
used_chars[(int) (unsigned char) *pos] = 1;
6844
used_chars[(int) (uchar) *pos] = 1;
6648
6846
/* Handle other used characters */
6649
6847
for (chr= 0 ; chr < 256 ; chr++)
6651
6849
if (! used_chars[chr])
6652
set->next[chr]= chr ? default_state : -1;
6850
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;
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;
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);
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);
6733
6931
for (i=0 ; i < count ; i++)
6735
6933
to_array[i]=to_pos;
6736
to_pos=my_stpcpy(to_pos,to[i])+1;
6934
to_pos=strmov(to_pos,to[i])+1;
6738
6936
rep_str[0].found=1;
6739
6937
rep_str[0].replace_string=0;
6740
6938
for (i=1 ; i <= found_sets ; i++)
6742
6940
pos=from[found_set[i-1].table_offset];
6743
rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
6941
rep_str[i].found= !bcmp((const uchar*) pos,
6942
(const uchar*) "\\^", 3) ? 2 : 1;
6744
6943
rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
6745
6944
rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
6746
6945
rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6749
6948
for (i=0 ; i < sets.count ; i++)
6751
6950
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));
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));
6759
6958
free_sets(&sets);
6959
my_free(found_set,MYF(0));
6761
6960
return(replace);
6765
6964
int init_sets(REP_SETS *sets,uint states)
6767
memset(sets, 0, sizeof(*sets));
6966
bzero((char*) sets,sizeof(*sets));
6768
6967
sets->size_of_bits=((states+7)/8);
6769
6968
if (!(sets->set_buffer=(REP_SET*) my_malloc(sizeof(REP_SET)*SET_MALLOC_HUNC,
6772
6971
if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
6773
SET_MALLOC_HUNC,MYF(MY_WME))))
6972
SET_MALLOC_HUNC,MYF(MY_WME))))
6974
my_free(sets->set,MYF(0));
6797
6996
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);
6997
bzero((char*) set->bits,sizeof(uint)*sets->size_of_bits);
6998
bzero((char*) &set->next[0],sizeof(set->next[0])*LAST_CHAR_CODE);
6800
6999
set->found_offset=0;
6801
7000
set->found_len=0;
6802
set->table_offset= UINT32_MAX;
7001
set->table_offset= (uint) ~0;
6803
7002
set->size_of_bits=sets->size_of_bits;
6806
7005
count=sets->count+sets->invisible+SET_MALLOC_HUNC;
6807
if (!(set=(REP_SET*) my_realloc((unsigned char*) sets->set_buffer,
7006
if (!(set=(REP_SET*) my_realloc((uchar*) sets->set_buffer,
6808
7007
sizeof(REP_SET)*count,
6811
7010
sets->set_buffer=set;
6812
7011
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,
7012
if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
7013
(sizeof(uint)*sets->size_of_bits)*count,
6817
7016
sets->bit_buffer=bit_buffer;
6818
7017
for (i=0 ; i < count ; i++)
6925
7125
for (i=0 ; (uint) i < found_sets ; i++)
6926
7126
if (found_set[i].table_offset == table_offset &&
6927
found_set[i].found_offset == found_offset)
7127
found_set[i].found_offset == found_offset)
6929
7129
found_set[i].table_offset=table_offset;
6930
7130
found_set[i].found_offset=found_offset;
6932
return -i-2; /* return new postion */
7132
return -i-2; /* return new postion */
6935
7135
/* Return 1 if regexp starts with \b or ends with \b*/
6937
7137
uint start_at_word(char * pos)
6939
return (((!memcmp(pos, "\\b",2) && pos[2]) ||
6940
!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);
6943
7143
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;
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;
6950
7152
/****************************************************************************
6951
7153
* Handle replacement of strings
6952
7154
****************************************************************************/
6954
#define PC_MALLOC 256 /* Bytes for pointers */
6955
#define PS_MALLOC 512 /* Bytes for data */
7156
#define PC_MALLOC 256 /* Bytes for pointers */
7157
#define PS_MALLOC 512 /* Bytes for data */
6957
7159
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
6959
7161
uint i,length,old_count;
6960
unsigned char *new_pos;
6961
7163
const char **new_array;
6964
7166
if (! pa->typelib.count)
6966
7168
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))))
7169
my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
7170
(sizeof(char *)+sizeof(*pa->flag))*
7171
(sizeof(char *)+sizeof(*pa->flag))),MYF(MY_WME))))
6971
if (!(pa->str= (unsigned char*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
7173
if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
6974
free((char*) pa->typelib.type_names);
7176
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);
7179
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
7181
pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
6981
7183
pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
6982
7184
pa->array_allocs=1;
7004
7206
pa->array_allocs++;
7005
7207
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)),
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)),
7012
7214
pa->typelib.type_names=new_array;
7013
7215
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));
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));
7019
pa->flag[pa->typelib.count]=0; /* Reset flag */
7221
pa->flag[pa->typelib.count]=0; /* Reset flag */
7020
7222
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);
7223
pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
7224
VOID(strmov((char*) pa->str+pa->length,name));
7023
7225
pa->length+=length;
7025
7227
} /* insert_pointer_name */
7042
7244
/* Functions that uses replace and replace_regex */
7044
7246
/* Append the string to ds, with optional replace */
7045
void replace_append_mem(string *ds,
7046
const char *val, int len)
7247
void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
7248
const char *val, int len)
7048
char *v= strdup(val);
7050
7250
if (glob_replace_regex)
7052
7252
/* Regex replace */
7053
if (!multi_reg_replace(glob_replace_regex, v))
7253
if (!multi_reg_replace(glob_replace_regex, (char*)val))
7055
v= glob_replace_regex->buf;
7255
val= glob_replace_regex->buf;
7060
7260
if (glob_replace)
7062
7262
/* Normal replace */
7063
replace_strings_append(glob_replace, ds, v, len);
7263
replace_strings_append(glob_replace, ds, val, len);
7266
dynstr_append_mem(ds, val, len);
7072
7270
/* Append zero-terminated string to ds, with optional replace */
7073
void replace_append(string *ds, const char *val)
7271
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
7075
replace_append_mem(ds, val, strlen(val));
7273
replace_dynstr_append_mem(ds, val, strlen(val));
7078
7276
/* Append uint to ds, with optional replace */
7079
void replace_append_uint(string *ds, uint val)
7277
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
7081
7279
char buff[22]; /* This should be enough for any int */
7082
7280
char *end= int64_t10_to_str(val, buff, 10);
7083
replace_append_mem(ds, buff, end - buff);
7281
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())
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;
7107
7311
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;
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);
7119
7321
/* Insert line(s) in array */
7324
char* line_end= (char*)start;
7122
eol_pos= ds_input->find_first_of('\n', start_pos);
7123
7326
/* 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);
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);
7129
7342
/* Create new result */
7130
while (!lines.empty()) {
7131
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);