diff options
-rw-r--r-- | client/mysqlbinlog.cc | 733 | ||||
-rw-r--r-- | include/mysqld_error.h | 76 | ||||
-rw-r--r-- | mysql-test/r/drop_temp_table.result | 8 | ||||
-rw-r--r-- | mysql-test/r/insert.result | 1 | ||||
-rw-r--r-- | mysql-test/r/mysqlbinlog.result | 38 | ||||
-rw-r--r-- | mysql-test/r/query_cache.result | 4 | ||||
-rw-r--r-- | mysql-test/r/rpl_error_ignored_table.result | 24 | ||||
-rw-r--r-- | mysql-test/r/rpl_relayrotate.result | 6 | ||||
-rw-r--r-- | mysql-test/r/rpl_trunc_binlog.result | 2 | ||||
-rw-r--r-- | mysql-test/r/sp-error.result | 4 | ||||
-rw-r--r-- | mysql-test/r/sp.result | 2 | ||||
-rw-r--r-- | mysql-test/r/system_mysql_db.result | 1 | ||||
-rw-r--r-- | mysql-test/r/variables.result | 2 | ||||
-rw-r--r-- | mysql-test/t/rpl_error_ignored_table.test | 2 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 98 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 8 | ||||
-rw-r--r-- | sql/log_event.cc | 374 | ||||
-rw-r--r-- | sql/set_var.cc | 366 | ||||
-rw-r--r-- | sql/share/danish/errmsg.txt | 29 | ||||
-rw-r--r-- | sql/share/dutch/errmsg.txt | 29 | ||||
-rw-r--r-- | sql/share/english/errmsg.txt | 34 | ||||
-rw-r--r-- | sql/share/estonian/errmsg.txt | 29 | ||||
-rw-r--r-- | sql/sp.cc | 2 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/sql_table.cc | 1 |
25 files changed, 1041 insertions, 834 deletions
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 746899604fa..818b402d014 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2003 MySQL AB +/* Copyright (C) 2001-2004 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 @@ -49,9 +49,9 @@ ulong server_id = 0; // needed by net_serv.c ulong bytes_sent = 0L, bytes_received = 0L; ulong mysqld_net_retry_count = 10L; +ulong open_files_limit; uint test_flags = 0; static uint opt_protocol= 0; - static FILE *result_file; #ifndef DBUG_OFF @@ -75,42 +75,70 @@ static short binlog_flags = 0; static MYSQL* mysql = NULL; static const char* dirname_for_local_load= 0; -static void dump_local_log_entries(const char* logname); -static void dump_remote_log_entries(const char* logname); -static void dump_log_entries(const char* logname); -static void dump_remote_file(NET* net, const char* fname); +/* + check_header() will set the pointer below. + Why do we need here a pointer on an event instead of an event ? + This is because the event will be created (alloced) in read_log_event() + (which returns a pointer) in check_header(). +*/ +Format_description_log_event* description_event; + +static int dump_local_log_entries(const char* logname); +static int dump_remote_log_entries(const char* logname); +static int dump_log_entries(const char* logname); +static int dump_remote_file(NET* net, const char* fname); static void die(const char* fmt, ...); static MYSQL* safe_connect(); + class Load_log_processor { - char target_dir_name[MY_NFILE]; + char target_dir_name[FN_REFLEN]; int target_dir_name_len; DYNAMIC_ARRAY file_names; - const char *create_file(Create_file_log_event *ce); - void append_to_file(const char* fname, int flags, - gptr data, uint size) + /* + Looking for new uniquie filename that doesn't exist yet by + adding postfix -%x + + SYNOPSIS + create_unique_file() + + filename buffer for filename + file_name_end tail of buffer that should be changed + should point to a memory enough to printf("-%x",..) + + RETURN VALUES + values less than 0 - can't find new filename + values great or equal 0 - created file with found filename + */ + File create_unique_file(char *filename, char *file_name_end) { - File file; - if (((file= my_open(fname,flags,MYF(MY_WME))) < 0) || - my_write(file,(byte*) data,size,MYF(MY_WME|MY_NABP)) || - my_close(file,MYF(MY_WME))) - exit(1); + File res; + /* If we have to try more than 1000 times, something is seriously wrong */ + for (uint version= 0; version<1000; version++) + { + sprintf(file_name_end,"-%x",version); + if ((res= my_create(filename,0, + O_CREAT|O_EXCL|O_BINARY|O_WRONLY,MYF(0)))!=-1) + return res; + } + return -1; } public: - Load_log_processor() - { - init_dynamic_array(&file_names,sizeof(Create_file_log_event*), - 100,100 CALLER_INFO); - } - + Load_log_processor() {} ~Load_log_processor() - { - destroy(); - delete_dynamic(&file_names); - } + { + destroy(); + delete_dynamic(&file_names); + } + + int init() + { + return init_dynamic_array(&file_names,sizeof(Create_file_log_event*), + 100,100 CALLER_INFO); + } void init_by_dir_name(const char *dir) { @@ -147,82 +175,274 @@ public: *ptr= 0; return res; } - void process(Create_file_log_event *ce) - { - const char *fname= create_file(ce); - append_to_file(fname,O_CREAT|O_EXCL|O_BINARY|O_WRONLY,ce->block, - ce->block_len); - } - void process(Append_block_log_event *ae) + int process(Create_file_log_event *ce); + int process(Append_block_log_event *ae); + File prepare_new_file_for_old_format(Load_log_event *le, char *filename); + int load_old_format_file(NET* net, const char *server_fname, + uint server_fname_len, File file); +}; + + + +File Load_log_processor::prepare_new_file_for_old_format(Load_log_event *le, + char *filename) +{ + uint len; + char *tail; + File file; + + fn_format(filename, le->fname, target_dir_name, "", 1); + len= strlen(filename); + tail= filename + len; + + if ((file= create_unique_file(filename,tail)) < 0) + { + sql_print_error("Could not construct local filename %s",filename); + return -1; + } + + le->set_fname_outside_temp_buf(filename,len+strlen(tail)); + + return file; +} + + +int Load_log_processor::load_old_format_file(NET* net, const char*server_fname, + uint server_fname_len, File file) +{ + char buf[FN_REFLEN+1]; + buf[0] = 0; + memcpy(buf + 1, server_fname, server_fname_len + 1); + if (my_net_write(net, buf, server_fname_len +2) || net_flush(net)) + { + sql_print_error("Failed requesting the remote dump of %s", server_fname); + return -1; + } + + for (;;) + { + uint packet_len = my_net_read(net); + if (packet_len == 0) { - Create_file_log_event* ce= (ae->file_id < file_names.elements) ? - *((Create_file_log_event**)file_names.buffer + ae->file_id) : 0; - - if (ce) - append_to_file(ce->fname,O_APPEND|O_BINARY|O_WRONLY, ae->block, - ae->block_len); - else + if (my_net_write(net, "", 0) || net_flush(net)) { - /* - There is no Create_file event (a bad binlog or a big - --position). Assuming it's a big --position, we just do nothing and - print a warning. - */ - fprintf(stderr,"Warning: ignoring Append_block as there is no \ -Create_file event for file_id: %u\n",ae->file_id); + sql_print_error("Failed sending the ack packet"); + return -1; } + /* + we just need to send something, as the server will read but + not examine the packet - this is because mysql_load() sends + an OK when it is done + */ + break; } -}; + else if (packet_len == packet_error) + { + sql_print_error("Failed reading a packet during the dump of %s ", + server_fname); + return -1; + } + + if (my_write(file, (byte*) net->read_pos, packet_len,MYF(MY_WME|MY_NABP))) + return -1; + } + + return 0; +} -const char *Load_log_processor::create_file(Create_file_log_event *ce) +int Load_log_processor::process(Create_file_log_event *ce) { const char *bname= ce->fname+dirname_length(ce->fname); uint blen= ce->fname_len - (bname-ce->fname); uint full_len= target_dir_name_len + blen + 9 + 9 + 1; - uint version= 0; - char *tmp, *ptr; + int error= 0; + char *fname, *ptr; + File file; + DBUG_ENTER("Load_log_processor::process"); - if (!(tmp= my_malloc(full_len,MYF(MY_WME))) || - set_dynamic(&file_names,(gptr)&ce,ce->file_id)) + if (set_dynamic(&file_names,(gptr)&ce,ce->file_id)) { - die("Could not construct local filename %s%s",target_dir_name,bname); - return 0; + sql_print_error("Could not construct local filename %s%s", + target_dir_name,bname); + DBUG_RETURN(-1); } + if (!(fname= my_malloc(full_len,MYF(MY_WME)))) + DBUG_RETURN(-1); - memcpy(tmp, target_dir_name, target_dir_name_len); - ptr= tmp+ target_dir_name_len; + memcpy(fname, target_dir_name, target_dir_name_len); + ptr= fname + target_dir_name_len; memcpy(ptr,bname,blen); ptr+= blen; ptr+= my_sprintf(ptr,(ptr,"-%x",ce->file_id)); - /* - Note that this code has a possible race condition if there was was - many simultaneous clients running which tried to create files at the same - time. Fortunately this should never be the case. + if ((file= create_unique_file(fname,ptr)) < 0) + { + sql_print_error("Could not construct local filename %s%s", + target_dir_name,bname); + DBUG_RETURN(-1); + } + ce->set_fname_outside_temp_buf(fname,strlen(fname)); + + if (my_write(file,(byte*) ce->block,ce->block_len,MYF(MY_WME|MY_NABP))) + error= -1; + if (my_close(file, MYF(MY_WME))) + error= -1; + DBUG_RETURN(error); +} + + +int Load_log_processor::process(Append_block_log_event *ae) +{ + DBUG_ENTER("Load_log_processor::process"); + Create_file_log_event* ce= ((ae->file_id < file_names.elements) ? + *((Create_file_log_event**)file_names.buffer + + ae->file_id) : + 0); + + if (ce) + { + File file; + int error= 0; + if (((file= my_open(ce->fname, + O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0)) + DBUG_RETURN(-1); + if (my_write(file,(byte*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP))) + error= -1; + if (my_close(file,MYF(MY_WME))) + error= -1; + DBUG_RETURN(error); + } - A better way to do this would be to use 'create_tmp_file() and avoid this - race condition altogether on the expense of getting more cryptic file - names. + /* + There is no Create_file event (a bad binlog or a big + --position). Assuming it's a big --position, we just do nothing and + print a warning. */ - for (;;) + fprintf(stderr,"Warning: ignoring Append_block as there is no \ +Create_file event for file_id: %u\n",ae->file_id); + DBUG_RETURN(-1); +} + + +Load_log_processor load_processor; + + +int process_event(ulonglong *rec_count, LAST_EVENT_INFO *last_event_info, + Log_event *ev, my_off_t pos) +{ + char ll_buff[21]; + DBUG_ENTER("process_event"); + + if ((*rec_count) >= offset) { - sprintf(ptr,"-%x",version); - if (access(tmp,F_OK)) + if (!short_form) + fprintf(result_file, "# at %s\n",llstr(pos,ll_buff)); + + switch (ev->get_type_code()) { + case QUERY_EVENT: + if (one_database) + { + const char * log_dbname = ((Query_log_event*)ev)->db; + if ((log_dbname != NULL) && (strcmp(log_dbname, database))) + goto end; + } + ev->print(result_file, short_form, last_event_info); break; - /* If we have to try more than 1000 times, something is seriously wrong */ - if (version++ > 1000) + case CREATE_FILE_EVENT: { - die("Could not construct local filename %s%s",target_dir_name,bname); - return 0; + Create_file_log_event* ce= (Create_file_log_event*)ev; + if (one_database) + { + /* + We test if this event has to be ignored. If yes, we don't save + this event; this will have the good side-effect of ignoring all + related Append_block and Exec_load. + Note that Load event from 3.23 is not tested. + */ + const char * log_dbname = ce->db; + if ((log_dbname != NULL) && (strcmp(log_dbname, database))) + goto end; // Next event + } + /* + We print the event, but with a leading '#': this is just to inform + the user of the original command; the command we want to execute + will be a derivation of this original command (we will change the + filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT' + below. + */ + ce->print(result_file, short_form, last_event_info, TRUE); + // If this binlog is not 3.23 ; why this test?? + if (description_event->binlog_version >= 3) + { + if (load_processor.process(ce)) + break; // Error + ev= 0; + } + break; + } + case APPEND_BLOCK_EVENT: + ev->print(result_file, short_form, 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); + Execute_load_log_event *exv= (Execute_load_log_event*)ev; + Create_file_log_event *ce= load_processor.grab_event(exv->file_id); + /* + if ce is 0, it probably means that we have not seen the Create_file + event (a bad binlog, or most probably --position is after the + Create_file event). Print a warning comment. + */ + if (ce) + { + ce->print(result_file, short_form, last_event_info, TRUE); + my_free((char*)ce->fname,MYF(MY_WME)); + delete ce; + } + else + fprintf(stderr,"Warning: ignoring Exec_load as there is no \ +Create_file event for file_id: %u\n",exv->file_id); + break; + } + case FORMAT_DESCRIPTION_EVENT: + delete description_event; + description_event= (Format_description_log_event*) ev; + ev->print(result_file, short_form, 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 + error). Not serious error, because we will free description_event + later. + */ + ev= 0; + break; + case ROTATE_EVENT: + /* see comments in sql/slave.cc:process_io_rotate() */ + if (description_event->binlog_version >= 4) + { + delete description_event; + /* start from format 3 (MySQL 4.0) again */ + description_event= new Format_description_log_event(3); + if (!description_event || !description_event->is_valid()) + die("Invalid Format_description log event; could be out of memory"); + } + ev->print(result_file, short_form, last_event_info); + break; + default: + ev->print(result_file, short_form, last_event_info); } } - ce->set_fname_outside_temp_buf(tmp,strlen(tmp)); - return tmp; -} +end: + (*rec_count)++; + if (ev) + delete ev; + DBUG_RETURN(0); +} -Load_log_processor load_processor; static struct my_option my_long_options[] = { @@ -259,18 +479,22 @@ static struct my_option my_long_options[] = {"read-from-remote-server", 'R', "Read binary logs from a MySQL server", (gptr*) &remote_opt, (gptr*) &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"open_files_limit", OPT_OPEN_FILES_LIMIT, + "Used to reserve file descriptors for usage by this program", + (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG, + REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0}, {"short-form", 's', "Just show the queries, no extra info.", (gptr*) &short_form, (gptr*) &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "Socket file to use for connection.", - (gptr*) &sock, (gptr*) &sock, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, + (gptr*) &sock, (gptr*) &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"user", 'u', "Connect to the remote server as username.", (gptr*) &user, (gptr*) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"local-load", 'l', "Prepare files for local load in directory.", + {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.", (gptr*) &dirname_for_local_load, (gptr*) &dirname_for_local_load, 0, - GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, + GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} @@ -290,6 +514,10 @@ void sql_print_error(const char *format,...) static void cleanup() { my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); + my_free((char*) database, MYF(MY_ALLOW_ZERO_PTR)); + my_free((char*) host, MYF(MY_ALLOW_ZERO_PTR)); + my_free((char*) user, MYF(MY_ALLOW_ZERO_PTR)); + my_free((char*) dirname_for_local_load, MYF(MY_ALLOW_ZERO_PTR)); } static void die(const char* fmt, ...) @@ -301,12 +529,13 @@ static void die(const char* fmt, ...) fprintf(stderr, "\n"); va_end(args); cleanup(); + my_end(0); exit(1); } static void print_version() { - printf("%s Ver 2.5 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); + printf("%s Ver 3.1 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); } @@ -325,37 +554,6 @@ the mysql command line client\n\n"); my_print_variables(my_long_options); } -static void dump_remote_file(NET* net, const char* fname) -{ - char buf[FN_REFLEN+1]; - uint len = (uint) strlen(fname); - buf[0] = 0; - memcpy(buf + 1, fname, len + 1); - if(my_net_write(net, buf, len +2) || net_flush(net)) - die("Failed requesting the remote dump of %s", fname); - for(;;) - { - uint packet_len = my_net_read(net); - if(packet_len == 0) - { - if(my_net_write(net, "", 0) || net_flush(net)) - die("Failed sending the ack packet"); - - // we just need to send something, as the server will read but - // not examine the packet - this is because mysql_load() sends an OK when it is done - break; - } - else if(packet_len == packet_error) - die("Failed reading a packet during the dump of %s ", fname); - - if(!short_form) - (void)my_fwrite(result_file, (byte*) net->read_pos, packet_len,MYF(0)); - } - - fflush(result_file); -} - - extern "C" my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) @@ -430,6 +628,7 @@ static int parse_args(int *argc, char*** argv) static MYSQL* safe_connect() { MYSQL *local_mysql = mysql_init(NULL); + if (!local_mysql) die("Failed on mysql_init"); @@ -441,12 +640,11 @@ static MYSQL* safe_connect() return local_mysql; } -static void dump_log_entries(const char* logname) +static int dump_log_entries(const char* logname) { if (remote_opt) - dump_remote_log_entries(logname); - else - dump_local_log_entries(logname); + return dump_remote_log_entries(logname); + return dump_local_log_entries(logname); } /* @@ -509,24 +707,26 @@ static int check_master_version(MYSQL* mysql, } -/* - I thought I'd wait for both dump_*_log_entries to be merged, but it's not - yet, so I must update this one too. -*/ - -static void dump_remote_log_entries(const char* logname) +static int dump_remote_log_entries(const char* logname) { char buf[128]; LAST_EVENT_INFO last_event_info; - uint len; + uint len, logname_len; NET* net = &mysql->net; - Format_description_log_event* description_event; + DBUG_ENTER("dump_remote_log_entries"); if (check_master_version(mysql, &description_event)) - die("Could not find server version"); + { + fprintf(stderr, "Could not find server version"); + DBUG_RETURN(1); + } if (!description_event || !description_event->is_valid()) - die("Invalid Format_description log event; could be out of memory"); + { + fprintf(stderr, "Invalid Format_description log event; \ +could be out of memory"); + DBUG_RETURN(1); + } if (!position) position = BIN_LOG_HEADER_SIZE; @@ -537,58 +737,109 @@ static void dump_remote_log_entries(const char* logname) } int4store(buf, position); int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags); - len = (uint) strlen(logname); + logname_len = (uint) strlen(logname); int4store(buf + 6, 0); - memcpy(buf + 10, logname,len); - if (simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1)) - die("Error sending the log dump command"); + memcpy(buf + 10, logname, logname_len); + if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1)) + { + fprintf(stderr,"Got fatal error sending the log dump command\n"); + DBUG_RETURN(1); + } + + my_off_t old_off= position; + ulonglong rec_count= 0; + char fname[FN_REFLEN+1]; for (;;) { const char *error; len = net_safe_read(mysql); if (len == packet_error) - die("Error reading packet from server: %s", mysql_error(mysql)); + { + fprintf(stderr, "Got error reading packet from server: %s\n", + mysql_error(mysql)); + DBUG_RETURN(1); + } if (len < 8 && net->read_pos[0] == 254) break; // end of data DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n", len, net->read_pos[5])); Log_event *ev = Log_event::read_log_event((const char*) net->read_pos + 1 , - len - 1, &error, description_event); - if (ev) + len - 1, &error, + description_event); + if (!ev) + { + fprintf(stderr, "Could not construct log event object\n"); + DBUG_RETURN(1); + } + + Log_event_type type= ev->get_type_code(); + if (description_event->binlog_version >=3 || (type != LOAD_EVENT && type != CREATE_FILE_EVENT)) { - switch (ev->get_type_code()) + /* + If this is a Rotate event, maybe it's the end of the requested binlog; + in this case we are done (stop transfer). + This is suitable for binlogs, not relay logs (but for now we don't read + relay logs remotely because the server is not able to do that). If one + day we read relay logs remotely, then we will have a problem with the + detection below: relay logs contain Rotate events which are about the + binlogs, so which would trigger the end-detection below. + */ + if (type == ROTATE_EVENT) { - case FORMAT_DESCRIPTION_EVENT: - delete description_event; - description_event= (Format_description_log_event*) ev; - ev->print(result_file, short_form, &last_event_info); - break; - case ROTATE_EVENT: - /* see comments in sql/slave.cc:process_io_rotate() */ - if (description_event->binlog_version >= 4) + Rotate_log_event *rev= (Rotate_log_event *)ev; + /* + If this is a fake Rotate event, and not about our log, we can stop + transfer. If this a real Rotate event (so it's not about our log, + it's in our log describing the next log), we print it (because it's + part of our log) and then we will stop when we receive the fake one + soon. + */ + if (rev->when == 0) { - delete description_event; - /* start from format 3 (MySQL 4.0) again */ - description_event= new Format_description_log_event(3); - if (!description_event || !description_event->is_valid()) - die("Invalid Format_description log event; could be out of memory"); + if ((rev->ident_len != logname_len) || + memcmp(rev->new_log_ident, logname, logname_len)) + DBUG_RETURN(0); + /* + Otherwise, this is a fake Rotate for our log, at the very beginning + for sure. Skip it. + */ + continue; } - ev->print(result_file, short_form, &last_event_info); - delete ev; - break; - case LOAD_EVENT: - dump_remote_file(net, ((Load_log_event*)ev)->fname); - /* fall through */ - default: - ev->print(result_file, short_form, &last_event_info); - delete ev; } + if (process_event(&rec_count,&last_event_info,ev,old_off)) + DBUG_RETURN(1); } else - die("Could not construct log event object"); + { + Load_log_event *le= (Load_log_event*)ev; + const char *old_fname= le->fname; + uint old_len= le->fname_len; + File file; + + if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0) + DBUG_RETURN(1); + + if (process_event(&rec_count,&last_event_info,ev,old_off)) + { + my_close(file,MYF(MY_WME)); + DBUG_RETURN(1); + } + if (load_processor.load_old_format_file(net,old_fname,old_len,file)) + { + my_close(file,MYF(MY_WME)); + DBUG_RETURN(1); + } + my_close(file,MYF(MY_WME)); + } + /* + Let's adjust offset for remote log as for local log to produce + similar text. As we don't print the fake Rotate event, all events are + real so we can simply add the length. + */ + old_off+= len-1; } - delete description_event; + DBUG_RETURN(0); } @@ -687,35 +938,32 @@ at offset %lu ; this could be a log format error or read error", } -static void dump_local_log_entries(const char* logname) +static int dump_local_log_entries(const char* logname) { File fd = -1; IO_CACHE cache,*file= &cache; ulonglong rec_count = 0; LAST_EVENT_INFO last_event_info; byte tmp_buff[BIN_LOG_HEADER_SIZE]; - /* - check_header() will set the pointer below. - Why do we need here a pointer on an event instead of an event ? - This is because the event will be created (alloced) in read_log_event() - (which returns a pointer) in check_header(). - */ - Format_description_log_event* description_event; + int error= 0; if (logname && logname[0] != '-') { if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0) - exit(1); + return 1; if (init_io_cache(file, fd, 0, READ_CACHE, (my_off_t) position, 0, MYF(MY_WME | MY_NABP))) - exit(1); + { + my_close(fd, MYF(MY_WME)); + return 1; + } check_header(file, &description_event); } else // reading from stdin; TODO: check that it works { if (init_io_cache(file, fileno(result_file), 0, READ_CACHE, (my_off_t) 0, 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE))) - exit(1); + return 1; check_header(file, &description_event); if (position) { @@ -726,7 +974,10 @@ static void dump_local_log_entries(const char* logname) { tmp=min(length,sizeof(buff)); if (my_b_read(file, buff, (uint) tmp)) - exit(1); + { + error= 1; + goto end; + } } } file->pos_in_file=position; @@ -736,8 +987,11 @@ static void dump_local_log_entries(const char* logname) if (!description_event || !description_event->is_valid()) die("Invalid Format_description log event; could be out of memory"); - if (!position) - my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE); // Skip header + if (!position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE)) + { + error= 1; + goto end; + } for (;;) { char llbuff[21]; @@ -747,123 +1001,37 @@ static void dump_local_log_entries(const char* logname) if (!ev) { if (file->error) - die("\ -Could not read entry at offset %s : Error in log format or read error", - llstr(old_off,llbuff)); + fprintf(stderr, + "Could not read entry at offset %s:" + "Error in log format or read error\n", + llstr(old_off,llbuff)); + error= 1; // file->error == 0 means EOF, that's OK, we break in this case break; } - if (rec_count >= offset) - { - if (!short_form) - fprintf(result_file, "# at %s\n",llstr(old_off,llbuff)); - - switch (ev->get_type_code()) { - case QUERY_EVENT: - if (one_database) - { - const char * log_dbname = ((Query_log_event*)ev)->db; - if ((log_dbname != NULL) && (strcmp(log_dbname, database))) - { - rec_count++; - delete ev; - continue; // next - } - } - ev->print(result_file, short_form, &last_event_info); - break; - case CREATE_FILE_EVENT: - { - Create_file_log_event* ce= (Create_file_log_event*)ev; - if (one_database) - { - /* - We test if this event has to be ignored. If yes, we don't save this - event; this will have the good side-effect of ignoring all related - Append_block and Exec_load. - Note that Load event from 3.23 is not tested. - */ - const char * log_dbname = ce->db; - if ((log_dbname != NULL) && (strcmp(log_dbname, database))) - { - rec_count++; - delete ev; - continue; // next - } - } - /* - We print the event, but with a leading '#': this is just to inform - the user of the original command; the command we want to execute - will be a derivation of this original command (we will change the - filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT' - below. - */ - ce->print(result_file, short_form, &last_event_info, true); - load_processor.process(ce); - ev= 0; - break; - } - case APPEND_BLOCK_EVENT: - ev->print(result_file, short_form, &last_event_info); - load_processor.process((Append_block_log_event*)ev); - break; - case EXEC_LOAD_EVENT: - { - ev->print(result_file, short_form, &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); - /* - if ce is 0, it probably means that we have not seen the Create_file - event (a bad binlog, or most probably --position is after the - Create_file event). Print a warning comment. - */ - if (ce) - { - ce->print(result_file, short_form, &last_event_info,true); - my_free((char*)ce->fname,MYF(MY_WME)); - delete ce; - } - else - fprintf(stderr,"Warning: ignoring Exec_load as there is no \ -Create_file event for file_id: %u\n",exv->file_id); - break; - } - case FORMAT_DESCRIPTION_EVENT: - delete description_event; - description_event= (Format_description_log_event*) ev; - ev->print(result_file, short_form, &last_event_info); - break; - case ROTATE_EVENT: - /* see comments in sql/slave.cc:process_io_rotate() */ - if (description_event->binlog_version >= 4) - { - delete description_event; - /* start from format 3 (MySQL 4.0) again */ - description_event= new Format_description_log_event(3); - if (!description_event || !description_event->is_valid()) - die("Invalid Format_description log event; could be out of memory"); - } - ev->print(result_file, short_form, &last_event_info); - break; - default: - ev->print(result_file, short_form, &last_event_info); - } - } - rec_count++; - if (ev && ev->get_type_code()!=FORMAT_DESCRIPTION_EVENT) - delete ev; /* otherwise, deleted in the end */ + if (process_event(&rec_count,&last_event_info,ev,old_off)) + { + error= 1; + break; + } } + +end: if (fd >= 0) my_close(fd, MYF(MY_WME)); end_io_cache(file); delete description_event; + return error; } int main(int argc, char** argv) { static char **defaults_argv; + int exit_value; MY_INIT(argv[0]); + DBUG_ENTER("main"); + DBUG_PROCESS(argv[0]); parse_args(&argc, (char***)&argv); defaults_argv=argv; @@ -872,9 +1040,10 @@ int main(int argc, char** argv) { usage(); free_defaults(defaults_argv); - return -1; + exit(1); } + my_set_max_open_files(open_files_limit); if (remote_opt) mysql = safe_connect(); @@ -884,16 +1053,28 @@ int main(int argc, char** argv) { if (init_tmpdir(&tmpdir, 0)) exit(1); - dirname_for_local_load= my_tmpdir(&tmpdir); + dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME); } + if (load_processor.init()) + exit(1); if (dirname_for_local_load) load_processor.init_by_dir_name(dirname_for_local_load); else load_processor.init_by_cur_dir(); + exit_value= 0; + fprintf(result_file, + "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n"); while (--argc >= 0) - dump_log_entries(*(argv++)); + { + if (dump_log_entries(*(argv++))) + { + exit_value=1; + break; + } + } + if (tmpdir.list) free_tmpdir(&tmpdir); if (result_file != stdout) @@ -902,8 +1083,10 @@ int main(int argc, char** argv) mysql_close(mysql); cleanup(); free_defaults(defaults_argv); + my_free_open_file_info(); my_end(0); - return 0; + exit(exit_value); + DBUG_RETURN(exit_value); // Keep compilers happy } /* diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 2f2b8d9b6fb..3212104dcc6 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -311,41 +311,41 @@ #define ER_TRUNCATED_WRONG_VALUE 1292 #define ER_TOO_MUCH_AUTO_TIMESTAMP_COLS 1293 #define ER_INVALID_ON_UPDATE 1294 -#define ER_SP_NO_RECURSIVE_CREATE 1294 -#define ER_SP_ALREADY_EXISTS 1295 -#define ER_SP_DOES_NOT_EXIST 1296 -#define ER_SP_DROP_FAILED 1297 -#define ER_SP_STORE_FAILED 1298 -#define ER_SP_LILABEL_MISMATCH 1299 -#define ER_SP_LABEL_REDEFINE 1300 -#define ER_SP_LABEL_MISMATCH 1301 -#define ER_SP_UNINIT_VAR 1302 -#define ER_SP_BADSELECT 1303 -#define ER_SP_BADRETURN 1304 -#define ER_SP_BADSTATEMENT 1305 -#define ER_UPDATE_LOG_DEPRECATED_IGNORED 1306 -#define ER_UPDATE_LOG_DEPRECATED_TRANSLATED 1307 -#define ER_QUERY_INTERRUPTED 1308 -#define ER_SP_WRONG_NO_OF_ARGS 1309 -#define ER_SP_COND_MISMATCH 1310 -#define ER_SP_NORETURN 1311 -#define ER_SP_NORETURNEND 1312 -#define ER_SP_BAD_CURSOR_QUERY 1313 -#define ER_SP_BAD_CURSOR_SELECT 1314 -#define ER_SP_CURSOR_MISMATCH 1315 -#define ER_SP_CURSOR_ALREADY_OPEN 1316 -#define ER_SP_CURSOR_NOT_OPEN 1317 -#define ER_SP_UNDECLARED_VAR 1318 -#define ER_SP_WRONG_NO_OF_FETCH_ARGS 1319 -#define ER_SP_FETCH_NO_DATA 1320 -#define ER_SP_DUP_PARAM 1321 -#define ER_SP_DUP_VAR 1322 -#define ER_SP_DUP_COND 1323 -#define ER_SP_DUP_CURS 1324 -#define ER_SP_CANT_ALTER 1325 -#define ER_SP_SUBSELECT_NYI 1326 -#define ER_SP_NO_USE 1327 -#define ER_SP_VARCOND_AFTER_CURSHNDLR 1328 -#define ER_SP_CURSOR_AFTER_HANDLER 1329 -#define ER_SP_CASE_NOT_FOUND 1330 -#define ER_ERROR_MESSAGES 331 +#define ER_SP_NO_RECURSIVE_CREATE 1295 +#define ER_SP_ALREADY_EXISTS 1296 +#define ER_SP_DOES_NOT_EXIST 1297 +#define ER_SP_DROP_FAILED 1298 +#define ER_SP_STORE_FAILED 1299 +#define ER_SP_LILABEL_MISMATCH 1300 +#define ER_SP_LABEL_REDEFINE 1301 +#define ER_SP_LABEL_MISMATCH 1302 +#define ER_SP_UNINIT_VAR 1303 +#define ER_SP_BADSELECT 1304 +#define ER_SP_BADRETURN 1305 +#define ER_SP_BADSTATEMENT 1306 +#define ER_UPDATE_LOG_DEPRECATED_IGNORED 1307 +#define ER_UPDATE_LOG_DEPRECATED_TRANSLATED 1308 +#define ER_QUERY_INTERRUPTED 1309 +#define ER_SP_WRONG_NO_OF_ARGS 1310 +#define ER_SP_COND_MISMATCH 1311 +#define ER_SP_NORETURN 1312 +#define ER_SP_NORETURNEND 1313 +#define ER_SP_BAD_CURSOR_QUERY 1314 +#define ER_SP_BAD_CURSOR_SELECT 1315 +#define ER_SP_CURSOR_MISMATCH 1316 +#define ER_SP_CURSOR_ALREADY_OPEN 1317 +#define ER_SP_CURSOR_NOT_OPEN 1318 +#define ER_SP_UNDECLARED_VAR 1319 +#define ER_SP_WRONG_NO_OF_FETCH_ARGS 1320 +#define ER_SP_FETCH_NO_DATA 1321 +#define ER_SP_DUP_PARAM 1322 +#define ER_SP_DUP_VAR 1323 +#define ER_SP_DUP_COND 1324 +#define ER_SP_DUP_CURS 1325 +#define ER_SP_CANT_ALTER 1326 +#define ER_SP_SUBSELECT_NYI 1327 +#define ER_SP_NO_USE 1328 +#define ER_SP_VARCOND_AFTER_CURSHNDLR 1329 +#define ER_SP_CURSOR_AFTER_HANDLER 1330 +#define ER_SP_CASE_NOT_FOUND 1331 +#define ER_ERROR_MESSAGES 332 diff --git a/mysql-test/r/drop_temp_table.result b/mysql-test/r/drop_temp_table.result index 6eba97b089b..08793bcbd57 100644 --- a/mysql-test/r/drop_temp_table.result +++ b/mysql-test/r/drop_temp_table.result @@ -9,6 +9,10 @@ select get_lock("a",10); get_lock("a",10) 1 show binlog events; -master-bin.000001 246 Query 1 246 use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name` -master-bin.000001 375 Query 1 375 use `drop-temp+table-test`; DO RELEASE_LOCK("a") +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 95 Server ver: VERSION, Binlog ver: 4 +master-bin.000001 95 Query 1 190 use `test`; create database `drop-temp+table-test` +master-bin.000001 190 Query 1 306 use `drop-temp+table-test`; create temporary table `table:name` (a int) +master-bin.000001 306 Query 1 457 use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name` +master-bin.000001 457 Query 1 550 use `drop-temp+table-test`; DO RELEASE_LOCK("a") drop database `drop-temp+table-test`; diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 44950d0927c..0aaf77cd623 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -324,6 +324,7 @@ f_double_u 0 f_float_u 0 f_double_15_1_u 0.0 f_float_3_1_u 0.0 +use test; drop table if exists t1,t2,t3; create table t1(id1 int not null auto_increment primary key, t char(12)); create table t2(id2 int not null, t char(12)); diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 80260c42e4b..f54f233d929 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -14,6 +14,7 @@ insert into t1 values ("Alas"); flush logs; --- Local -- +/*!40019 SET @@session.max_insert_delayed_threads=0*/; use test; SET TIMESTAMP=1000000000; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; @@ -26,13 +27,14 @@ insert into t1 values ("abirvalg"); SET INSERT_ID=1; SET TIMESTAMP=1000000000; insert into t2 values (); -LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-1-0' INTO TABLE t1 FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); -LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-2-0' INTO TABLE t1 FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); -LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-3-0' INTO TABLE t1 FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); -LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-4-0' INTO TABLE t1 FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); -LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-5-0' INTO TABLE t1 FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-1-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-2-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-3-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-4-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-5-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); --- Broken LOAD DATA -- +/*!40019 SET @@session.max_insert_delayed_threads=0*/; use test; SET TIMESTAMP=1000000000; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; @@ -40,9 +42,11 @@ SET @@session.sql_mode=0; insert into t1 values ("Alas"); --- --database -- +/*!40019 SET @@session.max_insert_delayed_threads=0*/; SET INSERT_ID=1; --- --position -- +/*!40019 SET @@session.max_insert_delayed_threads=0*/; use test; SET TIMESTAMP=1000000000; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; @@ -50,6 +54,7 @@ SET @@session.sql_mode=0; insert into t1 values ("Alas"); --- Remote -- +/*!40019 SET @@session.max_insert_delayed_threads=0*/; use test; SET TIMESTAMP=1000000000; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; @@ -62,10 +67,14 @@ insert into t1 values ("abirvalg"); SET INSERT_ID=1; SET TIMESTAMP=1000000000; insert into t2 values (); -SET TIMESTAMP=1000000000; -insert into t1 values ("Alas"); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-1-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-2-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-3-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-4-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-5-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word); --- Broken LOAD DATA -- +/*!40019 SET @@session.max_insert_delayed_threads=0*/; use test; SET TIMESTAMP=1000000000; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; @@ -73,22 +82,11 @@ SET @@session.sql_mode=0; insert into t1 values ("Alas"); --- --database -- -use test; -SET TIMESTAMP=1000000000; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; -SET @@session.sql_mode=0; -create table t1 (word varchar(20)); -SET TIMESTAMP=1000000000; -create table t2 (id int auto_increment not null primary key); -SET TIMESTAMP=1000000000; -insert into t1 values ("abirvalg"); +/*!40019 SET @@session.max_insert_delayed_threads=0*/; SET INSERT_ID=1; -SET TIMESTAMP=1000000000; -insert into t2 values (); -SET TIMESTAMP=1000000000; -insert into t1 values ("Alas"); --- --position -- +/*!40019 SET @@session.max_insert_delayed_threads=0*/; use test; SET TIMESTAMP=1000000000; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 947a8ad25e1..0fa215f1cf5 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -857,7 +857,7 @@ Variable_name Value Qcache_queries_in_cache 0 show status like "Qcache_inserts"; Variable_name Value -Qcache_inserts 9 +Qcache_inserts 11 show status like "Qcache_hits"; Variable_name Value Qcache_hits 6 @@ -870,7 +870,7 @@ Variable_name Value Qcache_queries_in_cache 1 show status like "Qcache_inserts"; Variable_name Value -Qcache_inserts 10 +Qcache_inserts 12 show status like "Qcache_hits"; Variable_name Value Qcache_hits 7 diff --git a/mysql-test/r/rpl_error_ignored_table.result b/mysql-test/r/rpl_error_ignored_table.result index 4a562dbfc70..19c8ee2e8c7 100644 --- a/mysql-test/r/rpl_error_ignored_table.result +++ b/mysql-test/r/rpl_error_ignored_table.result @@ -9,7 +9,7 @@ insert into t1 values (1),(1); ERROR 23000: Duplicate entry '1' for key 1 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 213 slave-relay-bin.000002 257 master-bin.000001 Yes Yes test.t3,test.t1,test.t2 0 0 213 257 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 273 # # master-bin.000001 Yes Yes test.t3,test.t1,test.t2 0 0 273 # None 0 No # show tables like 't1'; Tables_in_test (t1) drop table t1; @@ -26,14 +26,14 @@ select (@id := id) - id from t3; 0 kill @id; drop table t2,t3; -show binlog events from 79; -Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.000001 79 Query 1 79 use `test`; create table t1 (a int primary key) -master-bin.000001 149 Query 1 149 use `test`; insert into t1 values (1),(1) -master-bin.000001 213 Query 1 213 use `test`; drop table t1 -master-bin.000001 261 Query 1 261 use `test`; create table t2 (a int primary key) -master-bin.000001 331 Query 1 331 use `test`; insert into t2 values(1) -master-bin.000001 390 Query 1 390 use `test`; create table t3 (id int) -master-bin.000001 449 Query 1 449 use `test`; insert into t3 values(connection_id()) -master-bin.000001 522 Query 1 522 use `test`; update t2 set a = a + 1 + get_lock('crash_lock%20C', 10) -master-bin.000001 613 Query 1 613 use `test`; drop table t2,t3 +show binlog events from 95; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 95 Query 1 187 use `test`; create table t1 (a int primary key) +master-bin.000001 187 Query 1 273 use `test`; insert into t1 values (1),(1) +master-bin.000001 273 Query 1 343 use `test`; drop table t1 +master-bin.000001 343 Query 1 435 use `test`; create table t2 (a int primary key) +master-bin.000001 435 Query 1 516 use `test`; insert into t2 values(1) +master-bin.000001 516 Query 1 597 use `test`; create table t3 (id int) +master-bin.000001 597 Query 1 692 use `test`; insert into t3 values(connection_id()) +master-bin.000001 692 Query 1 805 use `test`; update t2 set a = a + 1 + get_lock('crash_lock%20C', 10) +master-bin.000001 805 Query 1 878 use `test`; drop table t2,t3 diff --git a/mysql-test/r/rpl_relayrotate.result b/mysql-test/r/rpl_relayrotate.result index 42902e122b1..efdfefce67a 100644 --- a/mysql-test/r/rpl_relayrotate.result +++ b/mysql-test/r/rpl_relayrotate.result @@ -16,6 +16,9 @@ master_pos_wait('master-bin.001',3000)>=0 select max(a) from t1; max(a) 8000 +show slave status; +Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 687207 # # master-bin.000001 Yes Yes 0 0 687207 # None 0 No # show status like "binlog_cache_use"; Variable_name Value Binlog_cache_use 1 @@ -31,7 +34,4 @@ Binlog_cache_use 2 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 1 -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 687207 # # master-bin.000001 Yes Yes 0 0 687207 # None 0 No # drop table t1; diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result index ad0fb9e5022..5eb5f810a8f 100644 --- a/mysql-test/r/rpl_trunc_binlog.result +++ b/mysql-test/r/rpl_trunc_binlog.result @@ -10,4 +10,4 @@ reset slave; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 slave-relay-bin.000002 123 master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. A probable cause is that the master died while writing the transaction to its binary log. 0 79 326 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 # # master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. A probable cause is that the master died while writing the transaction to its binary log. 0 79 # None 0 No # diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 05e9379dd79..b2bba71ea6d 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -35,7 +35,7 @@ call foo()| ERROR 42000: PROCEDURE foo does not exist drop procedure if exists foo| Warnings: -Warning 1292 PROCEDURE foo does not exist +Warning 1297 PROCEDURE foo does not exist show create procedure foo| ERROR 42000: PROCEDURE foo does not exist create procedure foo() @@ -71,7 +71,7 @@ declare y int; set x = y; end| Warnings: -Warning 1298 Referring to uninitialized variable y +Warning 1303 Referring to uninitialized variable y drop procedure foo| create procedure foo() return 42| diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index cfe3e1255f7..38bd70b6951 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1048,7 +1048,7 @@ drop table if exists t3| create table t3 (s1 smallint)| insert into t3 values (123456789012)| Warnings: -Warning 1263 Data truncated, out of range for column 's1' at row 1 +Warning 1264 Data truncated, out of range for column 's1' at row 1 create procedure bug2780() begin declare exit handler for sqlwarning set @x = 1; diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index d53ace261bf..8376535593e 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -8,6 +8,7 @@ help_keyword help_relation help_topic host +proc tables_priv user show create table db; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 963dd97d336..f25a48525bb 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -364,7 +364,7 @@ set sql_log_bin=1; set sql_log_off=1; set sql_log_update=1; Warnings: -Note 1302 The update log is deprecated and replaced by the binary log. SET SQL_LOG_UPDATE has been ignored. +Note 1307 The update log is deprecated and replaced by the binary log. SET SQL_LOG_UPDATE has been ignored. set sql_low_priority_updates=1; set sql_max_join_size=200; select @@sql_max_join_size,@@max_join_size; diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index b7eec472375..5953fae6030 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -48,7 +48,7 @@ connection master; --error 0,1053; reap; connection master1; -show binlog events from 79; +show binlog events from 95; save_master_pos; connection slave; # SQL slave thread should not have stopped (because table of the killed diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 03ab44b3e46..5c300647d27 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -32,18 +32,18 @@ create function func1() returns int return 42| # Can't create recursively ---error 1290 +--error 1295 create procedure foo() create procedure bar() set @x=3| ---error 1290 +--error 1295 create procedure foo() create function bar() returns double return 2.3| # Already exists ---error 1291 +--error 1296 create procedure proc1() set @x = 42| ---error 1291 +--error 1296 create function func1() returns int return 42| @@ -51,39 +51,39 @@ drop procedure proc1| drop function func1| # Does not exist ---error 1292 +--error 1297 alter procedure foo| ---error 1292 +--error 1297 alter function foo| ---error 1292 +--error 1297 drop procedure foo| ---error 1292 +--error 1297 drop function foo| ---error 1292 +--error 1297 call foo()| drop procedure if exists foo| ---error 1292 +--error 1297 show create procedure foo| # LEAVE/ITERATE with no match ---error 1295 +--error 1300 create procedure foo() foo: loop leave bar; end loop| ---error 1295 +--error 1300 create procedure foo() foo: loop iterate bar; end loop| ---error 1295 +--error 1300 create procedure foo() foo: begin iterate foo; end| # Redefining label ---error 1296 +--error 1301 create procedure foo() foo: loop foo: loop @@ -92,7 +92,7 @@ foo: loop end loop foo| # End label mismatch ---error 1297 +--error 1302 create procedure foo() foo: loop set @x=2; @@ -107,12 +107,12 @@ end| drop procedure foo| # RETURN in FUNCTION only ---error 1300 +--error 1305 create procedure foo() return 42| # Doesn't allow queries in FUNCTIONs (for now :-( ) ---error 1301 +--error 1306 create function foo() returns int begin declare x int; @@ -126,19 +126,19 @@ create procedure p(x int) create function f(x int) returns int return x+42| ---error 1305 +--error 1310 call p()| ---error 1305 +--error 1310 call p(1, 2)| ---error 1305 +--error 1310 select f()| ---error 1305 +--error 1310 select f(1, 2)| drop procedure p| drop function f| ---error 1306 +--error 1311 create procedure p(val int, out res int) begin declare x int default 0; @@ -152,7 +152,7 @@ begin end if; end| ---error 1306 +--error 1311 create procedure p(val int, out res int) begin declare x int default 0; @@ -167,7 +167,7 @@ begin end if; end| ---error 1307 +--error 1312 create function f(val int) returns int begin declare x int; @@ -185,12 +185,12 @@ begin end if; end| ---error 1308 +--error 1313 select f(10)| drop function f| ---error 1309 +--error 1314 create procedure p() begin declare c cursor for insert into test.t1 values ("foo", 42); @@ -199,7 +199,7 @@ begin close c; end| ---error 1310 +--error 1315 create procedure p() begin declare x int; @@ -209,7 +209,7 @@ begin close c; end| ---error 1311 +--error 1316 create procedure p() begin declare c cursor for select * from test.t; @@ -231,7 +231,7 @@ begin open c; close c; end| ---error 1312 +--error 1317 call p()| drop procedure p| @@ -243,11 +243,11 @@ begin close c; close c; end| ---error 1313 +--error 1318 call p()| drop procedure p| ---error 1292 +--error 1297 alter procedure bar3 sql security invoker| --error 1059 alter procedure bar3 name @@ -261,7 +261,7 @@ drop table if exists t1| create table t1 (val int, x float)| insert into t1 values (42, 3.1), (19, 1.2)| ---error 1314 +--error 1319 create procedure p() begin declare x int; @@ -281,7 +281,7 @@ begin fetch c into x; close c; end| ---error 1315 +--error 1320 call p()| drop procedure p| @@ -296,34 +296,34 @@ begin fetch c into x, y, z; close c; end| ---error 1315 +--error 1320 call p()| drop procedure p| ---error 1317 +--error 1322 create procedure p(in x int, x char(10)) begin end| ---error 1317 +--error 1322 create function p(x int, x char(10)) begin end| ---error 1318 +--error 1323 create procedure p() begin declare x float; declare x int; end| ---error 1319 +--error 1324 create procedure p() begin declare c condition for 1064; declare c condition for 1065; end| ---error 1320 +--error 1325 create procedure p() begin declare c cursor for select * from t1; @@ -331,18 +331,18 @@ begin end| # USE is not allowed ---error 1323 +--error 1328 create procedure u() use sptmp| # Enforced standard order of declarations ---error 1324 +--error 1329 create procedure p() begin declare c cursor for select * from t1; declare x int; end| ---error 1324 +--error 1329 create procedure p() begin declare x int; @@ -350,7 +350,7 @@ begin declare foo condition for sqlstate '42S99'; end| ---error 1325 +--error 1330 create procedure p() begin declare x int; @@ -375,13 +375,13 @@ drop procedure bug1965| # # BUG#1966 # ---error 1314 +--error 1319 select 1 into a| # # BUG#336 # ---error 1322 +--error 1327 create procedure bug336(id char(16)) begin declare x int; @@ -391,7 +391,7 @@ end| # # BUG#1654 # ---error 1301 +--error 1306 create function bug1654() returns int return (select sum(t.data) from test.t2 t)| @@ -429,7 +429,7 @@ begin fetch c1 into v1; end| ---error 1313 +--error 1318 call bug2259()| drop procedure bug2259| @@ -485,7 +485,7 @@ begin end case; return 2; end| ---error 1326 +--error 1331 select bug3287()| drop function bug3287| @@ -496,7 +496,7 @@ when 0 then when 1 then insert into test.t1 values (x, 1.1); end case| ---error 1326 +--error 1331 call bug3287(2)| drop procedure bug3287| diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 31b7fb807f3..664968aaef4 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2019,10 +2019,10 @@ build_template( if (templ_type == ROW_MYSQL_REC_FIELDS && ((prebuilt->read_just_key && !index_contains_field) || - (!(fetch_all_in_key && index_contains_field) - !(fetch_primary_key_cols && - dict_table_col_in_clustered_key(index->table, i) && - thd->query_id != field->query_id))) { + (!(fetch_all_in_key && index_contains_field) && + !(fetch_primary_key_cols && + dict_table_col_in_clustered_key(index->table, i)) && + thd->query_id != field->query_id))) { /* This field is not needed in the query, skip it */ diff --git a/sql/log_event.cc b/sql/log_event.cc index 6a8d9d48d29..5a56cc139b0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2004 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 @@ -56,11 +56,21 @@ static void pretty_print_str(FILE* file, char* str, int len) #endif /* MYSQL_CLIENT */ +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) + +static void clear_all_errors(THD *thd, struct st_relay_log_info *rli) +{ + thd->query_error = 0; + thd->clear_error(); + *rli->last_slave_error = 0; + rli->last_slave_errno = 0; +} + + /* - ignored_error_code() + Ignore error code specified on command line */ -#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) inline int ignored_error_code(int err_code) { return ((err_code == ER_SLAVE_IGNORED_TABLE) || @@ -73,7 +83,7 @@ inline int ignored_error_code(int err_code) pretty_print_str() */ -#ifndef MYSQL_CLIENT +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) static char *pretty_print_str(char *packet, char *str, int len) { char *end= str + len; @@ -349,6 +359,8 @@ Log_event::Log_event(const char* buf, int Log_event::exec_event(struct st_relay_log_info* rli) { + DBUG_ENTER("Log_event::exec_event"); + /* rli is null when (as far as I (Guilhem) know) the caller is @@ -401,7 +413,7 @@ int Log_event::exec_event(struct st_relay_log_info* rli) rli->last_master_timestamp= when; } } - return 0; + DBUG_RETURN(0); } @@ -1047,7 +1059,9 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans), data_buf(0), query(query_arg), catalog(thd_arg->catalog), db(thd_arg->db), q_len((uint32) query_length), - error_code(thd_arg->killed != THD::NOT_KILLED ? thd->killed_errno() : thd_arg->net.last_errno), + error_code((thd_arg->killed != THD::NOT_KILLED) ? + ((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? + 0 : thd->killed_errno()) : thd_arg->net.last_errno), thread_id(thd_arg->thread_id), /* save the original thread id; we already know the server id */ slave_proxy_id(thd_arg->variables.pseudo_thread_id), @@ -1340,7 +1354,12 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) END of the current log event (COMMIT). We save it in rli so that InnoDB can access it. */ +#if MYSQL_VERSION_ID < 50000 + rli->future_group_master_log_pos= log_pos + get_event_len(); +#else rli->future_group_master_log_pos= log_pos; +#endif + clear_all_errors(thd, rli); if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { @@ -1350,9 +1369,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); - thd->query_error= 0; // clear error - thd->clear_error(); thd->variables.pseudo_thread_id= thread_id; // for temp tables + mysql_log.write(thd,COM_QUERY,"%s",thd->query); + DBUG_PRINT("query",("%s",thd->query)); if (flags2_inited) /* @@ -1378,97 +1397,105 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) (ulong) ((thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) | (sql_mode & ~(ulong) MODE_NO_DIR_IN_CREATE)); - /* - Sanity check to make sure the master did not get a really bad - error on the query (for example, if the query on the master was killed, we - don't want to play it on the slave, because we don't know how much of it - we have to play). - */ - if (ignored_error_code((expected_error = error_code)) || + if (ignored_error_code((expected_error= error_code)) || !check_expected_error(thd,rli,expected_error)) - { - mysql_log.write(thd,COM_QUERY,"%s",thd->query); - DBUG_PRINT("query",("%s",thd->query)); mysql_parse(thd, thd->query, q_len); - + else + { /* - If we expected a non-zero error code, and we don't get the same error - code, and none of them should be ignored. + The query got a really bad error on the master (thread killed etc), + which could be inconsistent. Parse it to test the table names: if the + replicate-*-do|ignore-table rules say "this query must be ignored" then + we exit gracefully; otherwise we warn about the bad error and tell DBA + to check/fix it. */ - DBUG_PRINT("info",("expected_error: %d last_errno: %d", - expected_error, thd->net.last_errno)); - if ((expected_error != (actual_error= thd->net.last_errno)) && - expected_error && - !ignored_error_code(actual_error) && - !ignored_error_code(expected_error)) + if (mysql_test_parse_for_slave(thd, thd->query, q_len)) + clear_all_errors(thd, rli); /* Can ignore query */ + else { - slave_print_error(rli, 0, + slave_print_error(rli,expected_error, "\ +Query '%s' partially completed on the master (error on master: %d) \ +and was aborted. There is a chance that your master is inconsistent at this \ +point. If you are sure that your master is ok, run this query manually on the \ +slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \ +START SLAVE; .", thd->query, expected_error); + thd->query_error= 1; + } + goto end; + } + + /* + If we expected a non-zero error code, and we don't get the same error + code, and none of them should be ignored. + */ + DBUG_PRINT("info",("expected_error: %d last_errno: %d", + expected_error, thd->net.last_errno)); + if ((expected_error != (actual_error= thd->net.last_errno)) && + expected_error && + !ignored_error_code(actual_error) && + !ignored_error_code(expected_error)) + { + slave_print_error(rli, 0, + "\ Query '%s' caused different errors on master and slave. \ Error on master: '%s' (%d), Error on slave: '%s' (%d). \ Default database: '%s'", - query, - ER_SAFE(expected_error), - expected_error, - actual_error ? thd->net.last_error: "no error", - actual_error, - print_slave_db_safe(db)); - thd->query_error= 1; - } - /* - If we get the same error code as expected, or they should be ignored. - */ - else if (expected_error == actual_error || - ignored_error_code(actual_error)) - { - DBUG_PRINT("info",("error ignored")); - thd->query_error = 0; - *rli->last_slave_error = 0; - rli->last_slave_errno = 0; - } - /* - Other cases: mostly we expected no error and get one. - */ - else if (thd->query_error || thd->is_fatal_error) + query, + ER_SAFE(expected_error), + expected_error, + actual_error ? thd->net.last_error: "no error", + actual_error, + print_slave_db_safe(db)); + thd->query_error= 1; + } + /* + If we get the same error code as expected, or they should be ignored. + */ + else if (expected_error == actual_error || + ignored_error_code(actual_error)) + { + DBUG_PRINT("info",("error ignored")); + clear_all_errors(thd, rli); + } + /* + Other cases: mostly we expected no error and get one. + */ + else if (thd->query_error || thd->is_fatal_error) + { + slave_print_error(rli,actual_error, + "Error '%s' on query '%s'. Default database: '%s'", + (actual_error ? thd->net.last_error : + "unexpected success or fatal error"), + query, + print_slave_db_safe(db)); + thd->query_error= 1; + } + + /* + TODO: compare the values of "affected rows" around here. Something + like: + if ((uint32) affected_in_event != (uint32) affected_on_slave) { - slave_print_error(rli,actual_error, - "Error '%s' on query '%s'. Default database: '%s'", - (actual_error ? thd->net.last_error : - "unexpected success or fatal error"), - query, - print_slave_db_safe(db)); - thd->query_error= 1; + sql_print_error("Slave: did not get the expected number of affected \ + rows running query from master - expected %d, got %d (this numbers \ + should have matched modulo 4294967296).", 0, ...); + thd->query_error = 1; } - /* - TODO: compare the values of "affected rows" around here. Something - like: - if ((uint32) affected_in_event != (uint32) affected_on_slave) - { - sql_print_error("Slave: did not get the expected number of affected \ - rows running query from master - expected %d, got %d (this numbers \ - should have matched modulo 4294967296).", 0, ...); - thd->query_error = 1; - } - We may also want an option to tell the slave to ignore "affected" - mismatch. This mismatch could be implemented with a new ER_ code, and - to ignore it you would use --slave-skip-errors... + We may also want an option to tell the slave to ignore "affected" + mismatch. This mismatch could be implemented with a new ER_ code, and + to ignore it you would use --slave-skip-errors... - To do the comparison we need to know the value of "affected" which the - above mysql_parse() computed. And we need to know the value of - "affected" in the master's binlog. Both will be implemented later. The - important thing is that we now have the format ready to log the values - of "affected" in the binlog. So we can release 5.0.0 before effectively - logging "affected" and effectively comparing it. - */ - } - /* - End of sanity check. If the test was false, the query got a really bad - error on the master, which could be inconsistent. check_expected_error() - already printed the message to stderr and rli, to tell the DBA to fix - things, and it has set thd->query_error to 1. + To do the comparison we need to know the value of "affected" which the + above mysql_parse() computed. And we need to know the value of + "affected" in the master's binlog. Both will be implemented later. The + important thing is that we now have the format ready to log the values + of "affected" in the binlog. So we can release 5.0.0 before effectively + logging "affected" and effectively comparing it. */ } /* End of if (db_ok(... */ +end: VOID(pthread_mutex_lock(&LOCK_thread_count)); /* Probably we have set thd->query, thd->db, thd->catalog to point to places @@ -1634,7 +1661,7 @@ int Start_log_event_v3::exec_event(struct st_relay_log_info* rli) { slave_print_error(rli, 0, "\ Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. \ -Probably cause is that the master died while writing the transaction to it's \ +A probable cause is that the master died while writing the transaction to its \ binary log."); return(1); } @@ -1924,7 +1951,7 @@ void Load_log_event::pack_info(Protocol *protocol) 18 + fname_len + 2 + // "LOAD DATA INFILE 'file''" 7 + // LOCAL 9 + // " REPLACE or IGNORE " - 11 + table_name_len + // "INTO TABLE table" + 13 + table_name_len*2 + // "INTO TABLE `table`" 21 + sql_ex.field_term_len*4 + 2 + // " FIELDS TERMINATED BY 'str'" 23 + sql_ex.enclosed_len*4 + 2 + // " OPTIONALLY ENCLOSED BY 'str'" 12 + sql_ex.escaped_len*4 + 2 + // " ESCAPED BY 'str'" @@ -1955,42 +1982,25 @@ void Load_log_event::pack_info(Protocol *protocol) else if (sql_ex.opt_flags & IGNORE_FLAG) pos= strmov(pos, " IGNORE "); - pos= strmov(pos ,"INTO TABLE "); + pos= strmov(pos ,"INTO TABLE `"); memcpy(pos, table_name, table_name_len); pos+= table_name_len; - if (sql_ex.field_term_len) - { - pos= strmov(pos, " FIELDS TERMINATED BY "); - pos= pretty_print_str(pos, sql_ex.field_term, sql_ex.field_term_len); - } - - if (sql_ex.enclosed_len) - { - if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) - pos= strmov(pos, " OPTIONALLY "); - pos= strmov(pos, " ENCLOSED BY "); - pos= pretty_print_str(pos, sql_ex.enclosed, sql_ex.enclosed_len); - } + /* We have to create all optinal fields as the default is not empty */ + pos= strmov(pos, "` FIELDS TERMINATED BY "); + pos= pretty_print_str(pos, sql_ex.field_term, sql_ex.field_term_len); + if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) + pos= strmov(pos, " OPTIONALLY "); + pos= strmov(pos, " ENCLOSED BY "); + pos= pretty_print_str(pos, sql_ex.enclosed, sql_ex.enclosed_len); - if (sql_ex.escaped_len) - { - pos= strmov(pos, " ESCAPED BY "); - pos= pretty_print_str(pos, sql_ex.escaped, sql_ex.escaped_len); - } - - bool line_lexem_added= false; - if (sql_ex.line_term_len) - { - pos= strmov(pos, " LINES TERMINATED BY "); - pos= pretty_print_str(pos, sql_ex.line_term, sql_ex.line_term_len); - line_lexem_added= true; - } + pos= strmov(pos, " ESCAPED BY "); + pos= pretty_print_str(pos, sql_ex.escaped, sql_ex.escaped_len); + pos= strmov(pos, " LINES TERMINATED BY "); + pos= pretty_print_str(pos, sql_ex.line_term, sql_ex.line_term_len); if (sql_ex.line_start_len) { - if (!line_lexem_added) - pos= strmov(pos," LINES"); pos= strmov(pos, " STARTING BY "); pos= pretty_print_str(pos, sql_ex.line_start, sql_ex.line_start_len); } @@ -2079,7 +2089,7 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, num_fields(0),fields(0), field_lens(0),field_block_len(0), table_name(table_name_arg ? table_name_arg : ""), - db(db_arg), fname(ex->file_name) + db(db_arg), fname(ex->file_name), local_fname(FALSE) { time_t end_time; time(&end_time); @@ -2161,22 +2171,24 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, Load_log_event::Load_log_event(const char *buf, uint event_len, const Format_description_log_event *description_event) - :Log_event(buf, description_event),num_fields(0),fields(0), + :Log_event(buf, description_event), num_fields(0), fields(0), field_lens(0),field_block_len(0), - table_name(0),db(0),fname(0) + table_name(0), db(0), fname(0), local_fname(FALSE) { - if (!event_len) // derived class, will call copy_log_event() itself - return; + DBUG_ENTER("Load_log_event"); /* I (Guilhem) manually tested replication of LOAD DATA INFILE for 3.23->5.0, 4.0->5.0 and 5.0->5.0 and it works. */ - copy_log_event(buf, event_len, - ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ? - LOAD_HEADER_LEN + - description_event->common_header_len : - LOAD_HEADER_LEN + LOG_EVENT_HEADER_LEN), - description_event); + if (event_len) + copy_log_event(buf, event_len, + ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ? + LOAD_HEADER_LEN + + description_event->common_header_len : + LOAD_HEADER_LEN + LOG_EVENT_HEADER_LEN), + description_event); + /* otherwise it's a derived class, will call copy_log_event() itself */ + DBUG_VOID_RETURN; } @@ -2188,6 +2200,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, int body_offset, const Format_description_log_event *description_event) { + DBUG_ENTER("Load_log_event::copy_log_event"); uint data_len; char* buf_end = (char*)buf + event_len; /* this is the beginning of the post-header */ @@ -2200,19 +2213,19 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET); if ((int) event_len < body_offset) - return 1; + DBUG_RETURN(1); /* Sql_ex.init() on success returns the pointer to the first byte after the sql_ex structure, which is the start of field lengths array. */ - if (!(field_lens=(uchar*)sql_ex.init((char*)buf + body_offset, - buf_end, - buf[EVENT_TYPE_OFFSET] != LOAD_EVENT))) - return 1; + if (!(field_lens= (uchar*)sql_ex.init((char*)buf + body_offset, + buf_end, + buf[EVENT_TYPE_OFFSET] != LOAD_EVENT))) + DBUG_RETURN(1); data_len = event_len - body_offset; if (num_fields > data_len) // simple sanity check against corruption - return 1; + DBUG_RETURN(1); for (uint i = 0; i < num_fields; i++) field_block_len += (uint)field_lens[i] + 1; @@ -2228,7 +2241,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, DATA INFILE in a completely different way (as a plain-text query) since 4.1 or 5.0 (Dmitri's WL#874) */ - return 0; + DBUG_RETURN(0); } @@ -2246,6 +2259,7 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, bool commented) { + DBUG_ENTER("Load_log_event::print"); if (!short_form) { print_header(file); @@ -2276,43 +2290,27 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev else if (sql_ex.opt_flags & IGNORE_FLAG) fprintf(file," IGNORE "); - fprintf(file, "INTO TABLE %s ", table_name); - if (sql_ex.field_term) - { - fprintf(file, " FIELDS TERMINATED BY "); - pretty_print_str(file, sql_ex.field_term, sql_ex.field_term_len); - } - - if (sql_ex.enclosed) - { - if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) - fprintf(file," OPTIONALLY "); - fprintf(file, " ENCLOSED BY "); - pretty_print_str(file, sql_ex.enclosed, sql_ex.enclosed_len); - } + fprintf(file, "INTO TABLE `%s`", table_name); + fprintf(file, " FIELDS TERMINATED BY "); + pretty_print_str(file, sql_ex.field_term, sql_ex.field_term_len); + + if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) + fprintf(file," OPTIONALLY "); + fprintf(file, " ENCLOSED BY "); + pretty_print_str(file, sql_ex.enclosed, sql_ex.enclosed_len); - if (sql_ex.escaped) - { - fprintf(file, " ESCAPED BY "); - pretty_print_str(file, sql_ex.escaped, sql_ex.escaped_len); - } + fprintf(file, " ESCAPED BY "); + pretty_print_str(file, sql_ex.escaped, sql_ex.escaped_len); - bool line_lexem_added= false; - if (sql_ex.line_term) - { - fprintf(file," LINES TERMINATED BY "); - pretty_print_str(file, sql_ex.line_term, sql_ex.line_term_len); - line_lexem_added= true; - } + fprintf(file," LINES TERMINATED BY "); + pretty_print_str(file, sql_ex.line_term, sql_ex.line_term_len); + if (sql_ex.line_start) { - if (!line_lexem_added) - fprintf(file," LINES"); fprintf(file," STARTING BY "); pretty_print_str(file, sql_ex.line_start, sql_ex.line_start_len); } - if ((long) skip_lines > 0) fprintf(file, " IGNORE %ld LINES", (long) skip_lines); @@ -2333,6 +2331,7 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev } fprintf(file, ";\n"); + DBUG_VOID_RETURN; } #endif /* MYSQL_CLIENT */ @@ -2389,10 +2388,18 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, DBUG_ASSERT(thd->query == 0); thd->query = 0; // Should not be needed thd->query_error = 0; - - /* Saved for InnoDB, see comment in Query_log_event::exec_event() */ - rli->future_group_master_log_pos= log_pos; - /* + clear_all_errors(thd, rli); + if (!use_rli_only_for_errors) + { + /* Saved for InnoDB, see comment in Query_log_event::exec_event() */ +#if MYSQL_VERSION_ID < 50000 + rli->future_group_master_log_pos= log_pos + get_event_len(); +#else + rli->future_group_master_log_pos= log_pos; +#endif + } + + /* We test replicate_*_db rules. Note that we have already prepared the file to load, even if we are going to ignore and delete it now. So it is possible that we did a lot of disk writes for nothing. In other words, a @@ -2417,6 +2424,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, tables.alias = tables.real_name = (char*)table_name; tables.lock_type = TL_WRITE; tables.updating= 1; + // the table will be opened in mysql_load if (table_rules_on && !tables_ok(thd, &tables)) { @@ -2598,12 +2606,13 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, const Format_description_log_event* description_event) :Log_event(buf, description_event) ,new_log_ident(NULL),alloced(0) { + DBUG_ENTER("Rotate_log_event::Rotate_log_event(char*,...)"); // The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET uint8 header_size= description_event->common_header_len; uint8 post_header_len= description_event->post_header_len[ROTATE_EVENT-1]; uint ident_offset; if (event_len < header_size) - return; + DBUG_VOID_RETURN; buf += header_size; pos = post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4; ident_len = (uint)(event_len - @@ -2614,8 +2623,9 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, ident_offset, (uint) ident_len, MYF(MY_WME)))) - return; + DBUG_VOID_RETURN; alloced = 1; + DBUG_VOID_RETURN; } @@ -3098,6 +3108,10 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) } } Item_func_set_user_var e(user_var_name, it); + /* + Item_func_set_user_var can't substitute something else on its place => + 0 can be passed as last argument (reference on item) + */ e.fix_fields(thd, 0, 0); e.update_hash(val, val_len, type, charset, DERIVATION_NONE); free_root(&thd->mem_root,0); @@ -3330,10 +3344,12 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex, char* block_arg, uint block_len_arg, bool using_trans) :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup, using_trans), - fake_base(0),block(block_arg),block_len(block_len_arg), + fake_base(0), block(block_arg), event_buf(0), block_len(block_len_arg), file_id(thd_arg->file_id = mysql_bin_log.next_file_id()) { + DBUG_ENTER("Create_file_log_event"); sql_ex.force_new_format(); + DBUG_VOID_RETURN; } #endif /* !MYSQL_CLIENT */ @@ -3389,18 +3405,20 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, const Format_description_log_event* description_event) :Load_log_event(buf,0,description_event),fake_base(0),block(0),inited_from_old(0) { + DBUG_ENTER("Create_file_log_event::Create_file_log_event(char*,...)"); uint block_offset; uint header_len= description_event->common_header_len; uint8 load_header_len= description_event->post_header_len[LOAD_EVENT-1]; uint8 create_file_header_len= description_event->post_header_len[CREATE_FILE_EVENT-1]; - if (copy_log_event(buf,len, + if (!(event_buf= my_memdup((byte*) buf, len, MYF(MY_WME))) || + copy_log_event(event_buf,len, ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ? load_header_len + header_len : (fake_base ? (header_len+load_header_len) : (header_len+load_header_len) + create_file_header_len)), description_event)) - return; + DBUG_VOID_RETURN; if (description_event->binlog_version!=1) { file_id= uint4korr(buf + @@ -3429,6 +3447,7 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, sql_ex.force_new_format(); inited_from_old = 1; } + DBUG_VOID_RETURN; } @@ -3582,15 +3601,17 @@ Append_block_log_event::Append_block_log_event(const char* buf, uint len, const Format_description_log_event* description_event) :Log_event(buf, description_event),block(0) { + DBUG_ENTER("Append_block_log_event::Append_block_log_event(char*,...)"); uint8 common_header_len= description_event->common_header_len; uint8 append_block_header_len= description_event->post_header_len[APPEND_BLOCK_EVENT-1]; uint total_header_len= common_header_len+append_block_header_len; if (len < total_header_len) - return; + DBUG_VOID_RETURN; file_id= uint4korr(buf + common_header_len + AB_FILE_ID_OFFSET); block= (char*)buf + total_header_len; block_len= len - total_header_len; + DBUG_VOID_RETURN; } @@ -3653,6 +3674,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli) char *p= slave_load_file_stem(fname, file_id, server_id); int fd; int error = 1; + DBUG_ENTER("Append_block_log_event::exec_event"); memcpy(p, ".data", 6); if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY, MYF(MY_WME))) < 0) @@ -3670,7 +3692,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli) err: if (fd >= 0) my_close(fd, MYF(0)); - return error ? error : Log_event::exec_event(rli); + DBUG_RETURN(error ? error : Log_event::exec_event(rli)); } #endif @@ -3880,6 +3902,12 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) lev->exec_event is the place where the table is loaded (it calls mysql_load()). */ + +#if MYSQL_VERSION_ID < 50000 + rli->future_group_master_log_pos= log_pos + get_event_len(); +#else + rli->future_group_master_log_pos= log_pos; +#endif if (lev->exec_event(0,rli,1)) { /* diff --git a/sql/set_var.cc b/sql/set_var.cc index b74bf3e5f7b..2af0a011b58 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -19,18 +19,18 @@ To add a new variable, one has to do the following: - - If the variable is thread specific, add it to 'system_variables' struct. - If not, add it to mysqld.cc and an declaration in 'mysql_priv.h' - - Don't forget to initialize new fields in global_system_variables and - max_system_variables! - Use one of the 'sys_var... classes from set_var.h or write a specific one for the variable type. - Define it in the 'variable definition list' in this file. - If the variable should be changeable or one should be able to access it with @@variable_name, it should be added to the 'list of all variables' - list in this file. + list (sys_variables) in this file. + - If the variable is thread specific, add it to 'system_variables' struct. + If not, add it to mysqld.cc and an declaration in 'mysql_priv.h' - If the variable should be changed from the command line, add a definition of it in the my_option structure list in mysqld.dcc + - Don't forget to initialize new fields in global_system_variables and + max_system_variables! - If the variable should show up in 'show variables' add it to the init_vars[] struct in this file @@ -73,16 +73,21 @@ TYPELIB delay_key_write_typelib= array_elements(delay_key_write_type_names)-1, "", delay_key_write_type_names }; -static bool sys_check_charset(THD *thd, set_var *var); +static int sys_check_charset(THD *thd, set_var *var); static bool sys_update_charset(THD *thd, set_var *var); static void sys_set_default_charset(THD *thd, enum_var_type type); +static int sys_check_ftb_syntax(THD *thd, set_var *var); +static bool sys_update_ftb_syntax(THD *thd, set_var * var); +static void sys_default_ftb_syntax(THD *thd, enum_var_type type); static bool sys_update_init_connect(THD*, set_var*); static void sys_default_init_connect(THD*, enum_var_type type); static bool sys_update_init_slave(THD*, set_var*); static void sys_default_init_slave(THD*, enum_var_type type); static bool set_option_bit(THD *thd, set_var *var); static bool set_option_autocommit(THD *thd, set_var *var); +static int check_log_update(THD *thd, set_var *var); static bool set_log_update(THD *thd, set_var *var); +static int check_pseudo_thread_id(THD *thd, set_var *var); static bool set_log_bin(THD *thd, set_var *var); static void fix_low_priority_updates(THD *thd, enum_var_type type); static void fix_tx_isolation(THD *thd, enum_var_type type); @@ -97,6 +102,8 @@ static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); static void fix_max_binlog_size(THD *thd, enum_var_type type); static void fix_max_relay_log_size(THD *thd, enum_var_type type); static void fix_max_connections(THD *thd, enum_var_type type); +static void fix_thd_mem_root(THD *thd, enum_var_type type); +static void fix_trans_mem_root(THD *thd, enum_var_type type); static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); static byte *get_error_count(THD *thd); @@ -117,13 +124,8 @@ sys_var_character_set_server sys_character_set_server("character_set_server"); sys_var_str sys_charset_system("character_set_system", sys_check_charset, sys_update_charset, - sys_set_default_charset); -sys_var_str sys_init_connect("init_connect", 0, - sys_update_init_connect, - sys_default_init_connect); -sys_var_str sys_init_slave("init_slave", 0, - sys_update_init_slave, - sys_default_init_slave); + sys_set_default_charset, + (char *)my_charset_utf8_general_ci.name); sys_var_character_set_database sys_character_set_database("character_set_database"); sys_var_character_set_client sys_character_set_client("character_set_client"); sys_var_character_set_connection sys_character_set_connection("character_set_connection"); @@ -149,6 +151,17 @@ sys_var_long_ptr sys_expire_logs_days("expire_logs_days", &expire_logs_days); sys_var_bool_ptr sys_flush("flush", &myisam_flush); sys_var_long_ptr sys_flush_time("flush_time", &flush_time); +sys_var_str sys_ft_boolean_syntax("ft_boolean_syntax", + sys_check_ftb_syntax, + sys_update_ftb_syntax, + sys_default_ftb_syntax, + ft_boolean_syntax); +sys_var_str sys_init_connect("init_connect", 0, + sys_update_init_connect, + sys_default_init_connect,0); +sys_var_str sys_init_slave("init_slave", 0, + sys_update_init_slave, + sys_default_init_slave,0); sys_var_thd_ulong sys_interactive_timeout("interactive_timeout", &SV::net_interactive_timeout); sys_var_thd_ulong sys_join_buffer_size("join_buffer_size", @@ -188,26 +201,25 @@ sys_var_long_ptr sys_max_connections("max_connections", fix_max_connections); sys_var_long_ptr sys_max_connect_errors("max_connect_errors", &max_connect_errors); -sys_var_long_ptr sys_max_delayed_threads("max_delayed_threads", - &max_insert_delayed_threads, - fix_max_connections); +sys_var_thd_ulong sys_max_insert_delayed_threads("max_insert_delayed_threads", + &SV::max_insert_delayed_threads); +sys_var_thd_ulong sys_max_delayed_threads("max_delayed_threads", + &SV::max_insert_delayed_threads, + 0, fix_max_connections); sys_var_thd_ulong sys_max_error_count("max_error_count", &SV::max_error_count); sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size", &SV::max_heap_table_size); -/* - sys_pseudo_thread_id has its own class (instead of sys_var_thd_ulong) because - we want a check() function. -*/ -sys_var_pseudo_thread_id sys_pseudo_thread_id("pseudo_thread_id", - &SV::pseudo_thread_id); +sys_var_thd_ulong sys_pseudo_thread_id("pseudo_thread_id", + &SV::pseudo_thread_id, + check_pseudo_thread_id, 0); sys_var_thd_ha_rows sys_max_join_size("max_join_size", &SV::max_join_size, fix_max_join_size); sys_var_thd_ulong sys_max_seeks_for_key("max_seeks_for_key", &SV::max_seeks_for_key); sys_var_thd_ulong sys_max_length_for_sort_data("max_length_for_sort_data", - &SV::max_length_for_sort_data); + &SV::max_length_for_sort_data); #ifndef TO_BE_DELETED /* Alias for max_join_size */ sys_var_thd_ha_rows sys_sql_max_join_size("sql_max_join_size", &SV::max_join_size, @@ -232,13 +244,13 @@ sys_var_thd_ulong sys_net_buffer_length("net_buffer_length", &SV::net_buffer_length); sys_var_thd_ulong sys_net_read_timeout("net_read_timeout", &SV::net_read_timeout, - fix_net_read_timeout); + 0, fix_net_read_timeout); sys_var_thd_ulong sys_net_write_timeout("net_write_timeout", &SV::net_write_timeout, - fix_net_write_timeout); + 0, fix_net_write_timeout); sys_var_thd_ulong sys_net_retry_count("net_retry_count", &SV::net_retry_count, - fix_net_retry_count); + 0, fix_net_retry_count); sys_var_thd_bool sys_new_mode("new", &SV::new_mode); sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords); sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size", @@ -261,13 +273,17 @@ sys_var_long_ptr sys_query_cache_size("query_cache_size", sys_var_thd_ulong sys_range_alloc_block_size("range_alloc_block_size", &SV::range_alloc_block_size); sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size", - &SV::query_alloc_block_size); + &SV::query_alloc_block_size, + 0, fix_thd_mem_root); sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size", - &SV::query_prealloc_size); + &SV::query_prealloc_size, + 0, fix_thd_mem_root); sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size", - &SV::trans_alloc_block_size); + &SV::trans_alloc_block_size, + 0, fix_trans_mem_root); sys_var_thd_ulong sys_trans_prealloc_size("transaction_prealloc_size", - &SV::trans_prealloc_size); + &SV::trans_prealloc_size, + 0, fix_trans_mem_root); #ifdef HAVE_QUERY_CACHE sys_var_long_ptr sys_query_cache_limit("query_cache_limit", @@ -278,6 +294,9 @@ sys_var_long_ptr sys_query_cache_min_res_unit("query_cache_min_res_unit", sys_var_thd_enum sys_query_cache_type("query_cache_type", &SV::query_cache_type, &query_cache_type_typelib); +sys_var_thd_bool +sys_query_cache_wlock_invalidate("query_cache_wlock_invalidate", + &SV::query_cache_wlock_invalidate); #endif /* HAVE_QUERY_CACHE */ sys_var_bool_ptr sys_secure_auth("secure_auth", &opt_secure_auth); sys_var_long_ptr sys_server_id("server_id",&server_id); @@ -313,7 +332,7 @@ sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", #ifdef HAVE_INNOBASE_DB sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct", &srv_max_buf_pool_modified_pct); -#endif +#endif /* Time/date/datetime formats */ @@ -329,50 +348,52 @@ sys_var_thd_date_time_format sys_datetime_format("datetime_format", /* Variables that are bits in THD */ -static sys_var_thd_bit sys_autocommit("autocommit", +static sys_var_thd_bit sys_autocommit("autocommit", 0, set_option_autocommit, OPTION_NOT_AUTOCOMMIT, 1); -static sys_var_thd_bit sys_big_tables("big_tables", +static sys_var_thd_bit sys_big_tables("big_tables", 0, set_option_bit, OPTION_BIG_TABLES); #ifndef TO_BE_DELETED /* Alias for big_tables */ -static sys_var_thd_bit sys_sql_big_tables("sql_big_tables", +static sys_var_thd_bit sys_sql_big_tables("sql_big_tables", 0, set_option_bit, OPTION_BIG_TABLES); #endif -static sys_var_thd_bit sys_big_selects("sql_big_selects", +static sys_var_thd_bit sys_big_selects("sql_big_selects", 0, set_option_bit, OPTION_BIG_SELECTS); -static sys_var_thd_bit sys_log_off("sql_log_off", +static sys_var_thd_bit sys_log_off("sql_log_off", 0, set_option_bit, OPTION_LOG_OFF); static sys_var_thd_bit sys_log_update("sql_log_update", + check_log_update, set_log_update, OPTION_UPDATE_LOG); static sys_var_thd_bit sys_log_binlog("sql_log_bin", - set_log_bin, - OPTION_BIN_LOG); -static sys_var_thd_bit sys_sql_warnings("sql_warnings", + check_log_update, + set_log_bin, + OPTION_BIN_LOG); +static sys_var_thd_bit sys_sql_warnings("sql_warnings", 0, set_option_bit, OPTION_WARNINGS); -static sys_var_thd_bit sys_auto_is_null("sql_auto_is_null", +static sys_var_thd_bit sys_auto_is_null("sql_auto_is_null", 0, set_option_bit, OPTION_AUTO_IS_NULL); -static sys_var_thd_bit sys_safe_updates("sql_safe_updates", +static sys_var_thd_bit sys_safe_updates("sql_safe_updates", 0, set_option_bit, OPTION_SAFE_UPDATES); -static sys_var_thd_bit sys_buffer_results("sql_buffer_result", +static sys_var_thd_bit sys_buffer_results("sql_buffer_result", 0, set_option_bit, OPTION_BUFFER_RESULT); -static sys_var_thd_bit sys_quote_show_create("sql_quote_show_create", +static sys_var_thd_bit sys_quote_show_create("sql_quote_show_create", 0, set_option_bit, OPTION_QUOTE_SHOW_CREATE); -static sys_var_thd_bit sys_foreign_key_checks("foreign_key_checks", +static sys_var_thd_bit sys_foreign_key_checks("foreign_key_checks", 0, set_option_bit, OPTION_NO_FOREIGN_KEY_CHECKS, 1); -static sys_var_thd_bit sys_unique_checks("unique_checks", +static sys_var_thd_bit sys_unique_checks("unique_checks", 0, set_option_bit, OPTION_RELAXED_UNIQUE_CHECKS, 1); @@ -407,6 +428,16 @@ static sys_var_thd_ulong sys_default_week_format("default_week_format", sys_var_thd_ulong sys_group_concat_max_len("group_concat_max_len", &SV::group_concat_max_len); + +/* Read only variables */ + +sys_var_const_str sys_os("version_compile_os", SYSTEM_TYPE); +/* Global read-only variable describing server license */ +sys_var_const_str sys_license("license", LICENSE); + + + + /* List of all variables for initialisation and storage in hash This is sorted in alphabetical order to make it easy to add new variables @@ -445,6 +476,7 @@ sys_var *sys_variables[]= &sys_expire_logs_days, &sys_flush, &sys_flush_time, + &sys_ft_boolean_syntax, &sys_foreign_key_checks, &sys_group_concat_max_len, &sys_identity, @@ -458,6 +490,7 @@ sys_var *sys_variables[]= &sys_key_cache_division_limit, &sys_key_cache_age_threshold, &sys_last_insert_id, + &sys_license, &sys_local_infile, &sys_log_binlog, &sys_log_off, @@ -472,6 +505,7 @@ sys_var *sys_variables[]= &sys_max_connections, &sys_max_delayed_threads, &sys_max_error_count, + &sys_max_insert_delayed_threads, &sys_max_heap_table_size, &sys_max_join_size, &sys_max_length_for_sort_data, @@ -501,6 +535,7 @@ sys_var *sys_variables[]= &sys_query_cache_limit, &sys_query_cache_min_res_unit, &sys_query_cache_type, + &sys_query_cache_wlock_invalidate, #endif /* HAVE_QUERY_CACHE */ &sys_quote_show_create, &sys_rand_seed1, @@ -539,6 +574,7 @@ sys_var *sys_variables[]= &sys_trans_alloc_block_size, &sys_trans_prealloc_size, &sys_tx_isolation, + &sys_os, #ifdef HAVE_INNOBASE_DB &sys_innodb_max_dirty_pages_pct, #endif @@ -556,22 +592,22 @@ struct show_var_st init_vars[]= { {"basedir", mysql_home, SHOW_CHAR}, #ifdef HAVE_BERKELEY_DB {"bdb_cache_size", (char*) &berkeley_cache_size, SHOW_LONG}, - {"bdb_log_buffer_size", (char*) &berkeley_log_buffer_size, SHOW_LONG}, {"bdb_home", (char*) &berkeley_home, SHOW_CHAR_PTR}, - {"bdb_max_lock", (char*) &berkeley_max_lock, SHOW_LONG}, {"bdb_logdir", (char*) &berkeley_logdir, SHOW_CHAR_PTR}, + {"bdb_log_buffer_size", (char*) &berkeley_log_buffer_size, SHOW_LONG}, + {"bdb_max_lock", (char*) &berkeley_max_lock, SHOW_LONG}, {"bdb_shared_data", (char*) &berkeley_shared_data, SHOW_BOOL}, {"bdb_tmpdir", (char*) &berkeley_tmpdir, SHOW_CHAR_PTR}, #endif {sys_binlog_cache_size.name,(char*) &sys_binlog_cache_size, SHOW_SYS}, {sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS}, - {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS}, - {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS}, - {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS}, {sys_character_set_client.name,(char*) &sys_character_set_client, SHOW_SYS}, {sys_character_set_connection.name,(char*) &sys_character_set_connection,SHOW_SYS}, - {"character-sets-dir", mysql_charsets_dir, SHOW_CHAR}, + {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS}, {sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS}, + {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS}, + {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS}, + {"character_sets_dir", mysql_charsets_dir, SHOW_CHAR}, {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, {sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS}, {sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS}, @@ -588,37 +624,36 @@ struct show_var_st init_vars[]= { {sys_expire_logs_days.name, (char*) &sys_expire_logs_days, SHOW_SYS}, {sys_flush.name, (char*) &sys_flush, SHOW_SYS}, {sys_flush_time.name, (char*) &sys_flush_time, SHOW_SYS}, - {"ft_boolean_syntax", (char*) ft_boolean_syntax, SHOW_CHAR}, - {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG}, + {sys_ft_boolean_syntax.name,(char*) &ft_boolean_syntax, SHOW_CHAR}, {"ft_max_word_len", (char*) &ft_max_word_len, SHOW_LONG}, + {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG}, {"ft_query_expansion_limit",(char*) &ft_query_expansion_limit, SHOW_LONG}, {"ft_stopword_file", (char*) &ft_stopword_file, SHOW_CHAR_PTR}, + {sys_group_concat_max_len.name, (char*) &sys_group_concat_max_len, SHOW_SYS}, {"have_bdb", (char*) &have_berkeley_db, SHOW_HAVE}, - {"have_crypt", (char*) &have_crypt, SHOW_HAVE}, {"have_compress", (char*) &have_compress, SHOW_HAVE}, + {"have_crypt", (char*) &have_crypt, SHOW_HAVE}, {"have_innodb", (char*) &have_innodb, SHOW_HAVE}, {"have_isam", (char*) &have_isam, SHOW_HAVE}, - {"have_raid", (char*) &have_raid, SHOW_HAVE}, - {"have_symlink", (char*) &have_symlink, SHOW_HAVE}, {"have_openssl", (char*) &have_openssl, SHOW_HAVE}, {"have_query_cache", (char*) &have_query_cache, SHOW_HAVE}, - {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR}, + {"have_raid", (char*) &have_raid, SHOW_HAVE}, + {"have_symlink", (char*) &have_symlink, SHOW_HAVE}, {"init_connect", (char*) &sys_init_connect, SHOW_SYS}, + {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR}, {"init_slave", (char*) &sys_init_slave, SHOW_SYS}, #ifdef HAVE_INNOBASE_DB {"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG }, - {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG }, {"innodb_buffer_pool_awe_mem_mb", (char*) &innobase_buffer_pool_awe_mem_mb, SHOW_LONG }, + {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG }, {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR}, {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR}, - {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG }, - {"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG }, - {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG }, - {"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG }, - {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT}, {"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL}, + {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG }, {"innodb_file_per_table", (char*) &innobase_file_per_table, SHOW_MY_BOOL}, + {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT}, {"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR}, + {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG }, {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG }, {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR}, {"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL}, @@ -626,60 +661,67 @@ struct show_var_st init_vars[]= { {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONG}, {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG}, {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, - {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, + {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, + {"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG }, + {"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG }, #endif {sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS}, {sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS}, {sys_key_buffer_size.name, (char*) &sys_key_buffer_size, SHOW_SYS}, + {sys_key_cache_age_threshold.name, (char*) &sys_key_cache_age_threshold, + SHOW_SYS}, {sys_key_cache_block_size.name, (char*) &sys_key_cache_block_size, - SHOW_SYS}, + SHOW_SYS}, {sys_key_cache_division_limit.name, (char*) &sys_key_cache_division_limit, - SHOW_SYS}, - {sys_key_cache_age_threshold.name, (char*) &sys_key_cache_age_threshold, - SHOW_SYS}, + SHOW_SYS}, {"language", language, SHOW_CHAR}, - {"large_files_support", (char*) &opt_large_files, SHOW_BOOL}, + {"large_files_support", (char*) &opt_large_files, SHOW_BOOL}, + {sys_license.name, (char*) &sys_license, SHOW_SYS}, {sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS}, #ifdef HAVE_MLOCKALL {"locked_in_memory", (char*) &locked_in_memory, SHOW_BOOL}, #endif {"log", (char*) &opt_log, SHOW_BOOL}, - {"log_update", (char*) &opt_update_log, SHOW_BOOL}, {"log_bin", (char*) &opt_bin_log, SHOW_BOOL}, + {"log_error", (char*) log_error_file, SHOW_CHAR}, #ifdef HAVE_REPLICATION {"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL}, #endif {"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL}, + {"log_update", (char*) &opt_update_log, SHOW_BOOL}, {sys_log_warnings.name, (char*) &sys_log_warnings, SHOW_SYS}, {sys_long_query_time.name, (char*) &sys_long_query_time, SHOW_SYS}, {sys_low_priority_updates.name, (char*) &sys_low_priority_updates, SHOW_SYS}, - {"lower_case_table_names", (char*) &lower_case_table_names, SHOW_MY_BOOL}, + {"lower_case_file_system", (char*) &lower_case_file_system, SHOW_BOOL}, + {"lower_case_table_names", (char*) &lower_case_table_names, SHOW_INT}, {sys_max_allowed_packet.name,(char*) &sys_max_allowed_packet, SHOW_SYS}, {sys_max_binlog_cache_size.name,(char*) &sys_max_binlog_cache_size, SHOW_SYS}, {sys_max_binlog_size.name, (char*) &sys_max_binlog_size, SHOW_SYS}, - {sys_max_connections.name, (char*) &sys_max_connections, SHOW_SYS}, {sys_max_connect_errors.name, (char*) &sys_max_connect_errors, SHOW_SYS}, - {sys_max_error_count.name, (char*) &sys_max_error_count, SHOW_SYS}, + {sys_max_connections.name, (char*) &sys_max_connections, SHOW_SYS}, {sys_max_delayed_threads.name,(char*) &sys_max_delayed_threads, SHOW_SYS}, + {sys_max_error_count.name, (char*) &sys_max_error_count, SHOW_SYS}, {sys_max_heap_table_size.name,(char*) &sys_max_heap_table_size, SHOW_SYS}, + {sys_max_insert_delayed_threads.name, + (char*) &sys_max_insert_delayed_threads, SHOW_SYS}, {sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS}, - {sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS}, - {sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS}, {sys_max_length_for_sort_data.name, (char*) &sys_max_length_for_sort_data, SHOW_SYS}, + {sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS}, + {sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS}, {sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS}, - {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS}, {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS}, + {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS}, {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS}, {sys_myisam_max_extra_sort_file_size.name, (char*) &sys_myisam_max_extra_sort_file_size, SHOW_SYS}, {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size, SHOW_SYS}, + {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads, SHOW_SYS}, - {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS}, #ifdef __NT__ {"named_pipe", (char*) &opt_enable_named_pipe, SHOW_MY_BOOL}, @@ -692,10 +734,9 @@ struct show_var_st init_vars[]= { {sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS}, {"open_files_limit", (char*) &open_files_limit, SHOW_LONG}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, - {"log_error", (char*) log_error_file, SHOW_CHAR}, {"port", (char*) &mysqld_port, SHOW_INT}, - {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, + {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size, SHOW_SYS}, #ifdef HAVE_QUERY_CACHE @@ -704,7 +745,6 @@ struct show_var_st init_vars[]= { SHOW_SYS}, {sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS}, {sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS}, - {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, #endif /* HAVE_QUERY_CACHE */ {sys_query_prealloc_size.name, (char*) &sys_query_prealloc_size, SHOW_SYS}, {sys_range_alloc_block_size.name, (char*) &sys_range_alloc_block_size, @@ -716,18 +756,18 @@ struct show_var_st init_vars[]= { {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, #endif {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, + {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, #ifdef HAVE_SMEM {"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL}, {"shared_memory_base_name", (char*) &shared_memory_base_name, SHOW_CHAR_PTR}, #endif {sys_server_id.name, (char*) &sys_server_id, SHOW_SYS}, -#ifdef HAVE_REPLICATION - {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, -#endif - {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS}, {"skip_external_locking", (char*) &my_disable_locking, SHOW_MY_BOOL}, {"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL}, {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL}, +#ifdef HAVE_REPLICATION + {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, +#endif {sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS}, #ifdef HAVE_SYS_UN_H {"socket", (char*) &mysqld_unix_port, SHOW_CHAR_PTR}, @@ -742,7 +782,6 @@ struct show_var_st init_vars[]= { {"thread_concurrency", (char*) &concurrency, SHOW_LONG}, #endif {"thread_stack", (char*) &thread_stack, SHOW_LONG}, - {sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS}, {sys_time_format.name, (char*) &sys_time_format, SHOW_SYS}, #ifdef HAVE_TZNAME {"timezone", time_zone, SHOW_CHAR}, @@ -752,13 +791,14 @@ struct show_var_st init_vars[]= { {sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size, SHOW_SYS}, {sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS}, + {sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS}, {"version", server_version, SHOW_CHAR}, #ifdef HAVE_BERKELEY_DB {"version_bdb", (char*) DB_VERSION_STRING, SHOW_CHAR}, #endif {"version_comment", (char*) MYSQL_COMPILATION_COMMENT, SHOW_CHAR}, {"version_compile_machine", (char*) MACHINE_TYPE, SHOW_CHAR}, - {"version_compile_os", (char*) SYSTEM_TYPE, SHOW_CHAR}, + {sys_os.name, (char*) &sys_os, SHOW_SYS}, {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS}, {NullS, NullS, SHOW_LONG} }; @@ -770,6 +810,18 @@ bool sys_var::check(THD *thd, set_var *var) return 0; } +bool sys_var_str::check(THD *thd, set_var *var) +{ + int res; + if (!check_func) + return 0; + + if ((res=(*check_func)(thd, var)) < 0) + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, + var->value->str_value.ptr()); + return res; +} + /* Functions to check and update variables */ @@ -786,15 +838,12 @@ bool sys_var::check(THD *thd, set_var *var) bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex, set_var *var) { - char *res= 0, *old_value; - uint new_length= 0; - /* If the string is "", delete old init command */ - if (var && (new_length= var->value->str_value.length())) - { - if (!(res= my_strdup_with_length((byte*) var->value->str_value.ptr(), - new_length, MYF(0)))) - return 1; - } + char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0); + uint new_length= (var ? var->value->str_value.length() : 0); + if (!old_value) + old_value= (char*) ""; + if (!(res= my_strdup_with_length(old_value, new_length, MYF(0)))) + return 1; /* Replace the old value in such a way that the any thread using the value will work. @@ -832,13 +881,37 @@ static void sys_default_init_slave(THD* thd, enum_var_type type) update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, 0); } +static int sys_check_ftb_syntax(THD *thd, set_var *var) +{ + if (thd->master_access & SUPER_ACL) + return ft_boolean_check_syntax_string((byte*) var->value->str_value.c_ptr()) ? + -1 : 0; + else + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + return 1; + } +} + +static bool sys_update_ftb_syntax(THD *thd, set_var * var) +{ + strmake(ft_boolean_syntax, var->value->str_value.c_ptr(), + sizeof(ft_boolean_syntax)-1); + return 0; +} + +static void sys_default_ftb_syntax(THD *thd, enum_var_type type) +{ + strmake(ft_boolean_syntax, opt_ft_boolean_syntax, + sizeof(ft_boolean_syntax)-1); +} /* The following 3 functions need to be changed in 4.1 when we allow one to change character sets */ -static bool sys_check_charset(THD *thd, set_var *var) +static int sys_check_charset(THD *thd, set_var *var) { return 0; } @@ -1014,7 +1087,26 @@ static void fix_max_relay_log_size(THD *thd, enum_var_type type) static void fix_max_connections(THD *thd, enum_var_type type) { - resize_thr_alarm(max_connections + max_insert_delayed_threads + 10); + resize_thr_alarm(max_connections + + global_system_variables.max_insert_delayed_threads + 10); +} + + +static void fix_thd_mem_root(THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + reset_root_defaults(&thd->mem_root, + thd->variables.query_alloc_block_size, + thd->variables.query_prealloc_size); +} + + +static void fix_trans_mem_root(THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + reset_root_defaults(&thd->transaction.mem_root, + thd->variables.trans_alloc_block_size, + thd->variables.trans_prealloc_size); } bool sys_var_long_ptr::update(THD *thd, set_var *var) @@ -1082,6 +1174,11 @@ byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) return (byte*) enum_names->type_names[*value]; } +bool sys_var_thd_ulong::check(THD *thd, set_var *var) +{ + return (sys_var_thd::check(thd, var) || + (check_func && (*check_func)(thd, var))); +} bool sys_var_thd_ulong::update(THD *thd, set_var *var) { @@ -1333,9 +1430,8 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) { if (var_type != OPT_DEFAULT) { - net_printf(thd, - var_type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : - ER_GLOBAL_VARIABLE, name); + net_printf(thd, ER_INCORRECT_GLOBAL_LOCAL_VAR, + name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL"); return 0; } /* As there was no local variable, return the global value */ @@ -1412,6 +1508,11 @@ byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type, return (byte*) enum_names->type_names[tmp]; } +bool sys_var_thd_bit::check(THD *thd, set_var *var) +{ + return (check_enum(thd, var, &bool_typelib) || + (check_func && (*check_func)(thd, var))); +} bool sys_var_thd_bit::update(THD *thd, set_var *var) { @@ -1580,7 +1681,10 @@ bool sys_var_collation::check(THD *thd, set_var *var) String str(buff,sizeof(buff), system_charset_info), *res; if (!(res=var->value->val_str(&str))) - res= &my_empty_string; + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL"); + return 1; + } if (!(tmp=get_charset_by_name(res->c_ptr(),MYF(0)))) { @@ -1602,7 +1706,7 @@ bool sys_var_character_set::check(THD *thd, set_var *var) { if (!nullable) { - my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "NULL"); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL"); return 1; } tmp= NULL; @@ -1876,7 +1980,7 @@ byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type, key_cache= &zero_key_cache; return (byte*) key_cache + offset ; } - + bool sys_var_key_buffer_size::update(THD *thd, set_var *var) { @@ -1971,14 +2075,14 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var) pthread_mutex_lock(&LOCK_global_system_variables); KEY_CACHE *key_cache= get_key_cache(base_name); - + if (!key_cache && !(key_cache= create_key_cache(base_name->str, base_name->length))) { error= 1; goto end; } - + /* Abort if some other thread is changing the key cache TODO: This should be changed so that we wait until the previous @@ -2080,28 +2184,12 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type, return (byte*) &thd->current_insert_id; } -bool sys_var_pseudo_thread_id::check(THD *thd, set_var *var) -{ - var->save_result.ulonglong_value= var->value->val_int(); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (thd->master_access & SUPER_ACL) - return 0; - else - { - my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - return 1; - } -#else - return 0; -#endif -} - #ifdef HAVE_REPLICATION bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) { int result= 0; - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); pthread_mutex_lock(&active_mi->rli.run_lock); if (active_mi->rli.slave_running) { @@ -2109,7 +2197,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) result=1; } pthread_mutex_unlock(&active_mi->rli.run_lock); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); var->save_result.ulong_value= (ulong) var->value->val_int(); return result; } @@ -2117,7 +2205,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) { - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); pthread_mutex_lock(&active_mi->rli.run_lock); /* The following test should normally never be true as we test this @@ -2131,7 +2219,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) pthread_mutex_unlock(&active_mi->rli.data_lock); } pthread_mutex_unlock(&active_mi->rli.run_lock); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); return 0; } #endif /* HAVE_REPLICATION */ @@ -2194,6 +2282,17 @@ static bool set_option_autocommit(THD *thd, set_var *var) return 0; } +static int check_log_update(THD *thd, set_var *var) +{ +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (!(thd->master_access & SUPER_ACL)) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + return 1; + } +#endif + return 0; +} static bool set_log_update(THD *thd, set_var *var) { @@ -2228,6 +2327,21 @@ static bool set_log_bin(THD *thd, set_var *var) return 0; } +static int check_pseudo_thread_id(THD *thd, set_var *var) +{ + var->save_result.ulonglong_value= var->value->val_int(); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (thd->master_access & SUPER_ACL) + return 0; + else + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + return 1; + } +#else + return 0; +#endif +} static byte *get_warning_count(THD *thd) { @@ -2460,7 +2574,7 @@ int set_var_user::check(THD *thd) { /* Item_func_set_user_var can't substitute something else on its place => - 0 can be passed as last argument + 0 can be passed as last argument (reference on item) */ return (user_var_item->fix_fields(thd, 0, (Item**) 0) || user_var_item->check()) ? -1 : 0; diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 05c34236d03..ce444c8fad1 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -301,35 +301,6 @@ character-set=latin1 "Truncated wrong %-.32s value: '%-.128s'" "Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" "Invalid ON UPDATE clause for '%-.64s' field", -"Row %ld was truncated; It contained more data than there where input columns", -"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", -"Data truncated, out of range for column '%s' at row %ld", -"Data truncated for column '%s' at row %ld", -"Using storage engine %s for table '%s'", -"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", -"Can't revoke all privileges, grant for one or more of the requested users", -"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", -"Illegal mix of collations for operation '%s'", -"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", -"Unknown collation: '%-.64s'", -"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.", -"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format", -"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d", -"Wrong parameter or combination of parameters for START SLAVE UNTIL", -"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart", -"SQL thread is not to be started so UNTIL options are ignored", -"Incorrect index name '%-.100s'", -"Incorrect catalog name '%-.100s'", -"Query cache failed to set size %lu, new query cache size is %lu", -"Column '%-.64s' cannot be part of FULLTEXT index", -"Unknown key cache '%-.100s'", -"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", -"Unknown table engine '%s'", -"'%s' is deprecated. Use '%s' instead.", -"The target table %-.100s of the %s is not updatable.", -"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" -"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 03174c83657..5ae00ef6421 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -309,35 +309,6 @@ character-set=latin1 "Truncated wrong %-.32s value: '%-.128s'" "Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" "Invalid ON UPDATE clause for '%-.64s' field", -"Row %ld was truncated; It contained more data than there where input columns", -"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", -"Data truncated, out of range for column '%s' at row %ld", -"Data truncated for column '%s' at row %ld", -"Using storage engine %s for table '%s'", -"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", -"Can't revoke all privileges, grant for one or more of the requested users", -"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", -"Illegal mix of collations for operation '%s'", -"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", -"Unknown collation: '%-.64s'", -"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.", -"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format", -"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d", -"Wrong parameter or combination of parameters for START SLAVE UNTIL", -"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart", -"SQL thread is not to be started so UNTIL options are ignored", -"Incorrect index name '%-.100s'", -"Incorrect catalog name '%-.100s'", -"Query cache failed to set size %lu, new query cache size is %lu", -"Column '%-.64s' cannot be part of FULLTEXT index", -"Unknown key cache '%-.100s'", -"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", -"Unknown table engine '%s'", -"'%s' is deprecated. Use '%s' instead.", -"The target table %-.100s of the %s is not updatable.", -"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" -"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index f475d270a54..234d9cf3916 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -298,40 +298,6 @@ character-set=latin1 "Truncated wrong %-.32s value: '%-.128s'" "Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" "Invalid ON UPDATE clause for '%-.64s' field", -"ZLIB: Not enough memory available for zlib", -"ZLIB: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", -"ZLIB: Input data was corrupted for zlib", -"%d line(s) was(were) cut by group_concat()", -"Row %ld doesn't contain data for all columns", -"Row %ld was truncated; It contained more data than there where input columns", -"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", -"Data truncated, out of range for column '%s' at row %ld", -"Data truncated for column '%s' at row %ld", -"Using storage engine %s for table '%s'", -"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", -"Can't revoke all privileges, grant for one or more of the requested users", -"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", -"Illegal mix of collations for operation '%s'", -"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", -"Unknown collation: '%-.64s'", -"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.", -"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format", -"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d", -"Wrong parameter or combination of parameters for START SLAVE UNTIL", -"It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL. Otherwise you will get problems if you get an unexpected slave's mysqld restart", -"SQL thread is not to be started so UNTIL options are ignored", -"Incorrect index name '%-.100s'", -"Incorrect catalog name '%-.100s'", -"Query cache failed to set size %lu, new query cache size is %lu", -"Column '%-.64s' cannot be part of FULLTEXT index", -"Unknown key cache '%-.100s'", -"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", -"Unknown table engine '%s'", -"'%s' is deprecated. Use '%s' instead.", -"The target table %-.100s of the %s is not updatable.", -"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working", -"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 161e2c6863d..275abf8690e 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -303,35 +303,6 @@ character-set=latin7 "Truncated wrong %-.32s value: '%-.128s'" "Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" "Invalid ON UPDATE clause for '%-.64s' field", -"Row %ld was truncated; It contained more data than there where input columns", -"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", -"Data truncated, out of range for column '%s' at row %ld", -"Data truncated for column '%s' at row %ld", -"Using storage engine %s for table '%s'", -"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", -"Can't revoke all privileges, grant for one or more of the requested users", -"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", -"Illegal mix of collations for operation '%s'", -"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", -"Unknown collation: '%-.64s'", -"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.", -"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format", -"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d", -"Wrong parameter or combination of parameters for START SLAVE UNTIL", -"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart", -"SQL thread is not to be started so UNTIL options are ignored", -"Incorrect index name '%-.100s'", -"Incorrect catalog name '%-.100s'", -"Query cache failed to set size %lu, new query cache size is %lu", -"Column '%-.64s' cannot be part of FULLTEXT index", -"Unknown key cache '%-.100s'", -"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", -"Unknown table engine '%s'", -"'%s' is deprecated. Use '%s' instead.", -"The target table %-.100s of the %s is not updatable.", -"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working" -"MySQL is started in --skip-grant-tables mode. You can't use this command" "Can't create a %s from within another stored routine" "%s %s already exists" "%s %s does not exist" diff --git a/sql/sp.cc b/sql/sp.cc index 2be9ceeaad3..0d0152658b7 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -548,7 +548,7 @@ db_show_routine_status(THD *thd, int type, const char *wild) } /* Init fields */ - setup_tables(&tables, 0); + setup_tables(&tables); for (used_field= &used_fields[0]; used_field->field_name; used_field++) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3e1a41ed049..01e31b3e7a4 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1351,7 +1351,7 @@ bool delayed_insert::handle_inserts(void) on this table until all entries has been processed */ if (group_count++ >= max_rows && (row= rows.head()) && - (!(row->log_query & DELAYED_LOG_BIN && using_bin_log) || + (!(row->log_query & using_bin_log) || row->query)) { group_count=0; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4b0ca67a549..54cf052643f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1982,7 +1982,6 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, } // Must be written before unlock - mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { thd->clear_error(); |