From d81d57d408c0965d8cce06a7b114f06235d65163 Mon Sep 17 00:00:00 2001 From: "lars@mysql.com" <> Date: Thu, 29 Sep 2005 10:42:23 +0200 Subject: [PATCH 01/13] mysqlbinlog --hexdump augments each log entry with byte information --- client/mysqlbinlog.cc | 30 ++++++---- sql/log_event.cc | 134 ++++++++++++++++++++++++++++++------------ sql/log_event.h | 69 ++++++++++++++-------- 3 files changed, 163 insertions(+), 70 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index eff05b9a8bf..577ae82eebd 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -62,6 +62,7 @@ static const char *load_default_groups[]= { "mysqlbinlog","client",0 }; void sql_print_error(const char *format, ...); static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0; +static bool opt_hexdump= 0; static const char* database= 0; static my_bool force_opt= 0, short_form= 0, remote_opt= 0; static ulonglong offset = 0; @@ -522,12 +523,15 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, } if (!short_form) fprintf(result_file, "# at %s\n",llstr(pos,ll_buff)); - + + /* Set pos to 0 if hexdump is disabled */ + pos= (opt_hexdump ? pos : 0); + switch (ev_type) { case QUERY_EVENT: if (check_database(((Query_log_event*)ev)->db)) goto end; - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, pos, last_event_info); break; case CREATE_FILE_EVENT: { @@ -547,7 +551,8 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT' below. */ - ce->print(result_file, short_form, last_event_info, TRUE); + ce->print(result_file, short_form, pos, last_event_info, TRUE); + // If this binlog is not 3.23 ; why this test?? if (description_event->binlog_version >= 3) { @@ -558,13 +563,13 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, break; } case APPEND_BLOCK_EVENT: - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, pos, last_event_info); if (load_processor.process((Append_block_log_event*) ev)) break; // Error break; case EXEC_LOAD_EVENT: { - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, pos, last_event_info); Execute_load_log_event *exv= (Execute_load_log_event*)ev; Create_file_log_event *ce= load_processor.grab_event(exv->file_id); /* @@ -574,7 +579,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, */ if (ce) { - ce->print(result_file, short_form, last_event_info, TRUE); + ce->print(result_file, short_form, pos, last_event_info, TRUE); my_free((char*)ce->fname,MYF(MY_WME)); delete ce; } @@ -586,7 +591,7 @@ Create_file event for file_id: %u\n",exv->file_id); case FORMAT_DESCRIPTION_EVENT: delete description_event; description_event= (Format_description_log_event*) ev; - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, pos, last_event_info); /* We don't want this event to be deleted now, so let's hide it (I (Guilhem) should later see if this triggers a non-serious Valgrind @@ -596,7 +601,7 @@ Create_file event for file_id: %u\n",exv->file_id); ev= 0; break; case BEGIN_LOAD_QUERY_EVENT: - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, pos, last_event_info); load_processor.process((Begin_load_query_log_event*) ev); break; case EXECUTE_LOAD_QUERY_EVENT: @@ -613,7 +618,7 @@ Create_file event for file_id: %u\n",exv->file_id); if (fname) { - exlq->print(result_file, short_form, last_event_info, fname); + exlq->print(result_file, short_form, pos, last_event_info, fname); my_free(fname, MYF(MY_WME)); } else @@ -622,7 +627,7 @@ Begin_load_query event for file_id: %u\n", exlq->file_id); break; } default: - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, pos, last_event_info); } } @@ -669,6 +674,8 @@ static struct my_option my_long_options[] = 0, 0}, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"hexdump", 'H', "Augment output with hexadecimal and ascii data dump.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Get the binlog from server.", (gptr*) &host, (gptr*) &host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"offset", 'o', "Skip the first N entries.", (gptr*) &offset, (gptr*) &offset, @@ -848,6 +855,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'd': one_database = 1; break; + case 'H': + opt_hexdump= 1; + break; case 'p': if (argument) { diff --git a/sql/log_event.cc b/sql/log_event.cc index 5cb4c289a10..631a4627f3a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -24,6 +24,8 @@ #include "mysql_priv.h" #include "slave.h" #include +#else +#include /* For isalnum() */ #endif /* MYSQL_CLIENT */ #define log_cs &my_charset_latin1 @@ -881,15 +883,58 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, Log_event::print_header() */ -void Log_event::print_header(FILE* file) +void Log_event::print_header(FILE* file, my_off_t start_pos) { char llbuff[22]; fputc('#', file); print_timestamp(file); fprintf(file, " server id %d end_log_pos %s ", server_id, llstr(log_pos,llbuff)); + + if (start_pos) + { + fprintf(file, "\n"); + unsigned char *ptr= (unsigned char*)temp_buf; + my_off_t i; + + char position[8+1] = {0}; + char b[3+1] = {0}; + char hex_string[16*3+1+1] = {0}; + char char_string[16+1] = {0}; + + for (i= 0; i < (log_pos-start_pos); i++, ptr++) + { + if (i % 16 == 0) + snprintf(position, sizeof(position), "%.8x", + (unsigned int) (start_pos+i)); + + snprintf(b, sizeof(b), "%02X ", *ptr); + strncat(hex_string, b, sizeof(hex_string)-strlen(hex_string)-1); + + snprintf(b, sizeof(b), "%c", isalnum(*ptr) ? *ptr : '.'); + strncat(char_string, b, sizeof(char_string)-strlen(char_string)-1); + + if (i % 16 == 15) + { + fprintf(file, "# %8.8s %-48.48s |%16s|\n", + position, hex_string, char_string); + hex_string[0] = 0; + char_string[0] = 0; + } + else if (i % 8 == 7) + { + /* Middle space */ + strncat(hex_string, " ", sizeof(hex_string)-strlen(hex_string)-1); + } + } + + if (strlen(hex_string)) { + printf("# %8.8s %-48.48s |%s|\n# ", position, hex_string, char_string); + } + } } + /* Log_event::print_timestamp() */ @@ -1373,6 +1418,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, #ifdef MYSQL_CLIENT void Query_log_event::print_query_header(FILE* file, bool short_form, + my_off_t start_pos, LAST_EVENT_INFO* last_event_info) { // TODO: print the catalog ?? @@ -1382,7 +1428,7 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, if (!short_form) { - print_header(file); + print_header(file, start_pos); fprintf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n", get_type_str(), (ulong) thread_id, (ulong) exec_time, error_code); } @@ -1503,10 +1549,10 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, } -void Query_log_event::print(FILE* file, bool short_form, +void Query_log_event::print(FILE* file, bool short_form, my_off_t start_pos, LAST_EVENT_INFO* last_event_info) { - print_query_header(file, short_form, last_event_info); + print_query_header(file, short_form, start_pos, last_event_info); my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME)); fputs(";\n", file); } @@ -1804,11 +1850,12 @@ void Start_log_event_v3::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Start_log_event_v3::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Start_log_event_v3::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { if (!short_form) { - print_header(file); + print_header(file, start_pos); fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version, server_version); print_timestamp(file); @@ -2532,19 +2579,20 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, */ #ifdef MYSQL_CLIENT -void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Load_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { - print(file, short_form, last_event_info, 0); + print(file, short_form, start_pos, last_event_info, 0); } -void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, - bool commented) +void Load_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info, bool commented) { DBUG_ENTER("Load_log_event::print"); if (!short_form) { - print_header(file); + print_header(file, start_pos); fprintf(file, "\tQuery\tthread_id=%ld\texec_time=%ld\n", thread_id, exec_time); } @@ -2949,13 +2997,14 @@ void Rotate_log_event::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Rotate_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Rotate_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { char buf[22]; if (short_form) return; - print_header(file); + print_header(file, start_pos); fprintf(file, "\tRotate to "); if (new_log_ident) my_fwrite(file, (byte*) new_log_ident, (uint)ident_len, @@ -3151,7 +3200,7 @@ bool Intvar_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void Intvar_log_event::print(FILE* file, bool short_form, +void Intvar_log_event::print(FILE* file, bool short_form, my_off_t start_pos, LAST_EVENT_INFO* last_event_info) { char llbuff[22]; @@ -3160,7 +3209,7 @@ void Intvar_log_event::print(FILE* file, bool short_form, if (!short_form) { - print_header(file); + print_header(file, start_pos); fprintf(file, "\tIntvar\n"); } @@ -3241,12 +3290,13 @@ bool Rand_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Rand_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Rand_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { char llbuff[22],llbuff2[22]; if (!short_form) { - print_header(file); + print_header(file, start_pos); fprintf(file, "\tRand\n"); } fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n", @@ -3311,14 +3361,15 @@ bool Xid_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Xid_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Xid_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { if (!short_form) { char buf[64]; longlong10_to_str(xid, buf, 10); - print_header(file); + print_header(file, start_pos); fprintf(file, "\tXid = %s\n", buf); fflush(file); } @@ -3509,11 +3560,12 @@ bool User_var_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void User_var_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { if (!short_form) { - print_header(file); + print_header(file, start_pos); fprintf(file, "\tUser_var\n"); } @@ -3684,11 +3736,12 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) #ifdef HAVE_REPLICATION #ifdef MYSQL_CLIENT -void Unknown_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Unknown_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file); + print_header(file, start_pos); fputc('\n', file); fprintf(file, "# %s", "Unknown event\n"); } @@ -3755,12 +3808,13 @@ Slave_log_event::~Slave_log_event() #ifdef MYSQL_CLIENT -void Slave_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Slave_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { char llbuff[22]; if (short_form) return; - print_header(file); + print_header(file, start_pos); fputc('\n', file); fprintf(file, "\ Slave: master_host: '%s' master_port: %d master_log: '%s' master_pos: %s\n", @@ -3840,12 +3894,13 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli) */ #ifdef MYSQL_CLIENT -void Stop_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Stop_log_event::print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file); + print_header(file, start_pos); fprintf(file, "\tStop\n"); fflush(file); } @@ -4019,19 +4074,20 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, */ #ifdef MYSQL_CLIENT -void Create_file_log_event::print(FILE* file, bool short_form, +void Create_file_log_event::print(FILE* file, bool short_form, my_off_t start_pos, LAST_EVENT_INFO* last_event_info, bool enable_local) { if (short_form) { if (enable_local && check_fname_outside_temp_buf()) - Load_log_event::print(file, 1, last_event_info); + Load_log_event::print(file, 1, start_pos, last_event_info); return; } if (enable_local) { - Load_log_event::print(file, short_form, last_event_info, !check_fname_outside_temp_buf()); + Load_log_event::print(file, short_form, start_pos, last_event_info, + !check_fname_outside_temp_buf()); /* That one is for "file_id: etc" below: in mysqlbinlog we want the #, in SHOW BINLOG EVENTS we don't. @@ -4044,9 +4100,10 @@ void Create_file_log_event::print(FILE* file, bool short_form, void Create_file_log_event::print(FILE* file, bool short_form, + my_off_t start_pos, LAST_EVENT_INFO* last_event_info) { - print(file,short_form,last_event_info,0); + print(file, short_form, start_pos, last_event_info, 0); } #endif /* MYSQL_CLIENT */ @@ -4207,11 +4264,12 @@ bool Append_block_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Append_block_log_event::print(FILE* file, bool short_form, + my_off_t start_pos, LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file); + print_header(file, start_pos); fputc('\n', file); fprintf(file, "#%s: file_id: %d block_len: %d\n", get_type_str(), file_id, block_len); @@ -4351,11 +4409,12 @@ bool Delete_file_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Delete_file_log_event::print(FILE* file, bool short_form, + my_off_t start_pos, LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file); + print_header(file, start_pos); fputc('\n', file); fprintf(file, "#Delete_file: file_id=%u\n", file_id); } @@ -4447,11 +4506,12 @@ bool Execute_load_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Execute_load_log_event::print(FILE* file, bool short_form, + my_off_t start_pos, LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file); + print_header(file, start_pos); fputc('\n', file); fprintf(file, "#Exec_load: file_id=%d\n", file_id); @@ -4659,17 +4719,19 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) #ifdef MYSQL_CLIENT void Execute_load_query_log_event::print(FILE* file, bool short_form, + my_off_t start_pos, LAST_EVENT_INFO* last_event_info) { - print(file, short_form, last_event_info, 0); + print(file, short_form, start_pos, last_event_info, 0); } void Execute_load_query_log_event::print(FILE* file, bool short_form, + my_off_t start_pos, LAST_EVENT_INFO* last_event_info, const char *local_fname) { - print_query_header(file, short_form, last_event_info); + print_query_header(file, short_form, start_pos, last_event_info); if (local_fname) { diff --git a/sql/log_event.h b/sql/log_event.h index 29580589a34..864266b5a90 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -589,9 +589,10 @@ public: static Log_event* read_log_event(IO_CACHE* file, const Format_description_log_event *description_event); /* print*() functions are used by mysqlbinlog */ - virtual void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0) = 0; + virtual void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0) = 0; void print_timestamp(FILE* file, time_t *ts = 0); - void print_header(FILE* file); + void print_header(FILE* file, my_off_t start_pos= 0); #endif static void *operator new(size_t size) @@ -751,8 +752,11 @@ public: uint32 q_len_arg); #endif /* HAVE_REPLICATION */ #else - void print_query_header(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print_query_header(FILE* file, bool short_form= 0, + my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Query_log_event(const char* buf, uint event_len, @@ -806,7 +810,8 @@ public: void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Slave_log_event(const char* buf, uint event_len); @@ -894,8 +899,10 @@ public: bool use_rli_only_for_errors); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info = 0); - void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, bool commented); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info = 0); + void print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info, bool commented); #endif /* @@ -984,7 +991,8 @@ public: #endif /* HAVE_REPLICATION */ #else Start_log_event_v3() {} - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Start_log_event_v3(const char* buf, @@ -1079,7 +1087,8 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Intvar_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1120,7 +1129,8 @@ class Rand_log_event: public Log_event int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Rand_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1157,7 +1167,8 @@ class Xid_log_event: public Log_event int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Xid_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1199,7 +1210,8 @@ public: void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif User_var_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1225,7 +1237,8 @@ public: {} int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Stop_log_event(const char* buf, const Format_description_log_event* description_event): @@ -1264,7 +1277,8 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Rotate_log_event(const char* buf, uint event_len, @@ -1317,8 +1331,10 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, bool enable_local); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info, bool enable_local); #endif Create_file_log_event(const char* buf, uint event_len, @@ -1385,7 +1401,8 @@ public: virtual int get_create_or_append() const; #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Append_block_log_event(const char* buf, uint event_len, @@ -1420,8 +1437,10 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, bool enable_local); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info, bool enable_local); #endif Delete_file_log_event(const char* buf, uint event_len, @@ -1456,7 +1475,8 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); #endif Execute_load_log_event(const char* buf, uint event_len, @@ -1541,11 +1561,11 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form = 0, + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, LAST_EVENT_INFO* last_event_info= 0); /* Prints the query as LOAD DATA LOCAL and with rewritten filename */ - void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, - const char *local_fname); + void print(FILE* file, bool short_form, my_off_t start_pos, + LAST_EVENT_INFO* last_event_info, const char *local_fname); #endif Execute_load_query_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event); @@ -1574,7 +1594,8 @@ public: Log_event(buf, description_event) {} ~Unknown_log_event() {} - void print(FILE* file, bool short_form= 0, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + LAST_EVENT_INFO* last_event_info= 0); Log_event_type get_type_code() { return UNKNOWN_EVENT;} bool is_valid() const { return 1; } }; From bf19d02b276d9b06abc81a7c6a93ca160a4f21f5 Mon Sep 17 00:00:00 2001 From: "lars@mysql.com" <> Date: Fri, 30 Sep 2005 00:12:14 +0200 Subject: [PATCH 02/13] mysqlbinlog --hexdump additional patch 2 - Fixes related to Guilhems review - Special printing of event header --- client/mysqlbinlog.cc | 10 ++- sql/log_event.cc | 153 ++++++++++++++++++++++-------------------- sql/log_event.h | 46 ++++++------- 3 files changed, 109 insertions(+), 100 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 577ae82eebd..d78b6ca4412 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -525,7 +525,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, fprintf(result_file, "# at %s\n",llstr(pos,ll_buff)); /* Set pos to 0 if hexdump is disabled */ - pos= (opt_hexdump ? pos : 0); + if (!opt_hexdump) pos= 0; switch (ev_type) { case QUERY_EVENT: @@ -674,8 +674,9 @@ static struct my_option my_long_options[] = 0, 0}, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"hexdump", 'H', "Augment output with hexadecimal and ascii data dump.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.", + (gptr*) &opt_hexdump, (gptr*) &opt_hexdump, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"host", 'h', "Get the binlog from server.", (gptr*) &host, (gptr*) &host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"offset", 'o', "Skip the first N entries.", (gptr*) &offset, (gptr*) &offset, @@ -855,9 +856,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'd': one_database = 1; break; - case 'H': - opt_hexdump= 1; - break; case 'p': if (argument) { diff --git a/sql/log_event.cc b/sql/log_event.cc index 631a4627f3a..c704e81007a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -24,8 +24,6 @@ #include "mysql_priv.h" #include "slave.h" #include -#else -#include /* For isalnum() */ #endif /* MYSQL_CLIENT */ #define log_cs &my_charset_latin1 @@ -883,53 +881,66 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, Log_event::print_header() */ -void Log_event::print_header(FILE* file, my_off_t start_pos) +void Log_event::print_header(FILE* file, my_off_t hexdump_from) { char llbuff[22]; fputc('#', file); print_timestamp(file); fprintf(file, " server id %d end_log_pos %s ", server_id, - llstr(log_pos,llbuff)); + llstr(log_pos,llbuff)); - if (start_pos) + /* mysqlbinlog --hexdump */ + if (hexdump_from) { fprintf(file, "\n"); - unsigned char *ptr= (unsigned char*)temp_buf; + uchar *ptr= (uchar*)temp_buf; + my_off_t size= + uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN; my_off_t i; - char position[8+1] = {0}; - char b[3+1] = {0}; - char hex_string[16*3+1+1] = {0}; - char char_string[16+1] = {0}; + /* Header len * 4 >= header len * (2 chars + space + extra space) */ + char *h, hex_string[LOG_EVENT_MINIMAL_HEADER_LEN*4]= {0}; + char *c, char_string[16+1]= {0}; - for (i= 0; i < (log_pos-start_pos); i++, ptr++) + /* Common header of event */ + fprintf(file, "# Position Timestamp Type Master ID " + "Size Master Pos Flags \n"); + fprintf(file, "# %8.8lx %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x\n", + hexdump_from, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], + ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], + ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]); + ptr += LOG_EVENT_MINIMAL_HEADER_LEN; + hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN; + + /* Rest of event (without common header) */ + for (i= 0, c= char_string, h=hex_string; + i < size; + i++, ptr++) { - if (i % 16 == 0) - snprintf(position, sizeof(position), "%.8x", - (unsigned int) (start_pos+i)); + my_snprintf(h, 4, "%02x ", *ptr); + h += 3; - snprintf(b, sizeof(b), "%02X ", *ptr); - strncat(hex_string, b, sizeof(hex_string)-strlen(hex_string)-1); - - snprintf(b, sizeof(b), "%c", isalnum(*ptr) ? *ptr : '.'); - strncat(char_string, b, sizeof(char_string)-strlen(char_string)-1); + *c++= my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.'; if (i % 16 == 15) { - fprintf(file, "# %8.8s %-48.48s |%16s|\n", - position, hex_string, char_string); - hex_string[0] = 0; - char_string[0] = 0; - } - else if (i % 8 == 7) - { - /* Middle space */ - strncat(hex_string, " ", sizeof(hex_string)-strlen(hex_string)-1); + fprintf(file, "# %8.8lx %-48.48s |%16s|\n", + hexdump_from + (i & 0xfffffff0), hex_string, char_string); + hex_string[0]= 0; + char_string[0]= 0; + c= char_string; + h= hex_string; } + else if (i % 8 == 7) *h++ = ' '; } + *c= '\0'; - if (strlen(hex_string)) { - printf("# %8.8s %-48.48s |%s|\n# ", position, hex_string, char_string); + /* Non-full last line */ + if (hex_string[0]) { + printf("# %8.8lx %-48.48s |%s|\n# ", + hexdump_from + (i & 0xfffffff0), hex_string, char_string); } } } @@ -1418,7 +1429,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, #ifdef MYSQL_CLIENT void Query_log_event::print_query_header(FILE* file, bool short_form, - my_off_t start_pos, + my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { // TODO: print the catalog ?? @@ -1428,7 +1439,7 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, if (!short_form) { - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n", get_type_str(), (ulong) thread_id, (ulong) exec_time, error_code); } @@ -1549,10 +1560,10 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, } -void Query_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Query_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { - print_query_header(file, short_form, start_pos, last_event_info); + print_query_header(file, short_form, hexdump_from, last_event_info); my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME)); fputs(";\n", file); } @@ -1850,12 +1861,12 @@ void Start_log_event_v3::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Start_log_event_v3::print(FILE* file, bool short_form, my_off_t start_pos, +void Start_log_event_v3::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { if (!short_form) { - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version, server_version); print_timestamp(file); @@ -2579,20 +2590,20 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, */ #ifdef MYSQL_CLIENT -void Load_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Load_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { - print(file, short_form, start_pos, last_event_info, 0); + print(file, short_form, hexdump_from, last_event_info, 0); } -void Load_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Load_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info, bool commented) { DBUG_ENTER("Load_log_event::print"); if (!short_form) { - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\tQuery\tthread_id=%ld\texec_time=%ld\n", thread_id, exec_time); } @@ -2997,14 +3008,14 @@ void Rotate_log_event::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Rotate_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Rotate_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { char buf[22]; if (short_form) return; - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\tRotate to "); if (new_log_ident) my_fwrite(file, (byte*) new_log_ident, (uint)ident_len, @@ -3200,7 +3211,7 @@ bool Intvar_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void Intvar_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Intvar_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { char llbuff[22]; @@ -3209,7 +3220,7 @@ void Intvar_log_event::print(FILE* file, bool short_form, my_off_t start_pos, if (!short_form) { - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\tIntvar\n"); } @@ -3290,13 +3301,13 @@ bool Rand_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Rand_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Rand_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { char llbuff[22],llbuff2[22]; if (!short_form) { - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\tRand\n"); } fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n", @@ -3361,7 +3372,7 @@ bool Xid_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Xid_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Xid_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { if (!short_form) @@ -3369,7 +3380,7 @@ void Xid_log_event::print(FILE* file, bool short_form, my_off_t start_pos, char buf[64]; longlong10_to_str(xid, buf, 10); - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\tXid = %s\n", buf); fflush(file); } @@ -3560,12 +3571,12 @@ bool User_var_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void User_var_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void User_var_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { if (!short_form) { - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\tUser_var\n"); } @@ -3736,12 +3747,12 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) #ifdef HAVE_REPLICATION #ifdef MYSQL_CLIENT -void Unknown_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Unknown_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file, start_pos); + print_header(file, hexdump_from); fputc('\n', file); fprintf(file, "# %s", "Unknown event\n"); } @@ -3808,13 +3819,13 @@ Slave_log_event::~Slave_log_event() #ifdef MYSQL_CLIENT -void Slave_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Slave_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { char llbuff[22]; if (short_form) return; - print_header(file, start_pos); + print_header(file, hexdump_from); fputc('\n', file); fprintf(file, "\ Slave: master_host: '%s' master_port: %d master_log: '%s' master_pos: %s\n", @@ -3894,13 +3905,13 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli) */ #ifdef MYSQL_CLIENT -void Stop_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Stop_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file, start_pos); + print_header(file, hexdump_from); fprintf(file, "\tStop\n"); fflush(file); } @@ -4074,19 +4085,19 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, */ #ifdef MYSQL_CLIENT -void Create_file_log_event::print(FILE* file, bool short_form, my_off_t start_pos, +void Create_file_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info, bool enable_local) { if (short_form) { if (enable_local && check_fname_outside_temp_buf()) - Load_log_event::print(file, 1, start_pos, last_event_info); + Load_log_event::print(file, 1, hexdump_from, last_event_info); return; } if (enable_local) { - Load_log_event::print(file, short_form, start_pos, last_event_info, + Load_log_event::print(file, short_form, hexdump_from, last_event_info, !check_fname_outside_temp_buf()); /* That one is for "file_id: etc" below: in mysqlbinlog we want the #, in @@ -4100,10 +4111,10 @@ void Create_file_log_event::print(FILE* file, bool short_form, my_off_t start_po void Create_file_log_event::print(FILE* file, bool short_form, - my_off_t start_pos, + my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { - print(file, short_form, start_pos, last_event_info, 0); + print(file, short_form, hexdump_from, last_event_info, 0); } #endif /* MYSQL_CLIENT */ @@ -4264,12 +4275,12 @@ bool Append_block_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Append_block_log_event::print(FILE* file, bool short_form, - my_off_t start_pos, + my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file, start_pos); + print_header(file, hexdump_from); fputc('\n', file); fprintf(file, "#%s: file_id: %d block_len: %d\n", get_type_str(), file_id, block_len); @@ -4409,12 +4420,12 @@ bool Delete_file_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Delete_file_log_event::print(FILE* file, bool short_form, - my_off_t start_pos, + my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file, start_pos); + print_header(file, hexdump_from); fputc('\n', file); fprintf(file, "#Delete_file: file_id=%u\n", file_id); } @@ -4506,12 +4517,12 @@ bool Execute_load_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Execute_load_log_event::print(FILE* file, bool short_form, - my_off_t start_pos, + my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { if (short_form) return; - print_header(file, start_pos); + print_header(file, hexdump_from); fputc('\n', file); fprintf(file, "#Exec_load: file_id=%d\n", file_id); @@ -4719,19 +4730,19 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) #ifdef MYSQL_CLIENT void Execute_load_query_log_event::print(FILE* file, bool short_form, - my_off_t start_pos, + my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info) { - print(file, short_form, start_pos, last_event_info, 0); + print(file, short_form, hexdump_from, last_event_info, 0); } void Execute_load_query_log_event::print(FILE* file, bool short_form, - my_off_t start_pos, + my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info, const char *local_fname) { - print_query_header(file, short_form, start_pos, last_event_info); + print_query_header(file, short_form, hexdump_from, last_event_info); if (local_fname) { diff --git a/sql/log_event.h b/sql/log_event.h index 864266b5a90..9351e9b1148 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -589,10 +589,10 @@ public: static Log_event* read_log_event(IO_CACHE* file, const Format_description_log_event *description_event); /* print*() functions are used by mysqlbinlog */ - virtual void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + virtual void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0) = 0; void print_timestamp(FILE* file, time_t *ts = 0); - void print_header(FILE* file, my_off_t start_pos= 0); + void print_header(FILE* file, my_off_t hexdump_from= 0); #endif static void *operator new(size_t size) @@ -753,9 +753,9 @@ public: #endif /* HAVE_REPLICATION */ #else void print_query_header(FILE* file, bool short_form= 0, - my_off_t start_pos= 0, + my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -810,7 +810,7 @@ public: void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -899,9 +899,9 @@ public: bool use_rli_only_for_errors); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info = 0); - void print(FILE* file, bool short_form, my_off_t start_pos, + void print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info, bool commented); #endif @@ -991,7 +991,7 @@ public: #endif /* HAVE_REPLICATION */ #else Start_log_event_v3() {} - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1087,7 +1087,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1129,7 +1129,7 @@ class Rand_log_event: public Log_event int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1167,7 +1167,7 @@ class Xid_log_event: public Log_event int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1210,7 +1210,7 @@ public: void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1237,7 +1237,7 @@ public: {} int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1277,7 +1277,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1331,9 +1331,9 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form, my_off_t start_pos, + void print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info, bool enable_local); #endif @@ -1401,7 +1401,7 @@ public: virtual int get_create_or_append() const; #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1437,9 +1437,9 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form, my_off_t start_pos, + void print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info, bool enable_local); #endif @@ -1475,7 +1475,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); #endif @@ -1561,10 +1561,10 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); /* Prints the query as LOAD DATA LOCAL and with rewritten filename */ - void print(FILE* file, bool short_form, my_off_t start_pos, + void print(FILE* file, bool short_form, my_off_t hexdump_from, LAST_EVENT_INFO* last_event_info, const char *local_fname); #endif Execute_load_query_log_event(const char* buf, uint event_len, @@ -1594,7 +1594,7 @@ public: Log_event(buf, description_event) {} ~Unknown_log_event() {} - void print(FILE* file, bool short_form= 0, my_off_t start_pos= 0, + void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, LAST_EVENT_INFO* last_event_info= 0); Log_event_type get_type_code() { return UNKNOWN_EVENT;} bool is_valid() const { return 1; } From 48457e08527fd74c9ccb1ddbb05bf9df4e395909 Mon Sep 17 00:00:00 2001 From: "lars@mysql.com" <> Date: Wed, 12 Oct 2005 23:37:21 +0200 Subject: [PATCH 03/13] mysqlbin --hexdump patch 3 --- client/mysqlbinlog.cc | 26 ++++--- sql/log_event.cc | 171 +++++++++++++++++++----------------------- sql/log_event.h | 88 ++++++++++------------ 3 files changed, 132 insertions(+), 153 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 7ae563c7209..2b96914bfc9 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -496,6 +496,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, char ll_buff[21]; Log_event_type ev_type= ev->get_type_code(); DBUG_ENTER("process_event"); + last_event_info->short_form= short_form; /* Format events are not concerned by --offset and such, we always need to @@ -524,14 +525,16 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, if (!short_form) fprintf(result_file, "# at %s\n",llstr(pos,ll_buff)); - /* Set pos to 0 if hexdump is disabled */ - if (!opt_hexdump) pos= 0; + if (!opt_hexdump) + last_event_info->hexdump_from= 0; /* Disabled */ + else + last_event_info->hexdump_from= pos; switch (ev_type) { case QUERY_EVENT: if (check_database(((Query_log_event*)ev)->db)) goto end; - ev->print(result_file, short_form, pos, last_event_info); + ev->print(result_file, last_event_info); break; case CREATE_FILE_EVENT: { @@ -551,7 +554,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT' below. */ - ce->print(result_file, short_form, pos, last_event_info, TRUE); + ce->print(result_file, last_event_info, TRUE); // If this binlog is not 3.23 ; why this test?? if (description_event->binlog_version >= 3) @@ -563,13 +566,13 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, break; } case APPEND_BLOCK_EVENT: - ev->print(result_file, short_form, pos, last_event_info); + ev->print(result_file, last_event_info); if (load_processor.process((Append_block_log_event*) ev)) break; // Error break; case EXEC_LOAD_EVENT: { - ev->print(result_file, short_form, pos, last_event_info); + ev->print(result_file, last_event_info); Execute_load_log_event *exv= (Execute_load_log_event*)ev; Create_file_log_event *ce= load_processor.grab_event(exv->file_id); /* @@ -579,7 +582,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, */ if (ce) { - ce->print(result_file, short_form, pos, last_event_info, TRUE); + ce->print(result_file, last_event_info, TRUE); my_free((char*)ce->fname,MYF(MY_WME)); delete ce; } @@ -591,7 +594,8 @@ Create_file event for file_id: %u\n",exv->file_id); case FORMAT_DESCRIPTION_EVENT: delete description_event; description_event= (Format_description_log_event*) ev; - ev->print(result_file, short_form, pos, last_event_info); + last_event_info->common_header_len= description_event->common_header_len; + ev->print(result_file, last_event_info); /* We don't want this event to be deleted now, so let's hide it (I (Guilhem) should later see if this triggers a non-serious Valgrind @@ -601,7 +605,7 @@ Create_file event for file_id: %u\n",exv->file_id); ev= 0; break; case BEGIN_LOAD_QUERY_EVENT: - ev->print(result_file, short_form, pos, last_event_info); + ev->print(result_file, last_event_info); load_processor.process((Begin_load_query_log_event*) ev); break; case EXECUTE_LOAD_QUERY_EVENT: @@ -618,7 +622,7 @@ Create_file event for file_id: %u\n",exv->file_id); if (fname) { - exlq->print(result_file, short_form, pos, last_event_info, fname); + exlq->print(result_file, last_event_info, fname); my_free(fname, MYF(MY_WME)); } else @@ -627,7 +631,7 @@ Begin_load_query event for file_id: %u\n", exlq->file_id); break; } default: - ev->print(result_file, short_form, pos, last_event_info); + ev->print(result_file, last_event_info); } } diff --git a/sql/log_event.cc b/sql/log_event.cc index c704e81007a..2a6dd04fea8 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -701,7 +701,6 @@ failed my_b_read")); */ DBUG_RETURN(0); } - uint data_len = uint4korr(head + EVENT_LEN_OFFSET); char *buf= 0; const char *error= 0; @@ -881,16 +880,18 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, Log_event::print_header() */ -void Log_event::print_header(FILE* file, my_off_t hexdump_from) +void Log_event::print_header(FILE* file, LAST_EVENT_INFO* last_event_info) { char llbuff[22]; + my_off_t hexdump_from= last_event_info->hexdump_from; + fputc('#', file); print_timestamp(file); fprintf(file, " server id %d end_log_pos %s ", server_id, llstr(log_pos,llbuff)); /* mysqlbinlog --hexdump */ - if (hexdump_from) + if (last_event_info->hexdump_from) { fprintf(file, "\n"); uchar *ptr= (uchar*)temp_buf; @@ -902,17 +903,20 @@ void Log_event::print_header(FILE* file, my_off_t hexdump_from) char *h, hex_string[LOG_EVENT_MINIMAL_HEADER_LEN*4]= {0}; char *c, char_string[16+1]= {0}; - /* Common header of event */ - fprintf(file, "# Position Timestamp Type Master ID " - "Size Master Pos Flags \n"); - fprintf(file, "# %8.8lx %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x\n", - hexdump_from, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], - ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], - ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]); - ptr += LOG_EVENT_MINIMAL_HEADER_LEN; - hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN; + /* Pretty-print event common header if header is exactly 19 bytes */ + if (last_event_info->common_header_len == 19) + { + fprintf(file, "# Position Timestamp Type Master ID " + "Size Master Pos Flags \n"); + fprintf(file, "# %8.8lx %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x\n", + hexdump_from, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], + ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], + ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]); + ptr += LOG_EVENT_MINIMAL_HEADER_LEN; + hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN; + } /* Rest of event (without common header) */ for (i= 0, c= char_string, h=hex_string; @@ -1428,18 +1432,17 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, */ #ifdef MYSQL_CLIENT -void Query_log_event::print_query_header(FILE* file, bool short_form, - my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Query_log_event::print_query_header(FILE* file, + LAST_EVENT_INFO* last_event_info) { // TODO: print the catalog ?? char buff[40],*end; // Enough for SET TIMESTAMP bool different_db= 1; uint32 tmp; - if (!short_form) + if (!last_event_info->short_form) { - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n", get_type_str(), (ulong) thread_id, (ulong) exec_time, error_code); } @@ -1560,10 +1563,9 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, } -void Query_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Query_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - print_query_header(file, short_form, hexdump_from, last_event_info); + print_query_header(file, last_event_info); my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME)); fputs(";\n", file); } @@ -1861,12 +1863,11 @@ void Start_log_event_v3::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Start_log_event_v3::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Start_log_event_v3::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - if (!short_form) + if (!last_event_info->short_form) { - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version, server_version); print_timestamp(file); @@ -2590,20 +2591,19 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, */ #ifdef MYSQL_CLIENT -void Load_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Load_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - print(file, short_form, hexdump_from, last_event_info, 0); + print(file, last_event_info, 0); } -void Load_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info, bool commented) +void Load_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info, + bool commented) { DBUG_ENTER("Load_log_event::print"); - if (!short_form) + if (!last_event_info->short_form) { - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\tQuery\tthread_id=%ld\texec_time=%ld\n", thread_id, exec_time); } @@ -3008,14 +3008,13 @@ void Rotate_log_event::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Rotate_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Rotate_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { char buf[22]; - if (short_form) + if (last_event_info->short_form) return; - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\tRotate to "); if (new_log_ident) my_fwrite(file, (byte*) new_log_ident, (uint)ident_len, @@ -3211,16 +3210,15 @@ bool Intvar_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void Intvar_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Intvar_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { char llbuff[22]; const char *msg; LINT_INIT(msg); - if (!short_form) + if (!last_event_info->short_form) { - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\tIntvar\n"); } @@ -3301,13 +3299,12 @@ bool Rand_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Rand_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Rand_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { char llbuff[22],llbuff2[22]; - if (!short_form) + if (!last_event_info->short_form) { - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\tRand\n"); } fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n", @@ -3372,15 +3369,14 @@ bool Xid_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Xid_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Xid_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - if (!short_form) + if (!last_event_info->short_form) { char buf[64]; longlong10_to_str(xid, buf, 10); - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\tXid = %s\n", buf); fflush(file); } @@ -3571,12 +3567,11 @@ bool User_var_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void User_var_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void User_var_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - if (!short_form) + if (!last_event_info->short_form) { - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\tUser_var\n"); } @@ -3747,12 +3742,11 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) #ifdef HAVE_REPLICATION #ifdef MYSQL_CLIENT -void Unknown_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Unknown_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - if (short_form) + if (last_event_info->short_form) return; - print_header(file, hexdump_from); + print_header(file, last_event_info); fputc('\n', file); fprintf(file, "# %s", "Unknown event\n"); } @@ -3819,13 +3813,12 @@ Slave_log_event::~Slave_log_event() #ifdef MYSQL_CLIENT -void Slave_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Slave_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { char llbuff[22]; - if (short_form) + if (last_event_info->short_form) return; - print_header(file, hexdump_from); + print_header(file, last_event_info); fputc('\n', file); fprintf(file, "\ Slave: master_host: '%s' master_port: %d master_log: '%s' master_pos: %s\n", @@ -3905,13 +3898,12 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli) */ #ifdef MYSQL_CLIENT -void Stop_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Stop_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - if (short_form) + if (last_event_info->short_form) return; - print_header(file, hexdump_from); + print_header(file, last_event_info); fprintf(file, "\tStop\n"); fflush(file); } @@ -4085,19 +4077,19 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, */ #ifdef MYSQL_CLIENT -void Create_file_log_event::print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info, bool enable_local) +void Create_file_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info, + bool enable_local) { - if (short_form) + if (last_event_info->short_form) { if (enable_local && check_fname_outside_temp_buf()) - Load_log_event::print(file, 1, hexdump_from, last_event_info); + Load_log_event::print(file, last_event_info); return; } if (enable_local) { - Load_log_event::print(file, short_form, hexdump_from, last_event_info, + Load_log_event::print(file, last_event_info, !check_fname_outside_temp_buf()); /* That one is for "file_id: etc" below: in mysqlbinlog we want the #, in @@ -4110,11 +4102,9 @@ void Create_file_log_event::print(FILE* file, bool short_form, my_off_t hexdump_ } -void Create_file_log_event::print(FILE* file, bool short_form, - my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info) +void Create_file_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - print(file, short_form, hexdump_from, last_event_info, 0); + print(file, last_event_info, 0); } #endif /* MYSQL_CLIENT */ @@ -4274,13 +4264,12 @@ bool Append_block_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void Append_block_log_event::print(FILE* file, bool short_form, - my_off_t hexdump_from, +void Append_block_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - if (short_form) + if (last_event_info->short_form) return; - print_header(file, hexdump_from); + print_header(file, last_event_info); fputc('\n', file); fprintf(file, "#%s: file_id: %d block_len: %d\n", get_type_str(), file_id, block_len); @@ -4419,13 +4408,12 @@ bool Delete_file_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void Delete_file_log_event::print(FILE* file, bool short_form, - my_off_t hexdump_from, +void Delete_file_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - if (short_form) + if (last_event_info->short_form) return; - print_header(file, hexdump_from); + print_header(file, last_event_info); fputc('\n', file); fprintf(file, "#Delete_file: file_id=%u\n", file_id); } @@ -4516,13 +4504,12 @@ bool Execute_load_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void Execute_load_log_event::print(FILE* file, bool short_form, - my_off_t hexdump_from, +void Execute_load_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - if (short_form) + if (last_event_info->short_form) return; - print_header(file, hexdump_from); + print_header(file, last_event_info); fputc('\n', file); fprintf(file, "#Exec_load: file_id=%d\n", file_id); @@ -4729,20 +4716,18 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Execute_load_query_log_event::print(FILE* file, bool short_form, - my_off_t hexdump_from, +void Execute_load_query_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) { - print(file, short_form, hexdump_from, last_event_info, 0); + print(file, last_event_info, 0); } -void Execute_load_query_log_event::print(FILE* file, bool short_form, - my_off_t hexdump_from, +void Execute_load_query_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info, const char *local_fname) { - print_query_header(file, short_form, hexdump_from, last_event_info); + print_query_header(file, last_event_info); if (local_fname) { @@ -4763,7 +4748,7 @@ void Execute_load_query_log_event::print(FILE* file, bool short_form, fprintf(file, ";\n"); } - if (!short_form) + if (!last_event_info->short_form) fprintf(file, "# file_id: %d \n", file_id); } #endif diff --git a/sql/log_event.h b/sql/log_event.h index 9351e9b1148..80dd40f0dd5 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -451,12 +451,18 @@ struct st_relay_log_info; #ifdef MYSQL_CLIENT /* - A structure for mysqlbinlog to remember the last db, flags2, sql_mode etc; it - is passed to events' print() methods, so that they print only the necessary - USE and SET commands. + A structure for mysqlbinlog to know how to print events + + This structure is passed to the event's print() methods so that only + the necessary USE and SET commands are printed. Last db, flags2, + sql_mode etc are stored here. + + The structure also contain other information on how to print the + events, e.g. short_form, hexdump_from. */ typedef struct st_last_event_info { + /* Old settings for database, sql_mode etc */ // TODO: have the last catalog here ?? char db[FN_REFLEN+1]; // TODO: make this a LEX_STRING when thd->db is bool flags2_inited; @@ -480,6 +486,12 @@ typedef struct st_last_event_info bzero(charset, sizeof(charset)); bzero(time_zone_str, sizeof(time_zone_str)); } + + /* Settings on how to print the events */ + bool short_form; + my_off_t hexdump_from; + uint8 common_header_len; + } LAST_EVENT_INFO; #endif @@ -589,10 +601,9 @@ public: static Log_event* read_log_event(IO_CACHE* file, const Format_description_log_event *description_event); /* print*() functions are used by mysqlbinlog */ - virtual void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0) = 0; + virtual void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0) = 0; void print_timestamp(FILE* file, time_t *ts = 0); - void print_header(FILE* file, my_off_t hexdump_from= 0); + void print_header(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif static void *operator new(size_t size) @@ -752,11 +763,8 @@ public: uint32 q_len_arg); #endif /* HAVE_REPLICATION */ #else - void print_query_header(FILE* file, bool short_form= 0, - my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print_query_header(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Query_log_event(const char* buf, uint event_len, @@ -810,8 +818,7 @@ public: void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Slave_log_event(const char* buf, uint event_len); @@ -899,10 +906,8 @@ public: bool use_rli_only_for_errors); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info = 0); - void print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info, bool commented); + void print(FILE* file, LAST_EVENT_INFO* last_event_info = 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info, bool commented); #endif /* @@ -991,8 +996,7 @@ public: #endif /* HAVE_REPLICATION */ #else Start_log_event_v3() {} - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Start_log_event_v3(const char* buf, @@ -1087,8 +1091,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Intvar_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1129,8 +1132,7 @@ class Rand_log_event: public Log_event int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Rand_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1167,8 +1169,7 @@ class Xid_log_event: public Log_event int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Xid_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1210,8 +1211,7 @@ public: void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif User_var_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1237,8 +1237,7 @@ public: {} int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Stop_log_event(const char* buf, const Format_description_log_event* description_event): @@ -1277,8 +1276,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Rotate_log_event(const char* buf, uint event_len, @@ -1331,10 +1329,8 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info, bool enable_local); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info, bool enable_local); #endif Create_file_log_event(const char* buf, uint event_len, @@ -1401,8 +1397,7 @@ public: virtual int get_create_or_append() const; #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Append_block_log_event(const char* buf, uint event_len, @@ -1437,10 +1432,8 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info, bool enable_local); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info, bool enable_local); #endif Delete_file_log_event(const char* buf, uint event_len, @@ -1475,8 +1468,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); #endif Execute_load_log_event(const char* buf, uint event_len, @@ -1561,11 +1553,10 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); /* Prints the query as LOAD DATA LOCAL and with rewritten filename */ - void print(FILE* file, bool short_form, my_off_t hexdump_from, - LAST_EVENT_INFO* last_event_info, const char *local_fname); + void print(FILE* file, LAST_EVENT_INFO* last_event_info, + const char *local_fname); #endif Execute_load_query_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event); @@ -1594,8 +1585,7 @@ public: Log_event(buf, description_event) {} ~Unknown_log_event() {} - void print(FILE* file, bool short_form= 0, my_off_t hexdump_from= 0, - LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); Log_event_type get_type_code() { return UNKNOWN_EVENT;} bool is_valid() const { return 1; } }; From 0abcffcb5df992724794582f21bbcdb552fa6d98 Mon Sep 17 00:00:00 2001 From: "lars@mysql.com" <> Date: Fri, 14 Oct 2005 01:14:23 +0200 Subject: [PATCH 04/13] WL#2835: Base64 mysys functions --- .../util/Base64.hpp => include/base64.h | 41 ++- mysys/Makefile.am | 7 +- mysys/base64.c | 265 ++++++++++++++++++ ndb/config/type_ndbapi.mk.am | 4 +- ndb/config/type_util.mk.am | 7 +- ndb/src/common/util/Base64.cpp | 212 -------------- ndb/src/common/util/Makefile.am | 2 +- ndb/src/common/util/Parser.cpp | 7 +- ndb/src/mgmapi/mgmapi.cpp | 14 +- ndb/src/mgmsrv/Services.cpp | 12 +- 10 files changed, 330 insertions(+), 241 deletions(-) rename ndb/include/util/Base64.hpp => include/base64.h (53%) create mode 100644 mysys/base64.c delete mode 100644 ndb/src/common/util/Base64.cpp diff --git a/ndb/include/util/Base64.hpp b/include/base64.h similarity index 53% rename from ndb/include/util/Base64.hpp rename to include/base64.h index f4b11ad9214..fcc2f8b40dc 100644 --- a/ndb/include/util/Base64.hpp +++ b/include/base64.h @@ -14,15 +14,38 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __BASE64_HPP_INCLUDED__ -#define __BASE64_HPP_INCLUDED__ +#ifndef __BASE64_H_INCLUDED__ +#define __BASE64_H_INCLUDED__ -#include -#include +#ifdef __cplusplus +extern "C" { +#endif -int base64_encode(const UtilBuffer &src, BaseString &dst); -int base64_encode(const void * s, size_t src_len, BaseString &dst); -int base64_decode(const BaseString &src, UtilBuffer &dst); -int base64_decode(const char * s, size_t len, UtilBuffer &dst); -#endif /* !__BASE64_HPP_INCLUDED__ */ +#include + +/* + Calculate how much memory needed for dst of base64_encode() +*/ +int base64_needed_encoded_length(int length_of_data); + +/* + Calculate how much memory needed for dst of base64_decode() +*/ +int base64_needed_decoded_length(int length_of_encoded_data); + +/* + Encode data as a base64 string +*/ +int base64_encode(const void *src, size_t src_len, char *dst); + +/* + Decode a base64 string into data +*/ +int base64_decode(const char *src, size_t src_len, void *dst); + + +#ifdef __cplusplus +} +#endif +#endif /* !__BASE64_H_INCLUDED__ */ diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 9c58c18cf59..ee0dcb544b6 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -55,7 +55,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ charset.c charset-def.c my_bitmap.c my_bit.c md5.c \ my_gethostbyname.c rijndael.c my_aes.c sha1.c \ my_handler.c my_netware.c my_largepage.c \ - my_windac.c my_access.c + my_windac.c my_access.c base64.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ thr_mutex.c thr_rwlock.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ @@ -116,5 +116,10 @@ test_gethwaddr$(EXEEXT): my_gethwaddr.c $(LIBRARIES) $(LINK) $(FLAGS) -DMAIN ./test_gethwaddr.c $(LDADD) $(LIBS) $(RM) -f ./test_gethwaddr.c +test_base64$(EXEEXT): base64.c $(LIBRARIES) + $(CP) $(srcdir)/base64.c ./test_base64.c + $(LINK) $(FLAGS) -DMAIN ./test_base64.c $(LDADD) $(LIBS) + $(RM) -f ./test_base64.c + # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/mysys/base64.c b/mysys/base64.c new file mode 100644 index 00000000000..d4ddf333c84 --- /dev/null +++ b/mysys/base64.c @@ -0,0 +1,265 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include // strchr() + +#ifndef MAIN + +static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + +int +base64_needed_encoded_length(int length_of_data) +{ + return ceil(length_of_data * 4 / 3) /* base64 chars */ + + ceil(length_of_data / (76 * 3 / 4)) /* Newlines */ + + 3 /* Padding */; +} + + +int +base64_needed_decoded_length(int length_of_encoded_data) +{ + return ceil(length_of_encoded_data * 3 / 4); +} + + +/* + Encode a data as base64. + + Note: We require that dst is pre-allocated to correct size. + See base64_needed_encoded_length(). +*/ + +int +base64_encode(const void *src, size_t src_len, char *dst) +{ + const unsigned char *s= (const unsigned char*)src; + size_t i= 0; + size_t len= 0; + + for (; i < src_len; len += 4) + { + if (len == 76) + { + len= 0; + *dst++= '\n'; + } + + unsigned c; + c= s[i++]; + c <<= 8; + + if (i < src_len) + c += s[i]; + c <<= 8; + i++; + + if (i < src_len) + c += s[i]; + i++; + + *dst++= base64_table[(c >> 18) & 0x3f]; + *dst++= base64_table[(c >> 12) & 0x3f]; + + if (i > (src_len + 1)) + *dst++= '='; + else + *dst++= base64_table[(c >> 6) & 0x3f]; + + if (i > src_len) + *dst++= '='; + else + *dst++= base64_table[(c >> 0) & 0x3f]; + } + + return 0; +} + + +static inline unsigned +pos(unsigned char c) +{ + return strchr(base64_table, c) - base64_table; +} + + +#define SKIP_SPACE(src, i, size) \ +{ \ + while (i < size && my_isspace(default_charset_info, * src)) \ + { \ + i++; \ + src++; \ + } \ + if (i == size) \ + { \ + i= size + 1; \ + break; \ + } \ +} + + +/* + Decode a base64 string + + Note: We require that dst is pre-allocated to correct size. + See base64_needed_decoded_length(). + + RETURN Number of bytes produced in dst or -1 in case of failure +*/ +int +base64_decode(const char *src, size_t size, void *dst) +{ + char b[3]; + size_t i= 0; + void *d= dst; + size_t j; + + while (i < size) + { + unsigned c= 0; + size_t mark= 0; + + SKIP_SPACE(src, i, size); + + c += pos(*src++); + c <<= 6; + i++; + + SKIP_SPACE(src, i, size); + + c += pos(*src++); + c <<= 6; + i++; + + SKIP_SPACE(src, i, size); + + if (* src != '=') + c += pos(*src++); + else + { + i= size; + mark= 2; + c <<= 6; + goto end; + } + c <<= 6; + i++; + + SKIP_SPACE(src, i, size); + + if (*src != '=') + c += pos(*src++); + else + { + i= size; + mark= 1; + goto end; + } + i++; + + end: + b[0]= (c >> 16) & 0xff; + b[1]= (c >> 8) & 0xff; + b[2]= (c >> 0) & 0xff; + + for (j=0; j<3-mark; j++) + *(char *)d++= b[j]; + } + + if (i != size) + { + return -1; + } + return d - dst; +} + + +#else /* MAIN */ + +#define require(b) { \ + if (!(b)) { \ + printf("Require failed at %s:%d\n", __FILE__, __LINE__); \ + abort(); \ + } \ +} + + +int +main(void) +{ + int i; + size_t j; + size_t k, l; + size_t dst_len; + + for (i= 0; i < 500; i++) + { + /* Create source data */ + const size_t src_len= rand() % 1000 + 1; + + char * src= (char *) malloc(src_len); + char * s= src; + + for (j= 0; j -#include - -static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -int -base64_encode(const UtilBuffer &src, BaseString &dst) -{ - return base64_encode(src.get_data(), src.length(), dst); -} - -int -base64_encode(const void * _s, size_t src_len, BaseString &dst) { - const unsigned char * s = (const unsigned char*)_s; - size_t i = 0; - size_t len = 0; - while(i < src_len) { - if(len == 76){ - len = 0; - dst.append('\n'); - } - - unsigned c; - c = s[i++]; - c <<= 8; - - if(i < src_len) - c += s[i]; - c <<= 8; - i++; - - if(i < src_len) - c += s[i]; - i++; - - dst.append(base64_table[(c >> 18) & 0x3f]); - dst.append(base64_table[(c >> 12) & 0x3f]); - - if(i > (src_len + 1)) - dst.append('='); - else - dst.append(base64_table[(c >> 6) & 0x3f]); - - if(i > src_len) - dst.append('='); - else - dst.append(base64_table[(c >> 0) & 0x3f]); - - len += 4; - } - return 0; -} - -static inline unsigned -pos(unsigned char c) { - return strchr(base64_table, c) - base64_table; -} - - -int -base64_decode(const BaseString &src, UtilBuffer &dst) { - return base64_decode(src.c_str(), src.length(), dst); -} - -#define SKIP_SPACE(src, i, size){ \ - while(i < size && isspace(* src)){ \ - i++; \ - src++; \ - } \ - if(i == size){ \ - i = size + 1; \ - break; \ - } \ -} - -int -base64_decode(const char * src, size_t size, UtilBuffer &dst) { - size_t i = 0; - while(i < size){ - unsigned c = 0; - int mark = 0; - - SKIP_SPACE(src, i, size); - - c += pos(*src++); - c <<= 6; - i++; - - SKIP_SPACE(src, i, size); - - c += pos(*src++); - c <<= 6; - i++; - - SKIP_SPACE(src, i, size); - - if(* src != '=') - c += pos(*src++); - else { - i = size; - mark = 2; - c <<= 6; - goto end; - } - c <<= 6; - i++; - - SKIP_SPACE(src, i, size); - - if(*src != '=') - c += pos(*src++); - else { - i = size; - mark = 1; - goto end; - } - i++; - - end: - char b[3]; - b[0] = (c >> 16) & 0xff; - b[1] = (c >> 8) & 0xff; - b[2] = (c >> 0) & 0xff; - - dst.append((void *)b, 3-mark); - } - - if(i != size){ - abort(); - return -1; - } - return 0; -} - -#ifdef __TEST__B64 -/** - * USER_FLAGS="-D__TEST__B64" make Base64.o && g++ Base64.o BaseString.o - */ -inline -void -require(bool b){ - if(!b) - abort(); -} - -int -main(void){ - for(int i = 0; i < 500; i++){ - const size_t len = rand() % 10000 + 1; - UtilBuffer src; - for(size_t j = 0; j%s<\n", str.c_str()); - } - - UtilBuffer dst; - require(base64_decode(str, dst) == 0); - require(dst.length() == src.length()); - - const char * c_src = (char*)src.get_data(); - const char * c_dst = (char*)dst.get_data(); - if(memcmp(src.get_data(), dst.get_data(), src.length()) != 0){ - printf("-- src --\n"); - for(int i2 = 0; i2 #include -#include #undef DEBUG #define DEBUG(x) ndbout << x << endl; @@ -316,11 +315,7 @@ ParserImpl::parseArg(Context * ctx, } case DummyRow::Properties: { - Properties *sp = new Properties(); - BaseString v(value); - UtilBuffer b; - base64_decode(v, b); - sp->unpack((const Uint32 *)b.get_data(), b.length()); + abort(); break; } default: diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index 8263e8cbc93..df27b1b358a 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -34,8 +34,8 @@ #include #include #include -#include +#include #define MGM_CMD(name, fun, desc) \ { name, \ @@ -1770,11 +1770,15 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { } while(start < len); if(buf64 == 0) break; - + + void *tmp_data = malloc(base64_needed_decoded_length((size_t) (len - 1))); + const int res = base64_decode(buf64, len-1, tmp_data); + delete[] buf64; UtilBuffer tmp; - const int res = base64_decode(buf64, len-1, tmp); - delete[] buf64; - if(res != 0){ + tmp.append((void *) tmp_data, res); + free(tmp_data); + if (res < 0) + { fprintf(handle->errstream, "Failed to decode buffer\n"); break; } diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index ed32ab9c963..9a4980eefdc 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -33,6 +32,8 @@ #include "Services.hpp" #include "../mgmapi/ndb_logevent.hpp" +#include + extern bool g_StopServer; static const unsigned int MAX_READ_TIMEOUT = 1000 ; @@ -598,17 +599,18 @@ MgmApiSession::getConfig_common(Parser_t::Context &, cfg->pack(src); NdbMutex_Unlock(m_mgmsrv.m_configMutex); - BaseString str; - int res = base64_encode(src, str); + char *tmp_str = (char *) malloc(base64_needed_encoded_length(src.length())); + int res = base64_encode(src.get_data(), src.length(), tmp_str); m_output->println("get config reply"); m_output->println("result: Ok"); - m_output->println("Content-Length: %d", str.length()); + m_output->println("Content-Length: %d", strlen(tmp_str)); m_output->println("Content-Type: ndbconfig/octet-stream"); m_output->println("Content-Transfer-Encoding: base64"); m_output->println(""); - m_output->println(str.c_str()); + m_output->println(tmp_str); + free(tmp_str); return; } From 588add26673f4135774f546772b616463f399ad6 Mon Sep 17 00:00:00 2001 From: "lars@mysql.com" <> Date: Tue, 18 Oct 2005 16:18:08 +0200 Subject: [PATCH 05/13] WL#2835: Base64 Fixes after Jonas review --- mysys/base64.c | 2 +- ndb/config/type_util.mk.am | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/mysys/base64.c b/mysys/base64.c index d4ddf333c84..7dcca6f14ac 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -102,7 +102,7 @@ pos(unsigned char c) #define SKIP_SPACE(src, i, size) \ { \ - while (i < size && my_isspace(default_charset_info, * src)) \ + while (i < size && my_isspace(&my_charset_latin1, * src)) \ { \ i++; \ src++; \ diff --git a/ndb/config/type_util.mk.am b/ndb/config/type_util.mk.am index 9e716d7cca6..4f2d605dc91 100644 --- a/ndb/config/type_util.mk.am +++ b/ndb/config/type_util.mk.am @@ -6,6 +6,3 @@ INCLUDES += -I$(srcdir) \ -I$(top_srcdir)/ndb/include/util \ -I$(top_srcdir)/ndb/include/portlib \ -I$(top_srcdir)/ndb/include/logger - -LDADD += \ - $(top_builddir)/mysys/libmysys.a From 4ccb1c6e36b91201c4fa3f8094bbc0038bbe04bb Mon Sep 17 00:00:00 2001 From: "lars@mysql.com" <> Date: Wed, 19 Oct 2005 19:31:24 +0200 Subject: [PATCH 06/13] mysqlbinlog --hexdump patch 4: Rename last_event_info to print_event_info to better reflect the new semantics --- client/mysqlbinlog.cc | 38 +++++----- sql/log_event.cc | 170 +++++++++++++++++++++--------------------- sql/log_event.h | 71 ++++++++++-------- 3 files changed, 142 insertions(+), 137 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 2b96914bfc9..9cbf211bb4d 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -490,13 +490,13 @@ static bool check_database(const char *log_dbname) -int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, +int process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, my_off_t pos) { char ll_buff[21]; Log_event_type ev_type= ev->get_type_code(); DBUG_ENTER("process_event"); - last_event_info->short_form= short_form; + print_event_info->short_form= short_form; /* Format events are not concerned by --offset and such, we always need to @@ -526,15 +526,15 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, fprintf(result_file, "# at %s\n",llstr(pos,ll_buff)); if (!opt_hexdump) - last_event_info->hexdump_from= 0; /* Disabled */ + print_event_info->hexdump_from= 0; /* Disabled */ else - last_event_info->hexdump_from= pos; + print_event_info->hexdump_from= pos; switch (ev_type) { case QUERY_EVENT: if (check_database(((Query_log_event*)ev)->db)) goto end; - ev->print(result_file, last_event_info); + ev->print(result_file, print_event_info); break; case CREATE_FILE_EVENT: { @@ -554,7 +554,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT' below. */ - ce->print(result_file, last_event_info, TRUE); + ce->print(result_file, print_event_info, TRUE); // If this binlog is not 3.23 ; why this test?? if (description_event->binlog_version >= 3) @@ -566,13 +566,13 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, break; } case APPEND_BLOCK_EVENT: - ev->print(result_file, last_event_info); + ev->print(result_file, print_event_info); if (load_processor.process((Append_block_log_event*) ev)) break; // Error break; case EXEC_LOAD_EVENT: { - ev->print(result_file, last_event_info); + ev->print(result_file, print_event_info); Execute_load_log_event *exv= (Execute_load_log_event*)ev; Create_file_log_event *ce= load_processor.grab_event(exv->file_id); /* @@ -582,7 +582,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, */ if (ce) { - ce->print(result_file, last_event_info, TRUE); + ce->print(result_file, print_event_info, TRUE); my_free((char*)ce->fname,MYF(MY_WME)); delete ce; } @@ -594,8 +594,8 @@ Create_file event for file_id: %u\n",exv->file_id); case FORMAT_DESCRIPTION_EVENT: delete description_event; description_event= (Format_description_log_event*) ev; - last_event_info->common_header_len= description_event->common_header_len; - ev->print(result_file, last_event_info); + print_event_info->common_header_len= description_event->common_header_len; + ev->print(result_file, print_event_info); /* We don't want this event to be deleted now, so let's hide it (I (Guilhem) should later see if this triggers a non-serious Valgrind @@ -605,7 +605,7 @@ Create_file event for file_id: %u\n",exv->file_id); ev= 0; break; case BEGIN_LOAD_QUERY_EVENT: - ev->print(result_file, last_event_info); + ev->print(result_file, print_event_info); load_processor.process((Begin_load_query_log_event*) ev); break; case EXECUTE_LOAD_QUERY_EVENT: @@ -622,7 +622,7 @@ Create_file event for file_id: %u\n",exv->file_id); if (fname) { - exlq->print(result_file, last_event_info, fname); + exlq->print(result_file, print_event_info, fname); my_free(fname, MYF(MY_WME)); } else @@ -631,7 +631,7 @@ Begin_load_query event for file_id: %u\n", exlq->file_id); break; } default: - ev->print(result_file, last_event_info); + ev->print(result_file, print_event_info); } } @@ -1014,7 +1014,7 @@ static int dump_remote_log_entries(const char* logname) { char buf[128]; - LAST_EVENT_INFO last_event_info; + PRINT_EVENT_INFO print_event_info; uint len, logname_len; NET* net; int error= 0; @@ -1136,7 +1136,7 @@ could be out of memory"); len= 1; // fake Rotate, so don't increment old_off } } - if ((error= process_event(&last_event_info,ev,old_off))) + if ((error= process_event(&print_event_info, ev, old_off))) { error= ((error < 0) ? 0 : 1); goto err; @@ -1155,7 +1155,7 @@ could be out of memory"); goto err; } - if ((error= process_event(&last_event_info,ev,old_off))) + if ((error= process_event(&print_event_info, ev, old_off))) { my_close(file,MYF(MY_WME)); error= ((error < 0) ? 0 : 1); @@ -1284,7 +1284,7 @@ static int dump_local_log_entries(const char* logname) { File fd = -1; IO_CACHE cache,*file= &cache; - LAST_EVENT_INFO last_event_info; + PRINT_EVENT_INFO print_event_info; byte tmp_buff[BIN_LOG_HEADER_SIZE]; int error= 0; @@ -1356,7 +1356,7 @@ static int dump_local_log_entries(const char* logname) // file->error == 0 means EOF, that's OK, we break in this case break; } - if ((error= process_event(&last_event_info,ev,old_off))) + if ((error= process_event(&print_event_info, ev, old_off))) { if (error < 0) error= 0; diff --git a/sql/log_event.cc b/sql/log_event.cc index 44a631f434a..389e70416fa 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -875,10 +875,10 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, Log_event::print_header() */ -void Log_event::print_header(FILE* file, LAST_EVENT_INFO* last_event_info) +void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) { char llbuff[22]; - my_off_t hexdump_from= last_event_info->hexdump_from; + my_off_t hexdump_from= print_event_info->hexdump_from; fputc('#', file); print_timestamp(file); @@ -886,7 +886,7 @@ void Log_event::print_header(FILE* file, LAST_EVENT_INFO* last_event_info) llstr(log_pos,llbuff)); /* mysqlbinlog --hexdump */ - if (last_event_info->hexdump_from) + if (print_event_info->hexdump_from) { fprintf(file, "\n"); uchar *ptr= (uchar*)temp_buf; @@ -899,7 +899,7 @@ void Log_event::print_header(FILE* file, LAST_EVENT_INFO* last_event_info) char *c, char_string[16+1]= {0}; /* Pretty-print event common header if header is exactly 19 bytes */ - if (last_event_info->common_header_len == 19) + if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN) { fprintf(file, "# Position Timestamp Type Master ID " "Size Master Pos Flags \n"); @@ -1428,24 +1428,24 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, #ifdef MYSQL_CLIENT void Query_log_event::print_query_header(FILE* file, - LAST_EVENT_INFO* last_event_info) + PRINT_EVENT_INFO* print_event_info) { // TODO: print the catalog ?? char buff[40],*end; // Enough for SET TIMESTAMP bool different_db= 1; uint32 tmp; - if (!last_event_info->short_form) + if (!print_event_info->short_form) { - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n", get_type_str(), (ulong) thread_id, (ulong) exec_time, error_code); } if (!(flags & LOG_EVENT_SUPPRESS_USE_F) && db) { - if (different_db= memcmp(last_event_info->db, db, db_len + 1)) - memcpy(last_event_info->db, db, db_len + 1); + if (different_db= memcmp(print_event_info->db, db, db_len + 1)) + memcpy(print_event_info->db, db, db_len + 1); if (db[0] && different_db) fprintf(file, "use %s;\n", db); } @@ -1465,12 +1465,12 @@ void Query_log_event::print_query_header(FILE* file, if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */ { /* tmp is a bitmask of bits which have changed. */ - if (likely(last_event_info->flags2_inited)) + if (likely(print_event_info->flags2_inited)) /* All bits which have changed */ - tmp= (last_event_info->flags2) ^ flags2; + tmp= (print_event_info->flags2) ^ flags2; else /* that's the first Query event we read */ { - last_event_info->flags2_inited= 1; + print_event_info->flags2_inited= 1; tmp= ~((uint32)0); /* all bits have changed */ } @@ -1485,7 +1485,7 @@ void Query_log_event::print_query_header(FILE* file, print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2, "@@session.unique_checks", &need_comma); fprintf(file,";\n"); - last_event_info->flags2= flags2; + print_event_info->flags2= flags2; } } @@ -1504,37 +1504,37 @@ void Query_log_event::print_query_header(FILE* file, if (likely(sql_mode_inited)) { - if (unlikely(!last_event_info->sql_mode_inited)) /* first Query event */ + if (unlikely(!print_event_info->sql_mode_inited)) /* first Query event */ { - last_event_info->sql_mode_inited= 1; + print_event_info->sql_mode_inited= 1; /* force a difference to force write */ - last_event_info->sql_mode= ~sql_mode; + print_event_info->sql_mode= ~sql_mode; } - if (unlikely(last_event_info->sql_mode != sql_mode)) + if (unlikely(print_event_info->sql_mode != sql_mode)) { fprintf(file,"SET @@session.sql_mode=%lu;\n",(ulong)sql_mode); - last_event_info->sql_mode= sql_mode; + print_event_info->sql_mode= sql_mode; } } - if (last_event_info->auto_increment_increment != auto_increment_increment || - last_event_info->auto_increment_offset != auto_increment_offset) + if (print_event_info->auto_increment_increment != auto_increment_increment || + print_event_info->auto_increment_offset != auto_increment_offset) { fprintf(file,"SET @@session.auto_increment_increment=%lu, @@session.auto_increment_offset=%lu;\n", auto_increment_increment,auto_increment_offset); - last_event_info->auto_increment_increment= auto_increment_increment; - last_event_info->auto_increment_offset= auto_increment_offset; + print_event_info->auto_increment_increment= auto_increment_increment; + print_event_info->auto_increment_offset= auto_increment_offset; } /* TODO: print the catalog when we feature SET CATALOG */ if (likely(charset_inited)) { - if (unlikely(!last_event_info->charset_inited)) /* first Query event */ + if (unlikely(!print_event_info->charset_inited)) /* first Query event */ { - last_event_info->charset_inited= 1; - last_event_info->charset[0]= ~charset[0]; // force a difference to force write + print_event_info->charset_inited= 1; + print_event_info->charset[0]= ~charset[0]; // force a difference to force write } - if (unlikely(bcmp(last_event_info->charset, charset, 6))) + if (unlikely(bcmp(print_event_info->charset, charset, 6))) { fprintf(file,"SET " "@@session.character_set_client=%d," @@ -1544,23 +1544,23 @@ void Query_log_event::print_query_header(FILE* file, uint2korr(charset), uint2korr(charset+2), uint2korr(charset+4)); - memcpy(last_event_info->charset, charset, 6); + memcpy(print_event_info->charset, charset, 6); } } if (time_zone_len) { - if (bcmp(last_event_info->time_zone_str, time_zone_str, time_zone_len+1)) + if (bcmp(print_event_info->time_zone_str, time_zone_str, time_zone_len+1)) { fprintf(file,"SET @@session.time_zone='%s';\n", time_zone_str); - memcpy(last_event_info->time_zone_str, time_zone_str, time_zone_len+1); + memcpy(print_event_info->time_zone_str, time_zone_str, time_zone_len+1); } } } -void Query_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - print_query_header(file, last_event_info); + print_query_header(file, print_event_info); my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME)); fputs(";\n", file); } @@ -1858,11 +1858,11 @@ void Start_log_event_v3::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Start_log_event_v3::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - if (!last_event_info->short_form) + if (!print_event_info->short_form) { - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version, server_version); print_timestamp(file); @@ -2586,19 +2586,19 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, */ #ifdef MYSQL_CLIENT -void Load_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Load_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - print(file, last_event_info, 0); + print(file, print_event_info, 0); } -void Load_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info, +void Load_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool commented) { DBUG_ENTER("Load_log_event::print"); - if (!last_event_info->short_form) + if (!print_event_info->short_form) { - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\tQuery\tthread_id=%ld\texec_time=%ld\n", thread_id, exec_time); } @@ -2612,9 +2612,9 @@ void Load_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info, But if commented, the "use" is going to be commented so we should not update the last_db. */ - if ((different_db= memcmp(last_event_info->db, db, db_len + 1)) && + if ((different_db= memcmp(print_event_info->db, db, db_len + 1)) && !commented) - memcpy(last_event_info->db, db, db_len + 1); + memcpy(print_event_info->db, db, db_len + 1); } if (db && db[0] && different_db) @@ -3003,13 +3003,13 @@ void Rotate_log_event::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Rotate_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Rotate_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { char buf[22]; - if (last_event_info->short_form) + if (print_event_info->short_form) return; - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\tRotate to "); if (new_log_ident) my_fwrite(file, (byte*) new_log_ident, (uint)ident_len, @@ -3205,15 +3205,15 @@ bool Intvar_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void Intvar_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { char llbuff[22]; const char *msg; LINT_INIT(msg); - if (!last_event_info->short_form) + if (!print_event_info->short_form) { - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\tIntvar\n"); } @@ -3294,12 +3294,12 @@ bool Rand_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Rand_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Rand_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { char llbuff[22],llbuff2[22]; - if (!last_event_info->short_form) + if (!print_event_info->short_form) { - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\tRand\n"); } fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n", @@ -3364,14 +3364,14 @@ bool Xid_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT -void Xid_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - if (!last_event_info->short_form) + if (!print_event_info->short_form) { char buf[64]; longlong10_to_str(xid, buf, 10); - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\tXid = %s\n", buf); fflush(file); } @@ -3562,11 +3562,11 @@ bool User_var_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void User_var_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - if (!last_event_info->short_form) + if (!print_event_info->short_form) { - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\tUser_var\n"); } @@ -3737,11 +3737,11 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) #ifdef HAVE_REPLICATION #ifdef MYSQL_CLIENT -void Unknown_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Unknown_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - if (last_event_info->short_form) + if (print_event_info->short_form) return; - print_header(file, last_event_info); + print_header(file, print_event_info); fputc('\n', file); fprintf(file, "# %s", "Unknown event\n"); } @@ -3808,12 +3808,12 @@ Slave_log_event::~Slave_log_event() #ifdef MYSQL_CLIENT -void Slave_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Slave_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { char llbuff[22]; - if (last_event_info->short_form) + if (print_event_info->short_form) return; - print_header(file, last_event_info); + print_header(file, print_event_info); fputc('\n', file); fprintf(file, "\ Slave: master_host: '%s' master_port: %d master_log: '%s' master_pos: %s\n", @@ -3893,12 +3893,12 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli) */ #ifdef MYSQL_CLIENT -void Stop_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - if (last_event_info->short_form) + if (print_event_info->short_form) return; - print_header(file, last_event_info); + print_header(file, print_event_info); fprintf(file, "\tStop\n"); fflush(file); } @@ -4072,19 +4072,19 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, */ #ifdef MYSQL_CLIENT -void Create_file_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info, +void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool enable_local) { - if (last_event_info->short_form) + if (print_event_info->short_form) { if (enable_local && check_fname_outside_temp_buf()) - Load_log_event::print(file, last_event_info); + Load_log_event::print(file, print_event_info); return; } if (enable_local) { - Load_log_event::print(file, last_event_info, + Load_log_event::print(file, print_event_info, !check_fname_outside_temp_buf()); /* That one is for "file_id: etc" below: in mysqlbinlog we want the #, in @@ -4097,9 +4097,9 @@ void Create_file_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info, } -void Create_file_log_event::print(FILE* file, LAST_EVENT_INFO* last_event_info) +void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - print(file, last_event_info, 0); + print(file, print_event_info, 0); } #endif /* MYSQL_CLIENT */ @@ -4260,11 +4260,11 @@ bool Append_block_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Append_block_log_event::print(FILE* file, - LAST_EVENT_INFO* last_event_info) + PRINT_EVENT_INFO* print_event_info) { - if (last_event_info->short_form) + if (print_event_info->short_form) return; - print_header(file, last_event_info); + print_header(file, print_event_info); fputc('\n', file); fprintf(file, "#%s: file_id: %d block_len: %d\n", get_type_str(), file_id, block_len); @@ -4404,11 +4404,11 @@ bool Delete_file_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Delete_file_log_event::print(FILE* file, - LAST_EVENT_INFO* last_event_info) + PRINT_EVENT_INFO* print_event_info) { - if (last_event_info->short_form) + if (print_event_info->short_form) return; - print_header(file, last_event_info); + print_header(file, print_event_info); fputc('\n', file); fprintf(file, "#Delete_file: file_id=%u\n", file_id); } @@ -4500,11 +4500,11 @@ bool Execute_load_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Execute_load_log_event::print(FILE* file, - LAST_EVENT_INFO* last_event_info) + PRINT_EVENT_INFO* print_event_info) { - if (last_event_info->short_form) + if (print_event_info->short_form) return; - print_header(file, last_event_info); + print_header(file, print_event_info); fputc('\n', file); fprintf(file, "#Exec_load: file_id=%d\n", file_id); @@ -4712,17 +4712,17 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) #ifdef MYSQL_CLIENT void Execute_load_query_log_event::print(FILE* file, - LAST_EVENT_INFO* last_event_info) + PRINT_EVENT_INFO* print_event_info) { - print(file, last_event_info, 0); + print(file, print_event_info, 0); } void Execute_load_query_log_event::print(FILE* file, - LAST_EVENT_INFO* last_event_info, + PRINT_EVENT_INFO* print_event_info, const char *local_fname) { - print_query_header(file, last_event_info); + print_query_header(file, print_event_info); if (local_fname) { @@ -4743,7 +4743,7 @@ void Execute_load_query_log_event::print(FILE* file, fprintf(file, ";\n"); } - if (!last_event_info->short_form) + if (!print_event_info->short_form) fprintf(file, "# file_id: %d \n", file_id); } #endif diff --git a/sql/log_event.h b/sql/log_event.h index 80dd40f0dd5..db212c8b4b1 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -453,16 +453,21 @@ struct st_relay_log_info; /* A structure for mysqlbinlog to know how to print events - This structure is passed to the event's print() methods so that only - the necessary USE and SET commands are printed. Last db, flags2, - sql_mode etc are stored here. + This structure is passed to the event's print() methods, - The structure also contain other information on how to print the - events, e.g. short_form, hexdump_from. + There are two types of settings stored here: + 1. Last db, flags2, sql_mode etc comes from the last printed event. + They are stored so that only the necessary USE and SET commands + are printed. + 2. Other information on how to print the events, e.g. short_form, + hexdump_from. These are not dependent on the last event. */ -typedef struct st_last_event_info +typedef struct st_print_event_info { - /* Old settings for database, sql_mode etc */ + /* + Settings for database, sql_mode etc that comes from the last event + that was printed. + */ // TODO: have the last catalog here ?? char db[FN_REFLEN+1]; // TODO: make this a LEX_STRING when thd->db is bool flags2_inited; @@ -473,12 +478,12 @@ typedef struct st_last_event_info bool charset_inited; char charset[6]; // 3 variables, each of them storable in 2 bytes char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH]; - st_last_event_info() + st_print_event_info() :flags2_inited(0), sql_mode_inited(0), auto_increment_increment(1),auto_increment_offset(1), charset_inited(0) { /* - Currently we only use static LAST_EVENT_INFO objects, so zeroed at + Currently we only use static PRINT_EVENT_INFO objects, so zeroed at program's startup, but these explicit bzero() is for the day someone creates dynamic instances. */ @@ -492,7 +497,7 @@ typedef struct st_last_event_info my_off_t hexdump_from; uint8 common_header_len; -} LAST_EVENT_INFO; +} PRINT_EVENT_INFO; #endif @@ -601,9 +606,9 @@ public: static Log_event* read_log_event(IO_CACHE* file, const Format_description_log_event *description_event); /* print*() functions are used by mysqlbinlog */ - virtual void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0) = 0; + virtual void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0) = 0; void print_timestamp(FILE* file, time_t *ts = 0); - void print_header(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print_header(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif static void *operator new(size_t size) @@ -763,8 +768,8 @@ public: uint32 q_len_arg); #endif /* HAVE_REPLICATION */ #else - void print_query_header(FILE* file, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print_query_header(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Query_log_event(const char* buf, uint event_len, @@ -818,7 +823,7 @@ public: void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Slave_log_event(const char* buf, uint event_len); @@ -906,8 +911,8 @@ public: bool use_rli_only_for_errors); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info = 0); - void print(FILE* file, LAST_EVENT_INFO* last_event_info, bool commented); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info = 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool commented); #endif /* @@ -996,7 +1001,7 @@ public: #endif /* HAVE_REPLICATION */ #else Start_log_event_v3() {} - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Start_log_event_v3(const char* buf, @@ -1091,7 +1096,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Intvar_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1132,7 +1137,7 @@ class Rand_log_event: public Log_event int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Rand_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1169,7 +1174,7 @@ class Xid_log_event: public Log_event int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Xid_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1211,7 +1216,7 @@ public: void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif User_var_log_event(const char* buf, const Format_description_log_event* description_event); @@ -1237,7 +1242,7 @@ public: {} int exec_event(struct st_relay_log_info* rli); #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Stop_log_event(const char* buf, const Format_description_log_event* description_event): @@ -1276,7 +1281,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Rotate_log_event(const char* buf, uint event_len, @@ -1329,8 +1334,8 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, LAST_EVENT_INFO* last_event_info, bool enable_local); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool enable_local); #endif Create_file_log_event(const char* buf, uint event_len, @@ -1397,7 +1402,7 @@ public: virtual int get_create_or_append() const; #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Append_block_log_event(const char* buf, uint event_len, @@ -1432,8 +1437,8 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); - void print(FILE* file, LAST_EVENT_INFO* last_event_info, bool enable_local); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool enable_local); #endif Delete_file_log_event(const char* buf, uint event_len, @@ -1468,7 +1473,7 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); #endif Execute_load_log_event(const char* buf, uint event_len, @@ -1553,9 +1558,9 @@ public: int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); /* Prints the query as LOAD DATA LOCAL and with rewritten filename */ - void print(FILE* file, LAST_EVENT_INFO* last_event_info, + void print(FILE* file, PRINT_EVENT_INFO* print_event_info, const char *local_fname); #endif Execute_load_query_log_event(const char* buf, uint event_len, @@ -1585,7 +1590,7 @@ public: Log_event(buf, description_event) {} ~Unknown_log_event() {} - void print(FILE* file, LAST_EVENT_INFO* last_event_info= 0); + void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0); Log_event_type get_type_code() { return UNKNOWN_EVENT;} bool is_valid() const { return 1; } }; From bb1542523599b7fd9ac996f57ff7807a06a4cbe3 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.mysql.com" <> Date: Mon, 24 Oct 2005 15:05:06 +0200 Subject: [PATCH 07/13] Fix for dropping a table with frm file consisting of "junk" --- mysql-test/r/show_check.result | 14 +++++++------- sql/sql_table.cc | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 20f695d9ac0..fdb0db602ff 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -512,6 +512,13 @@ t1 CREATE TABLE `t1` ( KEY `c2` USING BTREE (`c2`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; +flush tables; +SHOW TABLE STATUS like 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 NULL NULL NULL NULL # # # # NULL NULL NULL NULL NULL NULL NULL NULL Incorrect information in file: './test/t1.frm' +show create table t1; +ERROR HY000: Incorrect information in file: './test/t1.frm' +drop table t1; CREATE TABLE txt1(a int); CREATE TABLE tyt2(a int); CREATE TABLE urkunde(a int); @@ -557,10 +564,3 @@ DROP TABLE tyt2; DROP TABLE urkunde; SHOW TABLES FROM non_existing_database; ERROR 42000: Unknown database 'non_existing_database' -flush tables; -SHOW TABLE STATUS like 't1'; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 NULL NULL NULL NULL # # # # NULL NULL NULL NULL NULL NULL NULL NULL Incorrect information in file: './test/t1.frm' -show create table t1; -ERROR HY000: Incorrect information in file: './test/t1.frm' -drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8f6f1e25264..1e96891113b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -273,7 +273,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, *(end=fn_ext(path))=0; // Remove extension for delete error= ha_delete_table(thd, table_type, path, table->table_name, !dont_log_query); - if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists) + if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && + (if_exists || table_type == DB_TYPE_UNKNOWN)) error= 0; if (error == HA_ERR_ROW_IS_REFERENCED) { From 4ce406844216231c0d9ddfcb67d700385c48643c Mon Sep 17 00:00:00 2001 From: "lars@mysql.com" <> Date: Mon, 24 Oct 2005 19:06:32 +0200 Subject: [PATCH 08/13] Reducing risk for incorrect merges. Since we are multiple teams working on different features, adding numbering to enums reduce the risk that code will be merged incorrectly. This particular enum must have fixed values to ensure that an upgraded server always can read old logs. I added this, since I noticed the incorrect order in the RBR clone. --- sql/log_event.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sql/log_event.h b/sql/log_event.h index b0f76aa1034..a9b20adaa58 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -403,20 +403,21 @@ enum Log_event_type Every time you update this enum (when you add a type), you have to fix Format_description_log_event::Format_description_log_event(). */ - UNKNOWN_EVENT= 0, START_EVENT_V3, QUERY_EVENT, STOP_EVENT, ROTATE_EVENT, - INTVAR_EVENT, LOAD_EVENT, SLAVE_EVENT, CREATE_FILE_EVENT, - APPEND_BLOCK_EVENT, EXEC_LOAD_EVENT, DELETE_FILE_EVENT, + UNKNOWN_EVENT= 0, START_EVENT_V3= 1, QUERY_EVENT= 2, STOP_EVENT= 3, + ROTATE_EVENT= 4, INTVAR_EVENT= 5, LOAD_EVENT= 6, SLAVE_EVENT= 7, + CREATE_FILE_EVENT= 8, APPEND_BLOCK_EVENT= 9, EXEC_LOAD_EVENT= 10, + DELETE_FILE_EVENT= 11, /* NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer sql_ex, allowing multibyte TERMINATED BY etc; both types share the same class (Load_log_event) */ - NEW_LOAD_EVENT, - RAND_EVENT, USER_VAR_EVENT, - FORMAT_DESCRIPTION_EVENT, - XID_EVENT, - BEGIN_LOAD_QUERY_EVENT, - EXECUTE_LOAD_QUERY_EVENT, + NEW_LOAD_EVENT= 12, + RAND_EVENT, USER_VAR_EVENT= 13, + FORMAT_DESCRIPTION_EVENT= 14, + XID_EVENT= 15, + BEGIN_LOAD_QUERY_EVENT= 16, + EXECUTE_LOAD_QUERY_EVENT= 17, /* add new events here - right above this comment! From 9a101971cf9ceb485c35f9d3dcf4d62450f7ae50 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Tue, 25 Oct 2005 00:27:15 +0400 Subject: [PATCH 09/13] BUG#11704: Make InnoDB not to convert TL_WRITE_ONLY locks to TL_WRITE_ALLOW_WRITE in OPTIMIZE TABLE. --- sql/ha_innodb.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index a7957ee3cbf..c9aa08f3992 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -6811,6 +6811,7 @@ ha_innobase::store_lock( || thd->lex->sql_command == SQLCOM_CALL) && !thd->tablespace_op && thd->lex->sql_command != SQLCOM_TRUNCATE + && thd->lex->sql_command != SQLCOM_OPTIMIZE && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { lock_type = TL_WRITE_ALLOW_WRITE; From 89b2b92b4e8444714fedaea570fdc3433454f124 Mon Sep 17 00:00:00 2001 From: "patg@krsna.patg.net" <> Date: Mon, 24 Oct 2005 13:51:05 -0700 Subject: [PATCH 10/13] Disabled federated test, added then removed federated.disabled and instead using disabled.def (per comments in this commit) disabled.def: disabled federated until bug 14272 is fixed. .del-federated.disabled~9e4cca59f547174d: Delete: mysql-test/t/federated.disabled federated.disabled: New BitKeeper file ``t/federated.disabled'' to disable federated test until Bug 14272 is fixed. new file --- mysql-test/t/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index fe95a543fb5..bc81f716ec7 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -15,3 +15,4 @@ rpl_relayrotate : Unstable test case, bug#12429 rpl_until : Unstable test case, bug#12429 rpl_deadlock : Unstable test case, bug#12429 kill : Unstable test case, bug#9712 +federated : Broken test case, bug#14272 From 6105040ac46a33970119f863ce3bdf97704312d3 Mon Sep 17 00:00:00 2001 From: "anozdrin@mysql.com" <> Date: Tue, 25 Oct 2005 00:54:04 +0400 Subject: [PATCH 11/13] Fix for BUG#13095: Cannot create VIEWs in prepared statements - allow CREATE VIEW as well as DROP VIEW to use in prepared statements; - fix CREATE VIEW implementation to make it work in prepared statements. --- mysql-test/r/sp.result | 43 ++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 56 ++++++++++++++++++++++++++++++++++++++++++ sql/sql_lex.h | 1 + sql/sql_prepare.cc | 2 ++ sql/sql_view.cc | 3 ++- sql/sql_yacc.yy | 2 ++ 6 files changed, 106 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 7fdbeff9a86..f91aadc02b6 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3532,4 +3532,47 @@ select @a| Local drop function bug13941| drop procedure bug13941| +DROP PROCEDURE IF EXISTS bug13095; +DROP TABLE IF EXISTS bug13095_t1; +DROP VIEW IF EXISTS bug13095_v1; +CREATE PROCEDURE bug13095(tbl_name varchar(32)) +BEGIN +SET @str = +CONCAT("CREATE TABLE ", tbl_name, "(stuff char(15))"); +SELECT @str; +PREPARE stmt FROM @str; +EXECUTE stmt; +SET @str = +CONCAT("INSERT INTO ", tbl_name, " VALUES('row1'),('row2'),('row3')" ); +SELECT @str; +PREPARE stmt FROM @str; +EXECUTE stmt; +SET @str = +CONCAT("CREATE VIEW bug13095_v1(c1) AS SELECT stuff FROM ", tbl_name); +SELECT @str; +PREPARE stmt FROM @str; +EXECUTE stmt; +SELECT * FROM bug13095_v1; +SET @str = +"DROP VIEW bug13095_v1"; +SELECT @str; +PREPARE stmt FROM @str; +EXECUTE stmt; +END| +CALL bug13095('bug13095_t1'); +@str +CREATE TABLE bug13095_t1(stuff char(15)) +@str +INSERT INTO bug13095_t1 VALUES('row1'),('row2'),('row3') +@str +CREATE VIEW bug13095_v1(c1) AS SELECT stuff FROM bug13095_t1 +c1 +row1 +row2 +row3 +@str +DROP VIEW bug13095_v1 +DROP PROCEDURE IF EXISTS bug13095; +DROP VIEW IF EXISTS bug13095_v1; +DROP TABLE IF EXISTS bug13095_t1; drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 18607c7f13c..ab57139bb77 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4433,6 +4433,62 @@ drop function bug13941| drop procedure bug13941| +# +# BUG#13095: Cannot create VIEWs in prepared statements +# + +delimiter ;| + +--disable_warnings +DROP PROCEDURE IF EXISTS bug13095; +DROP TABLE IF EXISTS bug13095_t1; +DROP VIEW IF EXISTS bug13095_v1; +--enable_warnings + +delimiter |; + +CREATE PROCEDURE bug13095(tbl_name varchar(32)) +BEGIN + SET @str = + CONCAT("CREATE TABLE ", tbl_name, "(stuff char(15))"); + SELECT @str; + PREPARE stmt FROM @str; + EXECUTE stmt; + + SET @str = + CONCAT("INSERT INTO ", tbl_name, " VALUES('row1'),('row2'),('row3')" ); + SELECT @str; + PREPARE stmt FROM @str; + EXECUTE stmt; + + SET @str = + CONCAT("CREATE VIEW bug13095_v1(c1) AS SELECT stuff FROM ", tbl_name); + SELECT @str; + PREPARE stmt FROM @str; + EXECUTE stmt; + + SELECT * FROM bug13095_v1; + + SET @str = + "DROP VIEW bug13095_v1"; + SELECT @str; + PREPARE stmt FROM @str; + EXECUTE stmt; +END| + +delimiter ;| + +CALL bug13095('bug13095_t1'); + +--disable_warnings +DROP PROCEDURE IF EXISTS bug13095; +DROP VIEW IF EXISTS bug13095_v1; +DROP TABLE IF EXISTS bug13095_t1; +--enable_warnings + +delimiter |; + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 1e935c6dc2a..1bf346eafb1 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -738,6 +738,7 @@ typedef struct st_lex /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; st_lex_user *create_view_definer; + char *create_view_start; char *create_view_select_start; List col_list; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 5f3539ca1e9..865c597e00d 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1742,6 +1742,8 @@ static bool check_prepared_statement(Prepared_statement *stmt, case SQLCOM_ROLLBACK: case SQLCOM_TRUNCATE: case SQLCOM_CALL: + case SQLCOM_CREATE_VIEW: + case SQLCOM_DROP_VIEW: break; default: diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 5db08275735..858f0c2520e 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -643,7 +643,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, view->query.length= str.length()-1; // we do not need last \0 view->source.str= thd->lex->create_view_select_start; view->source.length= (thd->query_length - - (thd->lex->create_view_select_start - thd->query)); + (thd->lex->create_view_select_start - + thd->lex->create_view_start)); view->file_version= 1; view->calc_md5(md5); view->md5.str= md5; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 94ce04fb5b1..670385dee93 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1263,6 +1263,7 @@ create: THD *thd= YYTHD; LEX *lex= thd->lex; lex->sql_command= SQLCOM_CREATE_VIEW; + lex->create_view_start= thd->query; /* first table in list is target VIEW name */ if (!lex->select_lex.add_table_to_list(thd, $7, NULL, 0)) YYABORT; @@ -3425,6 +3426,7 @@ alter: THD *thd= YYTHD; LEX *lex= thd->lex; lex->sql_command= SQLCOM_CREATE_VIEW; + lex->create_view_start= thd->query; lex->create_view_mode= VIEW_ALTER; /* first table in list is target VIEW name */ lex->select_lex.add_table_to_list(thd, $6, NULL, 0); From 8124629c51974254e53f2f2de34d8e20e2468a42 Mon Sep 17 00:00:00 2001 From: "lars@mysql.com" <> Date: Mon, 24 Oct 2005 23:09:14 +0200 Subject: [PATCH 12/13] Fixed enum numbering, patch 2 --- sql/log_event.h | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/sql/log_event.h b/sql/log_event.h index a9b20adaa58..2fe0882d6a5 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -403,9 +403,17 @@ enum Log_event_type Every time you update this enum (when you add a type), you have to fix Format_description_log_event::Format_description_log_event(). */ - UNKNOWN_EVENT= 0, START_EVENT_V3= 1, QUERY_EVENT= 2, STOP_EVENT= 3, - ROTATE_EVENT= 4, INTVAR_EVENT= 5, LOAD_EVENT= 6, SLAVE_EVENT= 7, - CREATE_FILE_EVENT= 8, APPEND_BLOCK_EVENT= 9, EXEC_LOAD_EVENT= 10, + UNKNOWN_EVENT= 0, + START_EVENT_V3= 1, + QUERY_EVENT= 2, + STOP_EVENT= 3, + ROTATE_EVENT= 4, + INTVAR_EVENT= 5, + LOAD_EVENT= 6, + SLAVE_EVENT= 7, + CREATE_FILE_EVENT= 8, + APPEND_BLOCK_EVENT= 9, + EXEC_LOAD_EVENT= 10, DELETE_FILE_EVENT= 11, /* NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer @@ -413,18 +421,20 @@ enum Log_event_type same class (Load_log_event) */ NEW_LOAD_EVENT= 12, - RAND_EVENT, USER_VAR_EVENT= 13, - FORMAT_DESCRIPTION_EVENT= 14, - XID_EVENT= 15, - BEGIN_LOAD_QUERY_EVENT= 16, - EXECUTE_LOAD_QUERY_EVENT= 17, + RAND_EVENT= 13, + USER_VAR_EVENT= 14, + FORMAT_DESCRIPTION_EVENT= 15, + XID_EVENT= 16, + BEGIN_LOAD_QUERY_EVENT= 17, + EXECUTE_LOAD_QUERY_EVENT= 18, /* - add new events here - right above this comment! - existing events should never change their numbers + Add new events here - right above this comment! + And change the ENUM_END_EVENT_MARKER below. + Existing events should never change their numbers */ - ENUM_END_EVENT /* end marker */ + ENUM_END_EVENT= 19 /* end marker */ }; /* From f5354eba90b731bb227d0bda0dfe491eee9e3ad7 Mon Sep 17 00:00:00 2001 From: "timour@mysql.com" <> Date: Tue, 25 Oct 2005 09:00:57 +0300 Subject: [PATCH 13/13] Fix for BUG#13832 - Unknown column t1.a in 'on clause'. The cause for the bug is that the priorities of all rules/terminals that process the FROM clause are not fully specified, and the parser generator produces a parser that doesn't always parse the FROM clause so that JOINs are left-associative. As a result the final join tree produced by the parser is incorrect, which is the cause for subsequent name resolution to fail. --- mysql-test/r/select.result | 12 ++++++++++++ mysql-test/t/select.test | 14 ++++++++++++++ sql/sql_yacc.yy | 32 +++++++++++++++++++++++--------- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index abf607dd438..57788800f60 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3124,3 +3124,15 @@ from t1 inner join (t2 right join t3 on t2.id = t3.b_id) on t1.id = t3.a_id; count(*) 6 drop table t1,t2,t3; +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +select * from t1 join t2 join t3 on (t1.a=t3.c); +a b c +select * from t1 join t2 left join t3 on (t1.a=t3.c); +a b c +select * from t1 join t2 right join t3 on (t1.a=t3.c); +a b c +select * from t1 join t2 straight_join t3 on (t1.a=t3.c); +a b c +drop table t1, t2 ,t3; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 6fc149e2e1f..3044aa466a2 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2649,3 +2649,17 @@ select count(*) from t1 inner join (t2 right join t3 on t2.id = t3.b_id) on t1.id = t3.a_id; drop table t1,t2,t3; + +# +# Bug #13832 Incorrect parse order of join productions due to unspecified +# operator priorities results in incorrect join tree. +# + +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +select * from t1 join t2 join t3 on (t1.a=t3.c); +select * from t1 join t2 left join t3 on (t1.a=t3.c); +select * from t1 join t2 right join t3 on (t1.a=t3.c); +select * from t1 join t2 straight_join t3 on (t1.a=t3.c); +drop table t1, t2 ,t3; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 14f617b9f8b..f44120ae1a8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -660,7 +660,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token YEAR_SYM %token ZEROFILL -%left JOIN_SYM +%left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT /* A dummy token to force the priority of table_ref production in a join. */ %left TABLE_REF_PRIORITY %left SET_VAR @@ -5225,14 +5225,22 @@ derived_table_list: } ; +/* + Notice that JOIN is a left-associative operation, and it must be parsed + as such, that is, the parser must process first the left join operand + then the right one. Such order of processing ensures that the parser + produces correct join trees which is essential for semantic analysis + and subsequent optimization phases. +*/ join_table: +/* INNER JOIN variants */ /* - Evaluate production 'table_ref' before 'normal_join' so that - [INNER | CROSS] JOIN is properly nested as other left-associative - joins. + Use %prec to evaluate production 'table_ref' before 'normal_join' + so that [INNER | CROSS] JOIN is properly nested as other + left-associative joins. */ table_ref %prec TABLE_REF_PRIORITY normal_join table_ref - { YYERROR_UNLESS($1 && ($$=$3)); } + { YYERROR_UNLESS($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref @@ -5274,6 +5282,13 @@ join_table: } '(' using_list ')' { add_join_natural($1,$3,$7); $$=$3; } + | table_ref NATURAL JOIN_SYM table_factor + { + YYERROR_UNLESS($1 && ($$=$4)); + add_join_natural($1,$4,NULL); + } + +/* LEFT JOIN variants */ | table_ref LEFT opt_outer JOIN_SYM table_ref ON { @@ -5305,6 +5320,8 @@ join_table: $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; } + +/* RIGHT JOIN variants */ | table_ref RIGHT opt_outer JOIN_SYM table_ref ON { @@ -5342,10 +5359,7 @@ join_table: LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) YYABORT; - } - | table_ref NATURAL JOIN_SYM table_factor - { YYERROR_UNLESS($1 && ($$=$4)); add_join_natural($1,$4,NULL); }; - + }; normal_join: JOIN_SYM {}