27 #define MTEST_VERSION "3.3"
29 #include "client_priv.h"
30 #include "my_default.h"
31 #include <mysql_version.h>
32 #include <mysqld_error.h>
33 #include <sql_common.h>
40 #ifdef HAVE_SYS_WAIT_H
47 #include <my_stacktrace.h>
49 #include <welcome_copyright_notice.h>
58 #define SIGNAL_FMT "exception 0x%x"
60 #define SIGNAL_FMT "signal %d"
64 #if MYSQL_VERSION_ID < 50000
68 #define MAX_VAR_NAME_LENGTH 256
69 #define MAX_COLUMNS 256
70 #define MAX_EMBEDDED_SERVER_ARGS 64
71 #define MAX_DELIMITER_LENGTH 16
72 #define DEFAULT_MAX_CONN 128
75 #define QUERY_SEND_FLAG 1
76 #define QUERY_REAP_FLAG 2
79 static int setenv(
const char *
name,
const char *value,
int overwrite);
83 static sig_handler signal_handler(
int sig);
84 static my_bool get_one_option(
int optid,
const struct my_option *,
89 OPT_PS_PROTOCOL=OPT_MAX_CLIENT_OPTION, OPT_SP_PROTOCOL,
90 OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL, OPT_MAX_CONNECT_RETRIES,
91 OPT_MAX_CONNECTIONS, OPT_MARK_PROGRESS, OPT_LOG_DIR,
92 OPT_TAIL_LINES, OPT_RESULT_FORMAT_VERSION, OPT_TRACE_PROTOCOL,
93 OPT_EXPLAIN_PROTOCOL, OPT_JSON_EXPLAIN_PROTOCOL
96 static int record= 0, opt_sleep= -1;
97 static char *opt_db= 0, *opt_pass= 0;
98 const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir=
"./";
99 static char *shared_memory_base_name=0;
100 const char *opt_logdir=
"";
101 const char *opt_include= 0, *opt_charsets_dir;
102 static int opt_port= 0;
103 static int opt_max_connect_retries;
104 static int opt_result_format_version;
105 static int opt_max_connections= DEFAULT_MAX_CONN;
106 static my_bool opt_compress= 0, silent= 0, verbose= 0;
107 static my_bool debug_info_flag= 0, debug_check_flag= 0;
108 static my_bool tty_password= 0;
109 static my_bool opt_mark_progress= 0;
110 static my_bool ps_protocol= 0, ps_protocol_enabled= 0;
111 static my_bool sp_protocol= 0, sp_protocol_enabled= 0;
112 static my_bool view_protocol= 0, view_protocol_enabled= 0;
113 static my_bool opt_trace_protocol= 0, opt_trace_protocol_enabled= 0;
114 static my_bool explain_protocol= 0, explain_protocol_enabled= 0;
115 static my_bool json_explain_protocol= 0, json_explain_protocol_enabled= 0;
116 static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0;
117 static my_bool parsing_disabled= 0;
118 static my_bool display_result_vertically= FALSE, display_result_lower= FALSE,
119 display_metadata= FALSE, display_result_sorted= FALSE;
120 static my_bool disable_query_log= 0, disable_result_log= 0;
121 static my_bool disable_connect_log= 1;
122 static my_bool disable_warnings= 0;
123 static my_bool disable_info= 1;
124 static my_bool abort_on_error= 1;
125 static my_bool server_initialized= 0;
126 static my_bool is_windows= 0;
127 static char **default_argv;
128 static const char *load_default_groups[]= {
"mysqltest",
"client", 0 };
129 static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
130 #if !defined(HAVE_YASSL)
131 static const char *opt_server_public_key= 0;
133 static my_bool can_handle_expired_passwords= TRUE;
142 const char *env_name;
145 static struct property prop_list[] = {
146 { &abort_on_error, 0, 1, 0,
"$ENABLED_ABORT_ON_ERROR" },
147 { &disable_connect_log, 0, 1, 1,
"$ENABLED_CONNECT_LOG" },
148 { &disable_info, 0, 1, 1,
"$ENABLED_INFO" },
149 { &display_metadata, 0, 0, 0,
"$ENABLED_METADATA" },
150 { &ps_protocol_enabled, 0, 0, 0,
"$ENABLED_PS_PROTOCOL" },
151 { &disable_query_log, 0, 0, 1,
"$ENABLED_QUERY_LOG" },
152 { &disable_result_log, 0, 0, 1,
"$ENABLED_RESULT_LOG" },
153 { &disable_warnings, 0, 0, 1,
"$ENABLED_WARNINGS" }
156 static my_bool once_property= FALSE;
170 static uint start_lineno= 0;
171 static uint my_end_arg= 0;
174 static uint opt_tail_lines= 0;
176 static uint opt_connect_timeout= 0;
178 static char delimiter[MAX_DELIMITER_LENGTH]=
";";
179 static uint delimiter_length= 1;
181 static char TMPDIR[FN_REFLEN];
195 char delim[MAX_DELIMITER_LENGTH];
198 static struct st_block block_stack[32];
199 static struct st_block *cur_block, *block_stack_end;
216 static const char *embedded_server_groups[]=
224 static int embedded_server_arg_count=0;
225 static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
231 static char *timer_file = NULL;
232 static ulonglong timer_start;
233 static void timer_output(
void);
234 static ulonglong timer_now(
void);
237 static ulong connection_retry_sleep= 100000;
239 static char *opt_plugin_dir= 0;
249 static void init_re(
void);
251 static void free_re(
void);
253 #ifndef EMBEDDED_LIBRARY
254 static uint opt_protocol= 0;
259 #include "sslopt-vars.h"
263 int read_lines,current_line;
268 char file[FN_REFLEN];
273 const char *result_file_name= 0;
304 #ifdef EMBEDDED_LIBRARY
306 const char *cur_query;
309 pthread_mutex_t query_mutex;
310 pthread_cond_t query_cond;
311 pthread_mutex_t result_mutex;
312 pthread_cond_t result_cond;
319 struct st_connection* cur_con= NULL, *next_con, *connections_end;
327 Q_CONNECTION=1, Q_QUERY,
328 Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
330 Q_SOURCE, Q_DISCONNECT,
332 Q_WHILE, Q_END_BLOCK,
334 Q_REQUIRE, Q_SAVE_MASTER_POS,
336 Q_SYNC_SLAVE_WITH_MASTER,
339 Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
342 Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
343 Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
344 Q_ENABLE_CONNECT_LOG, Q_DISABLE_CONNECT_LOG,
345 Q_WAIT_FOR_SLAVE_TO_STOP,
346 Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
347 Q_ENABLE_INFO, Q_DISABLE_INFO,
348 Q_ENABLE_METADATA, Q_DISABLE_METADATA,
349 Q_EXEC, Q_EXECW, Q_DELIMITER,
350 Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
351 Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
352 Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
354 Q_START_TIMER, Q_END_TIMER,
355 Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
356 Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
358 Q_DISABLE_PARSING, Q_ENABLE_PARSING,
359 Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST,
360 Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP,
361 Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
362 Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
363 Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE,
364 Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER,
365 Q_RESULT_FORMAT_VERSION,
366 Q_MOVE_FILE, Q_REMOVE_FILES_WILDCARD, Q_SEND_EVAL,
369 Q_COMMENT_WITH_COMMAND,
374 const char *command_names[]=
394 "sync_slave_with_master",
409 "disable_result_log",
410 "enable_connect_log",
411 "disable_connect_log",
412 "wait_for_slave_to_stop",
422 "disable_abort_on_error",
423 "enable_abort_on_error",
425 "horizontal_results",
433 "disable_ps_protocol",
434 "enable_ps_protocol",
460 "list_files_write_file",
461 "list_files_append_file",
466 "remove_files_wildcard",
489 enum match_err_type type;
493 char sqlstate[SQLSTATE_LENGTH+1];
506 char *
query, *query_buf,*first_argument,*last_argument,*end;
508 int first_word_len, query_len;
509 my_bool abort_on_error, used_replace;
511 char require_file[FN_REFLEN];
512 enum enum_commands
type;
515 TYPELIB command_typelib= {array_elements(command_names),
"",
523 char builtin_echo[FN_REFLEN];
548 const char *from,
int len);
550 static void cleanup_and_exit(
int exit_code) __attribute__((noreturn));
552 void die(
const char *
fmt, ...)
553 ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
554 void abort_not_supported_test(const
char *fmt, ...)
555 ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
556 void verbose_msg(const
char *fmt, ...)
557 ATTRIBUTE_FORMAT(printf, 1, 2);
558 void log_msg(const
char *fmt, ...)
559 ATTRIBUTE_FORMAT(printf, 1, 2);
561 VAR* var_from_env(const
char *, const
char *);
562 VAR* var_init(
VAR* v, const
char *
name,
int name_len, const
char *val,
564 VAR* var_get(const
char *var_name, const
char** var_name_end,
565 my_bool raw, my_bool ignore_not_existing);
566 void eval_expr(
VAR* v, const
char *p, const
char** p_end,
567 bool open_end=false,
bool do_eval=true);
568 my_bool match_delimiter(
int c, const
char *delim, uint length);
569 void dump_result_to_reject_file(
char *
buf,
int size);
570 void dump_warning_messages();
573 const
char *query_end, my_bool pass_through_escape_chars);
574 void str_to_file(const
char *fname,
char *str,
int size);
575 void str_to_file2(const
char *fname,
char *str,
int size, my_bool append);
577 void fix_win_paths(const
char *val,
int len);
578 const
char *get_errname_from_code (uint error_code);
582 void free_tmp_sh_file();
583 void free_win_path_patterns();
588 static char *replace_column[MAX_COLUMNS];
589 static uint max_replace_column= 0;
590 void do_get_replace_column(
struct st_command*);
591 void free_replace_column();
594 void do_get_replace(
struct st_command *command);
598 void do_get_replace_regex(
struct st_command *command);
599 void free_replace_regex();
602 void check_eol_junk_line(
const char *eol);
604 void free_all_replace(){
606 free_replace_regex();
607 free_replace_column();
613 char m_file_name[FN_REFLEN];
614 size_t m_bytes_written;
616 LogFile() : m_file(NULL), m_bytes_written(0) {
617 memset(m_file_name, 0,
sizeof(m_file_name));
624 const char* file_name()
const {
return m_file_name; }
625 size_t bytes_written()
const {
return m_bytes_written; }
627 void open(
const char* dir,
const char* name,
const char* ext)
629 DBUG_ENTER(
"LogFile::open");
630 DBUG_PRINT(
"enter", (
"dir: '%s', name: '%s'",
638 fn_format(m_file_name, name, dir, ext,
639 *dir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
642 DBUG_PRINT(
"info", (
"file_name: %s", m_file_name));
644 if ((m_file= fopen(m_file_name,
"wb+")) == NULL)
645 die(
"Failed to open log file %s, errno: %d", m_file_name, errno);
653 if (m_file != stdout)
663 if (m_file && m_file != stdout)
666 die(
"Failed to flush '%s', errno: %d", m_file_name, errno);
672 DBUG_ENTER(
"LogFile::write");
677 DBUG_ASSERT(ds->str);
679 if (fwrite(ds->str, 1, ds->length, m_file) != ds->length)
680 die(
"Failed to write %lu bytes to '%s', errno: %d",
681 (
unsigned long)ds->length, m_file_name, errno);
682 m_bytes_written+= ds->length;
686 void show_tail(uint lines) {
687 DBUG_ENTER(
"LogFile::show_tail");
689 if (!m_file || m_file == stdout)
699 bool found_bof=
false;
702 while (lines && !found_bof)
704 show_offset-=
sizeof(
buf);
705 while(fseek(m_file, show_offset, SEEK_END) != 0 && show_offset < 0)
712 if ((bytes= fread(buf, 1,
sizeof(buf), m_file)) <= 0)
717 "Failed to read from '%s', errno: %d, feof:%d, ferror:%d\n",
718 m_file_name, errno, feof(m_file), ferror(m_file));
722 DBUG_PRINT(
"info", (
"Read %lu bytes from file, buf: %s",
723 (
unsigned long)bytes, buf));
725 char* show_from= buf + bytes;
726 while(show_from > buf && lines > 0 )
729 if (*show_from ==
'\n')
732 if (show_from != buf)
735 show_offset+= (show_from -
buf) + 1;
736 DBUG_PRINT(
"info", (
"adjusted offset to %d", show_offset));
738 DBUG_PRINT(
"info", (
"show_offset: %d", show_offset));
741 fprintf(stderr,
"\nThe result from queries just before the failure was:\n");
743 DBUG_PRINT(
"info", (
"show_offset: %d", show_offset));
746 fprintf(stderr,
"< snip >\n");
748 if (fseek(m_file, show_offset, SEEK_END) != 0)
750 fprintf(stderr,
"Failed to seek to position %d in '%s', errno: %d",
751 show_offset, m_file_name, errno);
757 DBUG_PRINT(
"info", (
"Showing the whole file"));
758 if (fseek(m_file, 0L, SEEK_SET) != 0)
760 fprintf(stderr,
"Failed to seek to pos 0 in '%s', errno: %d",
766 while ((bytes= fread(buf, 1,
sizeof(buf), m_file)) > 0)
767 fwrite(buf, 1, bytes, stderr);
772 "\nMore results from queries before failure can be found in %s\n",
784 void replace_dynstr_append_mem(
DYNAMIC_STRING *ds,
const char *val,
790 static int match_expected_error(
struct st_command *command,
791 unsigned int err_errno,
792 const char *err_sqlstate);
794 unsigned int err_errno,
const char *err_error,
797 void revert_properties();
799 #ifdef EMBEDDED_LIBRARY
801 #define EMB_SEND_QUERY 1
802 #define EMB_READ_QUERY_RESULT 2
803 #define EMB_END_CONNECTION 3
806 pthread_attr_t cn_thd_attrib;
816 pthread_handler_t connection_thread(
void *arg)
821 while (cn->command != EMB_END_CONNECTION)
825 pthread_mutex_lock(&cn->query_mutex);
827 pthread_cond_wait(&cn->query_cond, &cn->query_mutex);
828 pthread_mutex_unlock(&cn->query_mutex);
832 case EMB_END_CONNECTION:
835 cn->result= mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len);
837 case EMB_READ_QUERY_RESULT:
838 cn->result= mysql_read_query_result(&cn->mysql);
844 pthread_mutex_lock(&cn->result_mutex);
846 pthread_cond_signal(&cn->result_cond);
847 pthread_mutex_unlock(&cn->result_mutex);
857 static void wait_query_thread_done(
struct st_connection *con)
859 DBUG_ASSERT(con->has_thread);
860 if (!con->query_done)
862 pthread_mutex_lock(&con->result_mutex);
863 while (!con->query_done)
864 pthread_cond_wait(&con->result_cond, &con->result_mutex);
865 pthread_mutex_unlock(&con->result_mutex);
870 static void signal_connection_thd(
struct st_connection *cn,
int command)
872 DBUG_ASSERT(cn->has_thread);
874 cn->command= command;
875 pthread_mutex_lock(&cn->query_mutex);
876 pthread_cond_signal(&cn->query_cond);
877 pthread_mutex_unlock(&cn->query_mutex);
888 static int do_send_query(
struct st_connection *cn,
const char *q,
int q_len)
891 return mysql_send_query(&cn->mysql, q, q_len);
893 cn->cur_query_len= q_len;
894 signal_connection_thd(cn, EMB_SEND_QUERY);
900 DBUG_ASSERT(cn->has_thread);
901 wait_query_thread_done(cn);
902 signal_connection_thd(cn, EMB_READ_QUERY_RESULT);
903 wait_query_thread_done(cn);
913 wait_query_thread_done(cn);
914 signal_connection_thd(cn, EMB_END_CONNECTION);
915 pthread_join(cn->tid, NULL);
916 cn->has_thread= FALSE;
917 pthread_mutex_destroy(&cn->query_mutex);
918 pthread_cond_destroy(&cn->query_cond);
919 pthread_mutex_destroy(&cn->result_mutex);
920 pthread_cond_destroy(&cn->result_cond);
928 if (pthread_mutex_init(&cn->query_mutex, NULL) ||
929 pthread_cond_init(&cn->query_cond, NULL) ||
930 pthread_mutex_init(&cn->result_mutex, NULL) ||
931 pthread_cond_init(&cn->result_cond, NULL) ||
932 pthread_create(&cn->tid, &cn_thd_attrib, connection_thread, (
void*)cn))
933 die(
"Error in the thread library");
939 #define do_send_query(cn,q,q_len) mysql_send_query(&cn->mysql, q, q_len)
940 #define do_read_query_result(cn) mysql_read_query_result(&cn->mysql)
945 const char *query_end, my_bool pass_through_escape_chars)
948 register char c, next_c;
949 register int escaped = 0;
951 DBUG_ENTER(
"do_eval");
953 for (p= query; (c= *p) && p < query_end; ++p)
960 dynstr_append_mem(query_eval, p, 1);
964 if (!(v= var_get(p, &p, 0, 0)))
965 die(
"Bad variable in eval");
966 dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
974 dynstr_append_mem(query_eval, p, 1);
976 else if (next_c ==
'\\' || next_c ==
'$' || next_c ==
'"')
981 if (pass_through_escape_chars)
984 dynstr_append_mem(query_eval, p, 1);
988 dynstr_append_mem(query_eval, p, 1);
992 dynstr_append_mem(query_eval, p, 1);
997 fix_win_paths(query_eval->str, query_eval->length);
1016 static void show_query(
MYSQL* mysql,
const char* query)
1019 DBUG_ENTER(
"show_query");
1024 if (mysql_query(mysql, query))
1026 log_msg(
"Error running query '%s': %d %s",
1027 query, mysql_errno(mysql), mysql_error(mysql));
1031 if ((res= mysql_store_result(mysql)) == NULL)
1040 unsigned int row_num= 0;
1041 unsigned int num_fields= mysql_num_fields(res);
1044 fprintf(stderr,
"=== %s ===\n", query);
1045 while ((row= mysql_fetch_row(res)))
1047 unsigned long *lengths= mysql_fetch_lengths(res);
1050 fprintf(stderr,
"---- %d. ----\n", row_num);
1051 for(i= 0; i < num_fields; i++)
1055 fprintf(stderr,
"%s\t%.*s\n",
1057 (
int)lengths[i], row[i] ? row[i] :
"NULL");
1060 for (i= 0; i < strlen(query)+8; i++)
1061 fprintf(stderr,
"=");
1062 fprintf(stderr,
"\n\n");
1064 mysql_free_result(res);
1083 static void show_warnings_before_error(
MYSQL* mysql)
1086 const char* query=
"SHOW WARNINGS";
1087 DBUG_ENTER(
"show_warnings_before_error");
1092 if (mysql_query(mysql, query))
1094 log_msg(
"Error running query '%s': %d %s",
1095 query, mysql_errno(mysql), mysql_error(mysql));
1099 if ((res= mysql_store_result(mysql)) == NULL)
1105 if (mysql_num_rows(res) <= 1)
1112 unsigned int row_num= 0;
1113 unsigned int num_fields= mysql_num_fields(res);
1115 fprintf(stderr,
"\nWarnings from just before the error:\n");
1116 while ((row= mysql_fetch_row(res)))
1119 unsigned long *lengths= mysql_fetch_lengths(res);
1121 if (++row_num >= mysql_num_rows(res))
1127 for(i= 0; i < num_fields; i++)
1131 fprintf(stderr,
"%.*s ", (
int)lengths[i],
1132 row[i] ? row[i] :
"NULL");
1134 fprintf(stderr,
"\n");
1137 mysql_free_result(res);
1150 const char *argname;
1154 const char *description;
1158 void check_command_args(
struct st_command *command,
1159 const char *arguments,
1161 int num_args,
const char delimiter_arg)
1164 const char *ptr= arguments;
1166 DBUG_ENTER(
"check_command_args");
1167 DBUG_PRINT(
"enter", (
"num_args: %d", num_args));
1169 for (i= 0; i < num_args; i++)
1174 switch (arg->type) {
1178 while (*ptr && *ptr ==
' ')
1181 delimiter = delimiter_arg;
1183 if (*ptr && strchr (
"'`\"", *ptr))
1189 while (*ptr && *ptr != delimiter)
1193 init_dynamic_string(arg->ds, 0, ptr-start, 32);
1194 do_eval(arg->ds, start, ptr, FALSE);
1199 init_dynamic_string(arg->ds,
"", 0, 0);
1203 while (*ptr && *ptr != delimiter_arg)
1206 command->last_argument= (
char*)ptr;
1209 if (*ptr && *ptr == delimiter_arg)
1211 DBUG_PRINT(
"info", (
"val: %s", arg->ds->str));
1217 init_dynamic_string(arg->ds, 0, command->query_len, 256);
1218 do_eval(arg->ds, start, command->end, FALSE);
1219 command->last_argument= command->end;
1220 DBUG_PRINT(
"info", (
"val: %s", arg->ds->str));
1224 DBUG_ASSERT(
"Unknown argument type");
1229 if (arg->ds->length == 0 && arg->required)
1230 die(
"Missing required argument '%s' to command '%.*s'", arg->argname,
1231 command->first_word_len, command->query);
1235 ptr= command->last_argument;
1236 while(ptr <= command->end && *ptr !=
'#')
1238 if (*ptr && *ptr !=
' ')
1239 die(
"Extra argument '%s' passed to '%.*s'",
1240 ptr, command->first_word_len, command->query);
1246 void handle_command_error(
struct st_command *command, uint error)
1248 DBUG_ENTER(
"handle_command_error");
1249 DBUG_PRINT(
"enter", (
"error: %d", error));
1254 if (command->abort_on_error)
1255 die(
"command \"%.*s\" failed with error %d. my_errno=%d",
1256 command->first_word_len, command->query, error, my_errno);
1258 i= match_expected_error(command, error, NULL);
1262 DBUG_PRINT(
"info", (
"command \"%.*s\" failed with expected error: %d",
1263 command->first_word_len, command->query, error));
1264 revert_properties();
1267 if (command->expected_errors.count > 0)
1268 die(
"command \"%.*s\" failed with wrong error: %d. my_errno=%d",
1269 command->first_word_len, command->query, error, my_errno);
1271 else if (command->expected_errors.err[0].type == ERR_ERRNO &&
1272 command->expected_errors.err[0].code.errnum != 0)
1275 die(
"command \"%.*s\" succeeded - should have failed with errno %d...",
1276 command->first_word_len, command->query,
1277 command->expected_errors.err[0].code.errnum);
1279 revert_properties();
1284 void close_connections()
1286 DBUG_ENTER(
"close_connections");
1287 for (--next_con; next_con >= connections; --next_con)
1289 #ifdef EMBEDDED_LIBRARY
1290 emb_close_connection(next_con);
1293 mysql_stmt_close(next_con->stmt);
1295 mysql_close(&next_con->mysql);
1296 if (next_con->util_mysql)
1297 mysql_close(next_con->util_mysql);
1298 my_free(next_con->name);
1300 my_free(connections);
1305 void close_statements()
1308 DBUG_ENTER(
"close_statements");
1309 for (con= connections; con < next_con; con++)
1312 mysql_stmt_close(con->stmt);
1321 DBUG_ENTER(
"close_files");
1322 for (; cur_file >= file_stack; cur_file--)
1324 if (cur_file->file && cur_file->file != stdin)
1326 DBUG_PRINT(
"info", (
"closing file: %s", cur_file->file_name));
1327 fclose(cur_file->file);
1329 my_free(cur_file->file_name);
1330 cur_file->file_name= 0;
1336 void free_used_memory()
1342 close_connections();
1344 my_hash_free(&var_hash);
1346 for (i= 0 ; i < q_lines.elements ; i++)
1349 my_free((*q)->query_buf);
1350 if ((*q)->content.str)
1351 dynstr_free(&(*q)->content);
1354 for (i= 0; i < 10; i++)
1356 if (var_reg[i].alloced_len)
1357 my_free(var_reg[i].str_val);
1359 while (embedded_server_arg_count > 1)
1360 my_free(embedded_server_args[--embedded_server_arg_count]);
1361 delete_dynamic(&q_lines);
1362 dynstr_free(&ds_res);
1364 dynstr_free(ds_warn);
1367 free_defaults(default_argv);
1371 free_win_path_patterns();
1375 if (server_initialized)
1383 static void cleanup_and_exit(
int exit_code)
1389 switch (exit_code) {
1397 printf(
"skipped\n");
1400 printf(
"unknown exit code: %d\n", exit_code);
1415 void print_file_stack()
1418 err_file != file_stack;
1421 fprintf(stderr,
"included from %s at line %d:\n",
1422 err_file->file_name, err_file->lineno);
1426 void die(
const char *fmt, ...)
1428 static int dying= 0;
1430 DBUG_PRINT(
"enter", (
"start_lineno: %d", start_lineno));
1438 cleanup_and_exit(1);
1442 fprintf(stderr,
"mysqltest: ");
1443 if (cur_file && cur_file != file_stack)
1445 fprintf(stderr,
"In included file \"%s\": \n",
1446 cur_file->file_name);
1450 if (start_lineno > 0)
1451 fprintf(stderr,
"At line %u: ", start_lineno);
1454 va_start(args, fmt);
1455 vfprintf(stderr, fmt, args);
1459 fprintf(stderr,
"unknown error");
1460 fprintf(stderr,
"\n");
1463 log_file.show_tail(opt_tail_lines);
1469 if (cur_con && !cur_con->pending)
1470 show_warnings_before_error(&cur_con->mysql);
1472 cleanup_and_exit(1);
1476 void abort_not_supported_test(
const char *fmt, ...)
1479 DBUG_ENTER(
"abort_not_supported_test");
1482 fprintf(stderr,
"The test '%s' is not supported by this installation\n",
1483 file_stack->file_name);
1484 fprintf(stderr,
"Detected in file %s at line %d\n",
1485 cur_file->file_name, cur_file->lineno);
1489 va_start(args, fmt);
1492 fprintf(stderr,
"reason: ");
1493 vfprintf(stderr, fmt, args);
1494 fprintf(stderr,
"\n");
1499 cleanup_and_exit(62);
1503 void abort_not_in_this_version()
1505 die(
"Not available in this version of mysqltest");
1509 void verbose_msg(
const char *fmt, ...)
1512 DBUG_ENTER(
"verbose_msg");
1516 va_start(args, fmt);
1517 fprintf(stderr,
"mysqltest: ");
1518 if (cur_file && cur_file != file_stack)
1519 fprintf(stderr,
"In included file \"%s\": ",
1520 cur_file->file_name);
1521 if (start_lineno != 0)
1522 fprintf(stderr,
"At line %u: ", start_lineno);
1523 vfprintf(stderr, fmt, args);
1524 fprintf(stderr,
"\n");
1531 void log_msg(
const char *fmt, ...)
1536 DBUG_ENTER(
"log_msg");
1538 va_start(args, fmt);
1539 len= my_vsnprintf(buff,
sizeof(buff)-1, fmt, args);
1542 dynstr_append_mem(&ds_res, buff, len);
1543 dynstr_append(&ds_res,
"\n");
1565 if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
1567 while((len= my_read(fd, (uchar*)&buff,
1568 sizeof(buff), MYF(0))) > 0)
1570 char *p= buff, *start= buff;
1571 while (p < buff+len)
1574 if (*p ==
'\r' && *(p+1) && *(p+1)==
'\n')
1579 dynstr_append_mem(ds, start, p-start);
1588 dynstr_append_mem(ds, start, p-start);
1590 my_close(fd, MYF(0));
1605 static int run_command(
char* cmd,
1612 if (!(res_file= popen(cmd,
"r")))
1613 die(
"popen(\"%s\", \"r\") failed", cmd);
1615 while (fgets(buf,
sizeof(buf), res_file))
1617 DBUG_PRINT(
"info", (
"buf: %s", buf));
1621 dynstr_append(ds_res, buf);
1626 fprintf(stdout,
"%s", buf);
1630 error= pclose(res_file);
1631 return WEXITSTATUS(error);
1647 static int run_tool(
const char *tool_path,
DYNAMIC_STRING *ds_res, ...)
1654 DBUG_ENTER(
"run_tool");
1655 DBUG_PRINT(
"enter", (
"tool_path: %s", tool_path));
1657 if (init_dynamic_string(&ds_cmdline, IF_WIN(
"\"",
""), FN_REFLEN, FN_REFLEN))
1658 die(
"Out of memory");
1660 dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
1661 dynstr_append(&ds_cmdline,
" ");
1663 va_start(args, ds_res);
1665 while ((arg= va_arg(args,
char *)))
1668 if (strncmp(arg,
"--", 2) == 0)
1669 dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
1671 dynstr_append(&ds_cmdline, arg);
1672 dynstr_append(&ds_cmdline,
" ");
1678 dynstr_append(&ds_cmdline,
"\"");
1681 DBUG_PRINT(
"info", (
"Running: %s", ds_cmdline.str));
1682 ret= run_command(ds_cmdline.str, ds_res);
1683 DBUG_PRINT(
"exit", (
"ret: %d", ret));
1684 dynstr_free(&ds_cmdline);
1702 static int diff_check(
const char *diff_name)
1708 my_snprintf(buf,
sizeof(buf),
"%s -v", diff_name);
1710 if (!(res_file= popen(buf,
"r")))
1711 die(
"popen(\"%s\", \"r\") failed", buf);
1714 if (fgets(buf,
sizeof(buf), res_file))
1739 const char* filename1,
const char* filename2)
1742 const char *diff_name = 0;
1744 if (init_dynamic_string(&ds_tmp,
"", 256, 256))
1745 die(
"Out of memory");
1755 if (diff_check(
"diff"))
1757 else if (diff_check(
"mtrdiff"))
1758 diff_name =
"mtrdiff";
1768 if (run_tool(diff_name,
1776 dynstr_set(&ds_tmp,
"");
1779 if (run_tool(diff_name,
1787 dynstr_set(&ds_tmp,
"");
1790 if (run_tool(diff_name,
1809 dynstr_append(&ds_tmp,
"\n");
1810 dynstr_append(&ds_tmp,
1812 "The two files differ but it was not possible to execute 'diff' in\n"
1813 "order to show only the difference. Instead the whole content of the\n"
1814 "two files was shown for you to diff manually.\n\n"
1815 "To get a better report you should install 'diff' on your system, which you\n"
1816 "for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1818 "or http://gnuwin32.sourceforge.net/packages/diffutils.htm\n"
1822 dynstr_append(&ds_tmp,
" --- ");
1823 dynstr_append(&ds_tmp, filename1);
1824 dynstr_append(&ds_tmp,
" >>>\n");
1825 cat_file(&ds_tmp, filename1);
1826 dynstr_append(&ds_tmp,
"<<<\n --- ");
1827 dynstr_append(&ds_tmp, filename1);
1828 dynstr_append(&ds_tmp,
" >>>\n");
1829 cat_file(&ds_tmp, filename2);
1830 dynstr_append(&ds_tmp,
"<<<<\n");
1836 dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
1841 fprintf(stderr,
"%s\n", ds_tmp.str);
1844 dynstr_free(&ds_tmp);
1849 enum compare_files_result_enum {
1851 RESULT_CONTENT_MISMATCH= 1,
1852 RESULT_LENGTH_MISMATCH= 2
1869 int compare_files2(File fd,
const char* filename2)
1871 int error= RESULT_OK;
1874 char buff[512], buff2[512];
1876 if ((fd2= my_open(filename2, O_RDONLY, MYF(0))) < 0)
1878 my_close(fd, MYF(0));
1879 die(
"Failed to open second file: '%s'", filename2);
1881 while((len= my_read(fd, (uchar*)&buff,
1882 sizeof(buff), MYF(0))) > 0)
1884 if ((len2= my_read(fd2, (uchar*)&buff2,
1885 sizeof(buff2), MYF(0))) < len)
1888 error= RESULT_LENGTH_MISMATCH;
1894 error= RESULT_LENGTH_MISMATCH;
1897 if ((memcmp(buff, buff2, len)))
1900 error= RESULT_CONTENT_MISMATCH;
1904 if (!error && my_read(fd2, (uchar*)&buff2,
1905 sizeof(buff2), MYF(0)) > 0)
1908 error= RESULT_LENGTH_MISMATCH;
1911 my_close(fd2, MYF(0));
1930 int compare_files(
const char* filename1,
const char* filename2)
1935 if ((fd= my_open(filename1, O_RDONLY, MYF(0))) < 0)
1936 die(
"Failed to open first file: '%s'", filename1);
1938 error= compare_files2(fd, filename2);
1940 my_close(fd, MYF(0));
1962 char temp_file_path[FN_REFLEN];
1964 DBUG_ENTER(
"dyn_string_cmp");
1965 DBUG_PRINT(
"enter", (
"fname: %s", fname));
1967 if ((fd= create_temp_file(temp_file_path, TMPDIR,
1968 "tmp", O_CREAT | O_SHARE | O_RDWR,
1970 die(
"Failed to create temporary file for ds");
1973 if (my_write(fd, (uchar *) ds->str, ds->length,
1974 MYF(MY_FNABP | MY_WME)) ||
1975 my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
1977 my_close(fd, MYF(0));
1979 my_delete(temp_file_path, MYF(0));
1980 die(
"Failed to write file '%s'", temp_file_path);
1983 error= compare_files2(fd, fname);
1985 my_close(fd, MYF(0));
1987 my_delete(temp_file_path, MYF(0));
2006 const char* mess=
"Result content mismatch\n";
2008 DBUG_ENTER(
"check_result");
2009 DBUG_ASSERT(result_file_name);
2010 DBUG_PRINT(
"enter", (
"result_file_name: %s", result_file_name));
2012 switch (compare_files(log_file.file_name(), result_file_name)) {
2015 case RESULT_LENGTH_MISMATCH:
2016 mess=
"Result length mismatch\n";
2018 case RESULT_CONTENT_MISMATCH:
2024 char reject_file[FN_REFLEN];
2025 size_t reject_length;
2026 dirname_part(reject_file, result_file_name, &reject_length);
2029 fn_format(reject_file, result_file_name, opt_logdir,
2030 ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
2032 if (my_copy(log_file.file_name(), reject_file, MYF(0)) != 0)
2033 die(
"Failed to copy '%s' to '%s', errno: %d",
2034 log_file.file_name(), reject_file, errno);
2036 show_diff(NULL, result_file_name, reject_file);
2041 die(
"Unknown error code from dyn_string_cmp()");
2065 DBUG_ENTER(
"check_require");
2067 if (dyn_string_cmp(ds, fname))
2069 char reason[FN_REFLEN];
2070 fn_format(reason, fname,
"",
"", MY_REPLACE_EXT | MY_REPLACE_DIR);
2071 abort_not_supported_test(
"Test requires: '%s'", reason);
2082 static int strip_surrounding(
char* str,
char c1,
char c2)
2087 while(*ptr && my_isspace(charset_info, *ptr))
2096 while(*ptr && my_isspace(charset_info, *ptr))
2113 static void strip_parentheses(
struct st_command *command)
2115 if (strip_surrounding(command->first_argument,
'(',
')'))
2116 die(
"%.*s - argument list started with '%c' must be ended with '%c'",
2117 command->first_word_len, command->query,
'(',
')');
2123 static uchar *get_var_key(
const uchar* var,
size_t *len,
2124 my_bool __attribute__((unused)) t)
2127 key = ((
VAR*)var)->name;
2128 *len = ((
VAR*)var)->name_len;
2133 static void var_free(
void *v)
2136 my_free(var->str_val);
2143 void var_check_int(
VAR *v)
2146 char *str= v->str_val;
2151 v->int_dirty=
false;
2154 v->int_val = (int) strtol(str, &endptr, 10);
2156 if (endptr > str && (!*endptr || *endptr ==
' ' || *endptr ==
'\t'))
2161 VAR *var_init(
VAR *v,
const char *name,
int name_len,
const char *val,
2166 if (!name_len && name)
2167 name_len = strlen(name);
2168 if (!val_len && val)
2169 val_len = strlen(val) ;
2172 val_alloc_len = val_len + 16;
2173 if (!(tmp_var=v) && !(tmp_var = (
VAR*)my_malloc(
sizeof(*tmp_var)
2174 + name_len+2, MYF(MY_WME))))
2175 die(
"Out of memory");
2179 tmp_var->name=
reinterpret_cast<char*
>(tmp_var) +
sizeof(*tmp_var);
2180 memcpy(tmp_var->name, name, name_len);
2181 tmp_var->name[name_len]= 0;
2184 tmp_var->name= NULL;
2186 tmp_var->alloced = (v == 0);
2188 if (!(tmp_var->str_val = (
char*)my_malloc(val_alloc_len+1, MYF(MY_WME))))
2189 die(
"Out of memory");
2192 memcpy(tmp_var->str_val, val, val_len);
2193 tmp_var->str_val[val_len]= 0;
2195 var_check_int(tmp_var);
2196 tmp_var->name_len = name_len;
2197 tmp_var->str_val_len = val_len;
2198 tmp_var->alloced_len = val_alloc_len;
2203 VAR* var_from_env(
const char *name,
const char *def_val)
2207 if (!(tmp = getenv(name)))
2210 v = var_init(0, name, strlen(name), tmp, strlen(tmp));
2211 my_hash_insert(&var_hash, (uchar*)v);
2216 VAR* var_get(
const char *var_name,
const char **var_name_end, my_bool raw,
2217 my_bool ignore_not_existing)
2221 DBUG_ENTER(
"var_get");
2222 DBUG_PRINT(
"enter", (
"var_name: %s",var_name));
2224 if (*var_name !=
'$')
2226 digit = *++var_name -
'0';
2227 if (digit < 0 || digit >= 10)
2229 const char *save_var_name = var_name, *end;
2231 end = (var_name_end) ? *var_name_end : 0;
2232 while (my_isvar(charset_info,*var_name) && var_name != end)
2234 if (var_name == save_var_name)
2236 if (ignore_not_existing)
2238 die(
"Empty variable");
2240 length= (uint) (var_name - save_var_name);
2241 if (length >= MAX_VAR_NAME_LENGTH)
2242 die(
"Too long variable name: %s", save_var_name);
2244 if (!(v = (
VAR*) my_hash_search(&var_hash, (
const uchar*) save_var_name,
2247 char buff[MAX_VAR_NAME_LENGTH+1];
2248 strmake(buff, save_var_name, length);
2249 v= var_from_env(buff,
"");
2254 v = var_reg + digit;
2256 if (!raw && v->int_dirty)
2258 sprintf(v->str_val,
"%d", v->int_val);
2259 v->int_dirty=
false;
2260 v->str_val_len = strlen(v->str_val);
2263 *var_name_end = var_name ;
2268 die(
"Unsupported variable name: %s", var_name);
2273 VAR *var_obtain(
const char *name,
int len)
2276 if ((v = (
VAR*)my_hash_search(&var_hash, (
const uchar *) name, len)))
2278 v = var_init(0, name, len,
"", 0);
2279 my_hash_insert(&var_hash, (uchar*)v);
2290 void var_set(
const char *var_name,
const char *var_name_end,
2291 const char *var_val,
const char *var_val_end)
2293 int digit, env_var= 0;
2295 DBUG_ENTER(
"var_set");
2296 DBUG_PRINT(
"enter", (
"var_name: '%.*s' = '%.*s' (length: %d)",
2297 (
int) (var_name_end - var_name), var_name,
2298 (
int) (var_val_end - var_val), var_val,
2299 (
int) (var_val_end - var_val)));
2301 if (*var_name !=
'$')
2306 digit= *var_name -
'0';
2307 if (!(digit < 10 && digit >= 0))
2309 v= var_obtain(var_name, (uint) (var_name_end - var_name));
2314 eval_expr(v, var_val, (
const char**) &var_val_end);
2320 sprintf(v->str_val,
"%d", v->int_val);
2322 v->str_val_len= strlen(v->str_val);
2325 DBUG_ASSERT(v->name[v->name_len] == 0);
2326 setenv(v->name, v->str_val, 1);
2332 void var_set_string(
const char* name,
const char* value)
2334 var_set(name, name + strlen(name), value, value + strlen(value));
2338 void var_set_int(
const char* name,
int value)
2341 my_snprintf(buf,
sizeof(buf),
"%d", value);
2342 var_set_string(name, buf);
2351 void var_set_errno(
int sql_errno)
2353 var_set_int(
"$mysql_errno", sql_errno);
2354 var_set_string(
"$mysql_errname", get_errname_from_code(sql_errno));
2359 void set_once_property(enum_prop prop, my_bool val)
2361 property &pr= prop_list[prop];
2365 var_set_int(pr.env_name, (val != pr.reverse));
2366 once_property= TRUE;
2369 void set_property(
st_command *command, enum_prop prop, my_bool val)
2371 char* p= command->first_argument;
2372 if (p && !strcmp (p,
"ONCE"))
2374 command->last_argument= p + 4;
2375 set_once_property(prop, val);
2378 property &pr= prop_list[prop];
2381 var_set_int(pr.env_name, (val != pr.reverse));
2384 void revert_properties()
2386 if (! once_property)
2388 for (
int i= 0; i < (int) P_MAX; i++)
2390 property &pr= prop_list[
i];
2395 var_set_int(pr.env_name, (pr.old != pr.reverse));
2398 once_property=FALSE;
2425 void var_query_set(
VAR *var,
const char *query,
const char** query_end)
2427 char *end = (
char*)((query_end && *query_end) ?
2428 *query_end : query + strlen(query));
2431 MYSQL* mysql = &cur_con->mysql;
2433 DBUG_ENTER(
"var_query_set");
2437 while (end > query && *end !=
'`')
2439 if (*end && (*end !=
' ' && *end !=
'\t' && *end !=
'\n' && *end !=
')'))
2440 die(
"Spurious text after `query` expression");
2445 die(
"Syntax error in query, missing '`'");
2449 init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
2450 do_eval(&ds_query, query, end, FALSE);
2452 if (mysql_real_query(mysql, ds_query.str, ds_query.length))
2454 handle_error (curr_command, mysql_errno(mysql), mysql_error(mysql),
2455 mysql_sqlstate(mysql), &ds_res);
2457 dynstr_free(&ds_query);
2458 eval_expr(var,
"", 0);
2462 if (!(res= mysql_store_result(mysql)))
2463 die(
"Query '%s' didn't return a result set", ds_query.str);
2464 dynstr_free(&ds_query);
2466 if ((row= mysql_fetch_row(res)) && row[0])
2476 init_dynamic_string(&result,
"", 512, 512);
2477 lengths= mysql_fetch_lengths(res);
2478 for (i= 0; i < mysql_num_fields(res); i++)
2484 int len= lengths[
i];
2486 if (glob_replace_regex)
2489 if (!multi_reg_replace(glob_replace_regex, (
char*)val))
2491 val= glob_replace_regex->buf;
2497 replace_strings_append(glob_replace, &result, val, len);
2499 dynstr_append_mem(&result, val, len);
2501 dynstr_append_mem(&result,
"\t", 1);
2503 end= result.str + result.length-1;
2505 eval_expr(var, result.str, (
const char**) &end,
false,
false);
2506 dynstr_free(&result);
2509 eval_expr(var,
"", 0);
2511 mysql_free_result(res);
2517 set_result_format_version(ulong new_version)
2519 switch (new_version){
2528 die(
"Version format %lu has not yet been implemented", new_version);
2531 opt_result_format_version= new_version;
2541 do_result_format_version(
struct st_command *command)
2546 {
"version", ARG_STRING, TRUE, &ds_version,
"Version to use"}
2549 DBUG_ENTER(
"do_result_format_version");
2551 check_command_args(command, command->first_argument,
2553 sizeof(result_format_args)/
sizeof(
struct command_arg),
2557 if (!str2int(ds_version.str, 10, (
long) 0, (
long) INT_MAX, &version))
2558 die(
"Invalid version number: '%s'", ds_version.str);
2560 set_result_format_version(version);
2562 dynstr_append(&ds_res,
"result_format: ");
2563 dynstr_append_mem(&ds_res, ds_version.str, ds_version.length);
2564 dynstr_append(&ds_res,
"\n");
2565 dynstr_free(&ds_version);
2577 static st_error global_error_names[] =
2579 {
"<No error>", -1
U,
"" },
2580 #include <mysqld_ername.h>
2584 uint get_errcode_from_name(
char *,
char *);
2601 void var_set_convert_error(
struct st_command *command,
VAR *var)
2604 char *first=command->query;
2605 const char *err_name;
2607 DBUG_ENTER(
"var_set_query_get_value");
2609 DBUG_PRINT(
"info", (
"query: %s", command->query));
2612 first=strchr(command->query,
'(') + 1;
2613 last=strchr(command->query,
')');
2618 eval_expr(var,
"0",0);
2628 num=get_errcode_from_name(first, last);
2629 sprintf(str,
"%i",num);
2630 eval_expr(var,str,0);
2632 else if (my_isdigit(charset_info, *first ))
2636 err=strtol(first,&last,0);
2637 err_name = get_errname_from_code(err);
2638 eval_expr(var,err_name,0);
2642 die(
"Invalid error in input");
2670 void var_set_query_get_value(
struct st_command *command,
VAR *var)
2675 MYSQL* mysql= &cur_con->mysql;
2680 const struct command_arg query_get_value_args[] = {
2681 {
"query", ARG_STRING, TRUE, &ds_query,
"Query to run"},
2682 {
"column name", ARG_STRING, TRUE, &ds_col,
"Name of column"},
2683 {
"row number", ARG_STRING, TRUE, &ds_row,
"Number for row"}
2686 DBUG_ENTER(
"var_set_query_get_value");
2689 strip_parentheses(command);
2690 DBUG_PRINT(
"info", (
"query: %s", command->query));
2691 check_command_args(command, command->first_argument, query_get_value_args,
2692 sizeof(query_get_value_args)/
sizeof(
struct command_arg),
2695 DBUG_PRINT(
"info", (
"query: %s", ds_query.str));
2696 DBUG_PRINT(
"info", (
"col: %s", ds_col.str));
2699 if (!str2int(ds_row.str, 10, (
long) 0, (
long) INT_MAX, &row_no))
2700 die(
"Invalid row number: '%s'", ds_row.str);
2701 DBUG_PRINT(
"info", (
"row: %s, row_no: %ld", ds_row.str, row_no));
2702 dynstr_free(&ds_row);
2705 if (strip_surrounding(ds_query.str,
'"',
'"'))
2706 die(
"Mismatched \"'s around query '%s'", ds_query.str);
2709 if (mysql_real_query(mysql, ds_query.str, ds_query.length))
2711 handle_error (curr_command, mysql_errno(mysql), mysql_error(mysql),
2712 mysql_sqlstate(mysql), &ds_res);
2714 dynstr_free(&ds_query);
2715 eval_expr(var,
"", 0);
2719 if (!(res= mysql_store_result(mysql)))
2720 die(
"Query '%s' didn't return a result set", ds_query.str);
2725 uint num_fields= mysql_num_fields(res);
2728 for (i= 0; i < num_fields; i++)
2730 if (strcmp(fields[i].name, ds_col.str) == 0 &&
2731 strlen(fields[i].name) == ds_col.length)
2739 mysql_free_result(res);
2740 die(
"Could not find column '%s' in the result of '%s'",
2741 ds_col.str, ds_query.str);
2743 DBUG_PRINT(
"info", (
"Found column %d with name '%s'",
2744 i, fields[i].name));
2746 dynstr_free(&ds_col);
2752 const char* value=
"No such row";
2754 while ((row= mysql_fetch_row(res)))
2756 if (++rows == row_no)
2759 DBUG_PRINT(
"info", (
"At row %ld, column %d is '%s'",
2760 row_no, col_no, row[col_no]));
2770 eval_expr(var, value, 0,
false,
false);
2772 dynstr_free(&ds_query);
2773 mysql_free_result(res);
2779 void var_copy(
VAR *dest,
VAR *src)
2781 dest->int_val= src->int_val;
2782 dest->is_int= src->is_int;
2783 dest->int_dirty= src->int_dirty;
2786 if (dest->alloced_len < src->alloced_len &&
2787 !(dest->str_val= dest->str_val
2788 ? (
char*)my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
2789 : (
char*)my_malloc(src->alloced_len, MYF(MY_WME))))
2790 die(
"Out of memory");
2792 dest->alloced_len= src->alloced_len;
2795 dest->str_val_len= src->str_val_len;
2796 if (src->str_val_len)
2797 memcpy(dest->str_val, src->str_val, src->str_val_len);
2801 void eval_expr(
VAR *v,
const char *p,
const char **p_end,
2802 bool open_end,
bool do_eval)
2805 DBUG_ENTER(
"eval_expr");
2806 DBUG_PRINT(
"enter", (
"p: '%s'", p));
2815 const char* expected_end= *p_end;
2816 if ((vp= var_get(p, p_end, 0, 0)))
2820 v->str_val[v->str_val_len]= 0;
2823 const char* end= *p_end + 1;
2824 if (end < expected_end && !open_end)
2825 die(
"Found junk '%.*s' after $variable in expression",
2826 (
int)(expected_end - end - 1), end);
2833 var_query_set(v, p, p_end);
2839 const char* get_value_str=
"query_get_value";
2840 const size_t len= strlen(get_value_str);
2841 if (strncmp(p, get_value_str, len)==0)
2844 memset(&command, 0,
sizeof(command));
2845 command.query= (
char*)p;
2846 command.first_word_len= len;
2847 command.first_argument= command.query + len;
2848 command.end= (
char*)*p_end;
2849 var_set_query_get_value(&command, v);
2853 const char* get_value_str1=
"convert_error";
2854 const size_t len1= strlen(get_value_str1);
2855 if (strncmp(p, get_value_str1, len1)==0)
2858 memset(&command, 0,
sizeof(command));
2859 command.query= (
char*)p;
2860 command.first_word_len= len;
2861 command.first_argument= command.query + len;
2862 command.end= (
char*)*p_end;
2863 var_set_convert_error(&command, v);
2870 int new_val_len = (p_end && *p_end) ?
2871 (
int) (*p_end - p) : (
int) strlen(p);
2872 if (new_val_len + 1 >= v->alloced_len)
2874 static int MIN_VAR_ALLOC= 32;
2875 v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
2876 MIN_VAR_ALLOC : new_val_len + 1;
2879 (
char*)my_realloc(v->str_val, v->alloced_len+1, MYF(MY_WME)) :
2880 (
char*)my_malloc(v->alloced_len+1, MYF(MY_WME))))
2881 die(
"Out of memory");
2883 v->str_val_len = new_val_len;
2884 memcpy(v->str_val, p, new_val_len);
2885 v->str_val[new_val_len] = 0;
2892 int open_file(
const char *name)
2894 char buff[FN_REFLEN];
2896 DBUG_ENTER(
"open_file");
2897 DBUG_PRINT(
"enter", (
"name: %s", name));
2900 if (dirname_part(buff, cur_file->file_name, &length))
2902 strxmov(buff, buff, name, NullS);
2903 if (access(buff, F_OK) == 0){
2904 DBUG_PRINT(
"info", (
"The file exists"));
2908 if (!test_if_hard_path(name))
2910 strxmov(buff, opt_basedir, name, NullS);
2913 fn_format(buff, name,
"",
"", MY_UNPACK_FILENAME);
2915 if (cur_file == file_stack_end)
2916 die(
"Source directives are nesting too deep");
2918 if (!(cur_file->file = fopen(buff,
"rb")))
2921 die(
"Could not open '%s' for reading, errno: %d", buff, errno);
2923 cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
2947 {
"filename", ARG_STRING, TRUE, &ds_filename,
"File to source" }
2949 DBUG_ENTER(
"do_source");
2951 check_command_args(command, command->first_argument, source_args,
2959 if (parser.current_line < (parser.read_lines - 1))
2963 DBUG_PRINT(
"info", (
"sourcing file: %s", ds_filename.str));
2964 open_file(ds_filename.str);
2967 dynstr_free(&ds_filename);
2976 char tmp_sh_name[64], tmp_sh_cmd[70];
2979 void init_tmp_sh_file()
2983 my_snprintf(tmp_sh_name,
sizeof(tmp_sh_name),
"tmp_%d.sh", getpid());
2985 my_snprintf(tmp_sh_cmd,
sizeof(tmp_sh_cmd),
"sh %s", tmp_sh_name);
2990 void free_tmp_sh_file()
2993 my_delete(tmp_sh_name, MYF(0));
3025 if (command->type == Q_EXECW)
3029 const char *cmd= ds_cmd->str;
3032 len= my_convert((
char *) wcmd,
sizeof(wcmd) -
sizeof(wcmd[0]),
3033 &my_charset_utf16le_bin,
3034 ds_cmd->str, strlen(ds_cmd->str), charset_info,
3036 wcmd[len /
sizeof(wchar_t)]= 0;
3037 len= my_convert((
char *) wmode,
sizeof(wmode) -
sizeof(wmode[0]),
3038 &my_charset_utf16le_bin,
3039 mode, strlen(mode), charset_info, &dummy_errors);
3040 wmode[len /
sizeof(wchar_t)]= 0;
3041 return _wpopen(wcmd, wmode);
3045 #if defined __WIN__ && defined USE_CYGWIN
3047 str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length);
3048 return popen(tmp_sh_cmd, mode);
3050 return popen(ds_cmd->str, mode);
3055 static void init_builtin_echo(
void)
3061 dirname_part(builtin_echo, my_progname, &echo_length);
3062 fn_format(builtin_echo,
".\\echo.exe",
3063 builtin_echo,
"", MYF(MY_REPLACE_DIR));
3066 if (access(builtin_echo, F_OK) != 0)
3096 const char *search_str, ulong search_len,
3097 const char *replace_str, ulong replace_len)
3100 const char *start= strstr(ds_str->str, search_str);
3103 init_dynamic_string(&ds_tmp,
"",
3104 ds_str->length + replace_len, 256);
3105 dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
3106 dynstr_append_mem(&ds_tmp, replace_str, replace_len);
3107 dynstr_append(&ds_tmp, start + search_len);
3108 dynstr_set(ds_str, ds_tmp.str);
3109 dynstr_free(&ds_tmp);
3140 char *cmd= command->first_argument;
3142 DBUG_ENTER(
"do_exec");
3143 DBUG_PRINT(
"enter", (
"cmd: '%s'", cmd));
3146 while (*cmd && my_isspace(charset_info, *cmd))
3149 die(
"Missing argument in exec");
3150 command->last_argument= command->end;
3152 init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
3154 do_eval(&ds_cmd, cmd, command->end, !is_windows);
3157 if (builtin_echo[0] && strncmp(cmd,
"echo", 4) == 0)
3160 replace(&ds_cmd,
"echo", 4, builtin_echo, strlen(builtin_echo));
3166 while(
replace(&ds_cmd,
"/dev/null", 9,
"NUL", 3) == 0)
3169 while(
replace(&ds_cmd,
">&-", 3,
">&4", 3) == 0)
3175 while(
replace(&ds_cmd,
"\n", 1,
" ", 1) == 0)
3178 DBUG_PRINT(
"info", (
"Executing '%s' as '%s'",
3179 command->first_argument, ds_cmd.str));
3181 if (!(res_file= my_popen(&ds_cmd,
"r", command)) && command->abort_on_error)
3183 dynstr_free(&ds_cmd);
3184 die(
"popen(\"%s\", \"r\") failed", command->first_argument);
3187 while (fgets(buf,
sizeof(buf), res_file))
3189 if (disable_result_log)
3191 buf[strlen(buf)-1]=0;
3192 DBUG_PRINT(
"exec_result",(
"%s", buf));
3196 replace_dynstr_append(&ds_res, buf);
3199 error= pclose(res_file);
3202 uint status= WEXITSTATUS(error);
3205 if (command->abort_on_error)
3207 log_msg(
"exec of '%s' failed, error: %d, status: %d, errno: %d",
3208 ds_cmd.str, error, status, errno);
3209 dynstr_free(&ds_cmd);
3210 die(
"command \"%s\" failed\n\nOutput from before failure:\n%s\n",
3211 command->first_argument, ds_res.str);
3215 (
"error: %d, status: %d", error, status));
3217 i= match_expected_error(command, status, NULL);
3220 DBUG_PRINT(
"info", (
"command \"%s\" failed with expected error: %d",
3221 command->first_argument, status));
3224 dynstr_free(&ds_cmd);
3225 if (command->expected_errors.count > 0)
3226 die(
"command \"%s\" failed with wrong error: %d",
3227 command->first_argument, status);
3230 else if (command->expected_errors.err[0].type == ERR_ERRNO &&
3231 command->expected_errors.err[0].code.errnum != 0)
3234 log_msg(
"exec of '%s failed, error: %d, errno: %d",
3235 ds_cmd.str, error, errno);
3236 dynstr_free(&ds_cmd);
3237 die(
"command \"%s\" succeeded - should have failed with errno %d...",
3238 command->first_argument, command->expected_errors.err[0].code.errnum);
3241 dynstr_free(&ds_cmd);
3266 int do_modify_var(
struct st_command *command,
3267 enum enum_operator op)
3269 const char *p= command->first_argument;
3272 die(
"Missing argument to %.*s", command->first_word_len, command->query);
3274 die(
"The argument to %.*s must be a variable (start with $)",
3275 command->first_word_len, command->query);
3276 v= var_get(p, &p, 1, 0);
3278 die(
"Cannot perform inc/dec on a non-numeric value");
3287 die(
"Invalid operator to do_modify_var");
3291 command->last_argument= (
char*)++p;
3307 void set_wild_chars (my_bool
set)
3309 static char old_many= 0, old_one, old_prefix;
3313 if (wild_many ==
'*')
return;
3314 old_many= wild_many;
3316 old_prefix= wild_prefix;
3323 if (! old_many)
return;
3324 wild_many= old_many;
3326 wild_prefix= old_prefix;
3341 void do_remove_file(
struct st_command *command)
3346 {
"filename", ARG_STRING, TRUE, &ds_filename,
"File to delete" }
3348 DBUG_ENTER(
"do_remove_file");
3350 check_command_args(command, command->first_argument,
3351 rm_args,
sizeof(rm_args)/
sizeof(
struct command_arg),
3354 DBUG_PRINT(
"info", (
"removing file: %s", ds_filename.str));
3355 error= my_delete(ds_filename.str, MYF(0)) != 0;
3356 handle_command_error(command, error);
3357 dynstr_free(&ds_filename);
3372 void do_remove_files_wildcard(
struct st_command *command)
3378 char dir_separator[2];
3382 char dirname[FN_REFLEN];
3385 {
"directory", ARG_STRING, TRUE, &ds_directory,
3386 "Directory containing files to delete" },
3387 {
"filename", ARG_STRING, FALSE, &ds_wild,
"File pattern to delete" }
3389 DBUG_ENTER(
"do_remove_files_wildcard");
3391 check_command_args(command, command->first_argument,
3392 rm_args,
sizeof(rm_args)/
sizeof(
struct command_arg),
3394 fn_format(dirname, ds_directory.str,
"",
"", MY_UNPACK_FILENAME);
3396 DBUG_PRINT(
"info", (
"listing directory: %s", dirname));
3398 if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT))))
3403 init_dynamic_string(&ds_file_to_remove, dirname, 1024, 1024);
3404 dir_separator[0]= FN_LIBCHAR;
3405 dir_separator[1]= 0;
3406 dynstr_append(&ds_file_to_remove, dir_separator);
3413 length= ds_file_to_remove.length;
3414 for (i= 0; i < (uint) dir_info->number_off_files; i++)
3416 ds_file_to_remove.length= length;
3417 file= dir_info->dir_entry +
i;
3421 if (MY_S_ISDIR(file->mystat->st_mode))
3423 if (ds_wild.length &&
3424 wild_compare(file->name, ds_wild.str, 0))
3430 dynstr_append(&ds_file_to_remove, file->name);
3431 DBUG_PRINT(
"info", (
"removing file: %s", ds_file_to_remove.str));
3432 error= my_delete(ds_file_to_remove.str, MYF(0)) != 0;
3437 my_dirend(dir_info);
3440 handle_command_error(command, error);
3441 dynstr_free(&ds_directory);
3442 dynstr_free(&ds_wild);
3443 dynstr_free(&ds_file_to_remove);
3460 void do_copy_file(
struct st_command *command)
3466 {
"from_file", ARG_STRING, TRUE, &ds_from_file,
"Filename to copy from" },
3467 {
"to_file", ARG_STRING, TRUE, &ds_to_file,
"Filename to copy to" }
3469 DBUG_ENTER(
"do_copy_file");
3471 check_command_args(command, command->first_argument,
3473 sizeof(copy_file_args)/
sizeof(
struct command_arg),
3476 DBUG_PRINT(
"info", (
"Copy %s to %s", ds_from_file.str, ds_to_file.str));
3478 error= (my_copy(ds_from_file.str, ds_to_file.str,
3479 MYF(MY_DONT_OVERWRITE_FILE | MY_HOLD_ORIGINAL_MODES)) != 0);
3480 handle_command_error(command, error);
3481 dynstr_free(&ds_from_file);
3482 dynstr_free(&ds_to_file);
3497 void do_move_file(
struct st_command *command)
3503 {
"from_file", ARG_STRING, TRUE, &ds_from_file,
"Filename to move from" },
3504 {
"to_file", ARG_STRING, TRUE, &ds_to_file,
"Filename to move to" }
3506 DBUG_ENTER(
"do_move_file");
3508 check_command_args(command, command->first_argument,
3510 sizeof(move_file_args)/
sizeof(
struct command_arg),
3513 DBUG_PRINT(
"info", (
"Move %s to %s", ds_from_file.str, ds_to_file.str));
3514 error= (my_rename(ds_from_file.str, ds_to_file.str,
3516 handle_command_error(command, error);
3517 dynstr_free(&ds_from_file);
3518 dynstr_free(&ds_to_file);
3534 void do_chmod_file(
struct st_command *command)
3541 {
"mode", ARG_STRING, TRUE, &ds_mode,
"Mode of file(octal) ex. 0660"},
3542 {
"filename", ARG_STRING, TRUE, &ds_file,
"Filename of file to modify" }
3544 DBUG_ENTER(
"do_chmod_file");
3546 check_command_args(command, command->first_argument,
3548 sizeof(chmod_file_args)/
sizeof(
struct command_arg),
3552 if (ds_mode.length != 4 ||
3553 str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
3554 die(
"You must write a 4 digit octal number for mode");
3556 DBUG_PRINT(
"info", (
"chmod %o %s", (uint)mode, ds_file.str));
3557 err_code= chmod(ds_file.str, mode);
3560 handle_command_error(command, err_code);
3561 dynstr_free(&ds_mode);
3562 dynstr_free(&ds_file);
3577 void do_file_exist(
struct st_command *command)
3582 {
"filename", ARG_STRING, TRUE, &ds_filename,
"File to check if it exist" }
3584 DBUG_ENTER(
"do_file_exist");
3586 check_command_args(command, command->first_argument,
3588 sizeof(file_exist_args)/
sizeof(
struct command_arg),
3591 DBUG_PRINT(
"info", (
"Checking for existence of file: %s", ds_filename.str));
3592 error= (access(ds_filename.str, F_OK) != 0);
3593 handle_command_error(command, error);
3594 dynstr_free(&ds_filename);
3614 {
"dirname", ARG_STRING, TRUE, &ds_dirname,
"Directory to create"}
3616 DBUG_ENTER(
"do_mkdir");
3618 check_command_args(command, command->first_argument,
3619 mkdir_args,
sizeof(mkdir_args)/
sizeof(
struct command_arg),
3622 DBUG_PRINT(
"info", (
"creating directory: %s", ds_dirname.str));
3623 error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
3624 handle_command_error(command, error);
3625 dynstr_free(&ds_dirname);
3644 {
"dirname", ARG_STRING, TRUE, &ds_dirname,
"Directory to remove"}
3646 DBUG_ENTER(
"do_rmdir");
3648 check_command_args(command, command->first_argument,
3649 rmdir_args,
sizeof(rmdir_args)/
sizeof(
struct command_arg),
3652 DBUG_PRINT(
"info", (
"removing directory: %s", ds_dirname.str));
3653 error= rmdir(ds_dirname.str) != 0;
3654 handle_command_error(command, error);
3655 dynstr_free(&ds_dirname);
3677 DBUG_ENTER(
"get_list_files");
3679 DBUG_PRINT(
"info", (
"listing directory: %s", ds_dirname->str));
3681 if (!(dir_info= my_dir(ds_dirname->str, MYF(0))))
3684 for (i= 0; i < (uint) dir_info->number_off_files; i++)
3686 file= dir_info->dir_entry +
i;
3687 if (file->name[0] ==
'.' &&
3688 (file->name[1] ==
'\0' ||
3689 (file->name[1] ==
'.' && file->name[2] ==
'\0')))
3691 if (ds_wild && ds_wild->length &&
3692 wild_compare(file->name, ds_wild->str, 0))
3694 replace_dynstr_append(ds, file->name);
3695 dynstr_append(ds,
"\n");
3698 my_dirend(dir_info);
3714 static void do_list_files(
struct st_command *command)
3720 {
"dirname", ARG_STRING, TRUE, &ds_dirname,
"Directory to list"},
3721 {
"file", ARG_STRING, FALSE, &ds_wild,
"Filename (incl. wildcard)"}
3723 DBUG_ENTER(
"do_list_files");
3724 command->used_replace= 1;
3726 check_command_args(command, command->first_argument,
3728 sizeof(list_files_args)/
sizeof(
struct command_arg),
' ');
3730 error= get_list_files(&ds_res, &ds_dirname, &ds_wild);
3731 handle_command_error(command, error);
3732 dynstr_free(&ds_dirname);
3733 dynstr_free(&ds_wild);
3752 static void do_list_files_write_file_command(
struct st_command *command,
3761 {
"filename", ARG_STRING, TRUE, &ds_filename,
"Filename for write"},
3762 {
"dirname", ARG_STRING, TRUE, &ds_dirname,
"Directory to list"},
3763 {
"file", ARG_STRING, FALSE, &ds_wild,
"Filename (incl. wildcard)"}
3765 DBUG_ENTER(
"do_list_files_write_file");
3766 command->used_replace= 1;
3768 check_command_args(command, command->first_argument,
3770 sizeof(list_files_args)/
sizeof(
struct command_arg),
' ');
3772 init_dynamic_string(&ds_content,
"", 1024, 1024);
3773 error= get_list_files(&ds_content, &ds_dirname, &ds_wild);
3774 handle_command_error(command, error);
3775 str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
3776 dynstr_free(&ds_content);
3777 dynstr_free(&ds_filename);
3778 dynstr_free(&ds_dirname);
3779 dynstr_free(&ds_wild);
3794 int my_getc(FILE *file)
3796 if (line_buffer_pos == line_buffer)
3798 return *--line_buffer_pos;
3802 void my_ungetc(
int c)
3804 *line_buffer_pos++= (char) c;
3812 DBUG_ENTER(
"read_until_delimiter");
3813 DBUG_PRINT(
"enter", (
"delimiter: %s, length: %u",
3814 ds_delimiter->str, (uint) ds_delimiter->length));
3816 if (ds_delimiter->length > MAX_DELIMITER_LENGTH)
3817 die(
"Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
3822 c= my_getc(cur_file->file);
3829 if (start_lineno == (cur_file->lineno - 1))
3832 else if (start_lineno == cur_file->lineno)
3838 die(
"Trailing characters found after command");
3841 if (feof(cur_file->file))
3842 die(
"End of file encountered before '%s' delimiter was found",
3845 if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
3847 DBUG_PRINT(
"exit", (
"Found delimiter '%s'", ds_delimiter->str));
3850 dynstr_append_mem(ds, (
const char*)&c, 1);
3852 DBUG_PRINT(
"exit", (
"ds: %s", ds->str));
3857 void do_write_file_command(
struct st_command *command, my_bool append)
3863 {
"filename", ARG_STRING, TRUE, &ds_filename,
"File to write to" },
3864 {
"delimiter", ARG_STRING, FALSE, &ds_delimiter,
"Delimiter to read until" }
3866 DBUG_ENTER(
"do_write_file");
3868 check_command_args(command,
3869 command->first_argument,
3871 sizeof(write_file_args)/
sizeof(
struct command_arg),
3874 if (!append && access(ds_filename.str, F_OK) == 0)
3877 die(
"File already exist: '%s'", ds_filename.str);
3880 ds_content= command->content;
3882 if (! ds_content.str)
3885 if (ds_delimiter.length == 0)
3886 dynstr_set(&ds_delimiter,
"EOF");
3888 init_dynamic_string(&ds_content,
"", 1024, 1024);
3889 read_until_delimiter(&ds_content, &ds_delimiter);
3890 command->content= ds_content;
3895 DBUG_PRINT(
"info", (
"Writing to file: %s", ds_filename.str));
3896 str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
3898 dynstr_free(&ds_filename);
3899 dynstr_free(&ds_delimiter);
3931 void do_write_file(
struct st_command *command)
3933 do_write_file_command(command, FALSE);
3962 void do_append_file(
struct st_command *command)
3964 do_write_file_command(command, TRUE);
3985 {
"filename", ARG_STRING, TRUE, &ds_filename,
"File to read from" }
3987 DBUG_ENTER(
"do_cat_file");
3989 check_command_args(command,
3990 command->first_argument,
3995 DBUG_PRINT(
"info", (
"Reading from, file: %s", ds_filename.str));
3997 error= cat_file(&ds_res, ds_filename.str);
3998 handle_command_error(command, error);
3999 dynstr_free(&ds_filename);
4016 void do_diff_files(
struct st_command *command)
4022 {
"file1", ARG_STRING, TRUE, &ds_filename,
"First file to diff" },
4023 {
"file2", ARG_STRING, TRUE, &ds_filename2,
"Second file to diff" }
4025 DBUG_ENTER(
"do_diff_files");
4027 check_command_args(command,
4028 command->first_argument,
4030 sizeof(diff_file_args)/
sizeof(
struct command_arg),
4033 if (access(ds_filename.str, F_OK) != 0)
4034 die(
"command \"diff_files\" failed, file '%s' does not exist",
4037 if (access(ds_filename2.str, F_OK) != 0)
4038 die(
"command \"diff_files\" failed, file '%s' does not exist",
4041 if ((error= compare_files(ds_filename.str, ds_filename2.str)) &&
4042 match_expected_error(command, error, NULL) < 0)
4048 show_diff(&ds_res, ds_filename.str, ds_filename2.str);
4049 log_file.write(&ds_res);
4051 dynstr_set(&ds_res, 0);
4054 dynstr_free(&ds_filename);
4055 dynstr_free(&ds_filename2);
4056 handle_command_error(command, error);
4061 struct st_connection * find_connection_by_name(
const char *name)
4064 for (con= connections; con < next_con; con++)
4066 if (!strcmp(con->name, name))
4085 void do_send_quit(
struct st_command *command)
4087 char *p= command->first_argument, *
name;
4090 DBUG_ENTER(
"do_send_quit");
4091 DBUG_PRINT(
"enter",(
"name: '%s'",p));
4094 die(
"Missing connection name in send_quit");
4096 while (*p && !my_isspace(charset_info,*p))
4101 command->last_argument= p;
4103 if (!(con= find_connection_by_name(name)))
4104 die(
"connection '%s' not found in connection pool", name);
4106 simple_command(&con->mysql,COM_QUIT,0,0,1);
4128 void do_change_user(
struct st_command *command)
4130 MYSQL *mysql = &cur_con->mysql;
4133 {
"user", ARG_STRING, FALSE, &ds_user,
"User to connect as" },
4134 {
"password", ARG_STRING, FALSE, &ds_passwd,
"Password used when connecting" },
4135 {
"database", ARG_STRING, FALSE, &ds_db,
"Database to select after connect" },
4138 DBUG_ENTER(
"do_change_user");
4140 check_command_args(command, command->first_argument,
4142 sizeof(change_user_args)/
sizeof(
struct command_arg),
4147 mysql_stmt_close(cur_con->stmt);
4148 cur_con->stmt= NULL;
4151 if (!ds_user.length)
4153 dynstr_set(&ds_user, mysql->user);
4155 if (!ds_passwd.length)
4156 dynstr_set(&ds_passwd, mysql->passwd);
4159 dynstr_set(&ds_db, mysql->db);
4162 DBUG_PRINT(
"info",(
"connection: '%s' user: '%s' password: '%s' database: '%s'",
4163 cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
4165 if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str))
4166 die(
"change user failed: %s", mysql_error(mysql));
4168 dynstr_free(&ds_user);
4169 dynstr_free(&ds_passwd);
4170 dynstr_free(&ds_db);
4200 char buf[FN_REFLEN];
4201 char temp_file_path[FN_REFLEN];
4205 {
"delimiter", ARG_STRING, FALSE, &ds_delimiter,
"Delimiter to read until" }
4207 DBUG_ENTER(
"do_perl");
4209 check_command_args(command,
4210 command->first_argument,
4215 ds_script= command->content;
4217 if (! ds_script.str)
4220 if (ds_delimiter.length == 0)
4221 dynstr_set(&ds_delimiter,
"EOF");
4223 init_dynamic_string(&ds_script,
"", 1024, 1024);
4224 read_until_delimiter(&ds_script, &ds_delimiter);
4225 command->content= ds_script;
4231 DBUG_PRINT(
"info", (
"Executing perl: %s", ds_script.str));
4234 if ((fd= create_temp_file(temp_file_path, getenv(
"MYSQLTEST_VARDIR"),
4235 "tmp", O_CREAT | O_SHARE | O_RDWR,
4237 die(
"Failed to create temporary file for perl command");
4238 my_close(fd, MYF(0));
4240 str_to_file(temp_file_path, ds_script.str, ds_script.length);
4243 my_snprintf(buf,
sizeof(buf),
"perl %s", temp_file_path);
4245 if (!(res_file= popen(buf,
"r")) && command->abort_on_error)
4246 die(
"popen(\"%s\", \"r\") failed", buf);
4248 while (fgets(buf,
sizeof(buf), res_file))
4250 if (disable_result_log)
4252 buf[strlen(buf)-1]=0;
4253 DBUG_PRINT(
"exec_result",(
"%s", buf));
4257 replace_dynstr_append(&ds_res, buf);
4260 error= pclose(res_file);
4264 my_delete(temp_file_path, MYF(0));
4267 int exstat= WEXITSTATUS(error);
4271 abort_not_supported_test(
"perl not found in path or did not start");
4274 abort_not_supported_test(
"perl not found in path");
4277 handle_command_error(command, exstat);
4279 dynstr_free(&ds_delimiter);
4311 DBUG_ENTER(
"do_echo");
4313 init_dynamic_string(&ds_echo,
"", command->query_len, 256);
4314 do_eval(&ds_echo, command->first_argument, command->end, FALSE);
4315 dynstr_append_mem(&ds_res, ds_echo.str, ds_echo.length);
4316 dynstr_append_mem(&ds_res,
"\n", 1);
4317 dynstr_free(&ds_echo);
4318 command->last_argument= command->end;
4323 void do_wait_for_slave_to_stop(
struct st_command *c __attribute__((unused)))
4325 static int SLAVE_POLL_INTERVAL= 300000;
4326 MYSQL* mysql = &cur_con->mysql;
4333 if (mysql_query(mysql,
"show status like 'Slave_running'") ||
4334 !(res=mysql_store_result(mysql)))
4335 die(
"Query failed while probing slave for stop: %s",
4336 mysql_error(mysql));
4337 if (!(row=mysql_fetch_row(res)) || !row[1])
4339 mysql_free_result(res);
4340 die(
"Strange result from query while probing slave for stop");
4342 done = !strcmp(row[1],
"OFF");
4343 mysql_free_result(res);
4346 my_sleep(SLAVE_POLL_INTERVAL);
4356 MYSQL *mysql= &cur_con->mysql;
4357 char query_buf[FN_REFLEN+128];
4360 if (!master_pos.file[0])
4361 die(
"Calling 'sync_with_master' without calling 'save_master_pos'");
4363 sprintf(query_buf,
"select master_pos_wait('%s', %ld, %d)",
4364 master_pos.file, master_pos.pos + offset, timeout);
4366 if (mysql_query(mysql, query_buf))
4367 die(
"failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
4368 mysql_error(mysql));
4370 if (!(res= mysql_store_result(mysql)))
4371 die(
"mysql_store_result() returned NULL for '%s'", query_buf);
4372 if (!(row= mysql_fetch_row(res)))
4374 mysql_free_result(res);
4375 die(
"empty result in %s", query_buf);
4379 const char* result_str= row[0];
4381 result= atoi(result_str);
4383 mysql_free_result(res);
4385 if (!result_str || result < 0)
4388 show_query(mysql,
"SHOW MASTER STATUS");
4389 show_query(mysql,
"SHOW SLAVE STATUS");
4390 show_query(mysql,
"SHOW PROCESSLIST");
4391 fprintf(stderr,
"analyze: sync_with_master\n");
4401 die(
"%.*s failed: '%s' returned NULL "\
4402 "indicating slave SQL thread failure",
4403 command->first_word_len, command->query, query_buf);
4408 die(
"%.*s failed: '%s' returned -1 "\
4409 "indicating timeout after %d seconds",
4410 command->first_word_len, command->query, query_buf, timeout);
4412 die(
"%.*s failed: '%s' returned unknown result :%d",
4413 command->first_word_len, command->query, query_buf, result);
4419 void do_sync_with_master(
struct st_command *command)
4422 char *p= command->first_argument;
4423 const char *offset_start= p;
4426 for (; my_isdigit(charset_info, *p); p++)
4427 offset = offset * 10 + *p -
'0';
4429 if(*p && !my_isspace(charset_info, *p))
4430 die(
"Invalid integer argument \"%s\"", offset_start);
4431 command->last_argument= p;
4433 do_sync_with_master2(command, offset);
4442 int do_save_master_pos()
4446 MYSQL *mysql = &cur_con->mysql;
4448 DBUG_ENTER(
"do_save_master_pos");
4450 #ifdef HAVE_NDB_BINLOG
4456 bool have_ndbcluster;
4457 if (mysql_query(mysql, query=
4458 "select count(*) from information_schema.engines"
4459 " where engine = 'ndbcluster' and"
4460 " support in ('YES', 'DEFAULT')"))
4461 die(
"'%s' failed: %d %s", query,
4462 mysql_errno(mysql), mysql_error(mysql));
4463 if (!(res= mysql_store_result(mysql)))
4464 die(
"mysql_store_result() returned NULL for '%s'", query);
4465 if (!(row= mysql_fetch_row(res)))
4466 die(
"Query '%s' returned empty result", query);
4468 have_ndbcluster= strcmp(row[0],
"1") == 0;
4469 mysql_free_result(res);
4471 if (have_ndbcluster)
4473 ulonglong start_epoch= 0, handled_epoch= 0,
4474 latest_trans_epoch=0,
4475 latest_handled_binlog_epoch= 0;
4480 const char binlog[]=
"binlog";
4481 const char latest_trans_epoch_str[]=
4482 "latest_trans_epoch=";
4483 const char latest_handled_binlog_epoch_str[]=
4484 "latest_handled_binlog_epoch=";
4487 if (mysql_query(mysql, query=
"show engine ndb status"))
4488 die(
"failed in '%s': %d %s", query,
4489 mysql_errno(mysql), mysql_error(mysql));
4490 if (!(res= mysql_store_result(mysql)))
4491 die(
"mysql_store_result() returned NULL for '%s'", query);
4492 while ((row= mysql_fetch_row(res)))
4494 if (strcmp(row[1], binlog) == 0)
4496 const char *status= row[2];
4499 while (*status && strncmp(status, latest_trans_epoch_str,
4500 sizeof(latest_trans_epoch_str)-1))
4504 status+=
sizeof(latest_trans_epoch_str)-1;
4505 latest_trans_epoch= strtoull(status, (
char**) 0, 10);
4508 die(
"result does not contain '%s' in '%s'",
4509 latest_trans_epoch_str, query);
4513 strncmp(status, latest_handled_binlog_epoch_str,
4514 sizeof(latest_handled_binlog_epoch_str)-1))
4518 status+=
sizeof(latest_handled_binlog_epoch_str)-1;
4519 latest_handled_binlog_epoch= strtoull(status, (
char**) 0, 10);
4522 die(
"result does not contain '%s' in '%s'",
4523 latest_handled_binlog_epoch_str, query);
4526 start_epoch= latest_trans_epoch;
4531 die(
"result does not contain '%s' in '%s'",
4533 if (latest_handled_binlog_epoch > handled_epoch)
4535 handled_epoch= latest_handled_binlog_epoch;
4537 if (latest_handled_binlog_epoch >= start_epoch)
4539 else if (count > 300)
4543 mysql_free_result(res);
4548 if (mysql_query(mysql, query=
"show master status"))
4549 die(
"failed in 'show master status': %d %s",
4550 mysql_errno(mysql), mysql_error(mysql));
4552 if (!(res = mysql_store_result(mysql)))
4553 die(
"mysql_store_result() retuned NULL for '%s'", query);
4554 if (!(row = mysql_fetch_row(res)))
4555 die(
"empty result in show master status");
4556 strnmov(master_pos.file, row[0],
sizeof(master_pos.file)-1);
4557 master_pos.pos = strtoul(row[1], (
char**) 0, 10);
4558 mysql_free_result(res);
4584 char *p= command->first_argument;
4585 char *var_name, *var_name_end;
4587 DBUG_ENTER(
"do_let");
4589 init_dynamic_string(&let_rhs_expr,
"", 512, 2048);
4593 die(
"Missing arguments to let");
4595 while (*p && (*p !=
'=') && !my_isspace(charset_info,*p))
4598 if (var_name == var_name_end ||
4599 (var_name+1 == var_name_end && *var_name ==
'$'))
4600 die(
"Missing variable name in let");
4601 while (my_isspace(charset_info,*p))
4604 die(
"Missing assignment operator in let");
4607 while (*p && my_isspace(charset_info,*p))
4610 do_eval(&let_rhs_expr, p, command->end, FALSE);
4612 command->last_argument= command->end;
4614 var_set(var_name, var_name_end, let_rhs_expr.str,
4615 (let_rhs_expr.str + let_rhs_expr.length));
4616 dynstr_free(&let_rhs_expr);
4617 revert_properties();
4644 int do_sleep(
struct st_command *command, my_bool real_sleep)
4647 char *sleep_start, *sleep_end;
4652 {
"sleep_delay", ARG_STRING, TRUE, &ds_sleep,
"Number of seconds to sleep." }
4654 check_command_args(command, command->first_argument, sleep_args,
4659 sleep_end= ds_sleep.str + ds_sleep.length;
4660 while (my_isspace(charset_info, *p))
4663 die(
"Missing argument to %.*s", command->first_word_len, command->query);
4666 if (!my_isdigit(charset_info, *sleep_start))
4667 die(
"Invalid argument to %.*s \"%s\"", command->first_word_len,
4668 command->query, sleep_start);
4669 sleep_val= my_strtod(sleep_start, &sleep_end, &error);
4670 check_eol_junk_line(sleep_end);
4672 die(
"Invalid argument to %.*s \"%s\"", command->first_word_len,
4673 command->query, command->first_argument);
4674 dynstr_free(&ds_sleep);
4677 if (opt_sleep >= 0 && !real_sleep)
4678 sleep_val= opt_sleep;
4680 DBUG_PRINT(
"info", (
"sleep_val: %f", sleep_val));
4682 my_sleep((ulong) (sleep_val * 1000000L));
4687 void do_get_file_name(
struct st_command *command,
4688 char* dest, uint dest_max_len)
4690 char *p= command->first_argument, *
name;
4692 die(
"Missing file name argument");
4694 while (*p && !my_isspace(charset_info,*p))
4698 command->last_argument= p;
4699 strmake(dest, name, dest_max_len - 1);
4703 void do_set_charset(
struct st_command *command)
4705 char *charset_name= command->first_argument;
4708 if (!charset_name || !*charset_name)
4709 die(
"Missing charset name in 'character_set'");
4712 while (*p && !my_isspace(charset_info,*p))
4716 command->last_argument= p;
4717 charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
4719 abort_not_supported_test(
"Test requires charset '%s'", charset_name);
4728 int query_get_string(
MYSQL* mysql,
const char* query,
4734 if (mysql_query(mysql, query))
4735 die(
"'%s' failed: %d %s", query,
4736 mysql_errno(mysql), mysql_error(mysql));
4737 if ((res= mysql_store_result(mysql)) == NULL)
4738 die(
"Failed to store result: %d %s",
4739 mysql_errno(mysql), mysql_error(mysql));
4741 if ((row= mysql_fetch_row(res)) == NULL)
4743 mysql_free_result(res);
4747 init_dynamic_string(ds, (row[column] ? row[column] :
"NULL"), ~0, 32);
4748 mysql_free_result(res);
4753 static int my_kill(
int pid,
int sig)
4757 if ((proc= OpenProcess(PROCESS_TERMINATE, FALSE, pid)) == NULL)
4764 (void)TerminateProcess(proc, 201);
4768 return kill(pid, sig);
4789 void do_shutdown_server(
struct st_command *command)
4794 MYSQL* mysql = &cur_con->mysql;
4797 {
"timeout", ARG_STRING, FALSE, &ds_timeout,
"Timeout before killing server"}
4799 DBUG_ENTER(
"do_shutdown_server");
4801 check_command_args(command, command->first_argument, shutdown_args,
4805 if (ds_timeout.length)
4808 timeout= strtol(ds_timeout.str, &endptr, 10);
4809 if (*endptr !=
'\0')
4810 die(
"Illegal argument for timeout: '%s'", ds_timeout.str);
4812 dynstr_free(&ds_timeout);
4815 if (query_get_string(mysql,
"SHOW VARIABLES LIKE 'pid_file'", 1,
4817 die(
"Failed to get pid_file from server");
4824 if ((fd= my_open(ds_pidfile_name.str, O_RDONLY, MYF(0))) < 0)
4825 die(
"Failed to open file '%s'", ds_pidfile_name.str);
4826 dynstr_free(&ds_pidfile_name);
4828 if (my_read(fd, (uchar*)&buff,
4829 sizeof(buff), MYF(0)) <= 0){
4830 my_close(fd, MYF(0));
4831 die(
"pid file was empty");
4833 my_close(fd, MYF(0));
4837 die(
"Pidfile didn't contain a valid number");
4839 DBUG_PRINT(
"info", (
"Got pid %d", pid));
4842 if (timeout && mysql_shutdown(mysql, SHUTDOWN_DEFAULT))
4843 die(
"mysql_shutdown failed");
4847 if (my_kill(pid, 0) < 0){
4848 DBUG_PRINT(
"info", (
"Process %d does not exist anymore", pid));
4851 DBUG_PRINT(
"info", (
"Sleeping, timeout: %ld", timeout));
4856 DBUG_PRINT(
"info", (
"Killing server, pid: %d", pid));
4857 (void)my_kill(pid, 9);
4865 uint get_errcode_from_name(
char *error_name,
char *error_end)
4870 DBUG_ENTER(
"get_errcode_from_name");
4871 DBUG_PRINT(
"enter", (
"error_name: %s", error_name));
4874 for (; e->name; e++)
4881 if (!strncmp(error_name, e->name, (
int) (error_end - error_name)) &&
4882 (uint) strlen(e->name) == (uint) (error_end - error_name))
4884 DBUG_RETURN(e->code);
4888 die(
"Unknown SQL error name '%s'", error_name);
4892 const char *get_errname_from_code (uint error_code)
4896 DBUG_ENTER(
"get_errname_from_code");
4897 DBUG_PRINT(
"enter", (
"error_code: %d", error_code));
4903 for (; e->name; e++)
4905 if (e->code == error_code)
4907 DBUG_RETURN(e->name);
4911 DBUG_RETURN(
"<Unknown>");
4914 void do_get_errcodes(
struct st_command *command)
4917 char *p= command->first_argument;
4921 DBUG_ENTER(
"do_get_errcodes");
4924 die(
"Missing argument(s) to 'error'");
4931 while (*p && *p ==
' ')
4936 while (*end && *end !=
',' && *end !=
' ')
4945 VAR *var = var_get(p,&fin,0,0);
4947 end=p+var->str_val_len;
4952 char *to_ptr= to->code.sqlstate;
4960 if ((end - p) != SQLSTATE_LENGTH)
4961 die(
"The sqlstate must be exactly %d chars long", SQLSTATE_LENGTH);
4964 while (*p && p < end)
4966 if (my_isdigit(charset_info, *p) || my_isupper(charset_info, *p))
4969 die(
"The sqlstate may only consist of digits[0-9] " \
4970 "and _uppercase_ letters");
4974 to->type= ERR_SQLSTATE;
4975 DBUG_PRINT(
"info", (
"ERR_SQLSTATE: %s", to->code.sqlstate));
4979 die(
"The sqlstate definition must start with an uppercase S");
4985 DBUG_PRINT(
"info", (
"Error name: %s", p));
4986 to->code.errnum= get_errcode_from_name(p, end);
4987 to->type= ERR_ERRNO;
4988 DBUG_PRINT(
"info", (
"ERR_ERRNO: %d", to->code.errnum));
4992 die(
"The error name definition must start with an uppercase E");
4999 while (*p && p != end)
5001 if (!my_isdigit(charset_info, *p))
5002 die(
"Invalid argument to error: '%s' - "\
5003 "the errno may only consist of digits[0-9]",
5004 command->first_argument);
5009 if (!str2int(start, 10, (
long) INT_MIN, (
long) INT_MAX, &val))
5010 die(
"Invalid argument to error: '%s'", command->first_argument);
5012 to->code.errnum= (uint) val;
5013 to->type= ERR_ERRNO;
5014 DBUG_PRINT(
"info", (
"ERR_ERRNO: %d", to->code.errnum));
5019 if (count >= (
sizeof(saved_expected_errors.err) /
5021 die(
"Too many errorcodes specified");
5027 while (*p && *p !=
',')
5035 command->last_argument= p;
5036 to->type= ERR_EMPTY;
5038 DBUG_PRINT(
"info", (
"Expected errors: %d", count));
5039 saved_expected_errors.count= count;
5051 char *get_string(
char **to_ptr,
char **from_ptr,
5055 char *to= *to_ptr, *from= *from_ptr, *start=
to;
5056 DBUG_ENTER(
"get_string");
5059 if (*from ==
'"' || *from ==
'\'')
5064 for ( ; (c=*from) ; from++)
5066 if (c ==
'\\' && from[1])
5092 if (c ==
' ' || c != *++from)
5099 if (*from !=
' ' && *from)
5100 die(
"Wrong string argument in %s", command->query);
5102 while (my_isspace(charset_info,*from))
5112 const char *end=
to;
5113 VAR *var=var_get(start, &end, 0, 1);
5114 if (var && to == (
char*) end+1)
5116 DBUG_PRINT(
"info",(
"var: '%s' -> '%s'", start, var->str_val));
5117 DBUG_RETURN(var->str_val);
5124 void set_reconnect(
MYSQL* mysql,
int val)
5126 my_bool reconnect= val;
5127 DBUG_ENTER(
"set_reconnect");
5128 DBUG_PRINT(
"info", (
"val: %d", val));
5129 #if MYSQL_VERSION_ID < 50000
5130 mysql->reconnect= reconnect;
5132 mysql_options(mysql, MYSQL_OPT_RECONNECT, (
char *)&reconnect);
5146 var_set_int(
"$mysql_get_server_version",
5147 mysql_get_server_version(&con->mysql));
5149 var_set_string(
"$CURRENT_CONNECTION", con->name);
5153 void select_connection_name(
const char *name)
5155 DBUG_ENTER(
"select_connection_name");
5156 DBUG_PRINT(
"enter",(
"name: '%s'", name));
5160 die(
"connection '%s' not found in connection pool", name);
5162 set_current_connection(con);
5165 if (!disable_connect_log && !disable_query_log)
5169 dynstr_append_mem(ds,
"connection ", 11);
5170 replace_dynstr_append(ds, name);
5171 dynstr_append_mem(ds,
";\n", 2);
5178 void select_connection(
struct st_command *command)
5180 DBUG_ENTER(
"select_connection");
5183 {
"connection_name", ARG_STRING, TRUE, &ds_connection,
"Name of the connection that we switch to." }
5185 check_command_args(command, command->first_argument, connection_args,
5186 sizeof(connection_args)/
sizeof(
struct command_arg),
5189 DBUG_PRINT(
"info", (
"changing connection: %s", ds_connection.str));
5190 select_connection_name(ds_connection.str);
5191 dynstr_free(&ds_connection);
5196 void do_close_connection(
struct st_command *command)
5198 DBUG_ENTER(
"close_connection");
5202 const struct command_arg close_connection_args[] = {
5203 {
"connection_name", ARG_STRING, TRUE, &ds_connection,
5204 "Name of the connection to close." }
5206 check_command_args(command, command->first_argument,
5207 close_connection_args,
5208 sizeof(close_connection_args)/
sizeof(
struct command_arg),
5211 DBUG_PRINT(
"enter",(
"connection name: '%s'", ds_connection.str));
5213 if (!(con= find_connection_by_name(ds_connection.str)))
5214 die(
"connection '%s' not found in connection pool", ds_connection.str);
5216 DBUG_PRINT(
"info", (
"Closing connection %s", con->name));
5217 #ifndef EMBEDDED_LIBRARY
5218 if (command->type == Q_DIRTY_CLOSE)
5220 if (con->mysql.net.vio)
5222 vio_delete(con->mysql.net.vio);
5223 con->mysql.net.vio = 0;
5232 emb_close_connection(con);
5235 mysql_stmt_close(con->stmt);
5238 mysql_close(&con->mysql);
5240 if (con->util_mysql)
5241 mysql_close(con->util_mysql);
5243 con->pending= FALSE;
5251 if (!(con->name = my_strdup(
"-closed_connection-", MYF(MY_WME))))
5252 die(
"Out of memory");
5257 var_set_int(
"$mysql_get_server_version", 0xFFFFFFFF);
5258 var_set_string(
"$CURRENT_CONNECTION", con->name);
5262 if (!disable_connect_log && !disable_query_log)
5266 dynstr_append_mem(ds,
"disconnect ", 11);
5267 replace_dynstr_append(ds, ds_connection.str);
5268 dynstr_append_mem(ds,
";\n", 2);
5271 dynstr_free(&ds_connection);
5301 void safe_connect(
MYSQL* mysql,
const char *name,
const char *host,
5302 const char *user,
const char *pass,
const char *db,
5303 int port,
const char *sock)
5305 int failed_attempts= 0;
5307 DBUG_ENTER(
"safe_connect");
5309 verbose_msg(
"Connecting to server %s:%d (socket %s) as '%s'"
5310 ", connection '%s', attempt %d ...",
5311 host, port, sock, user, name, failed_attempts);
5313 mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
5314 mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
5315 "program_name",
"mysqltest");
5316 mysql_options(mysql, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
5317 &can_handle_expired_passwords);
5318 while(!mysql_real_connect(mysql, host,user, pass, db, port, sock,
5319 CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
5329 if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
5330 mysql_errno(mysql) == CR_CONNECTION_ERROR) &&
5331 failed_attempts < opt_max_connect_retries)
5333 verbose_msg(
"Connect attempt %d/%d failed: %d: %s", failed_attempts,
5334 opt_max_connect_retries, mysql_errno(mysql),
5335 mysql_error(mysql));
5336 my_sleep(connection_retry_sleep);
5340 if (failed_attempts > 0)
5341 die(
"Could not open connection '%s' after %d attempts: %d %s", name,
5342 failed_attempts, mysql_errno(mysql), mysql_error(mysql));
5344 die(
"Could not open connection '%s': %d %s", name,
5345 mysql_errno(mysql), mysql_error(mysql));
5349 verbose_msg(
"... Connected.");
5377 int connect_n_handle_errors(
struct st_command *command,
5378 MYSQL* con,
const char* host,
5379 const char* user,
const char* pass,
5380 const char* db,
int port,
const char* sock)
5383 int failed_attempts= 0;
5388 if (command->expected_errors.count > 0 &&
5394 dynstr_append_mem(ds,
"connect(", 8);
5395 replace_dynstr_append(ds, host);
5396 dynstr_append_mem(ds,
",", 1);
5397 replace_dynstr_append(ds, user);
5398 dynstr_append_mem(ds,
",", 1);
5399 replace_dynstr_append(ds, pass);
5400 dynstr_append_mem(ds,
",", 1);
5402 replace_dynstr_append(ds, db);
5403 dynstr_append_mem(ds,
",", 1);
5404 replace_dynstr_append_uint(ds, port);
5405 dynstr_append_mem(ds,
",", 1);
5407 replace_dynstr_append(ds, sock);
5408 dynstr_append_mem(ds,
")", 1);
5409 dynstr_append_mem(ds, delimiter, delimiter_length);
5410 dynstr_append_mem(ds,
"\n", 1);
5413 if (!disable_connect_log && !disable_query_log)
5415 replace_dynstr_append(ds, command->query);
5416 dynstr_append_mem(ds,
";\n", 2);
5419 mysql_options(con, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
5420 mysql_options4(con, MYSQL_OPT_CONNECT_ATTR_ADD,
"program_name",
"mysqltest");
5421 mysql_options(con, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
5422 &can_handle_expired_passwords);
5423 while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
5424 CLIENT_MULTI_STATEMENTS))
5442 if (((mysql_errno(con) == ER_TOO_MANY_USER_CONNECTIONS) ||
5443 (mysql_errno(con) == ER_USER_LIMIT_REACHED)) &&
5444 (failed_attempts++ < opt_max_connect_retries))
5448 i= match_expected_error(command, mysql_errno(con), mysql_sqlstate(con));
5451 goto do_handle_error;
5453 my_sleep(connection_retry_sleep);
5458 var_set_errno(mysql_errno(con));
5459 handle_error(command, mysql_errno(con), mysql_error(con),
5460 mysql_sqlstate(con), ds);
5465 handle_no_error(command);
5466 revert_properties();
5500 int con_port= opt_port;
5502 my_bool con_ssl= 0, con_compress= 0;
5503 my_bool con_pipe= 0, con_shm= 0, con_cleartext_enable= 0;
5504 my_bool con_secure_auth= 1;
5520 {
"connection name", ARG_STRING, TRUE, &ds_connection_name,
"Name of the connection" },
5521 {
"host", ARG_STRING, TRUE, &ds_host,
"Host to connect to" },
5522 {
"user", ARG_STRING, FALSE, &ds_user,
"User to connect as" },
5523 {
"passsword", ARG_STRING, FALSE, &ds_password,
"Password used when connecting" },
5524 {
"database", ARG_STRING, FALSE, &ds_database,
"Database to select after connect" },
5525 {
"port", ARG_STRING, FALSE, &ds_port,
"Port to connect to" },
5526 {
"socket", ARG_STRING, FALSE, &ds_sock,
"Socket to connect with" },
5527 {
"options", ARG_STRING, FALSE, &ds_options,
"Options to use while connecting" },
5528 {
"default_auth", ARG_STRING, FALSE, &ds_default_auth,
"Default authentication to use" }
5531 DBUG_ENTER(
"do_connect");
5532 DBUG_PRINT(
"enter",(
"connect: %s", command->first_argument));
5534 strip_parentheses(command);
5535 check_command_args(command, command->first_argument, connect_args,
5542 con_port= atoi(ds_port.str);
5544 die(
"Illegal argument for port: '%s'", ds_port.str);
5549 init_dynamic_string(&ds_shm, ds_sock.str, 0, 0);
5559 if (*ds_sock.str != FN_LIBCHAR)
5561 char buff[FN_REFLEN];
5562 fn_format(buff, ds_sock.str, TMPDIR,
"", 0);
5563 dynstr_set(&ds_sock, buff);
5569 dynstr_set(&ds_sock, unix_sock);
5571 DBUG_PRINT(
"info", (
"socket: %s", ds_sock.str));
5575 con_options= ds_options.str;
5576 while (*con_options)
5580 while (*con_options && my_isspace(charset_info, *con_options))
5584 while (*end && !my_isspace(charset_info, *end))
5586 if (!strncmp(con_options,
"SSL", 3))
5588 else if (!strncmp(con_options,
"COMPRESS", 8))
5590 else if (!strncmp(con_options,
"PIPE", 4))
5592 else if (!strncmp(con_options,
"SHM", 3))
5594 else if (!strncmp(con_options,
"CLEARTEXT", 9))
5595 con_cleartext_enable= 1;
5596 else if (!strncmp(con_options,
"SKIPSECUREAUTH",14))
5599 die(
"Illegal option to connect: %.*s",
5600 (
int) (end - con_options), con_options);
5605 if (find_connection_by_name(ds_connection_name.str))
5606 die(
"Connection %s already exists", ds_connection_name.str);
5608 if (next_con != connections_end)
5612 if (!(con_slot= find_connection_by_name(
"-closed_connection-")))
5613 die(
"Connection limit exhausted, you can have max %d connections",
5614 opt_max_connections);
5617 #ifdef EMBEDDED_LIBRARY
5618 init_connection_thd(con_slot);
5621 if (!mysql_init(&con_slot->mysql))
5622 die(
"Failed on mysql_init()");
5624 if (opt_connect_timeout)
5625 mysql_options(&con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
5626 (
void *) &opt_connect_timeout);
5628 if (opt_compress || con_compress)
5629 mysql_options(&con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
5630 mysql_options(&con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
5631 mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_NAME,
5632 charset_info->csname);
5633 if (opt_charsets_dir)
5634 mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
5637 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
5644 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
5645 mysql_ssl_set(&con_slot->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
5646 opt_ssl_capath, opt_ssl_cipher);
5647 mysql_options(&con_slot->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
5648 mysql_options(&con_slot->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
5649 #if MYSQL_VERSION_ID >= 50000
5651 opt_ssl_verify_server_cert= !strcmp(ds_host.str,
"localhost");
5652 mysql_options(&con_slot->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
5653 &opt_ssl_verify_server_cert);
5660 #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
5661 opt_protocol= MYSQL_PROTOCOL_PIPE;
5665 #ifndef EMBEDDED_LIBRARY
5667 mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, (
char*) &opt_protocol);
5673 uint protocol= MYSQL_PROTOCOL_MEMORY;
5675 die(
"Missing shared memory base name");
5676 mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, ds_shm.str);
5677 mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol);
5681 else if (shared_memory_base_name)
5683 mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
5684 shared_memory_base_name);
5689 if (ds_database.length == 0)
5690 dynstr_set(&ds_database, opt_db);
5692 if (opt_plugin_dir && *opt_plugin_dir)
5693 mysql_options(&con_slot->mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
5695 if (ds_default_auth.length)
5696 mysql_options(&con_slot->mysql, MYSQL_DEFAULT_AUTH, ds_default_auth.str);
5698 #if !defined(HAVE_YASSL)
5700 if (opt_server_public_key && *opt_server_public_key)
5701 mysql_options(&con_slot->mysql, MYSQL_SERVER_PUBLIC_KEY,
5702 opt_server_public_key);
5705 if (con_cleartext_enable)
5706 mysql_options(&con_slot->mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
5707 (
char*) &con_cleartext_enable);
5709 if (!con_secure_auth)
5710 mysql_options(&con_slot->mysql, MYSQL_SECURE_AUTH,
5711 (
char*) &con_secure_auth);
5714 if (ds_database.length && !strcmp(ds_database.str,
"*NO-ONE*"))
5715 dynstr_set(&ds_database,
"");
5717 if (connect_n_handle_errors(command, &con_slot->mysql,
5718 ds_host.str,ds_user.str,
5719 ds_password.str, ds_database.str,
5720 con_port, ds_sock.str))
5722 DBUG_PRINT(
"info", (
"Inserting connection %s in connection pool",
5723 ds_connection_name.str));
5724 if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
5725 die(
"Out of memory");
5726 con_slot->name_len= strlen(con_slot->name);
5727 set_current_connection(con_slot);
5729 if (con_slot == next_con)
5733 dynstr_free(&ds_connection_name);
5734 dynstr_free(&ds_host);
5735 dynstr_free(&ds_user);
5736 dynstr_free(&ds_password);
5737 dynstr_free(&ds_database);
5738 dynstr_free(&ds_port);
5739 dynstr_free(&ds_sock);
5740 dynstr_free(&ds_options);
5741 dynstr_free(&ds_default_auth);
5743 dynstr_free(&ds_shm);
5752 if (cur_block == block_stack)
5754 if (*command->query !=
'}')
5755 die(
"Stray 'end' command - end of block before beginning");
5756 die(
"Stray '}' - end of block before beginning");
5760 if (cur_block->ok && cur_block->cmd == cmd_while)
5764 parser.current_line = cur_block->line;
5768 if (*cur_block->delim)
5771 strcpy (delimiter, cur_block->delim);
5772 delimiter_length= strlen(delimiter);
5776 parser.current_line++;
5794 enum block_op find_operand(
const char *start)
5797 char next= *(start+1);
5799 if (first ==
'=' && next ==
'=')
5801 if (first ==
'!' && next ==
'=')
5803 if (first ==
'>' && next ==
'=')
5807 if (first ==
'<' && next ==
'=')
5849 void do_block(
enum block_cmd cmd,
struct st_command* command)
5851 char *p= command->first_argument;
5852 const char *expr_start, *expr_end;
5854 const char *cmd_name= (cmd == cmd_while ?
"while" :
"if");
5855 my_bool not_expr= FALSE;
5856 DBUG_ENTER(
"do_block");
5857 DBUG_PRINT(
"enter", (
"%s", cmd_name));
5860 if (cur_block == block_stack_end)
5861 die(
"Nesting too deeply");
5864 cur_block->line= parser.current_line++;
5871 cur_block->cmd= cmd;
5872 cur_block->ok= FALSE;
5873 cur_block->delim[0]=
'\0';
5878 expr_start= strchr(p,
'(');
5880 die(
"missing '(' in %s", cmd_name);
5882 while (my_isspace(charset_info, *expr_start))
5886 if (*expr_start ==
'!')
5890 while (*expr_start && my_isspace(charset_info, *expr_start))
5894 expr_end= strrchr(expr_start,
')');
5896 die(
"missing ')' in %s", cmd_name);
5897 p= (
char*)expr_end+1;
5899 while (*p && my_isspace(charset_info, *p))
5901 if (*p && *p !=
'{')
5902 die(
"Missing '{' after %s. Found \"%s\"", cmd_name, p);
5904 var_init(&v,0,0,0,0);
5908 if (*expr_start ==
'$')
5910 const char *curr_ptr= expr_end;
5911 eval_expr(&v, expr_start, &curr_ptr,
true);
5912 while (my_isspace(charset_info, *++curr_ptr))
5915 if (curr_ptr == expr_end)
5918 enum block_op operand= find_operand(curr_ptr);
5919 if (operand == ILLEG_OP)
5920 die(
"Found junk '%.*s' after $variable in condition",
5921 (
int)(expr_end - curr_ptr), curr_ptr);
5925 die(
"Negation and comparison should not be combined, please rewrite");
5928 if (operand == LT_OP || operand == GT_OP)
5936 while (my_isspace(charset_info, *curr_ptr))
5938 if (curr_ptr == expr_end)
5939 die(
"Missing right operand in comparison");
5942 while (my_isspace(charset_info, expr_end[-1]))
5945 if (*curr_ptr ==
'\'' || *curr_ptr ==
'"')
5947 if (expr_end[-1] != *curr_ptr)
5948 die(
"Unterminated string value");
5953 var_init(&v2,0,0,0,0);
5954 eval_expr(&v2, curr_ptr, &expr_end);
5956 if ((operand!=EQ_OP && operand!=NE_OP) && ! (v.is_int && v2.is_int))
5957 die (
"Only == and != are supported for string values");
5965 v.int_val= (v2.is_int && v2.int_val == v.int_val);
5967 v.int_val= !strcmp (v.str_val, v2.str_val);
5972 v.int_val= ! (v2.is_int && v2.int_val == v.int_val);
5974 v.int_val= (strcmp (v.str_val, v2.str_val) != 0);
5978 v.int_val= (v.int_val < v2.int_val);
5981 v.int_val= (v.int_val <= v2.int_val);
5984 v.int_val= (v.int_val > v2.int_val);
5987 v.int_val= (v.int_val >= v2.int_val);
5990 die(
"Impossible operator, this cannot happen");
5997 if (*expr_start !=
'`' && ! my_isdigit(charset_info, *expr_start))
5998 die(
"Expression in if/while must beging with $, ` or a number");
5999 eval_expr(&v, expr_start, &expr_end);
6005 cur_block->cmd= cmd;
6008 cur_block->ok= (v.int_val != 0);
6014 while (*p && ((my_isspace(charset_info, *p) || *p ==
'-' || *p ==
'+')))
6017 cur_block->ok= (*p && *p !=
'0') ? TRUE : FALSE;
6021 cur_block->ok = !cur_block->ok;
6025 cur_block->delim[0]=
'\0';
6029 strcpy (cur_block->delim, delimiter);
6032 DBUG_PRINT(
"info", (
"OK: %d", cur_block->ok));
6039 void do_delimiter(
struct st_command* command)
6041 char* p= command->first_argument;
6042 DBUG_ENTER(
"do_delimiter");
6043 DBUG_PRINT(
"enter", (
"first_argument: %s", command->first_argument));
6045 while (*p && my_isspace(charset_info, *p))
6049 die(
"Can't set empty delimiter");
6051 strmake(delimiter, p,
sizeof(delimiter) - 1);
6052 delimiter_length= strlen(delimiter);
6054 DBUG_PRINT(
"exit", (
"delimiter: %s", delimiter));
6055 command->last_argument= p + delimiter_length;
6060 my_bool match_delimiter(
int c,
const char *delim, uint length)
6063 char tmp[MAX_DELIMITER_LENGTH];
6068 for (i= 1; i < length &&
6069 (c= my_getc(cur_file->file)) == *(delim + i);
6079 my_ungetc(tmp[--i]);
6084 my_bool end_of_query(
int c)
6086 return match_delimiter(c, delimiter, delimiter_length);
6114 int read_line(
char *buf,
int size)
6116 char c, UNINIT_VAR(last_quote), last_char= 0;
6117 char *p=
buf, *buf_end= buf + size - 1;
6119 my_bool have_slash= FALSE;
6121 enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
6122 R_COMMENT, R_LINE_START} state= R_LINE_START;
6123 DBUG_ENTER(
"read_line");
6125 start_lineno= cur_file->lineno;
6126 DBUG_PRINT(
"info", (
"Starting to read at lineno: %d", start_lineno));
6127 for (; p < buf_end ;)
6130 c= my_getc(cur_file->file);
6131 if (feof(cur_file->file))
6134 if (cur_file->file != stdin)
6136 fclose(cur_file->file);
6139 my_free(cur_file->file_name);
6140 cur_file->file_name= 0;
6141 if (cur_file == file_stack)
6146 if (cur_block != block_stack)
6147 die(
"Missing end of block");
6150 DBUG_PRINT(
"info", (
"end of file at line %d", cur_file->lineno));
6154 start_lineno= cur_file->lineno;
6164 if (p != buf && *(p-1) ==
'\r')
6170 if (end_of_query(c))
6173 DBUG_PRINT(
"exit", (
"Found delimiter '%s' at line %d",
6174 delimiter, cur_file->lineno));
6177 else if ((c ==
'{' &&
6178 (!my_strnncoll_simple(charset_info, (
const uchar*)
"while", 5,
6179 (uchar*) buf, min<my_ptrdiff_t>(5, p - buf), 0) ||
6180 !my_strnncoll_simple(charset_info, (
const uchar*)
"if", 2,
6181 (uchar*) buf, min<my_ptrdiff_t>(2, p - buf), 0))))
6186 DBUG_PRINT(
"exit", (
"Found '{' indicating start of block at line %d",
6190 else if (c ==
'\'' || c ==
'"' || c ==
'`')
6198 have_slash= (c ==
'\\');
6206 DBUG_PRINT(
"exit", (
"Found newline in comment at line: %d",
6213 if (c ==
'#' || c ==
'-')
6218 else if (my_isspace(charset_info, c))
6222 if (last_char ==
'\n')
6225 DBUG_PRINT(
"info", (
"Found two new lines in a row"));
6232 start_lineno= cur_file->lineno;
6233 DBUG_PRINT(
"info", (
"Query hasn't started yet, start_lineno: %d",
6240 else if (end_of_query(c))
6243 DBUG_PRINT(
"exit", (
"Found delimiter '%s' at line: %d",
6244 delimiter, cur_file->lineno));
6252 DBUG_PRINT(
"exit", (
"Found '}' in begining of a line at line: %d",
6256 else if (c ==
'\'' || c ==
'"' || c ==
'`')
6266 if (c == last_quote)
6269 state= R_SLASH_IN_Q;
6285 int charlen = my_mbcharlen(charset_info, (
unsigned char) c);
6288 if ((charlen > 1) && (p + charlen) <= buf_end)
6295 for (i= 1; i < charlen; i++)
6297 c= my_getc(cur_file->file);
6298 if (feof(cur_file->file))
6302 if (! my_ismbchar(charset_info, mb_start, p))
6306 while (p-1 > mb_start)
6315 die(
"The input buffer is too small for this query.x\n" \
6316 "check your query or increase MAX_QUERY and recompile");
6332 void convert_to_format_v1(
char* query)
6334 int last_c_was_quote= 0;
6335 char *p= query, *to= query;
6336 char *end= strend(query);
6341 if (*p ==
'\n' && !last_c_was_quote)
6346 while (*p && my_isspace(charset_info, *p))
6349 last_c_was_quote= 0;
6351 else if (*p ==
'\'' || *p ==
'"' || *p ==
'`')
6357 while (*p && *p != last_c)
6362 last_c_was_quote= 1;
6367 last_c_was_quote= 0;
6379 void check_eol_junk_line(
const char *line)
6381 const char *p= line;
6382 DBUG_ENTER(
"check_eol_junk_line");
6383 DBUG_PRINT(
"enter", (
"line: %s", line));
6386 if (*p && !strncmp(p, delimiter, delimiter_length))
6387 die(
"Extra delimiter \"%s\" found", delimiter);
6390 if (*p && *p !=
'#')
6393 die(
"Missing delimiter");
6394 die(
"End of line junk detected: \"%s\"", p);
6399 void check_eol_junk(
const char *eol)
6402 DBUG_ENTER(
"check_eol_junk");
6403 DBUG_PRINT(
"enter", (
"eol: %s", eol));
6406 while (*p && (my_isspace(charset_info, *p) || *p ==
'#' || *p ==
'\n'))
6409 if (*p && *p ==
'#')
6412 while (*p && *p !=
'\n')
6417 if (*p && *p ==
'\n')
6418 check_eol_junk_line(p);
6424 check_eol_junk_line(p);
6430 bool is_delimiter(
const char* p)
6433 char* delim= delimiter;
6434 while (*p && *p == *delim++)
6440 return (match == delimiter_length);
6461 #define MAX_QUERY (256*1024*2)
6462 static char read_command_buf[MAX_QUERY];
6464 int read_command(
struct st_command** command_ptr)
6466 char *p= read_command_buf;
6468 DBUG_ENTER(
"read_command");
6470 if (parser.current_line < parser.read_lines)
6472 get_dynamic(&q_lines, (uchar*) command_ptr, parser.current_line) ;
6475 if (!(*command_ptr= command=
6476 (
struct st_command*) my_malloc(
sizeof(*command),
6477 MYF(MY_WME|MY_ZEROFILL))) ||
6478 insert_dynamic(&q_lines, &command))
6479 die(
"Out of memory");
6480 command->type= Q_UNKNOWN;
6482 read_command_buf[0]= 0;
6483 if (read_line(read_command_buf,
sizeof(read_command_buf)))
6485 check_eol_junk(read_command_buf);
6489 if (opt_result_format_version == 1)
6490 convert_to_format_v1(read_command_buf);
6492 DBUG_PRINT(
"info", (
"query: '%s'", read_command_buf));
6495 command->type= Q_COMMENT;
6497 else if (p[0] ==
'-' && p[1] ==
'-')
6499 command->type= Q_COMMENT_WITH_COMMAND;
6502 else if (*p ==
'\n')
6504 command->type= Q_EMPTY_LINE;
6508 while (*p && my_isspace(charset_info, *p))
6511 if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME))))
6512 die(
"Out of memory");
6518 while (*p && !my_isspace(charset_info, *p) && *p !=
'(' && !is_delimiter(p))
6520 command->first_word_len= (uint) (p - command->query);
6521 DBUG_PRINT(
"info", (
"first_word: %.*s",
6522 command->first_word_len, command->query));
6525 while (*p && my_isspace(charset_info, *p))
6527 command->first_argument= p;
6529 command->end= strend(command->query);
6530 command->query_len= (command->end - command->query);
6531 parser.read_lines++;
6536 static struct my_option my_long_options[] =
6538 {
"help",
'?',
"Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
6540 {
"basedir",
'b',
"Basedir for tests.", &opt_basedir,
6541 &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6542 {
"character-sets-dir", OPT_CHARSETS_DIR,
6543 "Directory for character set files.", &opt_charsets_dir,
6544 &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6545 {
"compress",
'C',
"Use the compressed server/client protocol.",
6546 &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
6548 {
"cursor-protocol", OPT_CURSOR_PROTOCOL,
"Use cursors for prepared statements.",
6549 &cursor_protocol, &cursor_protocol, 0,
6550 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6551 {
"database",
'D',
"Database to use.", &opt_db, &opt_db, 0,
6552 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6554 {
"debug",
'#',
"This is a non-debug version. Catch this and exit",
6555 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
6557 {
"debug",
'#',
"Output debug log. Often this is 'd:t:o,filename'.",
6558 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
6560 {
"debug-check", OPT_DEBUG_CHECK,
"Check memory and open file usage at exit.",
6561 &debug_check_flag, &debug_check_flag, 0,
6562 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6563 {
"debug-info", OPT_DEBUG_INFO,
"Print some debug info at exit.",
6564 &debug_info_flag, &debug_info_flag,
6565 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6566 {
"host",
'h',
"Connect to host.", &opt_host, &opt_host, 0,
6567 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6568 {
"include",
'i',
"Include SQL before each test case.", &opt_include,
6569 &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6570 {
"logdir", OPT_LOG_DIR,
"Directory for log files", &opt_logdir,
6571 &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6572 {
"mark-progress", OPT_MARK_PROGRESS,
6573 "Write line number and elapsed time to <testname>.progress.",
6574 &opt_mark_progress, &opt_mark_progress, 0,
6575 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6576 {
"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
6577 "Maximum number of attempts to connect to server.",
6578 &opt_max_connect_retries, &opt_max_connect_retries, 0,
6579 GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
6580 {
"max-connections", OPT_MAX_CONNECTIONS,
6581 "Max number of open connections to server",
6582 &opt_max_connections, &opt_max_connections, 0,
6583 GET_INT, REQUIRED_ARG, 128, 8, 5120, 0, 0, 0},
6584 {
"password",
'p',
"Password to use when connecting to server.",
6585 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
6586 {
"protocol", OPT_MYSQL_PROTOCOL,
"The protocol of connection (tcp,socket,pipe,memory).",
6587 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6588 {
"port",
'P',
"Port number to use for connection or 0 for default to, in "
6589 "order of preference, my.cnf, $MYSQL_TCP_PORT, "
6590 #if MYSQL_PORT_DEFAULT == 0
6593 "built-in default (" STRINGIFY_ARG(MYSQL_PORT)
").",
6594 &opt_port, &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6595 {
"ps-protocol", OPT_PS_PROTOCOL,
6596 "Use prepared-statement protocol for communication.",
6597 &ps_protocol, &ps_protocol, 0,
6598 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6599 {
"quiet",
's',
"Suppress all normal output.", &silent,
6600 &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6601 {
"record",
'r',
"Record output of test_file into result file.",
6602 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6603 {
"result-file",
'R',
"Read/store result from/in this file.",
6604 &result_file_name, &result_file_name, 0,
6605 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6606 {
"result-format-version", OPT_RESULT_FORMAT_VERSION,
6607 "Version of the result file format to use",
6608 &opt_result_format_version,
6609 &opt_result_format_version, 0,
6610 GET_INT, REQUIRED_ARG, 1, 1, 2, 0, 0, 0},
6611 {
"server-arg",
'A',
"Send option value to embedded server as a parameter.",
6612 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6613 {
"server-file",
'F',
"Read embedded server arguments from file.",
6614 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6615 {
"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
6616 "Base name of shared memory.", &shared_memory_base_name,
6617 &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
6619 {
"silent",
's',
"Suppress all normal output. Synonym for --quiet.",
6620 &silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6621 {
"sleep",
'T',
"Always sleep this many seconds on sleep commands.",
6622 &opt_sleep, &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
6624 {
"socket",
'S',
"The socket file to use for connection.",
6625 &unix_sock, &unix_sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
6627 {
"sp-protocol", OPT_SP_PROTOCOL,
"Use stored procedures for select.",
6628 &sp_protocol, &sp_protocol, 0,
6629 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6630 #include "sslopt-longopts.h"
6631 {
"tail-lines", OPT_TAIL_LINES,
6632 "Number of lines of the result to include in a failure report.",
6633 &opt_tail_lines, &opt_tail_lines, 0,
6634 GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
6635 {
"test-file",
'x',
"Read test from/in this file (default stdin).",
6636 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6637 {
"timer-file",
'm',
"File where the timing in microseconds is stored.",
6638 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6639 {
"tmpdir",
't',
"Temporary directory where sockets are put.",
6640 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6641 {
"user",
'u',
"User for login.", &opt_user, &opt_user, 0,
6642 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6643 {
"verbose",
'v',
"Write more.", &verbose, &verbose, 0,
6644 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6645 {
"version",
'V',
"Output version information and exit.",
6646 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6647 {
"view-protocol", OPT_VIEW_PROTOCOL,
"Use views for select.",
6648 &view_protocol, &view_protocol, 0,
6649 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6650 {
"opt-trace-protocol", OPT_TRACE_PROTOCOL,
6651 "Trace DML statements with optimizer trace",
6652 &opt_trace_protocol, &opt_trace_protocol, 0,
6653 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6654 {
"explain-protocol", OPT_EXPLAIN_PROTOCOL,
6655 "Explain all SELECT/INSERT/REPLACE/UPDATE/DELETE statements",
6656 &explain_protocol, &explain_protocol, 0,
6657 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6658 {
"json-explain-protocol", OPT_JSON_EXPLAIN_PROTOCOL,
6659 "Explain all SELECT/INSERT/REPLACE/UPDATE/DELETE statements with FORMAT=JSON",
6660 &json_explain_protocol, &json_explain_protocol, 0,
6661 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6662 {
"connect_timeout", OPT_CONNECT_TIMEOUT,
6663 "Number of seconds before connection timeout.",
6664 &opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG,
6665 120, 0, 3600 * 12, 0, 0, 0},
6666 {
"plugin_dir", OPT_PLUGIN_DIR,
"Directory for client-side plugins.",
6667 &opt_plugin_dir, &opt_plugin_dir, 0,
6668 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6669 #if !defined(HAVE_YASSL)
6670 {
"server-public-key-path", OPT_SERVER_PUBLIC_KEY,
6671 "File path to the server public RSA key in PEM format.",
6672 &opt_server_public_key, &opt_server_public_key, 0,
6673 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6675 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
6679 void print_version(
void)
6681 printf(
"%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
6682 MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
6688 puts(ORACLE_WELCOME_COPYRIGHT_NOTICE(
"2000"));
6689 printf(
"Runs a test against the mysql server and compares output with a results file.\n\n");
6690 printf(
"Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
6691 my_print_help(my_long_options);
6692 printf(
" --no-defaults Don't read default options from any options file.\n");
6693 my_print_variables(my_long_options);
6702 void read_embedded_server_arguments(
const char *name)
6704 char argument[1024],buff[FN_REFLEN], *str=0;
6707 if (!test_if_hard_path(name))
6709 strxmov(buff, opt_basedir, name, NullS);
6712 fn_format(buff, name,
"",
"", MY_UNPACK_FILENAME);
6714 if (!embedded_server_arg_count)
6716 embedded_server_arg_count=1;
6717 embedded_server_args[0]= (
char*)
"";
6719 if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
6720 die(
"Failed to open file '%s'", buff);
6722 while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
6723 (str=fgets(argument,
sizeof(argument), file)))
6726 if (!(embedded_server_args[embedded_server_arg_count]=
6727 (
char*) my_strdup(str,MYF(MY_WME))))
6729 my_fclose(file,MYF(0));
6730 die(
"Out of memory");
6733 embedded_server_arg_count++;
6735 my_fclose(file,MYF(0));
6737 die(
"Too many arguments in option file: %s",name);
6744 get_one_option(
int optid,
const struct my_option *opt,
char *argument)
6749 DBUG_PUSH(argument ? argument :
"d:t:S:i:O,/tmp/mysqltest.trace");
6750 debug_check_flag= 1;
6758 char buff[FN_REFLEN];
6759 if (!test_if_hard_path(argument))
6761 strxmov(buff, opt_basedir, argument, NullS);
6764 fn_format(buff, argument,
"",
"", MY_UNPACK_FILENAME);
6765 DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
6766 if (!(cur_file->file=
6768 die(
"Could not open '%s' for reading, errno: %d", buff, errno);
6769 cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
6770 cur_file->lineno= 1;
6775 static char buff[FN_REFLEN];
6776 if (!test_if_hard_path(argument))
6778 strxmov(buff, opt_basedir, argument, NullS);
6781 fn_format(buff, argument,
"",
"", MY_UNPACK_FILENAME);
6787 if (argument == disabled_my_option)
6788 argument= (
char*)
"";
6792 opt_pass= my_strdup(argument, MYF(MY_FAE));
6793 while (*argument) *argument++=
'x';
6799 #include <sslopt-case.h>
6801 strnmov(TMPDIR, argument,
sizeof(TMPDIR));
6804 if (!embedded_server_arg_count)
6806 embedded_server_arg_count=1;
6807 embedded_server_args[0]= (
char*)
"";
6809 if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
6810 !(embedded_server_args[embedded_server_arg_count++]=
6811 my_strdup(argument, MYF(MY_FAE))))
6813 die(
"Can't use server argument");
6818 if (access(opt_logdir, F_OK) != 0)
6819 die(
"The specified log directory does not exist: '%s'", opt_logdir);
6822 read_embedded_server_arguments(argument);
6824 case OPT_RESULT_FORMAT_VERSION:
6825 set_result_format_version(opt_result_format_version);
6830 case OPT_MYSQL_PROTOCOL:
6831 #ifndef EMBEDDED_LIBRARY
6832 opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
6844 int parse_args(
int argc,
char **argv)
6846 if (load_defaults(
"my",load_default_groups,&argc,&argv))
6851 if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
6862 opt_pass= get_tty_password(NullS);
6863 if (debug_info_flag)
6864 my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
6865 if (debug_check_flag)
6866 my_end_arg= MY_CHECK_ERROR;
6872 if (result_file_name && access(result_file_name, F_OK) != 0)
6873 die(
"The specified result file '%s' does not exist", result_file_name);
6890 void str_to_file2(
const char *fname,
char *str,
int size, my_bool append)
6893 char buff[FN_REFLEN];
6894 int flags= O_WRONLY | O_CREAT;
6895 if (!test_if_hard_path(fname))
6897 strxmov(buff, opt_basedir, fname, NullS);
6900 fn_format(buff, fname,
"",
"", MY_UNPACK_FILENAME);
6904 if ((fd= my_open(buff, flags,
6905 MYF(MY_WME | MY_FFNF))) < 0)
6906 die(
"Could not open '%s' for writing, errno: %d", buff, errno);
6907 if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
6908 die(
"Could not find end of file '%s', errno: %d", buff, errno);
6909 if (my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP)))
6910 die(
"write failed, errno: %d", errno);
6911 my_close(fd, MYF(0));
6924 void str_to_file(
const char *fname,
char *str,
int size)
6926 str_to_file2(fname, str, size, FALSE);
6936 my_regerror(err,r,err_buf,
sizeof(err_buf));
6937 die(
"Regex error: %s\n", err_buf);
6955 void init_win_path_patterns()
6958 const char* paths[] = {
"$MYSQL_TEST_DIR",
6960 "$MYSQLTEST_VARDIR",
6965 int num_paths=
sizeof(paths)/
sizeof(
char*);
6969 DBUG_ENTER(
"init_win_path_patterns");
6971 my_init_dynamic_array(&patterns,
sizeof(
const char*), 16, 16);
6974 for (i= 0; i < num_paths; i++)
6977 if (*(paths[i]) ==
'$')
6979 v= var_get(paths[i], 0, 0, 0);
6980 p= my_strdup(v->str_val, MYF(MY_FAE));
6983 p= my_strdup(paths[i], MYF(MY_FAE));
6992 if (insert_dynamic(&patterns, &p))
6993 die(
"Out of memory");
6995 DBUG_PRINT(
"info", (
"p: %s", p));
7006 void free_win_path_patterns()
7009 for (i=0 ; i < patterns.elements ; i++)
7011 const char** pattern= dynamic_element(&patterns, i,
const char**);
7012 my_free((
void *) *pattern);
7014 delete_dynamic(&patterns);
7031 void fix_win_paths(
const char *val,
int len)
7036 DBUG_ENTER(
"fix_win_paths");
7037 for (i= 0; i < patterns.elements; i++)
7039 const char** pattern= dynamic_element(&patterns, i,
const char**);
7040 DBUG_PRINT(
"info", (
"pattern: %s", *pattern));
7043 while ((p= strstr((
char*)val, *pattern)))
7045 DBUG_PRINT(
"info", (
"Found %s in val p: %s", *pattern, p));
7047 while (*p && !my_isspace(charset_info, *p))
7053 DBUG_PRINT(
"info", (
"Converted \\ to /, p: %s", p));
7056 DBUG_PRINT(
"exit", (
" val: %s, len: %d", val, len));
7068 char* val, ulonglong len, my_bool is_null)
7070 char null[]=
"NULL";
7072 if (col_idx < max_replace_column && replace_column[col_idx])
7074 val= replace_column[col_idx];
7083 else if ((field->type == MYSQL_TYPE_DOUBLE ||
7084 field->type == MYSQL_TYPE_FLOAT ) &&
7085 field->decimals >= 31)
7088 char *start= strchr(val,
'e');
7089 if (start && strlen(start) >= 5 &&
7090 (start[1] ==
'-' || start[1] ==
'+') && start[2] ==
'0')
7093 if (field->flags & ZEROFILL_FLAG)
7096 memmove(val + 1, val, start - val);
7102 memmove(start, start + 1, strlen(start));
7109 if (!display_result_vertically)
7112 dynstr_append_mem(ds,
"\t", 1);
7113 replace_dynstr_append_mem(ds, val, (
int)len);
7117 dynstr_append(ds, field->name);
7118 dynstr_append_mem(ds,
"\t", 1);
7119 replace_dynstr_append_mem(ds, val, (
int)len);
7120 dynstr_append_mem(ds,
"\n", 1);
7133 uint num_fields= mysql_num_fields(res);
7137 while ((row = mysql_fetch_row(res)))
7140 lengths = mysql_fetch_lengths(res);
7141 for (i = 0; i < num_fields; i++)
7145 append_field(ds, i, &fields[i],
7146 row[i], lengths[i], !row[i]);
7148 if (!display_result_vertically)
7149 dynstr_append_mem(ds,
"\n", 1);
7169 MYF(MY_WME | MY_FAE | MY_ZEROFILL));
7170 length= (ulong*) my_malloc(num_fields *
sizeof(ulong),
7171 MYF(MY_WME | MY_FAE));
7172 is_null= (my_bool*) my_malloc(num_fields *
sizeof(my_bool),
7173 MYF(MY_WME | MY_FAE));
7176 for (i= 0; i < num_fields; i++)
7178 uint max_length= fields[
i].max_length + 1;
7179 my_bind[
i].buffer_type= MYSQL_TYPE_STRING;
7180 my_bind[
i].buffer= my_malloc(max_length, MYF(MY_WME | MY_FAE));
7181 my_bind[
i].buffer_length= max_length;
7182 my_bind[
i].is_null= &is_null[
i];
7183 my_bind[
i].length= &length[
i];
7185 DBUG_PRINT(
"bind", (
"col[%d]: buffer_type: %d, buffer_length: %lu",
7186 i, my_bind[i].buffer_type, my_bind[i].buffer_length));
7189 if (mysql_stmt_bind_result(stmt, my_bind))
7190 die(
"mysql_stmt_bind_result failed: %d: %s",
7191 mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
7193 while (mysql_stmt_fetch(stmt) == 0)
7195 for (i= 0; i < num_fields; i++)
7196 append_field(ds, i, &fields[i], (
char*)my_bind[i].buffer,
7197 *my_bind[i].length, *my_bind[i].is_null);
7198 if (!display_result_vertically)
7199 dynstr_append_mem(ds,
"\n", 1);
7203 if ((rc= mysql_stmt_fetch(stmt)) != MYSQL_NO_DATA)
7204 die(
"fetch didn't end with MYSQL_NO_DATA from statement: %d: %s; rc=%d",
7205 mysql_stmt_errno(stmt), mysql_stmt_error(stmt), rc);
7207 for (i= 0; i < num_fields; i++)
7210 my_free(my_bind[i].buffer);
7228 dynstr_append(ds,
"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
7229 "Column_alias\tType\tLength\tMax length\tIs_null\t"
7230 "Flags\tDecimals\tCharsetnr\n");
7232 for (field_end= field+num_fields ;
7236 dynstr_append_mem(ds, field->catalog,
7237 field->catalog_length);
7238 dynstr_append_mem(ds,
"\t", 1);
7239 dynstr_append_mem(ds, field->db, field->db_length);
7240 dynstr_append_mem(ds,
"\t", 1);
7241 dynstr_append_mem(ds, field->org_table,
7242 field->org_table_length);
7243 dynstr_append_mem(ds,
"\t", 1);
7244 dynstr_append_mem(ds, field->table,
7245 field->table_length);
7246 dynstr_append_mem(ds,
"\t", 1);
7247 dynstr_append_mem(ds, field->org_name,
7248 field->org_name_length);
7249 dynstr_append_mem(ds,
"\t", 1);
7250 dynstr_append_mem(ds, field->name, field->name_length);
7251 dynstr_append_mem(ds,
"\t", 1);
7252 replace_dynstr_append_uint(ds, field->type);
7253 dynstr_append_mem(ds,
"\t", 1);
7254 replace_dynstr_append_uint(ds, field->length);
7255 dynstr_append_mem(ds,
"\t", 1);
7256 replace_dynstr_append_uint(ds, field->max_length);
7257 dynstr_append_mem(ds,
"\t", 1);
7258 dynstr_append_mem(ds, (
char*) (IS_NOT_NULL(field->flags) ?
7260 dynstr_append_mem(ds,
"\t", 1);
7261 replace_dynstr_append_uint(ds, field->flags);
7262 dynstr_append_mem(ds,
"\t", 1);
7263 replace_dynstr_append_uint(ds, field->decimals);
7264 dynstr_append_mem(ds,
"\t", 1);
7265 replace_dynstr_append_uint(ds, field->charsetnr);
7266 dynstr_append_mem(ds,
"\n", 1);
7278 char buf[40], buff2[21];
7279 sprintf(buf,
"affected rows: %s\n", llstr(affected_rows, buff2));
7280 dynstr_append(ds, buf);
7283 dynstr_append(ds,
"info: ");
7284 dynstr_append(ds, info);
7285 dynstr_append_mem(ds,
"\n", 1);
7299 for (col_idx= 0; col_idx < num_fields; col_idx++)
7302 dynstr_append_mem(ds,
"\t", 1);
7303 replace_dynstr_append(ds, field[col_idx].name);
7305 dynstr_append_mem(ds,
"\n", 1);
7319 DBUG_ENTER(
"append_warnings");
7321 if (!(count= mysql_warning_count(mysql)))
7329 DBUG_ASSERT(!mysql_more_results(mysql));
7331 if (mysql_real_query(mysql,
"SHOW WARNINGS", 13))
7332 die(
"Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql));
7334 if (!(warn_res= mysql_store_result(mysql)))
7335 die(
"Warning count is %u but didn't get any warnings",
7338 append_result(ds, warn_res);
7339 mysql_free_result(warn_res);
7341 DBUG_PRINT(
"warnings", (
"%s", ds->str));
7361 int flags,
char *query,
int query_len,
7365 MYSQL *mysql= &cn->mysql;
7366 int err= 0, counter= 0;
7367 DBUG_ENTER(
"run_query_normal");
7368 DBUG_PRINT(
"enter",(
"flags: %d", flags));
7369 DBUG_PRINT(
"enter", (
"query: '%-.60s'", query));
7371 if (flags & QUERY_SEND_FLAG)
7376 if (do_send_query(cn, query, query_len))
7378 handle_error(command, mysql_errno(mysql), mysql_error(mysql),
7379 mysql_sqlstate(mysql), ds);
7383 if (!(flags & QUERY_REAP_FLAG))
7395 if ((counter==0) && do_read_query_result(cn))
7399 handle_error(command, mysql_errno(mysql), mysql_error(mysql),
7400 mysql_sqlstate(mysql), ds);
7408 if (mysql_field_count(mysql) && ((res= mysql_store_result(mysql)) == 0))
7410 handle_error(command, mysql_errno(mysql), mysql_error(mysql),
7411 mysql_sqlstate(mysql), ds);
7415 if (!disable_result_log)
7420 uint num_fields= mysql_num_fields(res);
7422 if (display_metadata)
7423 append_metadata(ds, fields, num_fields);
7425 if (!display_result_vertically)
7426 append_table_headings(ds, fields, num_fields);
7428 append_result(ds, res);
7436 append_info(ds, mysql_affected_rows(mysql), mysql_info(mysql));
7443 if (!disable_warnings && !mysql_more_results(mysql))
7445 if (append_warnings(ds_warnings, mysql) || ds_warnings->length)
7447 dynstr_append_mem(ds,
"Warnings:\n", 10);
7448 dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
7455 mysql_free_result(res);
7459 }
while (!(err= mysql_next_result(mysql)));
7463 handle_error(command, mysql_errno(mysql), mysql_error(mysql),
7464 mysql_sqlstate(mysql), ds);
7467 DBUG_ASSERT(err == -1);
7470 handle_no_error(command);
7471 revert_properties();
7481 var_set_errno(mysql_errno(mysql));
7506 static int match_expected_error(
struct st_command *command,
7507 unsigned int err_errno,
7508 const char *err_sqlstate)
7512 for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
7514 if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
7515 (command->expected_errors.err[
i].code.errnum == err_errno))
7518 if (command->expected_errors.err[i].type == ERR_SQLSTATE)
7523 if (unlikely(err_sqlstate == NULL))
7524 die(
"expecting a SQL-state (%s) from query '%s' which cannot produce one...",
7525 command->expected_errors.err[i].code.sqlstate, command->query);
7527 if (strncmp(command->expected_errors.err[i].code.sqlstate,
7528 err_sqlstate, SQLSTATE_LENGTH) == 0)
7552 void handle_error(
struct st_command *command,
7553 unsigned int err_errno,
const char *err_error,
7558 DBUG_ENTER(
"handle_error");
7560 if (command->require_file[0])
7567 if (err_errno == CR_SERVER_LOST ||
7568 err_errno == CR_SERVER_GONE_ERROR)
7569 die(
"require query '%s' failed: %d: %s", command->query,
7570 err_errno, err_error);
7573 abort_not_supported_test(
"Query '%s' failed, required functionality " \
7574 "not supported", command->query);
7577 if (command->abort_on_error)
7578 die(
"query '%s' failed: %d: %s", command->query, err_errno, err_error);
7580 DBUG_PRINT(
"info", (
"expected_errors.count: %d",
7581 command->expected_errors.count));
7583 i= match_expected_error(command, err_errno, err_sqlstate);
7587 if (!disable_result_log)
7589 if (command->expected_errors.count == 1)
7592 dynstr_append_mem(ds,
"ERROR ", 6);
7593 replace_dynstr_append(ds, err_sqlstate);
7594 dynstr_append_mem(ds,
": ", 2);
7595 replace_dynstr_append(ds, err_error);
7596 dynstr_append_mem(ds,
"\n",1);
7599 else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
7600 (command->expected_errors.err[0].type == ERR_ERRNO &&
7601 command->expected_errors.err[0].code.errnum != 0))
7602 dynstr_append(ds,
"Got one of the listed errors\n");
7605 revert_properties();
7609 DBUG_PRINT(
"info",(
"i: %d expected_errors: %d", i,
7610 command->expected_errors.count));
7612 if (!disable_result_log)
7614 dynstr_append_mem(ds,
"ERROR ",6);
7615 replace_dynstr_append(ds, err_sqlstate);
7616 dynstr_append_mem(ds,
": ", 2);
7617 replace_dynstr_append(ds, err_error);
7618 dynstr_append_mem(ds,
"\n", 1);
7621 if (command->expected_errors.count > 0)
7623 if (command->expected_errors.err[0].type == ERR_ERRNO)
7624 die(
"query '%s' failed with wrong errno %d: '%s', instead of %d...",
7625 command->query, err_errno, err_error,
7626 command->expected_errors.err[0].code.errnum);
7628 die(
"query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
7629 command->query, err_sqlstate, err_error,
7630 command->expected_errors.err[0].code.sqlstate);
7633 revert_properties();
7649 void handle_no_error(
struct st_command *command)
7651 DBUG_ENTER(
"handle_no_error");
7653 if (command->expected_errors.err[0].type == ERR_ERRNO &&
7654 command->expected_errors.err[0].code.errnum != 0)
7657 die(
"query '%s' succeeded - should have failed with errno %d...",
7658 command->query, command->expected_errors.err[0].code.errnum);
7660 else if (command->expected_errors.err[0].type == ERR_SQLSTATE &&
7661 strcmp(command->expected_errors.err[0].code.sqlstate,
"00000") != 0)
7664 die(
"query '%s' succeeded - should have failed with sqlstate %s...",
7665 command->query, command->expected_errors.err[0].code.sqlstate);
7694 DBUG_ENTER(
"run_query_stmt");
7695 DBUG_PRINT(
"query", (
"'%-.60s'", query));
7700 if(!(stmt= cur_con->stmt))
7702 if (!(stmt= mysql_stmt_init(mysql)))
7703 die(
"unable to init stmt structure");
7704 cur_con->stmt= stmt;
7708 if (!disable_warnings)
7710 init_dynamic_string(&ds_prepare_warnings, NULL, 0, 256);
7711 init_dynamic_string(&ds_execute_warnings, NULL, 0, 256);
7717 if (mysql_stmt_prepare(stmt, query, query_len))
7719 handle_error(command, mysql_stmt_errno(stmt),
7720 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
7728 if (!disable_warnings)
7729 append_warnings(&ds_prepare_warnings, mysql);
7736 #if MYSQL_VERSION_ID >= 50000
7737 if (cursor_protocol_enabled)
7742 ulong
type= CURSOR_TYPE_READ_ONLY;
7743 if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (
void*) &type))
7744 die(
"mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
7745 mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
7752 if (mysql_stmt_execute(stmt))
7754 handle_error(command, mysql_stmt_errno(stmt),
7755 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
7763 if (cursor_protocol_enabled && !disable_warnings)
7764 append_warnings(&ds_execute_warnings, mysql);
7773 if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (
void*) &one))
7774 die(
"mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s",
7775 mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
7783 if (mysql_stmt_field_count(stmt) && mysql_stmt_store_result(stmt))
7785 handle_error(command, mysql_stmt_errno(stmt),
7786 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
7791 handle_no_error(command);
7792 if (!disable_result_log)
7800 if ((res= mysql_stmt_result_metadata(stmt)) != NULL)
7804 uint num_fields= mysql_num_fields(res);
7806 if (display_metadata)
7807 append_metadata(ds, fields, num_fields);
7809 if (!display_result_vertically)
7810 append_table_headings(ds, fields, num_fields);
7812 append_stmt_result(ds, stmt, fields, num_fields);
7814 mysql_free_result(res);
7820 if (ds_execute_warnings.length || mysql->warning_count)
7821 dynstr_set(&ds_prepare_warnings, NULL);
7836 append_info(ds, mysql_stmt_affected_rows(stmt), mysql_info(mysql));
7838 if (!disable_warnings)
7843 if (append_warnings(&ds_execute_warnings, mysql) ||
7844 ds_execute_warnings.length ||
7845 ds_prepare_warnings.length ||
7846 ds_warnings->length)
7848 dynstr_append_mem(ds,
"Warnings:\n", 10);
7849 if (ds_warnings->length)
7850 dynstr_append_mem(ds, ds_warnings->str,
7851 ds_warnings->length);
7852 if (ds_prepare_warnings.length)
7853 dynstr_append_mem(ds, ds_prepare_warnings.str,
7854 ds_prepare_warnings.length);
7855 if (ds_execute_warnings.length)
7856 dynstr_append_mem(ds, ds_execute_warnings.str,
7857 ds_execute_warnings.length);
7863 if (!disable_warnings)
7865 dynstr_free(&ds_prepare_warnings);
7866 dynstr_free(&ds_execute_warnings);
7868 revert_properties();
7876 var_set_errno(mysql_stmt_errno(stmt));
7879 if (mysql->reconnect)
7881 mysql_stmt_close(stmt);
7882 cur_con->stmt= NULL;
7898 int util_query(
MYSQL* org_mysql,
const char* query){
7901 DBUG_ENTER(
"util_query");
7903 if(!(mysql= cur_con->util_mysql))
7905 DBUG_PRINT(
"info", (
"Creating util_mysql"));
7906 if (!(mysql= mysql_init(mysql)))
7907 die(
"Failed in mysql_init()");
7909 if (opt_connect_timeout)
7910 mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT,
7911 (
void *) &opt_connect_timeout);
7914 mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0);
7915 safe_connect(mysql,
"util", org_mysql->host, org_mysql->user,
7916 org_mysql->passwd, org_mysql->db, org_mysql->port,
7917 org_mysql->unix_socket);
7919 cur_con->util_mysql= mysql;
7922 DBUG_RETURN(mysql_query(mysql, query));
7942 MYSQL *mysql= &cn->mysql;
7951 my_bool view_created= 0, sp_created= 0;
7952 my_bool complete_query= ((flags & QUERY_SEND_FLAG) &&
7953 (flags & QUERY_REAP_FLAG));
7954 DBUG_ENTER(
"run_query");
7956 if (cn->pending && (flags & QUERY_SEND_FLAG))
7957 die (
"Cannot run query on connection between send and reap");
7959 if (!(flags & QUERY_SEND_FLAG) && !cn->pending)
7960 die (
"Cannot reap on a connection without pending send");
7962 init_dynamic_string(&ds_warnings, NULL, 0, 256);
7963 ds_warn= &ds_warnings;
7968 if (command->type == Q_EVAL || command->type == Q_SEND_EVAL)
7970 init_dynamic_string(&eval_query,
"", command->query_len+256, 1024);
7971 do_eval(&eval_query, command->query, command->end, FALSE);
7972 query = eval_query.str;
7973 query_len = eval_query.length;
7977 query = command->query;
7978 query_len = strlen(query);
7987 if (command->require_file[0])
7989 init_dynamic_string(&ds_result,
"", 1024, 1024);
7998 if (!disable_query_log && (flags & QUERY_SEND_FLAG))
8000 replace_dynstr_append_mem(ds, query, query_len);
8001 dynstr_append_mem(ds, delimiter, delimiter_length);
8002 dynstr_append_mem(ds,
"\n", 1);
8005 if (view_protocol_enabled &&
8007 match_re(&view_re, query))
8014 init_dynamic_string(&query_str,
8015 "CREATE OR REPLACE VIEW mysqltest_tmp_v AS ",
8017 dynstr_append_mem(&query_str, query, query_len);
8018 if (util_query(mysql, query_str.str))
8024 DBUG_PRINT(
"view_create_error",
8025 (
"Failed to create view '%s': %d: %s", query_str.str,
8026 mysql_errno(mysql), mysql_error(mysql)));
8029 verbose_msg(
"Failed to create view '%s' %d: %s", query_str.str,
8030 mysql_errno(mysql), mysql_error(mysql));
8038 query= (
char*)
"SELECT * FROM mysqltest_tmp_v";
8039 query_len = strlen(query);
8045 append_warnings(&ds_warnings, cur_con->util_mysql);
8048 dynstr_free(&query_str);
8052 if (sp_protocol_enabled &&
8054 match_re(&sp_re, query))
8061 init_dynamic_string(&query_str,
8062 "DROP PROCEDURE IF EXISTS mysqltest_tmp_sp;",
8064 util_query(mysql, query_str.str);
8065 dynstr_set(&query_str,
"CREATE PROCEDURE mysqltest_tmp_sp()\n");
8066 dynstr_append_mem(&query_str, query, query_len);
8067 if (util_query(mysql, query_str.str))
8073 DBUG_PRINT(
"sp_create_error",
8074 (
"Failed to create sp '%s': %d: %s", query_str.str,
8075 mysql_errno(mysql), mysql_error(mysql)));
8078 verbose_msg(
"Failed to create sp '%s' %d: %s", query_str.str,
8079 mysql_errno(mysql), mysql_error(mysql));
8086 query= (
char*)
"CALL mysqltest_tmp_sp()";
8087 query_len = strlen(query);
8089 dynstr_free(&query_str);
8092 if (display_result_sorted)
8099 init_dynamic_string(&ds_sorted,
"", 1024, 1024);
8113 if (ps_protocol_enabled &&
8115 match_re(&ps_re, query))
8116 run_query_stmt(mysql, command, query, query_len, ds, &ds_warnings);
8118 run_query_normal(cn, command, flags, query, query_len,
8121 dynstr_free(&ds_warnings);
8123 if (command->type == Q_EVAL || command->type == Q_SEND_EVAL)
8124 dynstr_free(&eval_query);
8126 if (display_result_sorted)
8129 dynstr_append_sorted(save_ds, &ds_sorted);
8131 dynstr_free(&ds_sorted);
8136 if (util_query(mysql,
"DROP PROCEDURE mysqltest_tmp_sp "))
8137 die(
"Failed to drop sp: %d: %s", mysql_errno(mysql), mysql_error(mysql));
8142 if (util_query(mysql,
"DROP VIEW mysqltest_tmp_v "))
8143 die(
"Failed to drop view: %d: %s",
8144 mysql_errno(mysql), mysql_error(mysql));
8147 if (command->require_file[0])
8153 check_require(ds, command->require_file);
8156 if (ds == &ds_result)
8157 dynstr_free(&ds_result);
8168 if (!disable_query_log &&
8169 opt_trace_protocol_enabled &&
8171 !command->expected_errors.count &&
8172 match_re(&opt_trace_re, command->query))
8176 init_dynamic_string(&query_str,
8177 "SELECT trace FROM information_schema.optimizer_trace"
8178 " /* injected by --opt-trace-protocol */",
8181 command->query= query_str.str;
8182 command->query_len= query_str.length;
8183 command->end= strend(command->query);
8187 display_result_sorted= FALSE;
8188 display_result_lower= FALSE;
8189 run_query(cn, command, flags);
8191 dynstr_free(&query_str);
8192 *command= save_command;
8198 int flags,
bool json)
8200 if ((flags & QUERY_REAP_FLAG) &&
8201 !command->expected_errors.count &&
8202 match_re(&explain_re, command->query))
8208 init_dynamic_string(&ds_warning_messages,
"", 0, 2048);
8209 init_dynamic_string(&query_str, json ?
"EXPLAIN FORMAT=JSON "
8210 :
"EXPLAIN EXTENDED ", 256, 256);
8211 dynstr_append_mem(&query_str, command->query,
8212 command->end - command->query);
8214 command->query= query_str.str;
8215 command->query_len= query_str.length;
8216 command->end= strend(command->query);
8218 run_query(cn, command, flags);
8220 dynstr_free(&query_str);
8221 dynstr_free(&ds_warning_messages);
8223 *command= save_command;
8233 char *re_eprint(
int err)
8235 static char epbuf[100];
8236 size_t len= my_regerror(MY_REG_ITOA | err, NULL, epbuf,
sizeof(epbuf));
8237 assert(len <=
sizeof(epbuf));
8241 void init_re_comp(
my_regex_t *re,
const char* str)
8243 int err= my_regcomp(re, str, (MY_REG_EXTENDED | MY_REG_ICASE | MY_REG_NOSUB),
8244 &my_charset_latin1);
8248 int len= my_regerror(err, re, erbuf,
sizeof(erbuf));
8249 die(
"error %s, %d/%d `%s'\n",
8250 re_eprint(err), (
int)len, (
int)
sizeof(erbuf), erbuf);
8260 const char *ps_re_str =
8262 "[[:space:]]*REPLACE[[:space:]]|"
8263 "[[:space:]]*INSERT[[:space:]]|"
8264 "[[:space:]]*UPDATE[[:space:]]|"
8265 "[[:space:]]*DELETE[[:space:]]|"
8266 "[[:space:]]*SELECT[[:space:]]|"
8267 "[[:space:]]*CREATE[[:space:]]+TABLE[[:space:]]|"
8268 "[[:space:]]*DO[[:space:]]|"
8269 "[[:space:]]*SET[[:space:]]+OPTION[[:space:]]|"
8270 "[[:space:]]*DELETE[[:space:]]+MULTI[[:space:]]|"
8271 "[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|"
8272 "[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
8278 const char *sp_re_str =ps_re_str;
8283 const char *view_re_str =
8285 "[[:space:]]*SELECT[[:space:]])";
8287 const char *opt_trace_re_str =
8289 "[[:space:]]*INSERT[[:space:]]|"
8290 "[[:space:]]*UPDATE[[:space:]]|"
8291 "[[:space:]]*DELETE[[:space:]]|"
8292 "[[:space:]]*EXPLAIN[[:space:]]|"
8293 "[[:space:]]*SELECT[[:space:]])";
8296 const char *explain_re_str =
8298 "[[:space:]]*(SELECT|DELETE|UPDATE|INSERT|REPLACE)[[:space:]])";
8300 init_re_comp(&ps_re, ps_re_str);
8301 init_re_comp(&sp_re, sp_re_str);
8302 init_re_comp(&view_re, view_re_str);
8303 init_re_comp(&opt_trace_re, opt_trace_re_str);
8304 init_re_comp(&explain_re, explain_re_str);
8310 while (my_isspace(charset_info, *str))
8312 if (str[0] ==
'/' && str[1] ==
'*')
8314 char *comm_end= strstr (str,
"*/");
8316 die(
"Statement is unterminated comment");
8320 int err= my_regexec(re, str, (
size_t)0, NULL, 0);
8324 else if (err == MY_REG_NOMATCH)
8329 int len= my_regerror(err, re, erbuf,
sizeof(erbuf));
8330 die(
"error %s, %d/%d `%s'\n",
8331 re_eprint(err), (
int)len, (
int)
sizeof(erbuf), erbuf);
8340 my_regfree(&view_re);
8341 my_regfree(&opt_trace_re);
8342 my_regfree(&explain_re);
8348 void get_command_type(
struct st_command* command)
8352 DBUG_ENTER(
"get_command_type");
8354 if (*command->query ==
'}')
8356 command->type = Q_END_BLOCK;
8360 save= command->query[command->first_word_len];
8361 command->query[command->first_word_len]= 0;
8362 type= find_type(command->query, &command_typelib, FIND_TYPE_NO_PREFIX);
8363 command->query[command->first_word_len]= save;
8366 command->type=(
enum enum_commands) type;
8372 if (type == Q_QUERY)
8375 command->query= command->first_argument;
8382 if (command->type != Q_COMMENT_WITH_COMMAND)
8385 command->type= Q_QUERY;
8390 die(
"Found line beginning with -- that didn't contain "\
8391 "a valid mysqltest command, check your syntax or "\
8392 "use # if you intended to write a comment");
8397 memcpy(&command->expected_errors, &saved_expected_errors,
8398 sizeof(saved_expected_errors));
8399 DBUG_PRINT(
"info", (
"There are %d expected errors",
8400 command->expected_errors.count));
8412 void mark_progress(
struct st_command* command __attribute__((unused)),
8415 static ulonglong progress_start= 0;
8419 ulonglong timer= timer_now();
8420 if (!progress_start)
8421 progress_start= timer;
8422 timer-= progress_start;
8424 if (init_dynamic_string(&ds_progress,
"", 256, 256))
8425 die(
"Out of memory");
8428 end= longlong2str(timer, buf, 10);
8429 dynstr_append_mem(&ds_progress, buf, (
int)(end-buf));
8430 dynstr_append_mem(&ds_progress,
"\t", 1);
8433 end= int10_to_str(line, buf, 10);
8434 dynstr_append_mem(&ds_progress, buf, (
int)(end-buf));
8435 dynstr_append_mem(&ds_progress,
"\t", 1);
8438 dynstr_append(&ds_progress, cur_file->file_name);
8439 dynstr_append_mem(&ds_progress,
":", 1);
8442 end= int10_to_str(cur_file->lineno, buf, 10);
8443 dynstr_append_mem(&ds_progress, buf, (
int)(end-buf));
8446 dynstr_append_mem(&ds_progress,
"\n", 1);
8448 progress_file.write(&ds_progress);
8450 dynstr_free(&ds_progress);
8454 #ifdef HAVE_STACKTRACE
8456 static void dump_backtrace(
void)
8460 fprintf(stderr,
"read_command_buf (%p): ", read_command_buf);
8461 my_safe_print_str(read_command_buf,
sizeof(read_command_buf));
8465 fprintf(stderr,
"conn->name (%p): ", conn->name);
8466 my_safe_print_str(conn->name, conn->name_len);
8467 #ifdef EMBEDDED_LIBRARY
8468 fprintf(stderr,
"conn->cur_query (%p): ", conn->cur_query);
8469 my_safe_print_str(conn->cur_query, conn->cur_query_len);
8472 fputs(
"Attempting backtrace...\n", stderr);
8473 my_print_stacktrace(NULL, my_thread_stack_size);
8478 static void dump_backtrace(
void)
8480 fputs(
"Backtrace not available.\n", stderr);
8485 static sig_handler signal_handler(
int sig)
8487 fprintf(stderr,
"mysqltest got " SIGNAL_FMT
"\n", sig);
8490 fprintf(stderr,
"Writing a core file...\n");
8500 LONG WINAPI exception_filter(EXCEPTION_POINTERS *exp)
8504 my_set_exception_pointers(exp);
8505 signal_handler(exp->ExceptionRecord->ExceptionCode);
8507 __except(EXCEPTION_EXECUTE_HANDLER)
8509 fputs(
"Got exception in exception handler!\n", stderr);
8512 return EXCEPTION_CONTINUE_SEARCH;
8516 static void init_signal_handling(
void)
8521 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
8522 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
8523 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
8524 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
8525 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
8526 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
8529 mode= SetErrorMode(0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
8532 SetUnhandledExceptionFilter(exception_filter);
8537 static void init_signal_handling(
void)
8540 DBUG_ENTER(
"init_signal_handling");
8542 #ifdef HAVE_STACKTRACE
8543 my_init_stacktrace();
8546 sa.sa_flags = SA_RESETHAND | SA_NODEFER;
8547 sigemptyset(&sa.sa_mask);
8548 sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
8550 sa.sa_handler= signal_handler;
8565 int main(
int argc,
char **argv)
8568 my_bool q_send_flag= 0, abort_flag= 0;
8569 uint command_executed= 0, last_command_executed= 0;
8570 char save_file[FN_REFLEN];
8576 init_signal_handling();
8579 memset(&saved_expected_errors, 0,
sizeof(saved_expected_errors));
8581 #ifdef EMBEDDED_LIBRARY
8583 (void) pthread_attr_init(&cn_thd_attrib);
8584 pthread_attr_setstacksize(&cn_thd_attrib, DEFAULT_THREAD_STACK);
8588 memset(file_stack, 0,
sizeof(file_stack));
8590 file_stack + (
sizeof(file_stack)/
sizeof(
struct st_test_file)) - 1;
8591 cur_file= file_stack;
8594 memset(block_stack, 0,
sizeof(block_stack));
8596 block_stack + (
sizeof(block_stack)/
sizeof(
struct st_block)) - 1;
8597 cur_block= block_stack;
8598 cur_block->ok= TRUE;
8599 cur_block->cmd= cmd_none;
8601 my_init_dynamic_array(&q_lines,
sizeof(
struct st_command*), 1024, 1024);
8603 if (my_hash_init(&var_hash, charset_info,
8604 1024, 0, 0, get_var_key, var_free, MYF(0)))
8605 die(
"Variable hash initialization failed");
8608 char path_separator[]= { FN_LIBCHAR, 0 };
8609 var_set_string(
"SYSTEM_PATH_SEPARATOR", path_separator);
8611 var_set_string(
"MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
8612 var_set_string(
"MYSQL_SYSTEM_TYPE", SYSTEM_TYPE);
8613 var_set_string(
"MYSQL_MACHINE_TYPE", MACHINE_TYPE);
8614 if (
sizeof(
void *) == 8) {
8615 var_set_string(
"MYSQL_SYSTEM_ARCHITECTURE",
"64");
8617 var_set_string(
"MYSQL_SYSTEM_ARCHITECTURE",
"32");
8620 memset(&master_pos, 0,
sizeof(master_pos));
8622 parser.current_line= parser.read_lines= 0;
8623 memset(&var_reg, 0,
sizeof(var_reg));
8625 init_builtin_echo();
8631 init_win_path_patterns();
8634 init_dynamic_string(&ds_res,
"", 2048, 2048);
8636 parse_args(argc, argv);
8638 log_file.open(opt_logdir, result_file_name,
".log");
8639 verbose_msg(
"Logging to '%s'.", log_file.file_name());
8640 if (opt_mark_progress)
8642 progress_file.open(opt_logdir, result_file_name,
".progress");
8643 verbose_msg(
"Tracing progress in '%s'.", progress_file.file_name());
8648 my_malloc((opt_max_connections+2) *
sizeof(
struct st_connection),
8649 MYF(MY_WME | MY_ZEROFILL));
8650 connections_end= connections + opt_max_connections +1;
8651 next_con= connections + 1;
8653 var_set_int(
"$PS_PROTOCOL", ps_protocol);
8654 var_set_int(
"$SP_PROTOCOL", sp_protocol);
8655 var_set_int(
"$VIEW_PROTOCOL", view_protocol);
8656 var_set_int(
"$OPT_TRACE_PROTOCOL", opt_trace_protocol);
8657 var_set_int(
"$EXPLAIN_PROTOCOL", explain_protocol);
8658 var_set_int(
"$JSON_EXPLAIN_PROTOCOL", json_explain_protocol);
8659 var_set_int(
"$CURSOR_PROTOCOL", cursor_protocol);
8661 var_set_int(
"$ENABLED_QUERY_LOG", 1);
8662 var_set_int(
"$ENABLED_ABORT_ON_ERROR", 1);
8663 var_set_int(
"$ENABLED_RESULT_LOG", 1);
8664 var_set_int(
"$ENABLED_CONNECT_LOG", 0);
8665 var_set_int(
"$ENABLED_WARNINGS", 1);
8666 var_set_int(
"$ENABLED_INFO", 0);
8667 var_set_int(
"$ENABLED_METADATA", 0);
8669 DBUG_PRINT(
"info",(
"result_file: '%s'",
8670 result_file_name ? result_file_name :
""));
8671 verbose_msg(
"Results saved in '%s'.",
8672 result_file_name ? result_file_name :
"");
8673 if (mysql_server_init(embedded_server_arg_count,
8674 embedded_server_args,
8675 (
char**) embedded_server_groups))
8676 die(
"Can't initialize MySQL server");
8677 server_initialized= 1;
8678 if (cur_file == file_stack && cur_file->file == 0)
8680 cur_file->file= stdin;
8681 cur_file->file_name= my_strdup(
"<stdin>", MYF(MY_WME));
8682 cur_file->lineno= 1;
8684 var_set_string(
"MYSQLTEST_FILE", cur_file->file_name);
8688 if (cursor_protocol)
8691 ps_protocol_enabled= ps_protocol;
8692 sp_protocol_enabled= sp_protocol;
8693 view_protocol_enabled= view_protocol;
8694 opt_trace_protocol_enabled= opt_trace_protocol;
8695 explain_protocol_enabled= explain_protocol;
8696 json_explain_protocol_enabled= json_explain_protocol;
8697 cursor_protocol_enabled= cursor_protocol;
8700 #ifdef EMBEDDED_LIBRARY
8701 init_connection_thd(con);
8703 if (!( mysql_init(&con->mysql)))
8704 die(
"Failed in mysql_init()");
8705 if (opt_connect_timeout)
8706 mysql_options(&con->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
8707 (
void *) &opt_connect_timeout);
8709 mysql_options(&con->mysql,MYSQL_OPT_COMPRESS,NullS);
8710 mysql_options(&con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
8711 mysql_options(&con->mysql, MYSQL_SET_CHARSET_NAME,
8712 charset_info->csname);
8713 if (opt_charsets_dir)
8714 mysql_options(&con->mysql, MYSQL_SET_CHARSET_DIR,
8717 #ifndef EMBEDDED_LIBRARY
8719 mysql_options(&con->mysql,MYSQL_OPT_PROTOCOL,(
char*)&opt_protocol);
8722 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
8726 mysql_ssl_set(&con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
8727 opt_ssl_capath, opt_ssl_cipher);
8728 mysql_options(&con->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
8729 mysql_options(&con->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
8730 #if MYSQL_VERSION_ID >= 50000
8732 opt_ssl_verify_server_cert= opt_host && !strcmp(opt_host,
"localhost");
8733 mysql_options(&con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
8734 &opt_ssl_verify_server_cert);
8740 if (shared_memory_base_name)
8741 mysql_options(&con->mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
8744 if (!(con->name = my_strdup(
"default", MYF(MY_WME))))
8745 die(
"Out of memory");
8747 safe_connect(&con->mysql, con->name, opt_host, opt_user, opt_pass,
8748 opt_db, opt_port, unix_sock);
8751 timer_start= timer_now();
8760 set_current_connection(con);
8764 open_file(opt_include);
8767 verbose_msg(
"Start processing test commands from '%s' ...", cur_file->file_name);
8768 while (!read_command(&command) && !abort_flag)
8770 int current_line_inc = 1, processed = 0;
8771 if (command->type == Q_UNKNOWN || command->type == Q_COMMENT_WITH_COMMAND)
8772 get_command_type(command);
8774 if (parsing_disabled &&
8775 command->type != Q_ENABLE_PARSING &&
8776 command->type != Q_DISABLE_PARSING)
8779 command->type= Q_COMMENT;
8783 command->abort_on_error= (command->expected_errors.count == 0 &&
8787 my_bool ok_to_do= cur_block->ok || command->type == Q_DELIMITER;
8795 if (command->type == Q_SOURCE ||
8796 command->type == Q_ERROR ||
8797 command->type == Q_WRITE_FILE ||
8798 command->type == Q_APPEND_FILE ||
8799 command->type == Q_PERL)
8801 for (
struct st_block *stb= cur_block-1; stb >= block_stack; stb--)
8803 if (stb->cmd == cmd_while)
8814 command->last_argument= command->first_argument;
8817 curr_command= command;
8818 switch (command->type) {
8820 do_connect(command);
8822 case Q_CONNECTION: select_connection(command);
break;
8825 do_close_connection(command);
break;
8826 case Q_ENABLE_QUERY_LOG:
8827 set_property(command, P_QUERY, 0);
8829 case Q_DISABLE_QUERY_LOG:
8830 set_property(command, P_QUERY, 1);
8832 case Q_ENABLE_ABORT_ON_ERROR:
8833 set_property(command, P_ABORT, 1);
8835 case Q_DISABLE_ABORT_ON_ERROR:
8836 set_property(command, P_ABORT, 0);
8838 case Q_ENABLE_RESULT_LOG:
8839 set_property(command, P_RESULT, 0);
8841 case Q_DISABLE_RESULT_LOG:
8842 set_property(command, P_RESULT, 1);
8844 case Q_ENABLE_CONNECT_LOG:
8845 set_property(command, P_CONNECT, 0);
8847 case Q_DISABLE_CONNECT_LOG:
8848 set_property(command, P_CONNECT, 1);
8850 case Q_ENABLE_WARNINGS:
8851 set_property(command, P_WARN, 0);
8853 case Q_DISABLE_WARNINGS:
8854 set_property(command, P_WARN, 1);
8857 set_property(command, P_INFO, 0);
8859 case Q_DISABLE_INFO:
8860 set_property(command, P_INFO, 1);
8862 case Q_ENABLE_METADATA:
8863 set_property(command, P_META, 1);
8865 case Q_DISABLE_METADATA:
8866 set_property(command, P_META, 0);
8868 case Q_SOURCE: do_source(command);
break;
8869 case Q_SLEEP: do_sleep(command, 0);
break;
8870 case Q_REAL_SLEEP: do_sleep(command, 1);
break;
8871 case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(command);
break;
8872 case Q_INC: do_modify_var(command, DO_INC);
break;
8873 case Q_DEC: do_modify_var(command, DO_DEC);
break;
8874 case Q_ECHO: do_echo(command); command_executed++;
break;
8876 die(
"'system' command is deprecated, use exec or\n"\
8877 " see the manual for portable commands to use");
8879 case Q_REMOVE_FILE: do_remove_file(command);
break;
8880 case Q_REMOVE_FILES_WILDCARD: do_remove_files_wildcard(command);
break;
8881 case Q_MKDIR: do_mkdir(command);
break;
8882 case Q_RMDIR: do_rmdir(command);
break;
8883 case Q_LIST_FILES: do_list_files(command);
break;
8884 case Q_LIST_FILES_WRITE_FILE:
8885 do_list_files_write_file_command(command, FALSE);
8887 case Q_LIST_FILES_APPEND_FILE:
8888 do_list_files_write_file_command(command, TRUE);
8890 case Q_FILE_EXIST: do_file_exist(command);
break;
8891 case Q_WRITE_FILE: do_write_file(command);
break;
8892 case Q_APPEND_FILE: do_append_file(command);
break;
8893 case Q_DIFF_FILES: do_diff_files(command);
break;
8894 case Q_SEND_QUIT: do_send_quit(command);
break;
8895 case Q_CHANGE_USER: do_change_user(command);
break;
8896 case Q_CAT_FILE: do_cat_file(command);
break;
8897 case Q_COPY_FILE: do_copy_file(command);
break;
8898 case Q_MOVE_FILE: do_move_file(command);
break;
8899 case Q_CHMOD_FILE: do_chmod_file(command);
break;
8900 case Q_PERL: do_perl(command);
break;
8901 case Q_RESULT_FORMAT_VERSION: do_result_format_version(command);
break;
8903 do_delimiter(command);
8905 case Q_DISPLAY_VERTICAL_RESULTS:
8906 display_result_vertically= TRUE;
8908 case Q_DISPLAY_HORIZONTAL_RESULTS:
8909 display_result_vertically= FALSE;
8911 case Q_SORTED_RESULT:
8916 display_result_sorted= TRUE;
8923 display_result_lower= TRUE;
8925 case Q_LET: do_let(command);
break;
8927 die(
"'eval_result' command is deprecated");
8929 case Q_QUERY_VERTICAL:
8930 case Q_QUERY_HORIZONTAL:
8931 if (command->query == command->query_buf)
8934 command->query= command->first_argument;
8935 command->first_word_len= 0;
8941 my_bool old_display_result_vertically= display_result_vertically;
8943 int flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
8948 flags= QUERY_SEND_FLAG;
8951 else if (command->type == Q_REAP)
8953 flags= QUERY_REAP_FLAG;
8957 display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
8965 if (explain_protocol_enabled)
8966 run_explain(cur_con, command, flags, 0);
8967 if (json_explain_protocol_enabled)
8968 run_explain(cur_con, command, flags, 1);
8972 strmake(command->require_file, save_file,
sizeof(save_file) - 1);
8975 run_query(cur_con, command, flags);
8976 display_opt_trace(cur_con, command, flags);
8978 command->last_argument= command->end;
8981 display_result_vertically= old_display_result_vertically;
8987 if (!*command->first_argument)
8998 if (command->query == command->query_buf)
8999 command->query= command->first_argument;
9007 run_query(cur_con, command, QUERY_SEND_FLAG);
9009 command->last_argument= command->end;
9012 do_get_file_name(command, save_file,
sizeof(save_file));
9015 do_get_errcodes(command);
9018 do_get_replace(command);
9020 case Q_REPLACE_REGEX:
9021 do_get_replace_regex(command);
9023 case Q_REPLACE_COLUMN:
9024 do_get_replace_column(command);
9026 case Q_SAVE_MASTER_POS: do_save_master_pos();
break;
9027 case Q_SYNC_WITH_MASTER: do_sync_with_master(command);
break;
9028 case Q_SYNC_SLAVE_WITH_MASTER:
9030 do_save_master_pos();
9031 if (*command->first_argument)
9032 select_connection(command);
9034 select_connection_name(
"slave");
9035 do_sync_with_master2(command, 0);
9040 command->last_argument= command->end;
9043 if (opt_result_format_version == 1)
9047 if (disable_query_log)
9051 const char* p= command->query;
9052 if (p && *p ==
'#' && *(p+1) ==
'#')
9054 dynstr_append_mem(&ds_res, command->query, command->query_len);
9055 dynstr_append(&ds_res,
"\n");
9061 if (opt_result_format_version == 1)
9065 if (disable_query_log)
9068 dynstr_append(&ds_res,
"\n");
9071 handle_command_error(command, mysql_ping(&cur_con->mysql));
9073 case Q_SEND_SHUTDOWN:
9074 handle_command_error(command,
9075 mysql_shutdown(&cur_con->mysql,
9078 case Q_SHUTDOWN_SERVER:
9079 do_shutdown_server(command);
9088 timer_start= timer_now();
9094 case Q_CHARACTER_SET:
9095 do_set_charset(command);
9097 case Q_DISABLE_PS_PROTOCOL:
9098 set_property(command, P_PS, 0);
9102 case Q_ENABLE_PS_PROTOCOL:
9103 set_property(command, P_PS, ps_protocol);
9105 case Q_DISABLE_RECONNECT:
9106 set_reconnect(&cur_con->mysql, 0);
9108 case Q_ENABLE_RECONNECT:
9109 set_reconnect(&cur_con->mysql, 1);
9113 case Q_DISABLE_PARSING:
9114 if (parsing_disabled == 0)
9115 parsing_disabled= 1;
9117 die(
"Parsing is already disabled");
9119 case Q_ENABLE_PARSING:
9124 if (parsing_disabled == 1)
9125 parsing_disabled= 0;
9127 die(
"Parsing is already enabled");
9131 die(
"%s", command->first_argument);
9138 abort_not_supported_test(
"%s", command->first_argument);
9142 die(
"result, deprecated command");
9153 current_line_inc= 0;
9154 switch (command->type) {
9155 case Q_WHILE: do_block(cmd_while, command);
break;
9156 case Q_IF: do_block(cmd_if, command);
break;
9157 case Q_END_BLOCK: do_done(command);
break;
9158 default: current_line_inc = 1;
break;
9162 check_eol_junk(command->last_argument);
9164 if (command->type != Q_ERROR &&
9165 command->type != Q_COMMENT)
9171 memset(&saved_expected_errors, 0,
sizeof(saved_expected_errors));
9174 if (command_executed != last_command_executed || command->used_replace)
9183 display_result_sorted= FALSE;
9184 display_result_lower= FALSE;
9186 last_command_executed= command_executed;
9188 parser.current_line += current_line_inc;
9189 if ( opt_mark_progress )
9190 mark_progress(command, parser.current_line);
9193 log_file.write(&ds_res);
9195 dynstr_set(&ds_res, 0);
9201 verbose_msg(
"... Done processing test commands.");
9203 if (parsing_disabled)
9204 die(
"Test ended with parsing disabled");
9206 my_bool empty_result= FALSE;
9213 if (log_file.bytes_written())
9215 if (result_file_name)
9224 if (my_copy(log_file.file_name(), result_file_name, MYF(0)) != 0)
9225 die(
"Failed to copy '%s' to '%s', errno: %d",
9226 log_file.file_name(), result_file_name, errno);
9239 if (! result_file_name ||
record ||
9240 compare_files (log_file.file_name(), result_file_name))
9242 die(
"The test didn't produce any output");
9250 if (!command_executed && result_file_name && !empty_result)
9251 die(
"No queries executed but non-empty result file found!");
9253 verbose_msg(
"Test has succeeded!");
9256 cleanup_and_exit(0);
9282 void timer_output(
void)
9287 ulonglong timer= timer_now() - timer_start;
9288 end= longlong2str(timer, buf, 10);
9289 str_to_file(timer_file,buf, (
int) (end-buf));
9296 ulonglong timer_now(
void)
9298 return my_micro_time() / 1000;
9310 void do_get_replace_column(
struct st_command *command)
9312 char *from= command->first_argument;
9314 DBUG_ENTER(
"get_replace_columns");
9316 free_replace_column();
9318 die(
"Missing argument in %s", command->query);
9321 start= buff= (
char*)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
9326 to= get_string(&buff, &from, command);
9327 if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
9328 die(
"Wrong column number to replace_column in '%s'", command->query);
9330 die(
"Wrong number of arguments to replace_column in '%s'", command->query);
9331 to= get_string(&buff, &from, command);
9332 my_free(replace_column[column_number-1]);
9333 replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
9334 set_if_bigger(max_replace_column, column_number);
9337 command->last_argument= command->end;
9343 void free_replace_column()
9346 for (i=0 ; i < max_replace_column ; i++)
9348 if (replace_column[i])
9350 my_free(replace_column[i]);
9351 replace_column[
i]= 0;
9354 max_replace_column= 0;
9369 uint array_allocs,max_count,length,max_length;
9372 struct st_replace *init_replace(
char * *from,
char * *to, uint count,
9373 char * word_end_chars);
9374 int insert_pointer_name(reg1
POINTER_ARRAY *pa,
char * name);
9385 void do_get_replace(
struct st_command *command)
9388 char *from= command->first_argument;
9390 char word_end_chars[256], *pos;
9392 DBUG_ENTER(
"get_replace");
9396 memset(&to_array, 0,
sizeof(to_array));
9397 memset(&from_array, 0,
sizeof(from_array));
9399 die(
"Missing argument in %s", command->query);
9400 start= buff= (
char*)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
9404 to= get_string(&buff, &from, command);
9406 die(
"Wrong number of arguments to replace_result in '%s'",
9409 fix_win_paths(to, from - to);
9411 insert_pointer_name(&from_array,to);
9412 to= get_string(&buff, &from, command);
9413 insert_pointer_name(&to_array,to);
9415 for (i= 1,pos= word_end_chars ; i < 256 ; i++)
9416 if (my_isspace(charset_info,i))
9419 if (!(glob_replace= init_replace((
char**) from_array.typelib.type_names,
9420 (
char**) to_array.typelib.type_names,
9421 (uint) from_array.typelib.count,
9423 die(
"Can't initialize replace from '%s'", command->query);
9424 free_pointer_array(&from_array);
9425 free_pointer_array(&to_array);
9427 command->last_argument= command->end;
9434 DBUG_ENTER(
"free_replace");
9435 my_free(glob_replace);
9448 char *replace_string;
9456 int len __attribute__((unused)))
9460 const char *start, *from;
9461 DBUG_ENTER(
"replace_strings_append");
9468 DBUG_PRINT(
"info", (
"Looping through states"));
9469 while (!rep_pos->found)
9470 rep_pos= rep_pos->next[(uchar) *from++];
9476 dynstr_append_mem(ds, start, from - start - 1);
9477 DBUG_PRINT(
"exit", (
"Found no more string to replace, appended: %s", start));
9482 DBUG_PRINT(
"info", (
"found: %d, to_offset: %d, from_offset: %d, string: %s",
9483 rep_str->found, rep_str->to_offset,
9484 rep_str->from_offset, rep_str->replace_string));
9487 dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
9490 dynstr_append_mem(ds, rep_str->replace_string,
9491 strlen(rep_str->replace_string));
9493 if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
9496 DBUG_PRINT(
"exit", (
"Found end of from string"));
9499 DBUG_ASSERT(from <= str+len);
9520 int reg_replace(
char** buf_p,
int* buf_len_p,
char *pattern,
char *
replace,
9521 char *
string,
int icase);
9530 #define PARSE_REGEX_ARG \
9531 while (p < expr_end) \
9536 if (last_c == '\\') \
9563 char*
buf,*expr_end;
9566 uint expr_len= strlen(expr);
9572 sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
9573 my_init_dynamic_array(&res->regex_arr,
sizeof(
struct st_regex),128,128);
9575 buf= (
char*)res +
sizeof(*res);
9576 expr_end= expr + expr_len;
9581 while (p < expr_end)
9583 memset(®, 0,
sizeof(reg));
9585 while (p < expr_end)
9592 if (p == expr_end || ++p == expr_end)
9594 if (res->regex_arr.elements)
9605 if (p == expr_end || ++p == expr_end)
9621 if (p < expr_end && *p ==
'i')
9625 if (insert_dynamic(&res->regex_arr, ®))
9626 die(
"Out of memory");
9628 res->odd_buf_len= res->even_buf_len= 8192;
9629 res->even_buf= (
char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
9630 res->odd_buf= (
char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
9631 res->buf= res->even_buf;
9637 die(
"Error parsing replace_regex \"%s\"", expr);
9663 char* in_buf, *out_buf;
9667 out_buf= r->even_buf;
9668 buf_len_p= &r->even_buf_len;
9672 for (i= 0; i < r->regex_arr.elements; i++)
9675 char* save_out_buf= out_buf;
9677 get_dynamic(&r->regex_arr,(uchar*)&re,i);
9679 if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
9683 if (save_out_buf != out_buf)
9685 if (save_out_buf == r->even_buf)
9686 r->even_buf= out_buf;
9688 r->odd_buf= out_buf;
9695 swap_variables(
char*,in_buf,out_buf);
9697 buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
9702 return (r->buf == 0);
9714 void do_get_replace_regex(
struct st_command *command)
9716 char *expr= command->first_argument;
9717 free_replace_regex();
9721 VAR *val= var_get(expr, NULL, 0, 1);
9722 expr= val ? val->str_val : NULL;
9724 if (expr && *expr && !(glob_replace_regex=init_replace_regex(expr)))
9725 die(
"Could not init replace_regex");
9726 command->last_argument= command->end;
9729 void free_replace_regex()
9731 if (glob_replace_regex)
9733 delete_dynamic(&glob_replace_regex->regex_arr);
9734 my_free(glob_replace_regex->even_buf);
9735 my_free(glob_replace_regex->odd_buf);
9736 my_free(glob_replace_regex);
9737 glob_replace_regex=0;
9747 #define SECURE_REG_BUF if (buf_len < need_buf_len) \
9749 int off= res_p - buf; \
9750 buf= (char*)my_realloc(buf,need_buf_len,MYF(MY_WME+MY_FAE)); \
9752 buf_len= need_buf_len; \
9767 int reg_replace(
char** buf_p,
int* buf_len_p,
char *pattern,
9768 char *
replace,
char *
string,
int icase)
9775 int buf_len, need_buf_len;
9776 int cflags= MY_REG_EXTENDED;
9778 char *res_p,*str_p,*str_end;
9780 buf_len= *buf_len_p;
9781 len= strlen(
string);
9782 str_end=
string + len;
9787 need_buf_len= len * 2 + 1;
9793 cflags|= MY_REG_ICASE;
9795 if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1)))
9797 check_regerr(&r,err_code);
9802 MYF(MY_WME+MY_FAE));
9806 replace_end= replace + strlen(replace);
9812 err_code= my_regexec(&r,str_p, r.re_nsub+1, subs,
9813 (str_p ==
string) ? MY_REG_NOTBOL : 0);
9816 if (err_code && err_code != MY_REG_NOMATCH)
9818 check_regerr(&r,err_code);
9826 char* expr_p= replace;
9833 need_buf_len= (res_p -
buf) + (
int) subs[0].rm_so;
9836 while (expr_p < replace_end)
9838 int back_ref_num= -1;
9841 if (c ==
'\\' && expr_p + 1 < replace_end)
9843 back_ref_num= (int) (expr_p[1] -
'0');
9847 if (back_ref_num >= 0 && back_ref_num <= (
int)r.re_nsub)
9849 my_regoff_t start_off, end_off;
9850 if ((start_off=subs[back_ref_num].rm_so) > -1 &&
9851 (end_off=subs[back_ref_num].rm_eo) > -1)
9853 need_buf_len += (int) (end_off - start_off);
9873 memcpy(res_p, str_p, (
size_t) subs[0].rm_so);
9874 res_p+= subs[0].rm_so;
9880 while (expr_p < replace_end)
9882 int back_ref_num= -1;
9885 if (c ==
'\\' && expr_p + 1 < replace_end)
9887 back_ref_num= expr_p[1] -
'0';
9890 if (back_ref_num >= 0 && back_ref_num <= (
int)r.re_nsub)
9892 my_regoff_t start_off, end_off;
9893 if ((start_off=subs[back_ref_num].rm_so) > -1 &&
9894 (end_off=subs[back_ref_num].rm_eo) > -1)
9896 int block_len= (int) (end_off - start_off);
9897 memcpy(res_p,str_p + start_off, block_len);
9904 *res_p++ = *expr_p++;
9909 if (subs[0].rm_so == subs[0].rm_eo)
9911 if (str_p + subs[0].rm_so >= str_end)
9913 str_p += subs[0].rm_eo ;
9914 *res_p++ = *str_p++;
9918 str_p += subs[0].rm_eo;
9923 int left_in_str= str_end-str_p;
9924 need_buf_len= (res_p-
buf) + left_in_str;
9926 memcpy(res_p,str_p,left_in_str);
9927 res_p += left_in_str;
9935 *buf_len_p= buf_len;
9941 #define WORD_BIT (8*sizeof(uint))
9944 #define SET_MALLOC_HUNC 64
9945 #define LAST_CHAR_CODE 259
9949 short next[LAST_CHAR_CODE];
9977 int init_sets(
REP_SETS *sets,uint states);
9979 void make_sets_invisible(
REP_SETS *sets);
9980 void free_last_set(
REP_SETS *sets);
9982 void internal_set_bit(
REP_SET *
set, uint bit);
9983 void internal_clear_bit(
REP_SET *
set, uint bit);
9987 int get_next_bit(
REP_SET *
set,uint lastpos);
9989 int find_found(
FOUND_SET *found_set,uint table_offset,
9991 uint start_at_word(
char * pos);
9992 uint end_of_word(
char * pos);
9994 static uint found_sets=0;
9997 uint replace_len(
char * str)
10010 REPLACE *init_replace(
char * *from,
char * *to,uint count,
10011 char * word_end_chars)
10013 static const int SPACE_CHAR= 256;
10014 static const int END_OF_LINE= 258;
10016 uint
i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
10017 int used_sets,chr,default_state;
10018 char used_chars[LAST_CHAR_CODE],is_word_end[256];
10019 char * pos, *to_pos, **to_array;
10021 REP_SET *
set,*start_states,*word_states,*new_set;
10026 DBUG_ENTER(
"init_replace");
10029 for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
10031 len=replace_len(from[i]);
10038 result_len+=(uint) strlen(to[i])+1;
10039 if (len > max_length)
10042 memset(is_word_end, 0,
sizeof(is_word_end));
10043 for (i=0 ; word_end_chars[
i] ; i++)
10044 is_word_end[(uchar) word_end_chars[
i]]=1;
10046 if (init_sets(&sets,states))
10055 (void) make_new_set(&sets);
10056 make_sets_invisible(&sets);
10058 word_states=make_new_set(&sets);
10059 start_states=make_new_set(&sets);
10060 if (!(follow=(
FOLLOWS*) my_malloc((states+2)*
sizeof(
FOLLOWS),MYF(MY_WME))))
10063 my_free(found_set);
10068 for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
10070 if (from[i][0] ==
'\\' && from[i][1] ==
'^')
10072 internal_set_bit(start_states,states+1);
10075 start_states->table_offset=
i;
10076 start_states->found_offset=1;
10079 else if (from[i][0] ==
'\\' && from[i][1] ==
'$')
10081 internal_set_bit(start_states,states);
10082 internal_set_bit(word_states,states);
10083 if (!from[i][2] && start_states->table_offset == (uint) ~0)
10085 start_states->table_offset=
i;
10086 start_states->found_offset=0;
10091 internal_set_bit(word_states,states);
10092 if (from[i][0] ==
'\\' && (from[i][1] ==
'b' && from[i][2]))
10093 internal_set_bit(start_states,states+1);
10095 internal_set_bit(start_states,states);
10097 for (pos=from[i], len=0; *pos ; pos++)
10099 follow_ptr->chr= (uchar) *pos;
10100 follow_ptr->table_offset=
i;
10101 follow_ptr->len= ++len;
10105 follow_ptr->table_offset=
i;
10106 follow_ptr->len=len;
10108 states+=(uint) len+1;
10112 for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
10114 set=sets.set+set_nr;
10119 for (i= (uint) ~0; (i=get_next_bit(
set,i)) ;)
10121 if (!follow[i].chr)
10123 if (! default_state)
10124 default_state= find_found(found_set,set->table_offset,
10125 set->found_offset+1);
10128 copy_bits(sets.set+used_sets,
set);
10129 if (!default_state)
10130 or_bits(sets.set+used_sets,sets.set);
10133 memset(used_chars, 0,
sizeof(used_chars));
10134 for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
10136 used_chars[follow[
i].chr]=1;
10137 if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
10138 follow[i].len > 1) || follow[
i].chr == END_OF_LINE)
10143 if (used_chars[SPACE_CHAR])
10144 for (pos= word_end_chars ; *pos ; pos++)
10145 used_chars[(
int) (uchar) *pos] = 1;
10148 for (chr= 0 ; chr < 256 ; chr++)
10150 if (! used_chars[chr])
10151 set->next[chr]= chr ? default_state : -1;
10154 new_set=make_new_set(&sets);
10156 set=sets.set+set_nr;
10157 new_set->table_offset=
set->table_offset;
10158 new_set->found_len=
set->found_len;
10159 new_set->found_offset=
set->found_offset+1;
10162 for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
10164 if (!follow[i].chr || follow[i].chr == chr ||
10165 (follow[i].chr == SPACE_CHAR &&
10166 (is_word_end[chr] ||
10167 (!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
10168 (follow[i].chr == END_OF_LINE && ! chr))
10170 if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
10171 follow[i].len > found_end)
10172 found_end=follow[
i].len;
10173 if (chr && follow[i].chr)
10174 internal_set_bit(new_set,i+1);
10176 internal_set_bit(new_set,i);
10181 new_set->found_len=0;
10183 for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
10185 if ((follow[i].chr == SPACE_CHAR ||
10186 follow[i].chr == END_OF_LINE) && ! chr)
10190 if (follow[bit_nr-1].len < found_end ||
10191 (new_set->found_len &&
10192 (chr == 0 || !follow[bit_nr].chr)))
10193 internal_clear_bit(new_set,i);
10196 if (chr == 0 || !follow[bit_nr].chr)
10198 new_set->table_offset=follow[bit_nr].table_offset;
10199 if (chr || (follow[i].chr == SPACE_CHAR ||
10200 follow[i].chr == END_OF_LINE))
10201 new_set->found_offset=found_end;
10202 new_set->found_len=found_end;
10209 set->next[chr] = find_found(found_set,
10210 new_set->table_offset,
10211 new_set->found_offset);
10212 free_last_set(&sets);
10215 set->next[chr] = find_set(&sets,new_set);
10218 set->next[chr] = find_set(&sets,new_set);
10227 sizeof(
char *)*count+result_len,
10228 MYF(MY_WME | MY_ZEROFILL))))
10231 to_array= (
char **) (rep_str+found_sets+1);
10232 to_pos=(
char *) (to_array+count);
10233 for (i=0 ; i < count ; i++)
10235 to_array[
i]=to_pos;
10236 to_pos=strmov(to_pos,to[i])+1;
10238 rep_str[0].found=1;
10239 rep_str[0].replace_string=0;
10240 for (i=1 ; i <= found_sets ; i++)
10242 pos=from[found_set[i-1].table_offset];
10243 rep_str[
i].found= !memcmp(pos,
"\\^", 3) ? 2 : 1;
10244 rep_str[
i].replace_string=to_array[found_set[i-1].table_offset];
10245 rep_str[
i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
10246 rep_str[
i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
10249 for (i=0 ; i < sets.count ; i++)
10251 for (j=0 ; j < 256 ; j++)
10252 if (sets.set[i].next[j] >= 0)
10253 replace[
i].next[j]=replace+sets.set[
i].next[j];
10255 replace[
i].next[j]=(
REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
10260 my_free(found_set);
10261 DBUG_PRINT(
"exit",(
"Replace table has %d states",sets.count));
10262 DBUG_RETURN(replace);
10266 int init_sets(
REP_SETS *sets,uint states)
10268 memset(sets, 0,
sizeof(*sets));
10269 sets->size_of_bits=((states+7)/8);
10270 if (!(sets->set_buffer=(
REP_SET*) my_malloc(
sizeof(
REP_SET)*SET_MALLOC_HUNC,
10273 if (!(sets->bit_buffer=(uint*) my_malloc(
sizeof(uint)*sets->size_of_bits*
10274 SET_MALLOC_HUNC,MYF(MY_WME))))
10276 my_free(sets->set);
10284 void make_sets_invisible(
REP_SETS *sets)
10286 sets->invisible=sets->count;
10287 sets->set+=sets->count;
10293 uint
i,count,*bit_buffer;
10298 set=sets->set+ sets->count++;
10299 memset(set->bits, 0,
sizeof(uint)*sets->size_of_bits);
10300 memset(&set->next[0], 0,
sizeof(set->next[0])*LAST_CHAR_CODE);
10301 set->found_offset=0;
10303 set->table_offset= (uint) ~0;
10304 set->size_of_bits=sets->size_of_bits;
10307 count=sets->count+sets->invisible+SET_MALLOC_HUNC;
10308 if (!(
set=(
REP_SET*) my_realloc((uchar*) sets->set_buffer,
10312 sets->set_buffer=
set;
10313 sets->set=
set+sets->invisible;
10314 if (!(bit_buffer=(uint*) my_realloc((uchar*) sets->bit_buffer,
10315 (
sizeof(uint)*sets->size_of_bits)*count,
10318 sets->bit_buffer=bit_buffer;
10319 for (i=0 ; i < count ; i++)
10321 sets->set_buffer[
i].bits=bit_buffer;
10322 bit_buffer+=sets->size_of_bits;
10324 sets->extra=SET_MALLOC_HUNC;
10325 return make_new_set(sets);
10328 void free_last_set(
REP_SETS *sets)
10337 my_free(sets->set_buffer);
10338 my_free(sets->bit_buffer);
10342 void internal_set_bit(
REP_SET *
set, uint bit)
10344 set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
10348 void internal_clear_bit(
REP_SET *
set, uint bit)
10350 set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
10358 for (i=0 ; i < to->size_of_bits ; i++)
10359 to->bits[i]|=from->bits[i];
10365 memcpy((uchar*) to->bits,(uchar*) from->bits,
10366 (
size_t) (
sizeof(uint) * to->size_of_bits));
10371 return memcmp(set1->bits, set2->bits,
10372 sizeof(uint) * set1->size_of_bits);
10378 int get_next_bit(
REP_SET *
set,uint lastpos)
10380 uint pos,*start,*end,bits;
10382 start=
set->bits+ ((lastpos+1) / WORD_BIT);
10383 end=
set->bits +
set->size_of_bits;
10384 bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
10386 while (! bits && ++start < end)
10390 pos=(uint) (start-set->bits)*WORD_BIT;
10391 while (! (bits & 1))
10406 for (i=0 ; i < sets->count-1 ; i++)
10408 if (!cmp_bits(sets->set+i,find))
10410 free_last_set(sets);
10424 int find_found(
FOUND_SET *found_set,uint table_offset,
int found_offset)
10427 for (i=0 ; (uint) i < found_sets ; i++)
10428 if (found_set[i].table_offset == table_offset &&
10429 found_set[i].found_offset == found_offset)
10431 found_set[
i].table_offset=table_offset;
10432 found_set[
i].found_offset=found_offset;
10439 uint start_at_word(
char * pos)
10441 return (((!memcmp(pos,
"\\b",2) && pos[2]) ||
10442 !memcmp(pos,
"\\^", 2)) ? 1 : 0);
10445 uint end_of_word(
char * pos)
10447 char * end=strend(pos);
10448 return ((end > pos+2 && !memcmp(end-2,
"\\b", 2)) ||
10449 (end >= pos+2 && !memcmp(end-2,
"\\$",2))) ? 1 : 0;
10456 #define PC_MALLOC 256
10457 #define PS_MALLOC 512
10459 int insert_pointer_name(reg1
POINTER_ARRAY *pa,
char * name)
10461 uint
i,length,old_count;
10463 const char **new_array;
10464 DBUG_ENTER(
"insert_pointer_name");
10466 if (! pa->typelib.count)
10468 if (!(pa->typelib.type_names=(
const char **)
10469 my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
10470 (
sizeof(
char *)+
sizeof(*pa->flag))*
10471 (
sizeof(
char *)+
sizeof(*pa->flag))),MYF(MY_WME))))
10473 if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
10476 my_free(pa->typelib.type_names);
10479 pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(
sizeof(uchar*)+
10480 sizeof(*pa->flag));
10481 pa->flag= (uint8*) (pa->typelib.type_names+pa->max_count);
10483 pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
10484 pa->array_allocs=1;
10486 length=(uint) strlen(name)+1;
10487 if (pa->length+length >= pa->max_length)
10489 if (!(new_pos= (uchar*) my_realloc((uchar*) pa->str,
10490 (uint) (pa->length+length+PS_MALLOC),
10493 if (new_pos != pa->str)
10495 my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
10496 for (i=0 ; i < pa->typelib.count ; i++)
10497 pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
10501 pa->max_length= pa->length+length+PS_MALLOC;
10503 if (pa->typelib.count >= pa->max_count-1)
10506 pa->array_allocs++;
10507 len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
10508 if (!(new_array=(
const char **) my_realloc((uchar*) pa->typelib.type_names,
10510 (
sizeof(uchar*)+
sizeof(*pa->flag))*
10511 (
sizeof(uchar*)+
sizeof(*pa->flag)),
10514 pa->typelib.type_names=new_array;
10515 old_count=pa->max_count;
10516 pa->max_count=len/(
sizeof(uchar*) +
sizeof(*pa->flag));
10517 pa->flag= (uint8*) (pa->typelib.type_names+pa->max_count);
10518 memcpy((uchar*) pa->flag,(
char *) (pa->typelib.type_names+old_count),
10519 old_count*
sizeof(*pa->flag));
10521 pa->flag[pa->typelib.count]=0;
10522 pa->typelib.type_names[pa->typelib.count++]= (
char*) pa->str+pa->length;
10523 pa->typelib.type_names[pa->typelib.count]= NullS;
10524 (
void) strmov((
char*) pa->str+pa->length,name);
10525 pa->length+=length;
10534 if (pa->typelib.count)
10536 pa->typelib.count=0;
10537 my_free(pa->typelib.type_names);
10538 pa->typelib.type_names=0;
10548 const char *val,
int len)
10552 fix_win_paths(val, len);
10555 if (display_result_lower)
10559 for (
const char *v= val; *v; v++)
10560 *c++= my_tolower(charset_info, *v);
10566 if (glob_replace_regex)
10569 if (!multi_reg_replace(glob_replace_regex, (
char*)val))
10571 val= glob_replace_regex->buf;
10579 replace_strings_append(glob_replace, ds, val, len);
10582 dynstr_append_mem(ds, val, len);
10589 replace_dynstr_append_mem(ds, val, strlen(val));
10596 char *end= longlong10_to_str(val, buff, 10);
10597 replace_dynstr_append_mem(ds, buff, end - buff);
10614 static int comp_lines(
const char **a,
const char **b)
10616 return (strcmp(*a,*b));
10622 char *start= ds_input->str;
10624 DBUG_ENTER(
"dynstr_append_sorted");
10629 my_init_dynamic_array(&lines,
sizeof(
const char*), 32, 32);
10632 while (*start && *start !=
'\n')
10635 dynstr_append_mem(ds, ds_input->str, start - ds_input->str);
10640 char* line_end= (
char*)start;
10643 while (*line_end && *line_end !=
'\n')
10648 if (insert_dynamic(&lines, &start))
10649 die(
"Out of memory inserting lines to sort");
10655 qsort(lines.buffer, lines.elements,
10656 sizeof(
char**), (qsort_cmp)comp_lines);
10659 for (i= 0; i < lines.elements ; i++)
10661 const char **line= dynamic_element(&lines, i,
const char**);
10662 dynstr_append(ds, *line);
10663 dynstr_append(ds,
"\n");
10666 delete_dynamic(&lines);
10670 #ifndef HAVE_SETENV
10671 static int setenv(
const char *name,
const char *value,
int overwrite)
10673 size_t buflen= strlen(name) + strlen(value) + 2;
10674 char *envvar= (
char *)malloc(buflen);
10677 strcpy(envvar, name);
10678 strcat(envvar,
"=");
10679 strcat(envvar, value);