From 3231241f837729781339f68c270252ac80d11a52 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 15:58:34 +0300 Subject: Rename decimal -> decimal_t, decimal_digit -> decimal_digit_t --- sql/log_event.cc | 6 +++--- sql/my_decimal.cc | 4 ++-- sql/my_decimal.h | 46 +++++++++++++++++++++++----------------------- 3 files changed, 28 insertions(+), 28 deletions(-) (limited to 'sql') diff --git a/sql/log_event.cc b/sql/log_event.cc index ba018e859c1..3581626ca5b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3336,7 +3336,7 @@ bool User_var_log_event::write(IO_CACHE* file) dec->fix_buffer_pointer(); buf2[0]= (char)(dec->intg + dec->frac); buf2[1]= (char)dec->frac; - decimal2bin((decimal*)val, buf2+2, buf2[0], buf2[1]); + decimal2bin((decimal_t*)val, buf2+2, buf2[0], buf2[1]); val_len= decimal_bin_size(buf2[0], buf2[1]) + 2; break; } @@ -3403,8 +3403,8 @@ void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* las int str_len= sizeof(str_buf) - 1; int precision= (int)val[0]; int scale= (int)val[1]; - decimal_digit dec_buf[10]; - decimal dec; + decimal_digit_t dec_buf[10]; + decimal_t dec; dec.len= 10; dec.buf= dec_buf; diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 334c40c0f70..19b6abd7243 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -88,7 +88,7 @@ int my_decimal2string(uint mask, const my_decimal *d, int result; if (str->alloc(length)) return check_result(mask, E_DEC_OOM); - result= decimal2string((decimal*) d, (char*) str->ptr(), + result= decimal2string((decimal_t*) d, (char*) str->ptr(), &length, fixed_prec, fixed_dec, filler); str->length(length); @@ -172,7 +172,7 @@ int str2my_decimal(uint mask, const char *from, uint length, charset= &my_charset_bin; } from_end= end= (char*) from+length; - err= string2decimal((char *)from, (decimal *)decimal_value, &end); + err= string2decimal((char *)from, (decimal_t*) decimal_value, &end); if (end != from_end && !err) { /* Give warining if there is something other than end space */ diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 44530acd0cc..03801390d82 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -69,15 +69,15 @@ inline uint my_decimal_size(uint precision, uint scale) /* - my_decimal class limits 'decimal' type to what we need in MySQL + my_decimal class limits 'decimal_t' type to what we need in MySQL It contains internally all necessary space needed by the instance so no extra memory is needed. One should call fix_buffer_pointer() function when he moves my_decimal objects in memory */ -class my_decimal :public decimal +class my_decimal :public decimal_t { - decimal_digit buffer[DECIMAL_BUFF_LENGTH]; + decimal_digit_t buffer[DECIMAL_BUFF_LENGTH]; public: @@ -97,8 +97,8 @@ public: } void fix_buffer_pointer() { buf= buffer; } - bool sign() const { return decimal::sign; } - void sign(bool s) { decimal::sign= s; } + bool sign() const { return decimal_t::sign; } + void sign(bool s) { decimal_t::sign= s; } }; @@ -165,7 +165,7 @@ inline int binary2my_decimal(uint mask, const char *bin, my_decimal *d, int prec, int scale) { - return check_result(mask, bin2decimal((char *)bin, (decimal*) d, prec, + return check_result(mask, bin2decimal((char *)bin, (decimal_t*) d, prec, scale)); } @@ -173,7 +173,7 @@ int binary2my_decimal(uint mask, const char *bin, my_decimal *d, int prec, inline int my_decimal_set_zero(my_decimal *d) { - decimal_make_zero(((decimal*) d)); + decimal_make_zero(((decimal_t*) d)); return 0; } @@ -181,7 +181,7 @@ int my_decimal_set_zero(my_decimal *d) inline bool my_decimal_is_zero(const my_decimal *decimal_value) { - return decimal_is_zero((decimal*) decimal_value); + return decimal_is_zero((decimal_t*) decimal_value); } @@ -189,7 +189,7 @@ inline int my_decimal_round(uint mask, const my_decimal *from, int scale, bool truncate, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, scale, + return check_result(mask, decimal_round((decimal_t*) from, to, scale, (truncate ? TRUNCATE : HALF_UP))); } @@ -197,14 +197,14 @@ int my_decimal_round(uint mask, const my_decimal *from, int scale, inline int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, 0, FLOOR)); + return check_result(mask, decimal_round((decimal_t*) from, to, 0, FLOOR)); } inline int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, 0, CEILING)); + return check_result(mask, decimal_round((decimal_t*) from, to, 0, CEILING)); } @@ -219,7 +219,7 @@ int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag, { my_decimal rounded; /* decimal_round can return only E_DEC_TRUNCATED */ - decimal_round((decimal*)d, &rounded, 0, HALF_UP); + decimal_round((decimal_t*)d, &rounded, 0, HALF_UP); return check_result(mask, (unsigned_flag ? decimal2ulonglong(&rounded, (ulonglong *)l) : decimal2longlong(&rounded, l))); @@ -230,14 +230,14 @@ inline int my_decimal2double(uint mask, const my_decimal *d, double *result) { /* No need to call check_result as this will always succeed */ - return decimal2double((decimal*) d, result); + return decimal2double((decimal_t*) d, result); } inline int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end) { - return check_result(mask, string2decimal(str, (decimal*) d, end)); + return check_result(mask, string2decimal(str, (decimal_t*) d, end)); } @@ -255,7 +255,7 @@ int string2my_decimal(uint mask, const String *str, my_decimal *d) inline int double2my_decimal(uint mask, double val, my_decimal *d) { - return check_result(mask, double2decimal(val, (decimal*) d)); + return check_result(mask, double2decimal(val, (decimal_t*) d)); } @@ -269,7 +269,7 @@ int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d) inline -void my_decimal_neg(st_decimal *arg) +void my_decimal_neg(decimal_t *arg) { decimal_neg(arg); } @@ -279,7 +279,7 @@ inline int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_add((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_add((decimal_t*) a, (decimal_t*) b, res)); } @@ -287,7 +287,7 @@ inline int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_sub((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_sub((decimal_t*) a, (decimal_t*) b, res)); } @@ -295,7 +295,7 @@ inline int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mul((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_mul((decimal_t*) a, (decimal_t*) b, res)); } @@ -303,7 +303,7 @@ inline int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b, int div_scale_inc) { - return check_result(mask, decimal_div((decimal*) a, (decimal*) b, res, + return check_result(mask, decimal_div((decimal_t*) a, (decimal_t*) b, res, div_scale_inc)); } @@ -312,7 +312,7 @@ inline int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mod((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_mod((decimal_t*) a, (decimal_t*) b, res)); } @@ -320,14 +320,14 @@ int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, inline int my_decimal_cmp(const my_decimal *a, const my_decimal *b) { - return decimal_cmp((decimal*) a, (decimal*) b); + return decimal_cmp((decimal_t*) a, (decimal_t*) b); } inline void max_my_decimal(my_decimal *to, int precision, int frac) { DBUG_ASSERT(precision <= DECIMAL_MAX_LENGTH); - max_decimal(precision, frac, (decimal*) to); + max_decimal(precision, frac, (decimal_t*) to); } #endif /*my_decimal_h*/ -- cgit v1.2.1 From 04a410d4e9a502f9950688fefd35451a84d0f1d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 16:31:15 +0100 Subject: Code cleanup: should use 'element_count' here, see include/my_tree.h (Change done by Ramil and sent via IRC) --- sql/item_sum.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_sum.cc b/sql/item_sum.cc index dd95a83a921..8ee9dc0859b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2158,7 +2158,7 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2) } -static int count_distinct_walk(void *elem, unsigned int count, void *arg) +static int count_distinct_walk(void *elem, element_count count, void *arg) { (*((ulonglong*)arg))++; return 0; -- cgit v1.2.1 From 802c41e04d0b4bb193abfff1b7084d3a6c971df6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Mar 2005 23:41:28 +0200 Subject: Cleanups during review of code Fixed newly introduced bug in rollup client/mysqldump.c: Safer buffer allocation Removed wrong assert mysql-test/r/olap.result: more tests mysql-test/t/olap.test: more tests sql/handler.cc: Simple cleanup Fixed wrong check for next digit (wrong debug output) sql/item.cc: Replace shrink_to_length() with mark_as_const() as the former allowed one to do changes to the string sql/item_sum.cc: Change reference to pointer Trivial optimzation of testing 'allways_null' sql/mysqld.cc: Proper indentation of comment sql/sql_select.cc: Fixed newly introduced bug in rollup sql/sql_string.h: Remove not needed 'shrink_to_length()' Added 'mark_as_const()' to be used when one want to ensure that a string is not changed --- sql/handler.cc | 14 +++++++++----- sql/item.cc | 14 ++------------ sql/item_sum.cc | 18 +++++++----------- sql/mysqld.cc | 7 ++++--- sql/sql_select.cc | 16 +++++++++------- sql/sql_string.h | 5 +---- 6 files changed, 32 insertions(+), 42 deletions(-) (limited to 'sql') diff --git a/sql/handler.cc b/sql/handler.cc index df0d7704163..98fc2be2f8a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -762,14 +762,13 @@ static char* xid_to_str(char *buf, XID *xid) for (i=0; i < xid->gtrid_length+xid->bqual_length; i++) { uchar c=(uchar)xid->data[i]; - bool is_next_dig; + /* is_next_dig is set if next character is a number */ + bool is_next_dig= FALSE; if (i < XIDDATASIZE) { - char ch=xid->data[i+1]; - is_next_dig=(c >= '0' && c <='9'); + char ch= xid->data[i+1]; + is_next_dig= (ch >= '0' && ch <='9'); } - else - is_next_dig=FALSE; if (i == xid->gtrid_length) { *s++='\''; @@ -782,6 +781,11 @@ static char* xid_to_str(char *buf, XID *xid) if (c < 32 || c > 126) { *s++='\\'; + /* + If next character is a number, write current character with + 3 octal numbers to ensure that the next number is not seen + as part of the octal number + */ if (c > 077 || is_next_dig) *s++=_dig_vec_lower[c >> 6]; if (c > 007 || is_next_dig) diff --git a/sql/item.cc b/sql/item.cc index 64fc2696f1f..91113db175e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -586,18 +586,8 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) return NULL; } conv->str_value.copy(); - /* - The above line executes str_value.realloc() internally, - which alligns Alloced_length using ALLIGN_SIZE. - In the case of Item_string::str_value we don't want - Alloced_length to be longer than str_length. - Otherwise, some functions like Item_func_concat::val_str() - try to reuse str_value as a buffer for concatenation result - for optimization purposes, so our string constant become - corrupted. See bug#8785 for more details. - Let's shrink Alloced_length to str_length to avoid this problem. - */ - conv->str_value.shrink_to_length(); + /* Ensure that no one is going to change the result string */ + conv->str_value.mark_as_const(); return conv; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 4b7415b6829..0676632d477 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2671,11 +2671,11 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), TABLE *table= item->table; char *record= (char*) table->record[0] + table->s->null_bytes; String tmp(table->record[1], table->s->reclength, default_charset_info), tmp2; - String &result= item->result; + String *result= &item->result; Item **arg= item->args, **arg_end= item->args + item->arg_count_field; - if (result.length()) - result.append(*item->separator); + if (result->length()) + result->append(*item->separator); tmp.length(0); @@ -2702,14 +2702,14 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), else res= (*arg)->val_str(&tmp); if (res) - result.append(*res); + result->append(*res); } /* stop if length of result more than max_length */ - if (result.length() > item->max_length) + if (result->length() > item->max_length) { item->count_cut_values++; - result.length(item->max_length); + result->length(item->max_length); item->warning_for_row= TRUE; return 1; } @@ -2910,8 +2910,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) MYF(0)); return TRUE; } - if (!args) /* allocation in constructor may fail */ - return TRUE; thd->allow_sum_func= 0; maybe_null= 0; @@ -2972,12 +2970,10 @@ bool Item_func_group_concat::setup(THD *thd) if (item->null_value) { always_null= 1; - break; + DBUG_RETURN(FALSE); } } } - if (always_null) - DBUG_RETURN(FALSE); List all_fields(list); /* diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6747b79703b..ecaa7ace841 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3310,9 +3310,10 @@ default_service_handling(char **argv, int main(int argc, char **argv) { - /* When several instances are running on the same machine, we - need to have an unique named hEventShudown through the - application PID e.g.: MySQLShutdown1890; MySQLShutdown2342 + /* + When several instances are running on the same machine, we + need to have an unique named hEventShudown through the + application PID e.g.: MySQLShutdown1890; MySQLShutdown2342 */ int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name, "MySQLShutdown"), 10); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1e05400e88e..f8caabaead4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10145,20 +10145,18 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), join->sum_funcs_end[send_group_parts]); if (join->having && join->having->val_int() == 0) error= -1; - else if ((error=table->file->write_row(table->record[0]))) + else if ((error= table->file->write_row(table->record[0]))) { if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param, error, 0)) DBUG_RETURN(-1); } - if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0) + if (join->rollup.state != ROLLUP::STATE_NONE) { if (join->rollup_write_data((uint) (idx+1), table)) - error= 1; + DBUG_RETURN(-1); } - if (error > 0) - DBUG_RETURN(-1); if (end_of_records) DBUG_RETURN(0); } @@ -12685,17 +12683,21 @@ bool JOIN::rollup_make_fields(List &fields_arg, List &sel_fields, { /* Check if this is something that is part of this group by */ ORDER *group_tmp; - for (group_tmp= start_group, i-- ; + for (group_tmp= start_group, i= pos ; group_tmp ; group_tmp= group_tmp->next, i++) { if (*group_tmp->item == item) { + Item_null_result *null_item; /* This is an element that is used by the GROUP BY and should be set to NULL in this level */ item->maybe_null= 1; // Value will be null sometimes - Item_null_result *null_item= rollup.null_items[i]; + null_item= rollup.null_items[i]; + DBUG_ASSERT(null_item->result_field == 0 || + null_item->result_field == + ((Item_field *) item)->result_field); null_item->result_field= ((Item_field *) item)->result_field; item= null_item; break; diff --git a/sql/sql_string.h b/sql/sql_string.h index fc1e9f171b6..7ece9885040 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -84,6 +84,7 @@ public: inline char& operator [] (uint32 i) const { return Ptr[i]; } inline void length(uint32 len) { str_length=len ; } inline bool is_empty() { return (str_length == 0); } + inline void mark_as_const() { Alloced_length= 0;} inline const char *ptr() const { return Ptr; } inline char *c_ptr() { @@ -205,10 +206,6 @@ public: } } } - inline void shrink_to_length() - { - Alloced_length= str_length; - } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { -- cgit v1.2.1 From ac46bf77aecd84eae40400afd5ffb79e93ab4b24 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 00:26:12 +0100 Subject: Last part of WL#1062: better replication of timezones: no more use of SET ONE_SHOT; storing tz info directly in event (if this info is needed), it's now allowed to have different global tz on master and slave. client/mysqlbinlog.cc: we need MAX_TIME_ZONE_NAME_LENGTH when processing log_event.h, and it's declared in mysql_priv.h mysql-test/r/rpl_timezone.result: result update mysql-test/t/rpl_timezone-slave.opt: Now that we can have different global value of timezone on master and slave, let's test it. mysql-test/t/rpl_timezone.test: Tests of the new replication of timezones: checking the output of mysqlbinlog, replication of CONVERT_TZ(). sql/ha_innodb.cc: No very fast shutdown on Netware (anyway it's disabled on all platforms, but this is so that we don't forget to keep it disabled on Netware in the future). sql/log.cc: No more need to write SET ONE_SHOT to binlog for character set and timezone (as we store this info directly nin the Query_log_event now). sql/log_event.cc: Exclude ::write() methods if MYSQL_CLIENT. Storing timezone info in the Query_log_event in master. Re-reading it in slave. Small code cleanups. I plan to not store the end 0 of catalog in binlog events soon. sql/log_event.h: replication of time zones: a place for tz info in Query_log_event, in LAST_EVENT_INFO. Plus if we are compiling a client, we don't need the ::write() methods, so keeping them out (of mysqlbinlog.cc; keeping them in, resulted in problem that mysqlbinlog does not know Timezone structure). sql/mysql_priv.h: moving this define from tztime.h (tztime.h has things which are too much for a client like mysqlbinlog). sql/set_var.cc: It's now allowed to change global value of charset or timezone even if using binlogging or if being a slave. Making CONVERT_TZ(,,@@session.time_zone) replicate. sql/set_var.h: these ::check()s are not needed anymore (changing global charset or timezone is now allowed even if binlogging or slave) sql/slave.cc: No more need to check for same global timezone if master is 5.x (ok, strictly speaking if it is > 5.0.3 but this is alpha). sql/slave.h: a function to wrap settings of charset to default. sql/tztime.cc: Adaptation of my_tz_find() to the case where it's not called from inside a query (i.e. cannot join its tz tables to the query's ones): this variant opens the tz tables itself, reads from them, and closes them. This is presently only used by the slave SQL thread (when it sets the tz before executing a query). sql/tztime.h: declaration of new function, plus moving symbol to mysql_priv.h for easier usage in mysqlbinlog (Dmitri, pardon me). BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- sql/ha_innodb.cc | 4 ++ sql/log.cc | 51 ----------------- sql/log_event.cc | 165 ++++++++++++++++++++++++++++++++++++++----------------- sql/log_event.h | 45 +++++++++++++-- sql/mysql_priv.h | 6 ++ sql/set_var.cc | 56 ++++--------------- sql/set_var.h | 6 -- sql/slave.cc | 21 +++++-- sql/slave.h | 1 + sql/tztime.cc | 56 ++++++++++++++++++- sql/tztime.h | 7 +-- 11 files changed, 248 insertions(+), 170 deletions(-) (limited to 'sql') diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 870ad1af52b..24f1579544b 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1307,6 +1307,9 @@ innobase_end(void) } #endif if (innodb_inited) { + +#ifndef __NETWARE__ /* NetWare can't close unclosed files, kill remaining + threads, etc, so we disable the very fast shutdown */ if (innobase_very_fast_shutdown) { srv_very_fast_shutdown = TRUE; fprintf(stderr, @@ -1314,6 +1317,7 @@ innobase_end(void) "InnoDB: the InnoDB buffer pool to data files. At the next mysqld startup\n" "InnoDB: InnoDB will do a crash recovery!\n"); } +#endif innodb_inited = 0; if (innobase_shutdown_for_mysql() != DB_SUCCESS) { diff --git a/sql/log.cc b/sql/log.cc index 43786990797..0c1d6836cce 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1638,57 +1638,6 @@ bool MYSQL_LOG::write(Log_event *event_info) if (thd) { -#if MYSQL_VERSION_ID < 50003 - /* - To make replication of charsets working in 4.1 we are writing values - of charset related variables before every statement in the binlog, - if values of those variables differ from global server-wide defaults. - We are using SET ONE_SHOT command so that the charset vars get reset - to default after the first non-SET statement. - In the next 5.0 this won't be needed as we will use the new binlog - format to store charset info. - */ - if ((thd->variables.character_set_client->number != - global_system_variables.collation_server->number) || - (thd->variables.character_set_client->number != - thd->variables.collation_connection->number) || - (thd->variables.collation_server->number != - thd->variables.collation_connection->number)) - { - char buf[200]; - int written= my_snprintf(buf, sizeof(buf)-1, - "SET ONE_SHOT CHARACTER_SET_CLIENT=%u,\ -COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", - (uint) thd->variables.character_set_client->number, - (uint) thd->variables.collation_connection->number, - (uint) thd->variables.collation_database->number, - (uint) thd->variables.collation_server->number); - Query_log_event e(thd, buf, written, 0, FALSE); - if (e.write(file)) - goto err; - } -#endif - /* - We use the same ONE_SHOT trick for making replication of time zones - working in 4.1. Again in 5.0 we have better means for doing this. - - TODO: we should do like we now do with charsets (no more ONE_SHOT; - logging in each event in a compact format). Dmitri says we can do: - if (time_zone_used) write the timezone to binlog (in a format to be - defined). - */ - if (thd->time_zone_used && - thd->variables.time_zone != global_system_variables.time_zone) - { - char buf[MAX_TIME_ZONE_NAME_LENGTH + 26]; - char *buf_end= strxmov(buf, "SET ONE_SHOT TIME_ZONE='", - thd->variables.time_zone->get_name()->ptr(), - "'", NullS); - Query_log_event e(thd, buf, buf_end - buf, 0, FALSE); - if (e.write(file)) - goto err; - } - if (thd->last_insert_id_used) { Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, diff --git a/sql/log_event.cc b/sql/log_event.cc index ba018e859c1..666c2427ac5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -506,8 +506,6 @@ void Log_event::init_show_field_list(List* field_list) field_list->push_back(new Item_empty_string("Info", 20)); } -#endif /* !MYSQL_CLIENT */ - /* Log_event::write() @@ -592,7 +590,6 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) */ -#ifndef MYSQL_CLIENT int Log_event::read_log_event(IO_CACHE* file, String* packet, pthread_mutex_t* log_lock) { @@ -956,6 +953,7 @@ void Query_log_event::pack_info(Protocol *protocol) } #endif +#ifndef MYSQL_CLIENT /* Query_log_event::write() @@ -973,7 +971,8 @@ bool Query_log_event::write(IO_CACHE* file) 1+8+ // code of sql_mode and sql_mode 1+1+FN_REFLEN+ // code of catalog and catalog length and catalog 1+4+ // code of autoinc and the 2 autoinc variables - 1+6 // code of charset and charset + 1+6+ // code of charset and charset + 1+1+MAX_TIME_ZONE_NAME_LENGTH // code of tz and tz length and tz name ], *start, *start_of_status; ulong event_length; @@ -1030,20 +1029,20 @@ bool Query_log_event::write(IO_CACHE* file) start_of_status= start= buf+QUERY_HEADER_LEN; if (flags2_inited) { - *(start++)= Q_FLAGS2_CODE; + *start++= Q_FLAGS2_CODE; int4store(start, flags2); start+= 4; } if (sql_mode_inited) { - *(start++)= Q_SQL_MODE_CODE; + *start++= Q_SQL_MODE_CODE; int8store(start, (ulonglong)sql_mode); start+= 8; } - if (catalog_len >= 0) // i.e. "catalog inited" (false for 4.0 events) + if (catalog_len) // i.e. "catalog inited" (false for 4.0 events) { - *(start++)= Q_CATALOG_CODE; - *(start++)= (uchar) catalog_len; + *start++= Q_CATALOG_CODE; + *start++= (uchar) catalog_len; bmove(start, catalog, catalog_len); start+= catalog_len; /* @@ -1071,15 +1070,24 @@ bool Query_log_event::write(IO_CACHE* file) } if (charset_inited) { - *(start++)= Q_CHARSET_CODE; + *start++= Q_CHARSET_CODE; memcpy(start, charset, 6); start+= 6; } + if (time_zone_len) + { + /* In the TZ sys table, column Name is of length 64 so this should be ok */ + DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH); + *start++= Q_TIME_ZONE_CODE; + *start++= time_zone_len; + memcpy(start, time_zone_str, time_zone_len); + start+= time_zone_len; + } /* Here there could be code like if (command-line-option-which-says-"log_this_variable" && inited) { - *(start++)= Q_THIS_VARIABLE_CODE; + *start++= Q_THIS_VARIABLE_CODE; int4store(start, this_variable); start+= 4; } @@ -1108,8 +1116,6 @@ bool Query_log_event::write(IO_CACHE* file) /* Query_log_event::Query_log_event() */ - -#ifndef MYSQL_CLIENT Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, bool suppress_use) @@ -1150,6 +1156,18 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, int2store(charset, thd_arg->variables.character_set_client->number); int2store(charset+2, thd_arg->variables.collation_connection->number); int2store(charset+4, thd_arg->variables.collation_server->number); + if (thd_arg->time_zone_used) + { + /* + Note that our event becomes dependent on the Time_zone object + representing the time zone. Fortunately such objects are never deleted + or changed during mysqld's lifetime. + */ + time_zone_len= thd_arg->variables.time_zone->get_name()->length(); + time_zone_str= thd_arg->variables.time_zone->get_name()->ptr(); + } + else + time_zone_len= 0; DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode)); } #endif /* MYSQL_CLIENT */ @@ -1163,15 +1181,17 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, Query_log_event::Query_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event, Log_event_type event_type) - :Log_event(buf, description_event), data_buf(0), query(NullS), catalog(NullS), + :Log_event(buf, description_event), data_buf(0), query(NullS), db(NullS), catalog_len(0), status_vars_len(0), flags2_inited(0), sql_mode_inited(0), charset_inited(0), - auto_increment_increment(1), auto_increment_offset(1) + auto_increment_increment(1), auto_increment_offset(1), + time_zone_len(0) { ulong data_len; uint32 tmp; uint8 common_header_len, post_header_len; - const char *start, *end; + char *start; + const char *end; DBUG_ENTER("Query_log_event::Query_log_event(char*,...)"); common_header_len= description_event->common_header_len; @@ -1191,7 +1211,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET); - db_len = (uint)buf[Q_DB_LEN_OFFSET]; + db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars error_code = uint2korr(buf + Q_ERR_CODE_OFFSET); /* @@ -1217,7 +1237,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, /* variable-part: the status vars; only in MySQL 5.0 */ start= (char*) (buf+post_header_len); - end= (char*) (start+status_vars_len); + end= (const char*) (start+status_vars_len); for (const uchar* pos= (const uchar*) start; pos < (const uchar*) end;) { switch (*pos++) { @@ -1240,8 +1260,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, break; } case Q_CATALOG_CODE: - catalog_len= *pos; - if (catalog_len) + if ((catalog_len= *pos)) catalog= (char*) pos+1; // Will be copied later pos+= catalog_len+2; break; @@ -1257,6 +1276,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, pos+= 6; break; } + case Q_TIME_ZONE_CODE: + { + if ((time_zone_len= *pos)) + time_zone_str= (char *)(pos+1); + pos+= time_zone_len+1; + break; + } default: /* That's why you must write status vars in growing order of code */ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ @@ -1265,24 +1291,29 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, } } - /* A 2nd variable part; this is common to all versions */ - - if (!(start= data_buf = (char*) my_malloc(catalog_len + data_len +2, MYF(MY_WME)))) + if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 + + time_zone_len + 1 + + data_len + 1, MYF(MY_WME)))) DBUG_VOID_RETURN; - if (catalog) // If catalog is given + if (catalog_len) // If catalog is given { - memcpy((char*) start, catalog, catalog_len+1); // Copy name and end \0 + memcpy(start, catalog, catalog_len+1); // Copy name and end \0 catalog= start; start+= catalog_len+1; } + if (time_zone_len) + { + memcpy(start, time_zone_str, time_zone_len); + time_zone_str= start; + start+= time_zone_len; + *start++= 0; + } + /* A 2nd variable part; this is common to all versions */ memcpy((char*) start, end, data_len); // Copy db and query - ((char*) start)[data_len]= '\0'; // End query with \0 (For safetly) + start[data_len]= '\0'; // End query with \0 (For safetly) db= start; query= start + db_len + 1; q_len= data_len - db_len -1; - /* This is used to detect wrong parsing. Could be removed in the future. */ - DBUG_PRINT("info", ("catalog: '%s' len: %u db: '%s' len: %u q_len: %lu", - catalog, (uint) catalog_len, db, (uint) db_len,q_len)); DBUG_VOID_RETURN; } @@ -1390,6 +1421,8 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, last_event_info->auto_increment_offset= auto_increment_offset; } + /* TODO: print the catalog when we feature SET CATALOG */ + if (likely(charset_inited)) { if (unlikely(!last_event_info->charset_inited)) /* first Query event */ @@ -1410,6 +1443,14 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, memcpy(last_event_info->charset, charset, 6); } } + if (time_zone_len) + { + if (bcmp(last_event_info->time_zone_str, time_zone_str, time_zone_len+1)) + { + fprintf(file,"SET @@session.time_zone='%s';\n", time_zone_str); + memcpy(last_event_info->time_zone_str, time_zone_str, time_zone_len+1); + } + } } @@ -1443,7 +1484,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query alloced block (see Query_log_event::exec_event()). Same for thd->db. Thank you. */ - thd->catalog= (char*) catalog; + thd->catalog= catalog_len ? (char *) catalog : (char *)""; thd->db_length= db_len; thd->db= (char*) rewrite_db(db, &thd->db_length); thd->variables.auto_increment_increment= auto_increment_increment; @@ -1513,20 +1554,28 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query get_charset(uint2korr(charset+4), MYF(MY_WME)))) { /* - We updated the thd->variables with nonsensical values (0), and the - thread is not guaranteed to terminate now (as it may be configured - to ignore EE_UNKNOWN_CHARSET);if we're going to execute a next - statement we'll have a new charset info with it, so no problem to - have stored 0 in thd->variables. But we invalidate cached - charset to force a check next time (otherwise if next time - charset is unknown again we won't detect it). + We updated the thd->variables with nonsensical values (0). Let's + set them to something safe (i.e. which avoids crash), and we'll + stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to + ignore this error). */ - rli->cached_charset_invalidate(); + set_slave_thread_default_charset(thd, rli); goto compare_errors; } thd->update_charset(); // for the charset change to take effect } } + if (time_zone_len) + { + String tmp(time_zone_str, time_zone_len, &my_charset_bin); + if (!(thd->variables.time_zone= + my_tz_find_with_opening_tz_tables(thd, &tmp))) + { + my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr()); + thd->variables.time_zone= global_system_variables.time_zone; + goto compare_errors; + } + } /* Execute the query (note that we bypass dispatch_command()) */ mysql_parse(thd, thd->query, thd->query_length); @@ -1751,6 +1800,7 @@ Start_log_event_v3::Start_log_event_v3(const char* buf, Start_log_event_v3::write() */ +#ifndef MYSQL_CLIENT bool Start_log_event_v3::write(IO_CACHE* file) { char buff[START_V3_HEADER_LEN]; @@ -1760,6 +1810,7 @@ bool Start_log_event_v3::write(IO_CACHE* file) return (write_header(file, sizeof(buff)) || my_b_safe_write(file, (byte*) buff, sizeof(buff))); } +#endif /* @@ -1975,7 +2026,7 @@ Format_description_log_event(const char* buf, DBUG_VOID_RETURN; } - +#ifndef MYSQL_CLIENT bool Format_description_log_event::write(IO_CACHE* file) { /* @@ -1992,6 +2043,7 @@ bool Format_description_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buff)) || my_b_safe_write(file, buff, sizeof(buff))); } +#endif /* SYNOPSIS @@ -2208,6 +2260,8 @@ void Load_log_event::pack_info(Protocol *protocol) #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ +#ifndef MYSQL_CLIENT + /* Load_log_event::write_data_header() */ @@ -2249,7 +2303,6 @@ bool Load_log_event::write_data_body(IO_CACHE* file) Load_log_event::Load_log_event() */ -#ifndef MYSQL_CLIENT Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, const char *db_arg, const char *table_name_arg, List &fields_arg, @@ -2863,6 +2916,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, Rotate_log_event::write() */ +#ifndef MYSQL_CLIENT bool Rotate_log_event::write(IO_CACHE* file) { char buf[ROTATE_HEADER_LEN]; @@ -2871,7 +2925,7 @@ bool Rotate_log_event::write(IO_CACHE* file) my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) || my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); } - +#endif /* Rotate_log_event::exec_event() @@ -2929,17 +2983,10 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli) master is 4.0 then the events are in the slave's format (conversion). */ set_slave_thread_options(thd); + set_slave_thread_default_charset(thd, rli); thd->variables.sql_mode= global_system_variables.sql_mode; thd->variables.auto_increment_increment= thd->variables.auto_increment_offset= 1; - thd->variables.character_set_client= - global_system_variables.character_set_client; - thd->variables.collation_connection= - global_system_variables.collation_connection; - thd->variables.collation_server= - global_system_variables.collation_server; - thd->update_charset(); - rli->cached_charset_invalidate(); } pthread_mutex_unlock(&rli->data_lock); pthread_cond_broadcast(&rli->data_cond); @@ -3001,6 +3048,7 @@ const char* Intvar_log_event::get_var_type_name() Intvar_log_event::write() */ +#ifndef MYSQL_CLIENT bool Intvar_log_event::write(IO_CACHE* file) { byte buf[9]; @@ -3009,6 +3057,7 @@ bool Intvar_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -3093,6 +3142,7 @@ Rand_log_event::Rand_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool Rand_log_event::write(IO_CACHE* file) { byte buf[16]; @@ -3101,6 +3151,7 @@ bool Rand_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif #ifdef MYSQL_CLIENT @@ -3164,11 +3215,13 @@ Xid_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool Xid_log_event::write(IO_CACHE* file) { return write_header(file, sizeof(xid)) || my_b_safe_write(file, (byte*) &xid, sizeof(xid)); } +#endif #ifdef MYSQL_CLIENT @@ -3302,6 +3355,7 @@ User_var_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool User_var_log_event::write(IO_CACHE* file) { char buf[UV_NAME_LEN_SIZE]; @@ -3361,6 +3415,7 @@ bool User_var_log_event::write(IO_CACHE* file) my_b_safe_write(file, (byte*) buf1, buf1_length) || my_b_safe_write(file, (byte*) pos, val_len)); } +#endif /* @@ -3634,6 +3689,7 @@ int Slave_log_event::get_data_size() } +#ifndef MYSQL_CLIENT bool Slave_log_event::write(IO_CACHE* file) { ulong event_length= get_data_size(); @@ -3644,6 +3700,7 @@ bool Slave_log_event::write(IO_CACHE* file) return (write_header(file, event_length) || my_b_safe_write(file, (byte*) mem_pool, event_length)); } +#endif void Slave_log_event::init_from_mem_pool(int data_size) @@ -3770,7 +3827,6 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex, sql_ex.force_new_format(); DBUG_VOID_RETURN; } -#endif /* !MYSQL_CLIENT */ /* @@ -3815,6 +3871,7 @@ bool Create_file_log_event::write_base(IO_CACHE* file) return res; } +#endif /* !MYSQL_CLIENT */ /* Create_file_log_event ctor @@ -4042,6 +4099,7 @@ Append_block_log_event::Append_block_log_event(const char* buf, uint len, Append_block_log_event::write() */ +#ifndef MYSQL_CLIENT bool Append_block_log_event::write(IO_CACHE* file) { byte buf[APPEND_BLOCK_HEADER_LEN]; @@ -4050,6 +4108,7 @@ bool Append_block_log_event::write(IO_CACHE* file) my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) || my_b_safe_write(file, (byte*) block, block_len)); } +#endif /* @@ -4171,6 +4230,7 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, uint len, Delete_file_log_event::write() */ +#ifndef MYSQL_CLIENT bool Delete_file_log_event::write(IO_CACHE* file) { byte buf[DELETE_FILE_HEADER_LEN]; @@ -4178,6 +4238,7 @@ bool Delete_file_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -4265,6 +4326,7 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, uint len, Execute_load_log_event::write() */ +#ifndef MYSQL_CLIENT bool Execute_load_log_event::write(IO_CACHE* file) { byte buf[EXEC_LOAD_HEADER_LEN]; @@ -4272,6 +4334,7 @@ bool Execute_load_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -4475,6 +4538,7 @@ ulong Execute_load_query_log_event::get_post_header_size_for_derived() } +#ifndef MYSQL_CLIENT bool Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) { @@ -4485,6 +4549,7 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) *(buf + 4 + 4 + 4)= (char)dup_handling; return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN); } +#endif #ifdef MYSQL_CLIENT diff --git a/sql/log_event.h b/sql/log_event.h index 43a801da851..72142db0aa7 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -237,6 +237,7 @@ struct sql_ex_info #define Q_CATALOG_CODE 2 #define Q_AUTO_INCREMENT 3 #define Q_CHARSET_CODE 4 +#define Q_TIME_ZONE_CODE 5 /* Intvar event post-header */ @@ -448,6 +449,7 @@ typedef struct st_last_event_info ulong auto_increment_increment, auto_increment_offset; bool charset_inited; char charset[6]; // 3 variables, each of them storable in 2 bytes + char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH]; st_last_event_info() :flags2_inited(0), sql_mode_inited(0), auto_increment_increment(1),auto_increment_offset(1), charset_inited(0) @@ -459,6 +461,7 @@ typedef struct st_last_event_info */ bzero(db, sizeof(db)); bzero(charset, sizeof(charset)); + bzero(time_zone_str, sizeof(time_zone_str)); } } LAST_EVENT_INFO; #endif @@ -583,6 +586,7 @@ public: my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); } +#ifndef MYSQL_CLIENT bool write_header(IO_CACHE* file, ulong data_length); virtual bool write(IO_CACHE* file) { @@ -590,13 +594,14 @@ public: write_data_header(file) || write_data_body(file)); } - virtual bool is_artificial_event() { return 0; } virtual bool write_data_header(IO_CACHE* file) { return 0; } virtual bool write_data_body(IO_CACHE* file __attribute__((unused))) { return 0; } +#endif virtual Log_event_type get_type_code() = 0; virtual bool is_valid() const = 0; + virtual bool is_artificial_event() { return 0; } inline bool get_cache_stmt() { return cache_stmt; } Log_event(const char* buf, const Format_description_log_event* description_event); virtual ~Log_event() { free_temp_buf();} @@ -672,7 +677,7 @@ public: concerned) from here. */ - int catalog_len; // <= 255 char; -1 means uninited + uint catalog_len; // <= 255 char; 0 means uninited /* We want to be able to store a variable number of N-bit status vars: @@ -714,6 +719,8 @@ public: ulong sql_mode; ulong auto_increment_increment, auto_increment_offset; char charset[6]; + uint time_zone_len; /* 0 means uninited */ + const char *time_zone_str; #ifndef MYSQL_CLIENT @@ -737,12 +744,13 @@ public: ~Query_log_event() { if (data_buf) - { my_free((gptr) data_buf, MYF(0)); - } } Log_event_type get_type_code() { return QUERY_EVENT; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); + virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; } +#endif bool is_valid() const { return query != 0; } /* @@ -751,7 +759,6 @@ public: */ virtual ulong get_post_header_size_for_derived() { return 0; } /* Writes derived event-specific part of post header. */ - virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; } }; #ifdef HAVE_REPLICATION @@ -790,7 +797,9 @@ public: int get_data_size(); bool is_valid() const { return master_host != 0; } Log_event_type get_type_code() { return SLAVE_EVENT; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif }; #endif /* HAVE_REPLICATION */ @@ -885,8 +894,10 @@ public: { return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT; } +#ifndef MYSQL_CLIENT bool write_data_header(IO_CACHE* file); bool write_data_body(IO_CACHE* file); +#endif bool is_valid() const { return table_name != 0; } int get_data_size() { @@ -962,7 +973,9 @@ public: const Format_description_log_event* description_event); ~Start_log_event_v3() {} Log_event_type get_type_code() { return START_EVENT_V3;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } int get_data_size() { @@ -1004,7 +1017,9 @@ public: const Format_description_log_event* description_event); ~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); } Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN : @@ -1054,7 +1069,9 @@ public: Log_event_type get_type_code() { return INTVAR_EVENT;} const char* get_var_type_name(); int get_data_size() { return 9; /* sizeof(type) + sizeof(val) */;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1092,7 +1109,9 @@ class Rand_log_event: public Log_event ~Rand_log_event() {} Log_event_type get_type_code() { return RAND_EVENT;} int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1127,7 +1146,9 @@ class Xid_log_event: public Log_event ~Xid_log_event() {} Log_event_type get_type_code() { return XID_EVENT;} int get_data_size() { return sizeof(xid); } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1169,7 +1190,9 @@ public: User_var_log_event(const char* buf, const Format_description_log_event* description_event); ~User_var_log_event() {} Log_event_type get_type_code() { return USER_VAR_EVENT;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1239,7 +1262,9 @@ public: Log_event_type get_type_code() { return ROTATE_EVENT;} int get_data_size() { return ident_len + ROTATE_HEADER_LEN;} bool is_valid() const { return new_log_ident != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif }; @@ -1299,6 +1324,7 @@ public: 4 + 1 + block_len); } bool is_valid() const { return inited_from_old || block != 0; } +#ifndef MYSQL_CLIENT bool write_data_header(IO_CACHE* file); bool write_data_body(IO_CACHE* file); /* @@ -1306,6 +1332,7 @@ public: write it as Load event - used on the slave */ bool write_base(IO_CACHE* file); +#endif }; @@ -1352,7 +1379,9 @@ public: Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;} int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;} bool is_valid() const { return block != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1386,7 +1415,9 @@ public: Log_event_type get_type_code() { return DELETE_FILE_EVENT;} int get_data_size() { return DELETE_FILE_HEADER_LEN ;} bool is_valid() const { return file_id != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1419,7 +1450,9 @@ public: Log_event_type get_type_code() { return EXEC_LOAD_EVENT;} int get_data_size() { return EXEC_LOAD_HEADER_LEN ;} bool is_valid() const { return file_id != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1507,7 +1540,9 @@ public: bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; } ulong get_post_header_size_for_derived(); +#ifndef MYSQL_CLIENT bool write_post_header_for_derived(IO_CACHE* file); +#endif }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index ba9f382fc33..64e7b2cdccf 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -257,6 +257,12 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; /* Flag set if setup_tables already done */ #define OPTION_SETUP_TABLES_DONE (1L << 30) +/* + Maximum length of time zone name that we support + (Time zone name is char(64) in db). mysqlbinlog needs it. +*/ +#define MAX_TIME_ZONE_NAME_LENGTH 72 + /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT diff --git a/sql/set_var.cc b/sql/set_var.cc index 23dbb22399b..9e74c9452da 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2095,27 +2095,6 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type) } } -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) -bool sys_var_character_set_server::check(THD *thd, set_var *var) -{ - /* - To be perfect we should fail even if we are a 5.0.3 slave, a 4.1 master, - and user wants to change our global character set variables. Because - replicating a 4.1 assumes those are not changed. But that's not easy to - do. - */ - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), - "character set, collation"); - return 1; - } - return sys_var_character_set::check(thd,var); -} -#endif - CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type) { @@ -2208,20 +2187,6 @@ void sys_var_collation_database::set_default(THD *thd, enum_var_type type) } } -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) -bool sys_var_collation_server::check(THD *thd, set_var *var) -{ - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), - "character set, collation"); - return 1; - } - return sys_var_collation::check(thd,var); -} -#endif bool sys_var_collation_server::update(THD *thd, set_var *var) { @@ -2560,16 +2525,6 @@ bool sys_var_thd_time_zone::check(THD *thd, set_var *var) String str(buff, sizeof(buff), &my_charset_latin1); String *res= var->value->val_str(&str); -#if defined(HAVE_REPLICATION) - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), "time zone"); - return 1; - } -#endif - if (!(var->save_result.time_zone= my_tz_find(res, thd->lex->time_zone_tables_used))) { @@ -2605,7 +2560,18 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, if (type == OPT_GLOBAL) return (byte *)(global_system_variables.time_zone->get_name()->ptr()); else + { + /* + This is an ugly fix for replication: we don't replicate properly queries + invoking system variables' values to update tables; but + CONVERT_TZ(,,@@session.time_zone) is so popular that we make it + replicable (i.e. we tell the binlog code to store the session + timezone). If it's the global value which was used we can't replicate + (binlog code stores session value only). + */ + thd->time_zone_used= 1; return (byte *)(thd->variables.time_zone->get_name()->ptr()); + } } diff --git a/sql/set_var.h b/sql/set_var.h index d78c228c142..585f6df3547 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -565,9 +565,6 @@ class sys_var_character_set_server :public sys_var_character_set public: sys_var_character_set_server(const char *name_arg) : sys_var_character_set(name_arg) {} -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) - bool check(THD *thd, set_var *var); -#endif void set_default(THD *thd, enum_var_type type); CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; @@ -603,9 +600,6 @@ class sys_var_collation_server :public sys_var_collation { public: sys_var_collation_server(const char *name_arg) :sys_var_collation(name_arg) {} -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) - bool check(THD *thd, set_var *var); -#endif bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); diff --git a/sql/slave.cc b/sql/slave.cc index 73dd0fd13c3..9e42206d4a3 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1421,7 +1421,7 @@ not always make sense; please check the manual before using it)."; We don't test equality of global collation_database either as it's is going to be deprecated (made read-only) in 4.1 very soon. The test is only relevant if master < 5.0.3 (we'll test only if it's older - than the 5 branch; < 5.0.3 was alpha...), as >= 5.0.3 master stores + than the 5 branch; < 5.0.4 were alpha...), as >= 5.0.4 master stores charset info in each binlog event. We don't do it for 3.23 because masters <3.23.50 hang on SELECT @@unknown_var (BUG#7965 - see changelog of 3.23.50). So finally we @@ -1456,11 +1456,10 @@ be equal for replication to work"; such check will broke everything for them. (And now everything will work for them because by default both their master and slave will have 'SYSTEM' time zone). - - TODO: when the new replication of timezones is sorted out with Dmitri, - change >= '4' to == '4'. + This check is only necessary for 4.x masters (and < 5.0.4 masters but + those were alpha). */ - if ((*mysql->server_version >= '4') && + if ((*mysql->server_version == '4') && !mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) && (master_res= mysql_store_result(mysql))) { @@ -2770,6 +2769,18 @@ void set_slave_thread_options(THD* thd) thd->variables.completion_type= 0; } +void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli) +{ + thd->variables.character_set_client= + global_system_variables.character_set_client; + thd->variables.collation_connection= + global_system_variables.collation_connection; + thd->variables.collation_server= + global_system_variables.collation_server; + thd->update_charset(); + rli->cached_charset_invalidate(); +} + /* init_slave_thread() */ diff --git a/sql/slave.h b/sql/slave.h index ee5541ffe08..bc41cd4deca 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -562,6 +562,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos, int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, const char** errmsg); void set_slave_thread_options(THD* thd); +void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli); void rotate_relay_log(MASTER_INFO* mi); extern "C" pthread_handler_decl(handle_slave_io,arg); diff --git a/sql/tztime.cc b/sql/tztime.cc index bd9d49f0ab0..983c630071e 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2178,7 +2178,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) DBUG_PRINT("enter", ("time zone name='%s'", name ? ((String *)name)->c_ptr() : "NULL")); - DBUG_ASSERT(!time_zone_tables_exist || tz_tables); + DBUG_ASSERT(!time_zone_tables_exist || tz_tables || current_thd->slave_thread); if (!name) DBUG_RETURN(0); @@ -2210,7 +2210,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) (const byte *)name->ptr(), name->length()))) result_tz= tmp_tzname->tz; - else if (time_zone_tables_exist) + else if (time_zone_tables_exist && tz_tables) result_tz= tz_load_from_open_tables(name, tz_tables); } @@ -2219,6 +2219,58 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) DBUG_RETURN(result_tz); } + +/* + A more standalone version of my_tz_find(): will open tz tables if needed. + This is so far only used by replication, where time zone setting does not + happen in the usual query context. + + SYNOPSIS + my_tz_find_with_opening_tz_tables() + thd - pointer to thread's THD structure + name - time zone specification + + DESCRIPTION + This function tries to find a time zone which matches the named passed in + argument. If it fails, it will open time zone tables and re-try the + search. + This function is needed for the slave SQL thread, which does not do the + addition of time zone tables which is usually done during query parsing + (as time zone setting by slave does not happen in mysql_parse() but + before). So it needs to open tz tables by itself if needed. + See notes of my_tz_find() as they also apply here. + + RETURN VALUE + Pointer to corresponding Time_zone object. 0 - in case of bad time zone + specification or other error. + +*/ +Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name) +{ + Time_zone *tz; + DBUG_ENTER("my_tz_find_with_opening_tables"); + DBUG_ASSERT(thd); + DBUG_ASSERT(thd->slave_thread); // intended for use with slave thread only + if (!(tz= my_tz_find(name, 0)) && time_zone_tables_exist) + { + /* + Probably we have not loaded this time zone yet so let us look it up in + our time zone tables. Note that if we don't have tz tables on this + slave, we don't even try. + */ + TABLE_LIST tables[4]; + TABLE_LIST *dummy; + TABLE_LIST **dummyp= &dummy; + tz_init_table_list(tables, &dummyp); + if (simple_open_n_lock_tables(thd, tables)) + DBUG_RETURN(0); + tz= my_tz_find(name, tables); + /* We need to close tables _now_ to not pollute coming query */ + close_thread_tables(thd); + } + DBUG_RETURN(tz); +} + #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ diff --git a/sql/tztime.h b/sql/tztime.h index caf663fc8cb..777e521d761 100644 --- a/sql/tztime.h +++ b/sql/tztime.h @@ -61,6 +61,7 @@ extern Time_zone * my_tz_UTC; extern Time_zone * my_tz_SYSTEM; extern TABLE_LIST * my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr); extern Time_zone * my_tz_find(const String *name, TABLE_LIST *tz_tables); +extern Time_zone * my_tz_find_with_opening_tz_tables(THD *thd, const String *name); extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap); extern void my_tz_free(); @@ -96,10 +97,4 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table, return FALSE; } -/* - Maximum length of time zone name that we support - (Time zone name is char(64) in db) -*/ -#define MAX_TIME_ZONE_NAME_LENGTH 72 - #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ -- cgit v1.2.1 From 0550fead3bb28b757998bafa57326197e6779fa0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 11:38:51 +0100 Subject: disabling rpl_timezone.test if --ps-protocol, as binlogging of CONVERT_TZ(,,@@time_zone) fails there; until we find reason (me and possibly Konstantin). mysql-test/t/rpl_timezone.test: disabling test if --ps-protocol, until we find reason sql/slave.cc: fixing comment --- sql/slave.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/slave.cc b/sql/slave.cc index 9e42206d4a3..c92350f4a2f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1421,7 +1421,7 @@ not always make sense; please check the manual before using it)."; We don't test equality of global collation_database either as it's is going to be deprecated (made read-only) in 4.1 very soon. The test is only relevant if master < 5.0.3 (we'll test only if it's older - than the 5 branch; < 5.0.4 were alpha...), as >= 5.0.4 master stores + than the 5 branch; < 5.0.3 was alpha...), as >= 5.0.3 master stores charset info in each binlog event. We don't do it for 3.23 because masters <3.23.50 hang on SELECT @@unknown_var (BUG#7965 - see changelog of 3.23.50). So finally we -- cgit v1.2.1 From a99cb51c9d93d34eedbc08a9fca793855e3b9e05 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 15:48:06 +0200 Subject: Hack to ensure that CHAR's created in 5.0 are not converted to VARCHAR even if the row type is dynamic (For 4.1 tables old 'VARCHAR' fields are converted to true VARCHAR in the next ALTER TABLE) This ensures that one can use MySQL 5.0 privilege tables with MySQL 4.1 mysql-test/r/information_schema.result: Update results (for .frm version number change) mysql-test/r/ndb_autodiscover.result: Update results (for .frm version number change) mysql-test/r/ps_1general.result: Update results (for .frm version number change) mysql-test/r/show_check.result: Update results (for .frm version number change) mysql-test/r/view.result: Update results (for .frm version number change) scripts/fill_func_tables.sh: Ensure that no privilege tables that is used in 4.1 uses VARCHAR scripts/mysql_create_system_tables.sh: Ensure that no privilege tables that is used in 4.1 uses VARCHAR scripts/mysql_fix_privilege_tables.sh: Fixed bug that made it impossible to run the script from the mysql source dist scripts/mysql_fix_privilege_tables.sql: Ensure that no privilege tables that is used in 4.1 uses VARCHAR sql/sql_table.cc: Only set create_info->varchar if we are using the new VARCHAR field sql/table.cc: Hack to ensure that CHAR's created in 5.0 are not converted to VARCHAR even if the row type is dynamic (For 4.1 tables old 'VARCHAR' fields are converted to true VARCHAR in the next ALTER TABLE) --- sql/sql_table.cc | 9 ++------- sql/table.cc | 10 ++++++++++ 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 82d887891cf..b125eeaf03a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -613,7 +613,7 @@ int prepare_create_field(create_field *sql_field, Prepares the table and key structures for table creation. NOTES - sets create_info->varchar if the table has a varchar or blob. + sets create_info->varchar if the table has a varchar RETURN VALUES 0 ok @@ -862,12 +862,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ×tamps, ×tamps_with_niladic, file->table_flags())) DBUG_RETURN(-1); - if (sql_field->sql_type == FIELD_TYPE_BLOB || - sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB || - sql_field->sql_type == FIELD_TYPE_TINY_BLOB || - sql_field->sql_type == FIELD_TYPE_LONG_BLOB || - sql_field->sql_type == FIELD_TYPE_GEOMETRY || - sql_field->sql_type == MYSQL_TYPE_VARCHAR) + if (sql_field->sql_type == MYSQL_TYPE_VARCHAR) create_info->varchar= 1; sql_field->offset= pos; if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) diff --git a/sql/table.cc b/sql/table.cc index 939690395d4..9238d8aa68e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -149,6 +149,15 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, *fn_ext(index_file)='\0'; // Remove .frm extension share->frm_version= head[2]; + /* + Check if .frm file created by MySQL 5.0. In this case we want to + display CHAR fields as CHAR and not as VARCHAR. + We do it this way as we want to keep the old frm version to enable + MySQL 4.1 to read these files. + */ + if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5) + share->frm_version= FRM_VER_TRUE_VARCHAR; + share->db_type= ha_checktype((enum db_type) (uint) *(head+3)); share->db_create_options= db_create_options=uint2korr(head+30); share->db_options_in_use= share->db_create_options; @@ -1317,6 +1326,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers int2store(fileinfo+30,create_info->table_options); fileinfo[32]=0; // No filename anymore + fileinfo[33]=5; // Mark for 5.0 frm file int4store(fileinfo+34,create_info->avg_row_length); fileinfo[38]= (create_info->default_table_charset ? create_info->default_table_charset->number : 0); -- cgit v1.2.1 From 06abeb4f639d8f06901588c4a958cba3eaee3a74 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Mar 2005 15:57:24 +0200 Subject: - Added new error message. - Changed error message in sql_acl.cc - Added some more tests for GRANT. Docs/mysqld_error.txt: Added new error message. mysql-test/r/grant2.result: Error message changed. mysql-test/r/grant3.result: Clean up. mysql-test/t/grant2.test: Error message changed. sql/share/errmsg.txt: Added new error message. sql/sql_acl.cc: Changed error message. mysql-test/t/grant3.test: Error message changed. --- sql/share/errmsg.txt | 2 ++ sql/sql_acl.cc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index d4caeebb70c..886c37b7061 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5332,3 +5332,5 @@ ER_STARTUP eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d %s" ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR eng "Can't load value from file with fixed size rows to variable" +ER_CANT_CREATE_USER_WITH_GRANT + eng "You are not allowed to create a user with GRANT" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index c51e5e00aa1..de5df4559db 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1627,7 +1627,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, else if (((thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER) && !password_len) || !create_user) { - my_error(ER_NO_PERMISSION_TO_CREATE_USER, MYF(0), + my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0), thd->user, thd->host_or_ip); goto end; } -- cgit v1.2.1