From 1c459785127d40db78cf763f0e9e99e99693387c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Nov 2003 18:14:49 +0400 Subject: Fix for bug #1564: CREATE TABLE + UNION + same table name = crash --- sql/sql_parse.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0789a1768d1..a9183c84128 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3496,6 +3496,9 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) return 0; } + /* We should skip first table if SQL command is SQLCOM_CREATE_TABLE */ + bool skip_first= (lex->sql_command == SQLCOM_CREATE_TABLE); + bool first_added= 0; SELECT_LEX *sl; TABLE_LIST **new_table_list= result, *aux; @@ -3512,9 +3515,11 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) TABLE_LIST *next; for (; aux; aux=next) { - TABLE_LIST *cursor; + TABLE_LIST *cursor= *result; + if (first_added && skip_first) + cursor= cursor->next; next= aux->next; - for (cursor= *result; cursor; cursor=cursor->next) + for ( ; cursor; cursor=cursor->next) if (!strcmp(cursor->db,aux->db) && !strcmp(cursor->real_name,aux->real_name) && !strcmp(cursor->alias, aux->alias)) @@ -3531,6 +3536,7 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) *new_table_list= cursor; new_table_list= &cursor->next; *new_table_list=0; // end result list + first_added= 1; } else aux->shared=1; // Mark that it's used twice -- cgit v1.2.1 From 36eadc818a051fb10bc985d22ade5989ebd57532 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 17 Nov 2003 18:34:06 +0400 Subject: Fix for bug #1564: 'CREATE TABLE + UNION + same table name = crash' (related to previous changeset) --- sql/sql_parse.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a9183c84128..54cb3ade404 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -62,7 +62,8 @@ static void remove_escape(char *name); static void refresh_status(void); static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name); -static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result); +static bool create_total_list(THD *thd, LEX *lex, + TABLE_LIST **result, bool skip_first); const char *any_db="*any*"; // Special symbol for check_access @@ -1352,7 +1353,9 @@ mysql_execute_command(void) #endif } - if (lex->select_lex.next && create_total_list(thd,lex,&tables)) + if (lex->select_lex.next && + create_total_list(thd,lex,&tables, + (lex->sql_command == SQLCOM_CREATE_TABLE))) DBUG_VOID_RETURN; /* @@ -3487,7 +3490,8 @@ void set_lock_for_tables(thr_lock_type lock_type) ** to the entries in this list. */ -static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) +static bool create_total_list(THD *thd, LEX *lex, + TABLE_LIST **result, bool skip_first) { /* Handle the case when we are not using union */ if (!lex->select_lex.next) @@ -3497,8 +3501,6 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) } /* We should skip first table if SQL command is SQLCOM_CREATE_TABLE */ - bool skip_first= (lex->sql_command == SQLCOM_CREATE_TABLE); - bool first_added= 0; SELECT_LEX *sl; TABLE_LIST **new_table_list= result, *aux; @@ -3516,7 +3518,7 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) for (; aux; aux=next) { TABLE_LIST *cursor= *result; - if (first_added && skip_first) + if (skip_first && cursor) cursor= cursor->next; next= aux->next; for ( ; cursor; cursor=cursor->next) @@ -3536,7 +3538,6 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) *new_table_list= cursor; new_table_list= &cursor->next; *new_table_list=0; // end result list - first_added= 1; } else aux->shared=1; // Mark that it's used twice -- cgit v1.2.1 From dcf29d5ec82cdc5320d42c86d2fb61c4c13cb848 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Nov 2003 15:58:27 +0200 Subject: Fix for bug when zeros are to be prepended to decimal field --- sql/field.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 43481ca0963..58781624239 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -632,7 +632,7 @@ void Field_decimal::store(const char *from,uint len) if (zerofill) { left_wall=to-1; - while (pos != left_wall) // Fill with zeros + while (pos > left_wall) // Fill with zeros *pos--='0'; } else @@ -640,7 +640,7 @@ void Field_decimal::store(const char *from,uint len) left_wall=to+(sign_char != 0)-1; if (!expo_sign_char) // If exponent was specified, ignore prezeros { - for (;pos != left_wall && pre_zeros_from !=pre_zeros_end; + for (;pos > left_wall && pre_zeros_from !=pre_zeros_end; pre_zeros_from++) *pos--= '0'; } -- cgit v1.2.1 From 03e04c02cdf33c443db5b46b48f8c4ef02ad1b9e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Nov 2003 18:12:49 +0200 Subject: database invalidation invalidate queries only of given database (BUG#1898) mysql-test/r/query_cache.result: test of drop database mysql-test/t/query_cache.test: test of drop database sql/sql_cache.cc: database invalidation invalidate queries only of given database every freed block header marked as FREE even if it will be merged to make moving & deleting tables block safe layout fixed (too long line) --- sql/sql_cache.cc | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 5d525c7be4e..8610fcb8f22 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1151,9 +1151,29 @@ void Query_cache::invalidate(char *db) if (query_cache_size > 0) { DUMP(this); - /* invalidate_table reduce list while only root of list remain */ - while (tables_blocks !=0 ) - invalidate_table(tables_blocks); + restart_search: + if (tables_blocks) + { + Query_cache_block *curr= tables_blocks; + Query_cache_block *next; + do + { + next= curr->next; + if (strcmp(db, (char*)(curr->table()->db())) == 0) + invalidate_table(curr); + /* + invalidate_table can freed block on which point 'next' (if + table of this block used only in queries which was deleted + by invalidate_table). As far as we do not allocate new blocks + and mark all headers of freed blocks as 'FREE' (even if they are + merged with other blocks) we can just test type of block + to be sure that block is not deleted + */ + if (next->type == Query_cache_block::FREE) + goto restart_search; + curr= next; + } while (curr != tables_blocks); + } } STRUCT_UNLOCK(&structure_guard_mutex); } @@ -2158,9 +2178,11 @@ void Query_cache::free_memory_block(Query_cache_block *block) { DBUG_ENTER("Query_cache::free_memory_block"); block->used=0; - DBUG_PRINT("qcache",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx", - (ulong) first_block, (ulong) block,block->pnext, - (ulong) block->pprev)); + block->type= Query_cache_block::FREE; // mark block as free in any case + DBUG_PRINT("qcache", + ("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx", + (ulong) first_block, (ulong) block,block->pnext, + (ulong) block->pprev)); if (block->pnext != first_block && block->pnext->is_free()) block = join_free_blocks(block, block->pnext); -- cgit v1.2.1 From 3f355523ba3e9eb814bbd37c0092755330fd2db9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 21 Nov 2003 00:03:04 +0300 Subject: fix for bug #1790: "BIT_AND() result in GROUP BY different when SQL_BIG_RESULT used" return value of BIT_AND changed to BIGINT SIGNED Also the patch fixes another bug: when temporary table is in use and one of values in group is NULL, BIT_AND always returns zero. Fixed it to always skip null values. mysql-test/r/func_group.result: bug #1790: test results fixed sql/item_sum.cc: fix for bug #1790: update_field() rewritten to use add() and thus was moved to Item_sum_bit::update_field() Item_sum_bit::reset_field() was rewritten to take into account reset_bits. sql/item_sum.h: fix for bug #1790: Item_sum::update_field() and Item_sum::reset_field() commented Item_sum_and changed to return BIGINT SIGNED Item_sum_and::update_field() and Item_sum_or::update_field) were replaced with generic Item_sum_bit::update_field() --- sql/item_sum.cc | 36 ++++++++++++------------------------ sql/item_sum.h | 22 +++++++++++++++++----- 2 files changed, 29 insertions(+), 29 deletions(-) (limited to 'sql') diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 835278ae262..36a3c6b009b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -614,10 +614,19 @@ void Item_sum_avg::reset_field() } void Item_sum_bit::reset_field() +{ + char *res= result_field->ptr; + bits= reset_bits; + add(); + int8store(res, bits); +} + +void Item_sum_bit::update_field() { char *res=result_field->ptr; - ulonglong nr=(ulonglong) args[0]->val_int(); - int8store(res,nr); + bits= uint8korr(res); + add(); + int8store(res, bits); } /* @@ -756,28 +765,6 @@ Item_sum_hybrid::min_max_update_int_field() } -void Item_sum_or::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr|= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - - -void Item_sum_and::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr&= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - - Item_avg_field::Item_avg_field(Item_sum_avg *item) { name=item->name; @@ -787,6 +774,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item) maybe_null=1; } + double Item_avg_field::val() { double nr; diff --git a/sql/item_sum.h b/sql/item_sum.h index 5189566fdfb..c91abbded28 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -55,7 +55,18 @@ public: virtual enum Sumfunctype sum_func () const=0; virtual void reset()=0; virtual bool add()=0; + /* + Called when new group is started and results are being saved in + a temporary table. Similar to reset(), but must also store value in + result_field. Like reset() it is supposed to reset start value to + default. + */ virtual void reset_field()=0; + /* + Called for each new value in the group, when temporary table is in use. + Similar to add(), but uses temporary table field to obtain current value, + Updated value is then saved in the field. + */ virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } @@ -360,20 +371,20 @@ class Item_sum_bit :public Item_sum_int void reset(); longlong val_int(); void reset_field(); + void update_field(); unsigned int size_of() { return sizeof(*this);} - void fix_length_and_dec() - { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; class Item_sum_or :public Item_sum_bit { - public: +public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} bool add(); - void update_field(); const char *func_name() const { return "bit_or"; } unsigned int size_of() { return sizeof(*this);} + void fix_length_and_dec() + { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; @@ -382,9 +393,10 @@ class Item_sum_and :public Item_sum_bit public: Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {} bool add(); - void update_field(); const char *func_name() const { return "bit_and"; } unsigned int size_of() { return sizeof(*this);} + void fix_length_and_dec() + { decimals=0; max_length=21; unsigned_flag=0; maybe_null=null_value=0; } }; /* -- cgit v1.2.1 From d8e425c240b01f263dd8cd8431e32e8ba9539b43 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Nov 2003 13:57:49 +0400 Subject: Fix for bug #1855: mysqld crashes with certain SSL connections --- sql/sql_acl.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sql') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 065394c87d0..03a359d44e7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -588,6 +588,11 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, /* Prepare certificate (if exists) */ DBUG_PRINT("info",("checkpoint 1")); X509* cert=SSL_get_peer_certificate(ssl); + if (!cert) + { + user_access=NO_ACCESS; + break; + } DBUG_PRINT("info",("checkpoint 2")); /* If X509 issuer is speified, we check it... */ if (acl_user->x509_issuer) -- cgit v1.2.1 From 8764ca94c958e5556b4fd0125ea1cf41f8b7af6c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 1 Dec 2003 14:59:35 +0100 Subject: Removing unneeded code: the Intvar_log_event constructor calls the Log_event constructor which does e.server_id=thd.server_id. sql/log.cc: unneeded: the Intvar_log_event constructor calls the Log_event constructor which does e.server_id=thd.server_id. --- sql/log.cc | 4 ---- 1 file changed, 4 deletions(-) (limited to 'sql') diff --git a/sql/log.cc b/sql/log.cc index 33ca82aa14f..e6eaa3b802c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1110,8 +1110,6 @@ bool MYSQL_LOG::write(Log_event* event_info) Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, thd->current_insert_id); e.set_log_pos(this); - if (thd->server_id) - e.server_id = thd->server_id; if (e.write(file)) goto err; } @@ -1119,8 +1117,6 @@ bool MYSQL_LOG::write(Log_event* event_info) { Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id); e.set_log_pos(this); - if (thd->server_id) - e.server_id = thd->server_id; if (e.write(file)) goto err; } -- cgit v1.2.1 From b9418600bf5d9ed110af1fe41f19c157b8f5dc8f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Dec 2003 16:49:46 +0100 Subject: There is no reason that Intvar_log_event's constructor calls Log_event::Log_event() instead of Log_event::Log_event(THD*, ...) when the event is built in the master to be written in the binlog. Rand_log_event already used the good constructor, so there really is no reason for Intvar_log_event to be an exception. This fixes a test failure of last night (which appeared after I removed a useless e.server_id=thd->server_id in log.cc; in fact this line was not useless because it hid the bad constructor). Replication tests pass, with Valgrind too. sql/log_event.h: There is no reason that Intvar_log_event's constructor calls Log_event::Log_event() instead of Log_event::Log_event(THD*, ...) when the event is built in the master to be written in the binlog. Rand_log_event already used the good constructor, so there really is no reason for Intvar_log_event to be an exception. This fixes a test failure of last night (which appeared after I removed a useless e.server_id=thd->server_id in log.cc; in fact this line was not useless because it hid the bad constructor). --- sql/log_event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/log_event.h b/sql/log_event.h index 2e6b7373dc2..929d550951e 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -529,7 +529,7 @@ public: #ifndef MYSQL_CLIENT Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg) - :Log_event(),val(val_arg),type(type_arg) + :Log_event(thd_arg,0,0),val(val_arg),type(type_arg) {} void pack_info(String* packet); int exec_event(struct st_relay_log_info* rli); -- cgit v1.2.1 From a2bdd6218c7ed36bf245eb378fa3b128ebf266ce Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Dec 2003 19:39:51 +0300 Subject: Post-review fixes for bug #1790 'BIT_AND() result in GROUP BY different when SQL_BIG_RESULT used': - BIT_AND now returns BIGINT UNSIGNED - in case there were no matching rows BIT_AND returns 18446744073709551615 (but not NULL), BIT_OR returns 0 (but not NULL). That's how Monty wants it and how is described in our docs. include/my_global.h: Added definition for ULONGLONG_MAX. This is also a check that ULL type specifier can be used on all supported platforms. mysql-test/r/func_group.result: bug #1790, post-review work: test results fixed sql/item_sum.cc: small cleanup sql/item_sum.h: few style fixes. BIT_AND and BIT_OR now are both BIGINT UNSIGNED --- sql/item_sum.cc | 6 ++---- sql/item_sum.h | 14 ++++++-------- 2 files changed, 8 insertions(+), 12 deletions(-) (limited to 'sql') diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 36a3c6b009b..5a5934db0cd 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -615,10 +615,8 @@ void Item_sum_avg::reset_field() void Item_sum_bit::reset_field() { - char *res= result_field->ptr; - bits= reset_bits; - add(); - int8store(res, bits); + reset(); + int8store(result_field->ptr, bits); } void Item_sum_bit::update_field() diff --git a/sql/item_sum.h b/sql/item_sum.h index c91abbded28..d3a328be032 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -361,10 +361,10 @@ public: class Item_sum_bit :public Item_sum_int { - protected: +protected: ulonglong reset_bits,bits; - public: +public: Item_sum_bit(Item *item_par,ulonglong reset_arg) :Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {} enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;} @@ -373,6 +373,8 @@ class Item_sum_bit :public Item_sum_int void reset_field(); void update_field(); unsigned int size_of() { return sizeof(*this);} + void fix_length_and_dec() + { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; @@ -383,20 +385,16 @@ public: bool add(); const char *func_name() const { return "bit_or"; } unsigned int size_of() { return sizeof(*this);} - void fix_length_and_dec() - { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; class Item_sum_and :public Item_sum_bit { - public: - Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {} +public: + Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} bool add(); const char *func_name() const { return "bit_and"; } unsigned int size_of() { return sizeof(*this);} - void fix_length_and_dec() - { decimals=0; max_length=21; unsigned_flag=0; maybe_null=null_value=0; } }; /* -- cgit v1.2.1 From f5d7229762e3c0e4cf98f223b41cb6d381a767bf Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Dec 2003 20:25:45 +0300 Subject: Fix for Bug #1448 "Date parsing fails, and fails to complain about it". Now numbers representing illegal timestamps are converted to 0 value if they are stored as timestamp or datetime. This behaviour is consistent with manual and with behaviour of string -> timestamp conversion. mysql-test/r/type_datetime.result: Added test if ranges are checked during integer, string -> timestamp conversion mysql-test/r/type_timestamp.result: Added test if ranges are checked during integer, string -> datetime conversion mysql-test/t/type_datetime.test: Added test if ranges are checked during integer, string -> datetime conversion mysql-test/t/type_timestamp.test: Added test if ranges are checked during integer, string -> timestamp conversion sql/field.cc: Checks of month, day, hour, minute and second ranges were added to storing of integer into Field_datetime and Field_timestamp and so for integer -> datetime, timestamp conversion. --- sql/field.cc | 72 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 22 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 43481ca0963..259314cb4db 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2520,31 +2520,59 @@ void Field_timestamp::store(double nr) ** function. */ -static longlong fix_datetime(longlong nr) +static longlong fix_datetime(longlong nr, TIME *time_res) { + long part1,part2; + if (nr == LL(0) || nr >= LL(10000101000000)) - return nr; // Normal datetime >= Year 1000 + goto ok; if (nr < 101) goto err; if (nr <= (YY_PART_YEAR-1)*10000L+1231L) - return (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + { + nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + goto ok; + } if (nr < (YY_PART_YEAR)*10000L+101L) goto err; if (nr <= 991231L) - return (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + { + nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + goto ok; + } if (nr < 10000101L) goto err; if (nr <= 99991231L) - return nr*1000000L; + { + nr= nr*1000000L; + goto ok; + } if (nr < 101000000L) goto err; if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959)) - return nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + { + nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + goto ok; + } if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000)) goto err; if (nr <= LL(991231235959)) - return nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 - + nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 + + ok: + part1=(long) (nr/LL(1000000)); + part2=(long) (nr - (longlong) part1*LL(1000000)); + time_res->year= (int) (part1/10000L); part1%=10000L; + time_res->month= (int) part1 / 100; + time_res->day= (int) part1 % 100; + time_res->hour= (int) (part2/10000L); part2%=10000L; + time_res->minute=(int) part2 / 100; + time_res->second=(int) part2 % 100; + + if (time_res->month <= 12 && time_res->day <= 31 && time_res->hour <= 23 && + time_res->minute <= 59 && time_res->second <= 59) + return nr; + err: current_thd->cuted_fields++; return LL(0); @@ -2555,20 +2583,18 @@ void Field_timestamp::store(longlong nr) { TIME l_time; time_t timestamp; - long part1,part2; - if ((nr=fix_datetime(nr))) + if ((nr=fix_datetime(nr, &l_time))) { long not_used; - part1=(long) (nr/LL(1000000)); - part2=(long) (nr - (longlong) part1*LL(1000000)); - l_time.year= (int) (part1/10000L); part1%=10000L; - l_time.month= (int) part1 / 100; - l_time.day= (int) part1 % 100; - l_time.hour= (int) (part2/10000L); part2%=10000L; - l_time.minute=(int) part2 / 100; - l_time.second=(int) part2 % 100; - timestamp=my_gmt_sec(&l_time, ¬_used); + + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) + { + current_thd->cuted_fields++; + timestamp=0; + } + else + timestamp=my_gmt_sec(&l_time, ¬_used); } else timestamp=0; @@ -3406,13 +3432,15 @@ void Field_datetime::store(double nr) void Field_datetime::store(longlong nr) { - if (nr < 0 || nr > LL(99991231235959)) + TIME l_time; + + nr=fix_datetime(nr, &l_time); + + if (l_time.year > 9999) { nr=0; current_thd->cuted_fields++; } - else - nr=fix_datetime(nr); #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { -- cgit v1.2.1 From 8be4234f6162da34e1ecd007b67b3ef0650b16d1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Dec 2003 21:05:40 +0300 Subject: Fix for bug #1980 BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- sql/uniques.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/uniques.cc b/sql/uniques.cc index d00893a8605..967392d12d5 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -37,14 +37,20 @@ int unique_write_to_file(gptr key, element_count count, Unique *unique) { + /* + Use unique->size (size of element stored in the tree) and not + unique->tree.size_of_element. The latter is different from unique->size + when tree implementation chooses to store pointer to key in TREE_ELEMENT + (instead of storing the element itself there) + */ return my_b_write(&unique->file, (byte*) key, - unique->tree.size_of_element) ? 1 : 0; + unique->size) ? 1 : 0; } int unique_write_to_ptrs(gptr key, element_count count, Unique *unique) { - memcpy(unique->record_pointers, key, unique->tree.size_of_element); - unique->record_pointers+=unique->tree.size_of_element; + memcpy(unique->record_pointers, key, unique->size); + unique->record_pointers+=unique->size; return 0; } @@ -132,7 +138,7 @@ bool Unique::get(TABLE *table) bzero((char*) &sort_param,sizeof(sort_param)); sort_param.max_rows= elements; sort_param.sort_form=table; - sort_param.sort_length=sort_param.ref_length=tree.size_of_element; + sort_param.sort_length=sort_param.ref_length=size; sort_param.keys= max_in_memory_size / sort_param.sort_length; sort_param.not_killable=1; -- cgit v1.2.1 From c2b60a6f59f12543a04497cf0196384782f3fbdd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 4 Dec 2003 14:12:01 +0400 Subject: Fix for bug#1944 'Function RPad() sometimes produce unexpected result' --- sql/item_strfunc.cc | 4 ++-- sql/item_strfunc.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index fe9c8b9e099..dd1ec6bd2da 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1806,7 +1806,7 @@ String *Item_func_rpad::val_str(String *str) const char *ptr_pad; int32 count= (int32) args[1]->val_int(); String *res =args[0]->val_str(str); - String *rpad = args[2]->val_str(str); + String *rpad = args[2]->val_str(&rpad_str); if (!res || args[1]->null_value || !rpad || count < 0) goto err; @@ -1866,7 +1866,7 @@ String *Item_func_lpad::val_str(String *str) const char *ptr_pad; ulong count= (long) args[1]->val_int(); String *res= args[0]->val_str(str); - String *lpad= args[2]->val_str(str); + String *lpad= args[2]->val_str(&lpad_str); if (!res || args[1]->null_value || !lpad) goto err; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 5c9706ed633..fc98ebfe67d 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -436,7 +436,7 @@ public: class Item_func_rpad :public Item_str_func { - String tmp_value; + String tmp_value, rpad_str; public: Item_func_rpad(Item *arg1,Item *arg2,Item *arg3) :Item_str_func(arg1,arg2,arg3) {} @@ -449,7 +449,7 @@ public: class Item_func_lpad :public Item_str_func { - String tmp_value; + String tmp_value, lpad_str; public: Item_func_lpad(Item *arg1,Item *arg2,Item *arg3) :Item_str_func(arg1,arg2,arg3) {} -- cgit v1.2.1 From 8479e5a379044acad53baa8f9b7a8cd9266c582a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 4 Dec 2003 15:30:14 +0100 Subject: Fix for BUG#2011 "rare race condition producing "binlog has bad magic number" error in slave". The problem was that when the slave SQL thread reads a hot relay log (hot = the one being written to by the slave I/O thread), it must have the LOCK_log. It already took it for read_log_event(), but needs it also for check_binlog_magic(). This should fix all recently reported failures of the rpl_max_relay_size test in 4.1 and 5.0 (though the bug exists since 4.0, it showed up first in 5.0). sql/slave.cc: Fix for BUG#2011 "rare race condition producing "binlog has bad magic number" error in slave". The problem was that when the slave SQL thread reads a hot relay log (hot = the one being written to by the slave I/O thread), it must have the LOCK_log. It already took it for read_log_event(), but needs it also for check_binlog_magic(). --- sql/slave.cc | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/slave.cc b/sql/slave.cc index 6816d968007..5bc31fd6a21 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3497,8 +3497,20 @@ rli->relay_log_pos=%s rli->pending=%lu", sizeof(rli->relay_log_name)-1); flush_relay_log_info(rli); } - - // next log is hot + + /* + Now we want to open this next log. To know if it's a hot log (the one + being written by the I/O thread now) or a cold log, we can use + is_active(); if it is hot, we use the I/O cache; if it's cold we open + the file normally. But if is_active() reports that the log is hot, this + may change between the test and the consequence of the test. So we may + open the I/O cache whereas the log is now cold, which is nonsense. + To guard against this, we need to have LOCK_log. + */ + + DBUG_PRINT("info",("hot_log: %d",hot_log)); + if (!hot_log) /* if hot_log, we already have this mutex */ + pthread_mutex_lock(log_lock); if (rli->relay_log.is_active(rli->linfo.log_file_name)) { #ifdef EXTRA_DEBUG @@ -3511,15 +3523,24 @@ rli->relay_log_pos=%s rli->pending=%lu", /* Read pointer has to be at the start since we are the only - reader + reader. + We must keep the LOCK_log to read the 4 first bytes, as this is a hot + log (same as when we call read_log_event() above: for a hot log we + take the mutex). */ if (check_binlog_magic(cur_log,&errmsg)) + { + if (!hot_log) pthread_mutex_unlock(log_lock); goto err; + } + if (!hot_log) pthread_mutex_unlock(log_lock); continue; } + if (!hot_log) pthread_mutex_unlock(log_lock); /* - if we get here, the log was not hot, so we will have to - open it ourselves + if we get here, the log was not hot, so we will have to open it + ourselves. We are sure that the log is still not hot now (a log can get + from hot to cold, but not from cold to hot). No need for LOCK_log. */ #ifdef EXTRA_DEBUG sql_print_error("next log '%s' is not active", -- cgit v1.2.1 From 8f4ed1d72cacfec81737af77c1b215ca7a9ed410 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 4 Dec 2003 19:02:48 +0300 Subject: Fix undeterministic behaviour of year check if we failed to classify integer as datetime in Field_datetime::store(). Stylistic clean-ups. sql/field.cc: Fix undeterministic behaviour of year check if we failed to classify integer as datetime Stylistic clean-ups. --- sql/field.cc | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 259314cb4db..1070d0f7b7d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2569,7 +2569,8 @@ static longlong fix_datetime(longlong nr, TIME *time_res) time_res->minute=(int) part2 / 100; time_res->second=(int) part2 % 100; - if (time_res->month <= 12 && time_res->day <= 31 && time_res->hour <= 23 && + if (time_res->year <= 9999 && time_res->month <= 12 && + time_res->day <= 31 && time_res->hour <= 23 && time_res->minute <= 59 && time_res->second <= 59) return nr; @@ -2584,7 +2585,7 @@ void Field_timestamp::store(longlong nr) TIME l_time; time_t timestamp; - if ((nr=fix_datetime(nr, &l_time))) + if ((nr= fix_datetime(nr, &l_time))) { long not_used; @@ -3432,15 +3433,10 @@ void Field_datetime::store(double nr) void Field_datetime::store(longlong nr) { - TIME l_time; + TIME not_used; - nr=fix_datetime(nr, &l_time); + nr= fix_datetime(nr, ¬_used); - if (l_time.year > 9999) - { - nr=0; - current_thd->cuted_fields++; - } #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { -- cgit v1.2.1 From ee52d2925d40f3d7e7d70a7e246023e8627be489 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 4 Dec 2003 19:48:10 +0200 Subject: Allow space in service names move bdb/innodb tests to right places mysql-test/r/bdb.result: Update results after test changes mysql-test/r/innodb.result: Update results after test changes mysql-test/r/multi_update.result: Update results after test changes mysql-test/t/bdb.test: Move bdb tests here mysql-test/t/innodb.test: Move innodb test here mysql-test/t/multi_update.test: move bdb/innodb tests to repective test sql/mysqld.cc: Allow space in service names --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4c6cf1d5039..2e87ade9174 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2573,7 +2573,7 @@ default_service_handling(char **argv, } /* We must have servicename last */ *pos++= ' '; - strmake(pos, servicename, (uint) (end+2 - pos)); + (void) add_quoted_string(pos, servicename, end); if (Service.got_service_option(argv, "install")) { -- cgit v1.2.1 From 66927c51fa8e25f9d8a9d818f4ff7ed2a64c5ecb Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 4 Dec 2003 22:42:18 +0100 Subject: - Fix for BUG#1858 "SQL-Thread stops working when using optimize table": we change THD::system_thread from a 'bool' to a bitmap to be able to distinguish between delayed-insert threads and slave threads. - Fix for BUG#1701 "Update from multiple tables" (one line in sql_parse.cc, plus a new test rpl_multi_update.test). That's just adding an initialization. sql/repl_failsafe.cc: comment to warn about this unused code sql/slave.cc: Now thd->system_thread is a bitmap, not a bool. sql/sql_class.h: 'bool' for THD::system_thread is not accurate enough; sometimes we need to distinguish between delayed-insert threads and slave threads; so changing THD::system_thread to a bitmap (uint). sql/sql_insert.cc: thd.system_thread is now a bitmap sql/sql_parse.cc: We need to initialize thd->lex.select_lex.options in mysql_init_query(); it's already initialized in dispatch_command() but replication calls mysql_parse() directly, thus bypassing dispatch_command(). Not initing it here leads to a query influencing the next query, in the slave SQL thread. The initialization in dispatch_command() must be kept as this command uses the variable in tests, even when the command was not a query (i.e. when mysql_init_query() was not called). --- sql/repl_failsafe.cc | 7 +++++++ sql/slave.cc | 4 +++- sql/sql_class.h | 9 +++++++-- sql/sql_insert.cc | 2 +- sql/sql_parse.cc | 6 ++++++ 5 files changed, 24 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 8deb23e8586..6b91d81b487 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -52,6 +52,13 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, const char* log_file_name, char* errmsg); +/* + All of the functions defined in this file which are not used (the ones to + handle failsafe) are not used; their code has not been updated for more than + one year now so should be considered as BADLY BROKEN. Do not enable it. + The used functions (to handle LOAD DATA FROM MASTER, plus some small + functions like register_slave()) are working. +*/ static int init_failsafe_rpl_thread(THD* thd) { diff --git a/sql/slave.cc b/sql/slave.cc index 5bc31fd6a21..25eeb34e3a7 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2021,7 +2021,9 @@ improper_arguments: %d timed_out: %d", static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) { DBUG_ENTER("init_slave_thread"); - thd->system_thread = thd->bootstrap = 1; + thd->system_thread = (thd_type == SLAVE_THD_SQL) ? + SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; + thd->bootstrap= 1; thd->host_or_ip= ""; thd->client_capabilities = 0; my_net_init(&thd->net, 0); diff --git a/sql/sql_class.h b/sql/sql_class.h index 58543a3d230..9287a0c8c79 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -460,7 +460,7 @@ public: long dbug_thread_id; pthread_t real_id; uint current_tablenr,tmp_table,cond_count; - uint server_status,open_options; + uint server_status,open_options,system_thread; uint32 query_length; uint32 db_length; /* variables.transaction_isolation is reset to this after each commit */ @@ -470,7 +470,7 @@ public: bool set_query_id,locked,count_cuted_fields,some_tables_deleted; bool no_errors, allow_sum_func, password, fatal_error; bool query_start_used,last_insert_id_used,insert_id_used,rand_used; - bool system_thread,in_lock_tables,global_read_lock; + bool in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; bool safe_to_cache_query; bool volatile killed; @@ -592,6 +592,11 @@ public: CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length); }; +/* Flags for the THD::system_thread (bitmap) variable */ +#define SYSTEM_THREAD_DELAYED_INSERT 1 +#define SYSTEM_THREAD_SLAVE_IO 2 +#define SYSTEM_THREAD_SLAVE_SQL 4 + /* Used to hold information about file and file structure in exchainge via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3aefee61c27..3414e76e092 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -550,7 +550,7 @@ public: thd.command=COM_DELAYED_INSERT; bzero((char*) &thd.net,sizeof(thd.net)); // Safety - thd.system_thread=1; + thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.host_or_ip= ""; bzero((char*) &info,sizeof(info)); pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0789a1768d1..2d40d6fcf36 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2902,6 +2902,12 @@ mysql_init_query(THD *thd) thd->lex.select_lex.table_list.first=0; thd->lex.select_lex.table_list.next= (byte**) &thd->lex.select_lex.table_list.first; thd->lex.select_lex.next=0; + /* + select_lex.options is also inited in dispatch_command(), but for + replication (which bypasses dispatch_command() and calls mysql_parse() + directly) we must do it here. + */ + thd->lex.select_lex.options=0; thd->lex.olap=0; thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE; thd->fatal_error=0; // Safety -- cgit v1.2.1 From 468dcb6092bce57a4c7529f40d10fcd7654f5ead Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 7 Dec 2003 15:10:21 +0400 Subject: WL#1175: more default_week_formats for iso compatibility New formats added for 'week()' function and 'default_week_format' option(4 - 7). Next formats is supported now: *Value* *Meaning* `0' Week starts on Sunday; First Sunday of the year starts week 1. Week() returns 0-53. `1' Week starts on Monday; Weeks numbered according to ISO 8601:1988. Week() returns 0-53. `2' Week starts on Sunday; First Sunday of the year starts week 1. Week() returns 1-53. `3' Week starts on Monday; Weeks numbered according to ISO 8601:1988. Week() returns 1-53. `4' Week starts on Sunday; Weeks numbered according to ISO 8601:1988. Week() returns 0-53. `5' Week starts on Monday; First Monday of the year starts week 1. Week() returns 0-53. `6' Week starts on Sunday; Weeks numbered according to ISO 8601:1988. Week() returns 1-53. `7' Week starts on Monday; First Monday of the year starts week 1. Week() returns 1-53. mysql-test/r/func_time.result: Test for 'default_week_format' option and 'week' function mysql-test/t/func_time.test: Test for 'default_week_format' option and 'week' function sql/item_timefunc.cc: WL#1175 more default_week_formats for iso compatibility sql/mysql_priv.h: WL#1175 more default_week_formats for iso compatibility sql/mysqld.cc: WL#1175 more default_week_formats for iso compatibility sql/time.cc: WL#1175 more default_week_formats for iso compatibility --- sql/item_timefunc.cc | 68 +++++++++++++++++++++++++++++++++++++++------------- sql/mysql_priv.h | 8 +++++-- sql/mysqld.cc | 2 +- sql/time.cc | 68 +++++++++++++++++++++++++++++++++++++--------------- 4 files changed, 108 insertions(+), 38 deletions(-) (limited to 'sql') diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index caea79314de..f2b4a041b6c 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -175,27 +175,51 @@ longlong Item_func_second::val_int() } -/* - Returns the week of year. +uint week_mode(uint mode) +{ + uint week_format= (mode & 7); + if (!(week_format & WEEK_MONDAY_FIRST)) + week_format^= WEEK_FIRST_WEEKDAY; + return week_format; +} - The bits in week_format has the following meaning: - 0 If not set: USA format: Sunday is first day of week - If set: ISO format: Monday is first day of week - 1 If not set: Week is in range 0-53 - If set Week is in range 1-53. +/* + The bits in week_format(for calc_week() function) has the following meaning: + WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week + If set Monday is first day of week + WEEK_YEAR (1) If not set Week is in range 0-53 + + Week 0 is returned for the the last week of the previous year (for + a date at start of january) In this case one can get 53 for the + first week of next year. This flag ensures that the week is + relevant for the given year. Note that this flag is only + releveant if WEEK_JANUARY is not set. + + If set Week is in range 1-53. + + In this case one may get week 53 for a date in January (when + the week is that last week of previous year) and week 1 for a + date in December. + + WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according + to ISO 8601:1988 + If set The week that contains the first + 'first-day-of-week' is week 1. + + ISO 8601:1988 means that if the week containing January 1 has + four or more days in the new year, then it is week 1; + Otherwise it is the last week of the previous year, and the + next week is week 1. */ longlong Item_func_week::val_int() { uint year; - uint week_format; TIME ltime; if (get_arg0_date(<ime,0)) return 0; - week_format= (uint) args[1]->val_int(); - return (longlong) calc_week(<ime, - (week_format & 2) != 0, - (week_format & 1) == 0, + return (longlong) calc_week(<ime, + week_mode((uint) args[1]->val_int()), &year); } @@ -206,7 +230,9 @@ longlong Item_func_yearweek::val_int() TIME ltime; if (get_arg0_date(<ime,0)) return 0; - week=calc_week(<ime, 1, (args[1]->val_int() & 1) == 0, &year); + week= calc_week(<ime, + (week_mode((uint) args[1]->val_int()) | WEEK_YEAR), + &year); return week+year*100; } @@ -844,7 +870,10 @@ String *Item_func_date_format::val_str(String *str) case 'u': { uint year; - sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year)); + sprintf(intbuff,"%02d", + calc_week(&l_time, + ((*ptr) == 'U' ? + WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST) , &year)); str->append(intbuff); } break; @@ -852,7 +881,11 @@ String *Item_func_date_format::val_str(String *str) case 'V': { uint year; - sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year)); + sprintf(intbuff,"%02d", + calc_week(&l_time, + ((*ptr) == 'V' ? WEEK_YEAR | WEEK_FIRST_WEEKDAY : + WEEK_YEAR | WEEK_MONDAY_FIRST), + &year)); str->append(intbuff); } break; @@ -860,7 +893,10 @@ String *Item_func_date_format::val_str(String *str) case 'X': { uint year; - (void) calc_week(&l_time, 1, (*ptr) == 'X', &year); + (void) calc_week(&l_time, + ((*ptr) == 'X' ? WEEK_YEAR | WEEK_FIRST_WEEKDAY : + WEEK_YEAR | WEEK_MONDAY_FIRST), + &year); sprintf(intbuff,"%04d",year); str->append(intbuff); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index adb7831896c..04529919990 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -247,6 +247,11 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); #define tmp_file_prefix "#sql" /* Prefix for tmp tables */ #define tmp_file_prefix_length 4 +/* Flags for calc_week() function. */ +#define WEEK_MONDAY_FIRST 1 +#define WEEK_YEAR 2 +#define WEEK_FIRST_WEEKDAY 4 + struct st_table; class THD; @@ -806,8 +811,7 @@ ha_rows filesort(TABLE *form,struct st_sort_field *sortorder, uint s_length, void change_double_for_sort(double nr,byte *to); int get_quick_record(SQL_SELECT *select); int calc_weekday(long daynr,bool sunday_first_day_of_week); -uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week, - uint *year); +uint calc_week(TIME *l_time, uint week_behaviour, uint *year); void find_date(char *pos,uint *vek,uint flag); TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); TYPELIB *typelib(List &strings); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e5ddbfe7a33..84287a6cba1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4105,7 +4105,7 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \ "The default week format used by WEEK() functions.", (gptr*) &global_system_variables.default_week_format, (gptr*) &max_system_variables.default_week_format, - 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0}, + 0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/sql/time.cc b/sql/time.cc index 321a8ba16e5..bf218fa58ab 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -175,42 +175,72 @@ uint calc_days_in_year(uint year) 366 : 365; } -/* Calculate week. If 'with_year' is not set, then return a week 0-53, where - 0 means that it's the last week of the previous year. - If 'with_year' is set then the week will always be in the range 1-53 and - the year out parameter will contain the year for the week */ -uint calc_week(TIME *l_time, bool with_year, bool sunday_first_day_of_week, - uint *year) +/* + The bits in week_format has the following meaning: + WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week + If set Monday is first day of week + WEEK_YEAR (1) If not set Week is in range 0-53 + + Week 0 is returned for the the last week of the previous year (for + a date at start of january) In this case one can get 53 for the + first week of next year. This flag ensures that the week is + relevant for the given year. Note that this flag is only + releveant if WEEK_JANUARY is not set. + + If set Week is in range 1-53. + + In this case one may get week 53 for a date in January (when + the week is that last week of previous year) and week 1 for a + date in December. + + WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according + to ISO 8601:1988 + If set The week that contains the first + 'first-day-of-week' is week 1. + + ISO 8601:1988 means that if the week containing January 1 has + four or more days in the new year, then it is week 1; + Otherwise it is the last week of the previous year, and the + next week is week 1. +*/ + +uint calc_week(TIME *l_time, uint week_behaviour, uint *year) { uint days; ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day); ulong first_daynr=calc_daynr(l_time->year,1,1); - uint weekday=calc_weekday(first_daynr,sunday_first_day_of_week); + bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST); + bool week_year= test(week_behaviour & WEEK_YEAR); + bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY); + + uint weekday=calc_weekday(first_daynr, !monday_first); *year=l_time->year; - if (l_time->month == 1 && l_time->day <= 7-weekday && - ((!sunday_first_day_of_week && weekday >= 4) || - (sunday_first_day_of_week && weekday != 0))) + + if (l_time->month == 1 && l_time->day <= 7-weekday) { - /* Last week of the previous year */ - if (!with_year) + if (!week_year && + (first_weekday && weekday != 0 || + !first_weekday && weekday >= 4)) return 0; - with_year=0; // Don't check the week again + week_year= 1; (*year)--; first_daynr-= (days=calc_days_in_year(*year)); weekday= (weekday + 53*7- days) % 7; } - if ((sunday_first_day_of_week && weekday != 0) || - (!sunday_first_day_of_week && weekday >= 4)) + + if ((first_weekday && weekday != 0) || + (!first_weekday && weekday >= 4)) days= daynr - (first_daynr+ (7-weekday)); else days= daynr - (first_daynr - weekday); - if (with_year && days >= 52*7) + + if (week_year && days >= 52*7) { - /* Check if we are on the first week of the next year (or week 53) */ weekday= (weekday + calc_days_in_year(*year)) % 7; - if (weekday < 4) - { // We are at first week on next year + if (!first_weekday && weekday < 4 || + first_weekday && weekday == 0) + { (*year)++; return 1; } -- cgit v1.2.1 From a50761a565a07f4d0494d0193f15a80b57fc7108 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Dec 2003 16:18:25 +0100 Subject: Fix for BUG#2045 "Sending SIGHUP to mysqld crashes it if running with --log-bin". The constructor of Rotate_log_event used when we are rotating our binlog or relay log, should not assume that there is a nonzero THD available. For example, when we are reacting to SIGHUP, the THD is 0. In fact we don't need to use the THD in this constructor; we can do like for Stop_log_event, and use the minimal Log_event constructor. If we were allowed to put Unix-specific commands in the testsuite, I'd add a test for this (). sql/log.cc: A comment to warn that thd can be 0. The part about LOG_EVENT_FORCED_ROTATE_F is just to avoid segfault; this flag is already removed in 4.1 anyway. sql/log_event.cc: A comment. sql/log_event.h: The constructor of Rotate_log_event used when we are rotating our binlog or relay log, should not assume that there is a nonzero THD available. For example, when we are reacting to SIGHUP, the THD is 0. In fact we don't need to use the THD in this constructor; we can do like for Stop_log_event, and use the minimal Log_event constructor. This fixes BUG#2045 "Sending SIGHUP to mysqld crashes it if running with --log-bin" --- sql/log.cc | 4 ++-- sql/log_event.cc | 7 ++++++- sql/log_event.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/log.cc b/sql/log.cc index e6eaa3b802c..8bd42d28e59 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -843,7 +843,7 @@ void MYSQL_LOG::new_file(bool need_lock) We log the whole file name for log file as the user may decide to change base names at some point. */ - THD* thd = current_thd; + THD* thd = current_thd; /* may be 0 if we are reacting to SIGHUP */ Rotate_log_event r(thd,new_name+dirname_length(new_name)); r.set_log_pos(this); @@ -852,7 +852,7 @@ void MYSQL_LOG::new_file(bool need_lock) the slave running with log-bin, we set the flag on rotate event to prevent infinite log rotation loop */ - if (thd->slave_thread) + if (thd && thd->slave_thread) r.flags|= LOG_EVENT_FORCED_ROTATE_F; r.write(&log_file); bytes_written += r.get_event_len(); diff --git a/sql/log_event.cc b/sql/log_event.cc index d17c94a2b44..9779b7401dd 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -128,7 +128,12 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))); } - +/* + This minimal constructor is for when you are not even sure that there is a + valid THD. For example in the server when we are shutting down or flushing + logs after receiving a SIGHUP (then we must write a Rotate to the binlog but + we have no THD, so we need this minimal constructor). +*/ Log_event::Log_event() :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0), thd(0) diff --git a/sql/log_event.h b/sql/log_event.h index 929d550951e..a1a7798be34 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -607,7 +607,7 @@ public: Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg, uint ident_len_arg = 0, ulonglong pos_arg = LOG_EVENT_OFFSET) - :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg), + :Log_event(), new_log_ident(new_log_ident_arg), pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg : (uint) strlen(new_log_ident_arg)), alloced(0) {} -- cgit v1.2.1 From 9a1cb59cd721a5a3a7e8a4ea1720fddc3d449892 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Dec 2003 20:53:46 +0100 Subject: Create PID file with O_TRUNC, so that it is emptied before it is written to. Otherwise, if the previous run ended with a crash, and the PID was 1234, and you have rebooted the machine and the new PID is 99 then in the PID file you will have 9934. Note: users of mysqld_safe did not have the problem because this script deletes the PID file before starting mysqld. --- sql/mysqld.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index daccfc52af4..9c68ae95ef2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1461,7 +1461,8 @@ static void start_signal_handler(void) if (!opt_bootstrap) { File pidFile; - if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0) + if ((pidFile = my_create(pidfile_name,0664, + O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) { char buff[21]; sprintf(buff,"%lu",(ulong) getpid()); @@ -1754,7 +1755,8 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) if (!opt_bootstrap) { File pidFile; - if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0) + if ((pidFile = my_create(pidfile_name,0664, + O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) { char buff[21]; sprintf(buff,"%lu",(ulong) getpid()); -- cgit v1.2.1 From c167af11e95823ac1147612866e1f2b738bc5941 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Dec 2003 12:36:57 +0400 Subject: Fix for the bug #1885: mysqldump does not dumps timestamp default. --- sql/sql_parse.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c867112bb2a..fc9c21586d9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3042,7 +3042,12 @@ bool add_field_to_list(char *field_name, enum_field_types type, if (default_value) { - if (default_value->type() == Item::NULL_ITEM) + if (type == FIELD_TYPE_TIMESTAMP) + { + net_printf(&thd->net, ER_INVALID_DEFAULT, field_name); + DBUG_RETURN(1); + } + else if (default_value->type() == Item::NULL_ITEM) { default_value=0; if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == -- cgit v1.2.1 From 589657539c6ce3acdbc579d6ba950655bdddae5f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Dec 2003 16:21:23 +0200 Subject: Don't limit number of tables in table cache --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index daccfc52af4..751cfe7473c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4067,7 +4067,7 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \ 1, 0}, {"table_cache", OPT_TABLE_CACHE, "The number of open tables for all threads.", (gptr*) &table_cache_size, - (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 16384, 0, 1, + (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, ~0L, 0, 1, 0}, {"thread_concurrency", OPT_THREAD_CONCURRENCY, "Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.", -- cgit v1.2.1 From 4e85bf326e8051533bb680d1a612813705dc789d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Dec 2003 20:17:28 +0200 Subject: Add newline after pid in pidfile --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3c196eddb47..70ee2f632ca 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1465,7 +1465,7 @@ static void start_signal_handler(void) O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) { char buff[21]; - sprintf(buff,"%lu",(ulong) getpid()); + sprintf(buff,"%lu\n",(ulong) getpid()); (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME)); (void) my_close(pidFile,MYF(0)); } -- cgit v1.2.1 From 7cfbf9e8f681eac207f8b37d12780f73ffa5dd70 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Dec 2003 20:49:48 +0100 Subject: code cleanup after some reasoning sql/mysqld.cc: code cleanup --- sql/mysqld.cc | 4 ++-- sql/opt_range.cc | 2 +- sql/repl_failsafe.cc | 1 - sql/table.cc | 5 ++--- 4 files changed, 5 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2e87ade9174..806a3524191 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4632,14 +4632,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), my_use_symdir=0; break; case (int) OPT_BIND_ADDRESS: - if (argument && isdigit(argument[0])) + if (isdigit(argument[0])) { my_bind_addr = (ulong) inet_addr(argument); } else { struct hostent *ent; - if (argument || argument[0]) + if (argument[0]) ent=gethostbyname(argument); else { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 63850709285..07f2f1eaf67 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2454,7 +2454,7 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) if (cp_buffer_from_ref(ref)) { if (thd->fatal_error) - return 0; // out of memory + goto err; // out of memory return quick; // empty range } diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 6b91d81b487..6599516044a 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -426,7 +426,6 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, my_snprintf(errmsg, SLAVE_ERRMSG_SIZE, "Could not find slave event in log '%s'", (char*)log_file_name); - delete ev; return 0; } diff --git a/sql/table.cc b/sql/table.cc index 422202301f1..0789f7469e7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1100,13 +1100,12 @@ rename_file_ext(const char * from,const char * to,const char * ext) char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr) { Field *field=table->field[fieldnr]; - char buff[MAX_FIELD_WIDTH]; + char buff[MAX_FIELD_WIDTH], *to; String str(buff,sizeof(buff)); field->val_str(&str,&str); uint length=str.length(); - if (!length) + if (!length || !(to= (char*) alloc_root(mem,length+1))) return NullS; - char *to= (char*) alloc_root(mem,length+1); memcpy(to,str.ptr(),(uint) length); to[length]=0; return to; -- cgit v1.2.1 From 1c30ec097027ebef052992ac7accfcdf8a19f227 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Dec 2003 23:52:58 +0300 Subject: Fix for bug #1335: filesort is missing in EXPLAIN if ORDER BY NULL is used mysql-test/r/group_by.result: test results fixed mysql-test/t/group_by.test: added few explicit tests for bug #1335 --- sql/sql_select.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7f8dfd219d0..df4b0226ff6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -696,8 +696,18 @@ mysql_select(THD *thd,TABLE_LIST *tables,List &fields,COND *conds, if (select_options & SELECT_DESCRIBE) { - if (!order && !no_order) - order=group; + /* + Check if we managed to optimize ORDER BY away and don't use temporary + table to resolve ORDER BY: in that case, we only may need to do + filesort for GROUP BY. + */ + if (!order && !no_order && (!skip_sort_order || !need_tmp)) + { + /* Reset 'order' to 'group' and reinit variables describing 'order' */ + order= group; + simple_order= simple_group; + skip_sort_order= 0; + } if (order && (join.const_tables == join.tables || ((simple_order || skip_sort_order) && -- cgit v1.2.1 From daccd19657bc076ab193919817ffe299c21ff747 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Dec 2003 21:56:11 +0100 Subject: followup --- sql/opt_range.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 07f2f1eaf67..4bbeaca8a79 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2447,6 +2447,7 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) QUICK_SELECT *quick=new QUICK_SELECT(thd, table, ref->key, 1); KEY *key_info = &table->key_info[ref->key]; KEY_PART *key_part; + QUICK_RANGE *range; uint part; if (!quick) @@ -2458,8 +2459,7 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) return quick; // empty range } - QUICK_RANGE *range= new QUICK_RANGE(); - if (!range) + if (!(range= new QUICK_RANGE())) goto err; // out of memory range->min_key=range->max_key=(char*) ref->key_buff; -- cgit v1.2.1 From 6b97c26a29127f73c699aaa13ffb5ae9f33703cf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Dec 2003 00:00:20 +0200 Subject: Added checking of return value from my_once_alloc() in charset Added checking of return value from malloc() in reg_init() client/mysqltest.c: Added comment dbug/dbug.c: Removed not needed test mysys/charset.c: Added checking of return value from my_once_alloc() regex/reginit.c: Abort if out of memory in reg_init() (unlikely) sql/item_strfunc.cc: Added comment --- sql/item_strfunc.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sql') diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index dd1ec6bd2da..40b18755744 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2043,6 +2043,10 @@ String* Item_func_export_set::val_str(String* str) null_value=1; return 0; } + /* + Arg count can only be 3, 4 or 5 here. This is guaranteed from the + grammar for EXPORT_SET() + */ switch(arg_count) { case 5: num_set_values = (uint) args[4]->val_int(); -- cgit v1.2.1 From 417d2b193adacb122d88c4443c1a982803e5eea0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Dec 2003 12:03:54 +0200 Subject: Add cast to remove compiler warning --- sql/sql_cache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 8610fcb8f22..63d4e4222b4 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2181,7 +2181,7 @@ void Query_cache::free_memory_block(Query_cache_block *block) block->type= Query_cache_block::FREE; // mark block as free in any case DBUG_PRINT("qcache", ("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx", - (ulong) first_block, (ulong) block,block->pnext, + (ulong) first_block, (ulong) block, (ulong) block->pnext, (ulong) block->pprev)); if (block->pnext != first_block && block->pnext->is_free()) -- cgit v1.2.1 From 02f56e77e0f71197679ea8784f07be98fb17ce27 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Dec 2003 15:17:23 +0300 Subject: followup to fix for bug #1790 BIT_AND() result in GROUP BY different when SQL_BIG_RESULT used": now BIT_AND() always returns 18446744073709551615 if no rows were found. This patch also fixes bug #1972: "BIT_AND() and BIT_OR() still return a *signed* 64bit value" mysql-test/r/func_group.result: followup to fix for bug #1790 BIT_AND() result in GROUP BY different when SQL_BIG_RESULT used": test results fixed bug #1972 "BIT_AND() and BIT_OR() still return a *signed* 64bit value": results of new tests mysql-test/t/func_group.test: added tests for bug #1972 "BIT_AND() and BIT_OR() still return a *signed* 64bit value" --- sql/item_sum.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 5a5934db0cd..e18fa83e49d 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -104,12 +104,13 @@ Item_sum_num::val_str(String *str) String * Item_sum_int::val_str(String *str) { - longlong nr=val_int(); + longlong nr= val_int(); if (null_value) return 0; - char buff[21]; - uint length= (uint) (longlong10_to_str(nr,buff,-10)-buff); - str->copy(buff,length); + if (unsigned_flag) + str->set((ulonglong) nr); + else + str->set(nr); return str; } -- cgit v1.2.1 From f195cf9d1455f05bd6e6b1e0225f1062dc28d9f7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Dec 2003 17:30:37 +0300 Subject: fix for bug #1993 'bit functions do not return unsigned values' introduced base class Item_func_bit for bit functions mysql-test/r/func_op.result: test results for bug #1993 'bit functions do not return unsigned values' mysql-test/t/func_op.test: added tests for bug #1993 'bit functions do not return unsigned values' --- sql/item_func.h | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'sql') diff --git a/sql/item_func.h b/sql/item_func.h index 09aba9694dd..4d171cda490 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -642,23 +642,30 @@ public: unsigned int size_of() { return sizeof(*this);} }; +/* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ -class Item_func_bit_or :public Item_int_func +class Item_func_bit: public Item_int_func { public: - Item_func_bit_or(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit(Item *a, Item *b) :Item_int_func(a, b) {} + Item_func_bit(Item *a) :Item_int_func(a) {} + void fix_length_and_dec() { unsigned_flag= 1; } +}; + +class Item_func_bit_or :public Item_func_bit +{ +public: + Item_func_bit_or(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "|"; } - void fix_length_and_dec() { unsigned_flag=1; } }; -class Item_func_bit_and :public Item_int_func +class Item_func_bit_and :public Item_func_bit { public: - Item_func_bit_and(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit_and(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "&"; } - void fix_length_and_dec() { unsigned_flag=1; } }; class Item_func_bit_count :public Item_int_func @@ -670,30 +677,28 @@ public: void fix_length_and_dec() { max_length=2; } }; -class Item_func_shift_left :public Item_int_func +class Item_func_shift_left :public Item_func_bit { public: - Item_func_shift_left(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_shift_left(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "<<"; } - void fix_length_and_dec() { unsigned_flag=1; } }; -class Item_func_shift_right :public Item_int_func +class Item_func_shift_right :public Item_func_bit { public: - Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_shift_right(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return ">>"; } }; -class Item_func_bit_neg :public Item_int_func +class Item_func_bit_neg :public Item_func_bit { public: - Item_func_bit_neg(Item *a) :Item_int_func(a) {} + Item_func_bit_neg(Item *a) :Item_func_bit(a) {} longlong val_int(); const char *func_name() const { return "~"; } - void fix_length_and_dec() { unsigned_flag=1; } }; class Item_func_set_last_insert_id :public Item_int_func @@ -1018,13 +1023,12 @@ enum Item_cast Item *create_func_cast(Item *a, Item_cast cast_type); -class Item_func_bit_xor : public Item_int_func +class Item_func_bit_xor : public Item_func_bit { public: - Item_func_bit_xor(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit_xor(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "^"; } - void fix_length_xor_dec() { unsigned_flag=1; } }; class Item_func_is_free_lock :public Item_int_func -- cgit v1.2.1 From ceab00b0c8ac072d83f565ac6c0f86bf8e0c22f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Dec 2003 22:26:31 +0300 Subject: cleanup: if there is return from if-part, we don't need else statement --- sql/field.cc | 4 ++-- sql/item.cc | 5 ++--- sql/item_cmpfunc.cc | 5 ++--- sql/item_func.cc | 25 ++++++++++--------------- sql/item_strfunc.cc | 13 +++++-------- sql/item_sum.cc | 6 ++---- sql/mysqld.cc | 2 +- sql/opt_range.cc | 2 +- sql/sql_analyse.cc | 8 ++------ sql/sql_insert.cc | 19 ++++++++----------- sql/sql_parse.cc | 3 +-- 11 files changed, 36 insertions(+), 56 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 1070d0f7b7d..d43089ec35c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -848,7 +848,7 @@ int Field_decimal::cmp(const char *a_ptr,const char *b_ptr) return 0; if (*a_ptr == '-') return -1; - else if (*b_ptr == '-') + if (*b_ptr == '-') return 1; while (a_ptr != end) @@ -3018,7 +3018,7 @@ void Field_year::store(const char *from, uint len) current_thd->cuted_fields++; return; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len)) + if (current_thd->count_cuted_fields && !test_if_int(from,len)) current_thd->cuted_fields++; if (nr != 0 || len != 4) { diff --git a/sql/item.cc b/sql/item.cc index fc6256d4fed..60fc383d757 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -694,10 +694,9 @@ Item_result item_cmp_type(Item_result a,Item_result b) { if (a == STRING_RESULT && b == STRING_RESULT) return STRING_RESULT; - else if (a == INT_RESULT && b == INT_RESULT) + if (a == INT_RESULT && b == INT_RESULT) return INT_RESULT; - else - return REAL_RESULT; + return REAL_RESULT; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 63f3a8985c5..82f368970e2 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -463,10 +463,9 @@ static Item_result item_store_type(Item_result a,Item_result b) { if (a == STRING_RESULT || b == STRING_RESULT) return STRING_RESULT; - else if (a == REAL_RESULT || b == REAL_RESULT) + if (a == REAL_RESULT || b == REAL_RESULT) return REAL_RESULT; - else - return INT_RESULT; + return INT_RESULT; } void diff --git a/sql/item_func.cc b/sql/item_func.cc index 8d7ee637d73..64b1c5d4d8a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -214,8 +214,7 @@ String *Item_real_func::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals); + str->set(nr,decimals); return str; } @@ -227,7 +226,7 @@ String *Item_num_func::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; /* purecov: inspected */ - else if (!unsigned_flag) + if (!unsigned_flag) str->set(nr); else str->set((ulonglong) nr); @@ -237,8 +236,7 @@ String *Item_num_func::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals); + str->set(nr,decimals); } return str; } @@ -257,7 +255,7 @@ String *Item_int_func::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) + if (!unsigned_flag) str->set(nr); else str->set((ulonglong) nr); @@ -286,7 +284,7 @@ String *Item_num_op::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; /* purecov: inspected */ - else if (!unsigned_flag) + if (!unsigned_flag) str->set(nr); else str->set((ulonglong) nr); @@ -296,8 +294,7 @@ String *Item_num_op::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals); + str->set(nr,decimals); } return str; } @@ -799,7 +796,7 @@ String *Item_func_min_max::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) + if (!unsigned_flag) str->set(nr); else str->set((ulonglong) nr); @@ -810,8 +807,7 @@ String *Item_func_min_max::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals); + str->set(nr,decimals); return str; } case STRING_RESULT: @@ -1392,8 +1388,7 @@ String *Item_func_udf_float::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals); + str->set(nr,decimals); return str; } @@ -1413,7 +1408,7 @@ String *Item_func_udf_int::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) + if (!unsigned_flag) str->set(nr); else str->set((ulonglong) nr); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 40b18755744..7434f6bd57b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1706,14 +1706,11 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value, str->length(length); return str; } - else - { - if (tmp_value->alloc(length)) - return 0; - (void) tmp_value->copy(*res); - tmp_value->length(length); - return tmp_value; - } + if (tmp_value->alloc(length)) + return 0; + (void) tmp_value->copy(*res); + tmp_value->length(length); + return tmp_value; } res->length(length); return res; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index e18fa83e49d..4121fa65433 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1153,8 +1153,7 @@ String *Item_sum_udf_float::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals); + str->set(nr,decimals); return str; } @@ -1172,8 +1171,7 @@ String *Item_sum_udf_int::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else - str->set(nr); + str->set(nr); return str; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 410a1644eec..b75a94a261c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1043,7 +1043,7 @@ static void set_user(const char *user) } return; } - else if (!user) + if (!user) { if (!opt_bootstrap) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 4bbeaca8a79..02b7699fad6 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1474,7 +1474,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) } return 0; } - else if (!key2) + if (!key2) { key1->use_count--; key1->free_tree(); diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index d6abe6497df..bd8c0e5ba87 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -220,8 +220,7 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) info->is_float = 1; // we can't use variable decimals here return 1; } - else - return 0; + return 0; } for (str++; *(end - 1) == '0'; end--); // jump over zeros at the end if (str == end) // number was something like '123.000' @@ -236,11 +235,8 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) info->dval = atod(begin); return 1; } - else - return 0; } - else - return 0; + return 0; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3414e76e092..a92379a6d3b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1409,18 +1409,15 @@ bool select_insert::send_eof() ::send_error(&thd->net); return 1; } + char buff[160]; + if (info.handle_duplicates == DUP_IGNORE) + sprintf(buff,ER(ER_INSERT_INFO),info.records,info.records-info.copied, + thd->cuted_fields); else - { - char buff[160]; - if (info.handle_duplicates == DUP_IGNORE) - sprintf(buff,ER(ER_INSERT_INFO),info.records,info.records-info.copied, - thd->cuted_fields); - else - sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted, - thd->cuted_fields); - ::send_ok(&thd->net,info.copied+info.deleted,last_insert_id,buff); - return 0; - } + sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted, + thd->cuted_fields); + ::send_ok(&thd->net,info.copied+info.deleted,last_insert_id,buff); + return 0; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fc9c21586d9..d59dda43d67 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -268,8 +268,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, decrease_user_connections(thd->user_connect); return error; } - else - send_ok(net); // Ready to handle questions + send_ok(net); // Ready to handle questions thd->password= test(passwd[0]); // Remember for error messages return 0; // ok } -- cgit v1.2.1 From 287661e66cc1fea6730b357bb56d48c6d065ef43 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Dec 2003 06:24:08 +0200 Subject: Fixed a possible memory leak on MacOSX when using the shared libmysql.so library (Bug #2061) mysql_server_init() now returns error code if something went wrong (Bug #2062) Don't use my_fopen() when reading symlink information as this may cause problems when a lot of files are opened. Free thread keys with pthread_key_delete() instead of relying on automatic free. (Bug #2062) Fixed bug in UNION statement with alias '*'. (Bug #1249) Fixed a bug in DELETE ... ORDER BY ... LIMIT where the rows where not deleted in the proper order. (Bug #1024). FOUND_ROWS() could return incorrect number of rows after a query with an impossible WHERE condition. HOW DATABASES doesn't anymore show .sym files (on windows) that doesn't point to a valid directory. (Bug #1385) include/config-win.h: Ensure that USE_SYMDIR is set for all windows versions (This is set in makefiles, so this is just an extra safety measure) include/my_pthread.h: Fixed a possible memory leak on MacOSX when using the shared libmysql.so library (Bug #2061) include/my_sys.h: my_init() now returns error code if something went wrong include/mysql.h: mysql_once_init() now returns error code if something went wrong include/mysql_com.h: my_init() now returns error code if something went wrong libmysql/libmysql.c: mysql_server_init() and mysql_once_init() now returns error code if something went wrong (Bug #2062) mysql-test/r/limit.result: Update results mysql-test/r/select_found.result: Update results mysql-test/r/union.result: Update results mysql-test/t/limit.test: Added test for DELETE ... ORDER BY ... LIMIT (bug #1024) mysql-test/t/select_found.test: Added test for problem with impossible WHERE (Bug #1468) mysql-test/t/union.test: Added test for problem with alias '*' (Bug #1249) mysys/mf_pack.c: Don't use my_fopen() when reading symlink information as this may cause problems when a lot of files are opened. mysys/my_init.c: my_init() now returns error code if something went wrong mysys/my_lib.c: More debug information mysys/my_thr_init.c: Free thread keys with pthread_key_delete() instead of relying on automatic free. (Bug #2062) sql/sql_base.cc: Fixed bug in UNION statement with alias '*'. (Bug #1249) sql/sql_delete.cc: Fixed a bug in DELETE ... ORDER BY ... LIMIT where the rows where not deleted in the proper order. (Bug #1024). sql/sql_select.cc: FOUND_ROWS() could return incorrect number of rows after a query with an impossible WHERE condition. sql/sql_show.cc: SHOW DATABASES doesn't anymore show .sym files (on windows) that doesn't point to a valid directory. (Bug #1385) sql/sql_yacc.yy: Allow syntax UNION DISTINCT --- sql/sql_base.cc | 7 ++++++- sql/sql_delete.cc | 12 +++++++++--- sql/sql_select.cc | 2 ++ sql/sql_show.cc | 12 ++++++++++++ sql/sql_yacc.yy | 1 + 5 files changed, 30 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e4694adb9a2..dd80062d6e7 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1868,8 +1868,13 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List &fields, while ((item=it++)) { + /* + Expand * to all fields if this is not the temporary table for an + a UNION result + */ if (item->type() == Item::FIELD_ITEM && - ((Item_field*) item)->field_name[0] == '*') + ((Item_field*) item)->field_name[0] == '*' && + !((Item_field*) item)->field) { uint elem=fields.elements; if (insert_fields(thd,tables,((Item_field*) item)->db_name, diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 34a79ecd78d..ee2b720907d 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -78,7 +78,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, DBUG_RETURN(-1); if ((select && select->check_quick(thd, test(thd->options & OPTION_SAFE_UPDATES), - limit)) || + limit)) || !limit) { delete select; @@ -117,13 +117,19 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, if (setup_order(thd, &tables, fields, all_fields, order) || !(sortorder=make_unireg_sortorder(order, &length)) || (table->found_records = filesort(table, sortorder, length, - (SQL_SELECT *) 0, 0L, HA_POS_ERROR, + select, 0L, HA_POS_ERROR, &examined_rows)) == HA_POS_ERROR) { delete select; - DBUG_RETURN(-1); // This will force out message + DBUG_RETURN(-1); // This will force out message } + /* + Filesort has already found and selected the rows we want to delete, + so we don't need the where clause + */ + delete select; + select= 0; } init_read_record(&info,thd,table,select,1,1); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index df4b0226ff6..892ad02bb5b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3273,6 +3273,8 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, } result->send_eof(); // Should be safe } + /* Update results for FOUND_ROWS */ + join->thd->limit_found_rows= join->thd->examined_row_count= 0; DBUG_RETURN(0); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a7de04d0bfa..cb6cd18b7c8 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -197,7 +197,19 @@ mysql_find_files(THD *thd,List *files, const char *db,const char *path, #ifdef USE_SYMDIR char *ext; if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym")) + { + /* Only show the sym file if it points to a directory */ + char buff[FN_REFLEN], *end; + MY_STAT status; *ext=0; /* Remove extension */ + unpack_dirname(buff, file->name); + end= strend(buff); + if (end != buff && end[-1] == FN_LIBCHAR) + end[-1]= 0; // Remove end FN_LIBCHAR + if (!my_stat(buff, &status, MYF(0)) || + !MY_S_ISDIR(status.st_mode)) + continue; + } else #endif { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 03837300904..b5b9a4cdfb7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4014,5 +4014,6 @@ optional_order_or_limit: union_option: /* empty */ {} + | DISTINCT {} | ALL { Lex->union_option=1; } ; -- cgit v1.2.1 From 9570d010d571d62a9cbdc9674606b1f154b4dead Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Dec 2003 14:55:48 -0800 Subject: Many files: Fixed a bug causing a crash for multi-update/multi-delete with impossible where (bug #1860). sql/sql_class.h: Fixed a bug causing a crash for multi-update/multi-delete with impossible where (bug #1860). sql/sql_delete.cc: Fixed a bug causing a crash for multi-update/multi-delete with impossible where (bug #1860). sql/sql_update.cc: Fixed a bug causing a crash for multi-update/multi-delete with impossible where (bug #1860). mysql-test/t/multi_update.test: Fixed a bug causing a crash for multi-update/multi-delete with impossible where (bug #1860). mysql-test/r/multi_update.result: Fixed a bug causing a crash for multi-update/multi-delete with impossible where (bug #1860). BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- sql/sql_class.h | 3 +++ sql/sql_delete.cc | 6 +++++- sql/sql_update.cc | 8 ++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/sql_class.h b/sql/sql_class.h index 9287a0c8c79..c487e212e24 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -848,6 +848,8 @@ class multi_delete : public select_result uint num_of_tables; int error; bool do_delete, transactional_tables, log_delayed, normal_tables; + bool tempfiles_inited; + public: multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables); ~multi_delete(); @@ -874,6 +876,7 @@ class multi_update : public select_result Copy_field *copy_field; enum enum_duplicates handle_duplicates; bool do_update, trans_safe, transactional_tables, log_delayed; + bool tmp_tables_inited; public: multi_update(THD *thd_arg, TABLE_LIST *ut, List *fields, diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index ee2b720907d..399f237bf2f 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -236,7 +236,8 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables_arg) : delete_tables(dt), thd(thd_arg), deleted(0), num_of_tables(num_of_tables_arg), error(0), - do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0) + do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0), + tempfiles_inited(0) { tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1)); } @@ -297,6 +298,7 @@ multi_delete::initialize_tables(JOIN *join) table->file->ref_length, MEM_STRIP_BUF_SIZE); } + tempfiles_inited= 1; init_ftfuncs(thd,1); DBUG_RETURN(thd->fatal_error != 0); } @@ -422,6 +424,8 @@ int multi_delete::do_deletes(bool from_send_error) table_being_deleted = delete_tables; do_delete= 0; + if (!tempfiles_inited) + DBUG_RETURN(0); for (table_being_deleted=table_being_deleted->next; table_being_deleted ; table_being_deleted=table_being_deleted->next, counter++) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d5034644830..19df0661db3 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -440,7 +440,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, :all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list), values(value_list), table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg), - do_update(1), trans_safe(0) + do_update(1), trans_safe(0), tmp_tables_inited(0) {} @@ -622,6 +622,7 @@ multi_update::initialize_tables(JOIN *join) DBUG_RETURN(1); tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE); } + tmp_tables_inited= 1; DBUG_RETURN(0); } @@ -819,8 +820,11 @@ int multi_update::do_updates(bool from_send_error) ha_rows org_updated; TABLE *table; DBUG_ENTER("do_updates"); + - do_update= 0; // Don't retry this function + do_update= 0; // Don't retry this function + if (!tmp_tables_inited) + DBUG_RETURN(0); for (cur_table= update_tables; cur_table ; cur_table= cur_table->next) { table = cur_table->table; -- cgit v1.2.1 From c545b02645cbc09e33a211955a8dbcc09a994b77 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Dec 2003 03:39:29 +0300 Subject: Fix for Bug #1952 "SHOW TABLE STATUS very slow w/large number of tables" Replaced old algorithm which were used in my_dir() and stored all information about directory entries in one chunk of memory with new one which stores file names and MY_STAT structures in separate memroot, so now we don't need to copy this data during reallocation of dir_entry array. include/my_dir.h: Changed mystat member of FILEINFO structure to pointer since this prevents unneeded memory allocation and initialization. Added comment about new hidden members of MY_DIR structure. mysys/my_lib.c: Replaced old algorithm in my_dir() which stored all information about directory entries in one chunk of memory with new one which stores file names and MY_STAT structures in separate memroot. Now we don't copy this data during reallocation of array with FILEINFO structures. Also tuned sizes of memory chunks during first-other reallocations (we suppose that we either have < 100 files in the directory or > 1000 of them). sql/sql_show.cc: Updated only place in code where mystat member of FILEINFO structure is used. --- sql/sql_show.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cb6cd18b7c8..1a2f900eb7e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -213,7 +213,7 @@ mysql_find_files(THD *thd,List *files, const char *db,const char *path, else #endif { - if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) || + if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) || (wild && wild_compare(file->name,wild))) continue; } -- cgit v1.2.1 From 4f90f2fc6734aa920d2c6a2252c7b7c8d29ebd67 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Dec 2003 21:26:20 +0400 Subject: Proposed fix for #2093 it happens because of the LEFT JOINT optimization in add_key_part() This optimization does exactly the same in JOIN and in WHERE conditions Not right. I moved that optimization one level upper. mysql-test/r/join_outer.result: appropriate test result mysql-test/t/join_outer.test: test case sql/sql_select.cc: optimizing of the left_join now only for WHERE conditions and for first table in list --- sql/sql_select.cc | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 892ad02bb5b..d0d6c1e5fa2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1683,10 +1683,6 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field) } } } - /* Mark that we can optimize LEFT JOIN */ - if (key_field->val->type() == Item::NULL_ITEM && - !key_field->field->real_maybe_null()) - key_field->field->table->reginfo.not_exists_optimize=1; } @@ -1777,13 +1773,26 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, { KEY_FIELD *key_fields,*end; + KEY_FIELD *field; if (!(key_fields=(KEY_FIELD*) thd->alloc(sizeof(key_fields[0])*(thd->cond_count+1)*2))) return TRUE; /* purecov: inspected */ - and_level=0; end=key_fields; + and_level=0; field=end=key_fields; + if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64)) + return TRUE; if (cond) + { add_key_fields(join_tab,&end,&and_level,cond,normal_tables); + for (; field != end ; field++) + { + add_key_part(keyuse,field); + /* Mark that we can optimize LEFT JOIN */ + if (field->val->type() == Item::NULL_ITEM && + !field->field->real_maybe_null()) + field->field->table->reginfo.not_exists_optimize=1; + } + } for (i=0 ; i < tables ; i++) { if (join_tab[i].on_expr) @@ -1792,11 +1801,16 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, join_tab[i].table->map); } } - if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64)) - return TRUE; /* fill keyuse with found key parts */ - for (KEY_FIELD *field=key_fields ; field != end ; field++) + for (; field != end ; field++) + { add_key_part(keyuse,field); + /* Mark that we can optimize LEFT JOIN */ + if (field->field->table == join_tab->table && + field->val->type() == Item::NULL_ITEM && + !field->field->real_maybe_null()) + join_tab->table->reginfo.not_exists_optimize=1; + } } if (thd->lex.select->ftfunc_list.elements) -- cgit v1.2.1 From e28af60ab68e9a0398fea2e9beaab5abb8ab13af Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Dec 2003 22:13:57 +0400 Subject: Fix #2093 Update after discussion with Monty sql/sql_select.cc: Wrong operation - deleted --- sql/sql_select.cc | 7 ------- 1 file changed, 7 deletions(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d0d6c1e5fa2..8f2d97affca 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1803,14 +1803,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, } /* fill keyuse with found key parts */ for (; field != end ; field++) - { add_key_part(keyuse,field); - /* Mark that we can optimize LEFT JOIN */ - if (field->field->table == join_tab->table && - field->val->type() == Item::NULL_ITEM && - !field->field->real_maybe_null()) - join_tab->table->reginfo.not_exists_optimize=1; - } } if (thd->lex.select->ftfunc_list.elements) -- cgit v1.2.1 From 759ea82ee1335543da1d484d76468b6686057e90 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Dec 2003 22:26:58 +0200 Subject: Fix autoincrement for signed columns (Bug #1366) Fixed problem with char > 128 in QUOTE() function. (Bug #1868) Disable creation of symlinks if my_disable_symlink is set Fixed searching of TEXT with end space. (Bug #1651) Fixed caching bug in multi-table-update where same table was used twice. (Bug #1711) Fixed problem with UNIX_TIMESTAMP() for timestamps close to 0. (Bug #1998) Fixed timestamp.test include/my_base.h: Add HA_END_SPACE_KEY to mark keys that has VARCHAR/TEXT fields. myisam/mi_check.c: Delete not used variable myisam/mi_key.c: Fix autoincrement for signed columns (Bug #1366). Patch by Holyfoot myisam/mi_open.c: Bug fix for future (doesn't affect current code) myisam/mi_search.c: Ignore end space for VARCHAR/TEXT columns mysql-test/r/auto_increment.result: Test auto_increment with signed numbers mysql-test/r/binary.result: Update results (old result was wrong) mysql-test/r/func_str.result: Added test of QUOTE() mysql-test/r/func_time.result: Add test of unix_timestamp() mysql-test/r/have_met_timezone.require: Fixed test mysql-test/r/innodb.result: Add test for InnoDB behaviour with TRUNCATE mysql-test/r/multi_update.result: Test of multi-update bug mysql-test/r/symlink.result: Test of ALTER TABLE and symlinks mysql-test/r/timezone.result: Test of from_unixtime() mysql-test/r/truncate.result: Test of truncate and auto_increment mysql-test/r/type_blob.result: Test of key search on TEXT/VARCHAR column with end space mysql-test/t/auto_increment.test: Test auto_increment with signed numbers mysql-test/t/func_str.test: Added test of QUOTE() mysql-test/t/func_time.test: Add test of unix_timestamp() mysql-test/t/innodb.test: Add test for InnoDB behaviour with TRUNCATE mysql-test/t/multi_update.test: Test of multi-update bug mysql-test/t/symlink.test: Test of ALTER TABLE and symlinks mysql-test/t/timezone.test: Test of from_unixtime() mysql-test/t/truncate.test: Test of truncate and auto_increment mysql-test/t/type_blob.test: Test of key search on TEXT/VARCHAR column with end space mysys/my_symlink2.c: Disable creation of symlinks if my_disable_symlink is set sql/field.h: Indentation cleanup sql/ha_innodb.cc: HA_PART_KEY -> HA_PART_KEY_SEG sql/item_strfunc.cc: Fixed problem with char > 128 in QUOTE() function. (Bug #1868) sql/mysql_priv.h: Make check_dup() external sql/opt_range.cc: Fixed searching of TEXT with end space. (Bug #1651) sql/records.cc: Fixed caching bug in multi-table-update where same table was used twice. (Bug #1711) sql/sql_acl.cc: Reset ip and ip_mask if hostname is NULL sql/sql_parse.cc: Make check_dup() global sql/sql_select.cc: Fixed searching of TEXT with end space. (Bug #1651) sql/sql_table.cc: Fixed searching of TEXT with end space. (Bug #1651) sql/sql_update.cc: Fixed caching bug in multi-table-update where same table was used twice. (Bug #1711) sql/table.cc: Fixed searching of TEXT with end space. (Bug #1651) sql/table.h: Fixed caching bug in multi-table-update where same table was used twice. (Bug #1711) sql/time.cc: Fixed problem with UNIX_TIMESTAMP() for timestamps close to 0. (Bug #1998) --- sql/field.h | 7 ++++--- sql/ha_innodb.cc | 4 ++-- sql/item_strfunc.cc | 2 +- sql/mysql_priv.h | 1 + sql/opt_range.cc | 46 +++++++++++++++++++++++++++++++++++++--------- sql/records.cc | 11 ++++++----- sql/sql_acl.cc | 4 ++-- sql/sql_parse.cc | 3 +-- sql/sql_select.cc | 12 +++++++----- sql/sql_table.cc | 8 ++++---- sql/sql_update.cc | 22 +++++++++++++++++++++- sql/table.cc | 21 +++++++++++++++------ sql/table.h | 2 +- sql/time.cc | 4 +++- 14 files changed, 105 insertions(+), 42 deletions(-) (limited to 'sql') diff --git a/sql/field.h b/sql/field.h index 3186f9f5275..8a829a455ed 100644 --- a/sql/field.h +++ b/sql/field.h @@ -799,9 +799,10 @@ public: binary_flag(binary_arg) { if (binary_arg) - flags|=BINARY_FLAG; + flags|= BINARY_FLAG; } - Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + Field_varstring(uint32 len_arg,bool maybe_null_arg, + const char *field_name_arg, struct st_table *table_arg, bool binary_arg) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, table_arg), @@ -856,7 +857,7 @@ public: { flags|= BLOB_FLAG; if (binary_arg) - flags|=BINARY_FLAG; + flags|= BINARY_FLAG; } enum_field_types type() const { return FIELD_TYPE_BLOB;} enum ha_base_keytype key_type() const diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 47c49b79d77..beff8c1f515 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1788,7 +1788,7 @@ ha_innobase::store_key_val_for_row( || mysql_type == FIELD_TYPE_BLOB || mysql_type == FIELD_TYPE_LONG_BLOB) { - ut_a(key_part->key_part_flag & HA_PART_KEY); + ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); if (is_null) { buff += key_part->length + 2; @@ -3270,7 +3270,7 @@ create_index( for (i = 0; i < n_fields; i++) { key_part = key->key_part + i; - /* (The flag HA_PART_KEY denotes in MySQL a column prefix + /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix field in an index: we only store a specified number of first bytes of the column to the index field.) The flag does not seem to be properly set by MySQL. Let us fall back on testing diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7434f6bd57b..a4d04253dd7 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2169,7 +2169,7 @@ String *Item_func_quote::val_str(String *str) new_length= arg_length+2; /* for beginning and ending ' signs */ for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) - new_length+= get_esc_bit(escmask, *from); + new_length+= get_esc_bit(escmask, (uchar) *from); /* We have to use realloc() instead of alloc() as we want to keep the diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 04529919990..d0e0e6992fa 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -364,6 +364,7 @@ void mysql_execute_command(void); bool do_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length); +bool check_dup(const char *db, const char *name, TABLE_LIST *tables); #ifndef EMBEDDED_LIBRARY bool check_stack_overrun(THD *thd,char *dummy); #else diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 02b7699fad6..74fa237fd73 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -942,9 +942,10 @@ static SEL_ARG * get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, Item_func::Functype type,Item *value) { - uint maybe_null=(uint) field->real_maybe_null(); + uint maybe_null=(uint) field->real_maybe_null(), copies; uint field_length=field->pack_length()+maybe_null; SEL_ARG *tree; + char *str, *str2; DBUG_ENTER("get_mm_leaf"); if (type == Item_func::LIKE_FUNC) @@ -1056,15 +1057,39 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, /* This happens when we try to insert a NULL field in a not null column */ DBUG_RETURN(&null_element); // cmp with NULL is never true } - // Get local copy of key - char *str= (char*) alloc_root(param->mem_root, - key_part->part_length+maybe_null); + /* Get local copy of key */ + copies= 1; + if (field->key_type() == HA_KEYTYPE_VARTEXT) + copies= 2; + str= str2= (char*) alloc_root(param->mem_root, + (key_part->part_length+maybe_null)*copies); if (!str) DBUG_RETURN(0); if (maybe_null) *str= (char) field->is_real_null(); // Set to 1 if null field->get_key_image(str+maybe_null,key_part->part_length); - if (!(tree=new SEL_ARG(field,str,str))) + if (copies == 2) + { + /* + The key is stored as 2 byte length + key + key doesn't match end space. In other words, a key 'X ' should match + all rows between 'X' and 'X ...' + */ + uint length= uint2korr(str+maybe_null); + char *end; + str2= str+ key_part->part_length + maybe_null; + /* remove end space. The 2 is for the packed length */ + while (length > 0 && str[length+2+maybe_null-1] == ' ') + length--; + int2store(str+maybe_null, length); + /* Create key that is space filled */ + memcpy(str2, str, length+2+maybe_null); + end= str2+ maybe_null + key_part->part_length; + for (char *pos= str2+ 2+ length + maybe_null; pos < end ; pos++) + *pos++= ' '; + int2store(str2+maybe_null, key_part->part_length); + } + if (!(tree=new SEL_ARG(field,str,str2))) DBUG_RETURN(0); // out of memory switch (type) { @@ -2233,7 +2258,8 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, param->range_count++; if (!tmp_min_flag && ! tmp_max_flag && (uint) key_tree->part+1 == param->table->key_info[keynr].key_parts && - (param->table->key_info[keynr].flags & HA_NOSAME) && + (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) == + HA_NOSAME && min_key_length == max_key_length && !memcmp(param->min_key,param->max_key,min_key_length)) tmp=1; // Max one record @@ -2367,7 +2393,8 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key, { KEY *table_key=quick->head->key_info+quick->index; flag=EQ_RANGE; - if (table_key->flags & HA_NOSAME && key->part == table_key->key_parts-1) + if ((table_key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME && + key->part == table_key->key_parts-1) { if (!(table_key->flags & HA_NULL_PART_KEY) || !null_part_in_key(key, @@ -2412,7 +2439,7 @@ bool QUICK_SELECT::unique_key_range() if (((tmp=ranges.head())->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE) { KEY *key=head->key_info+index; - return ((key->flags & HA_NOSAME) && + return ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME && key->key_length == tmp->min_length); } } @@ -2465,7 +2492,8 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) range->min_key=range->max_key=(char*) ref->key_buff; range->min_length=range->max_length=ref->key_length; range->flag= ((ref->key_length == key_info->key_length && - (key_info->flags & HA_NOSAME)) ? EQ_RANGE : 0); + (key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == + HA_NOSAME) ? EQ_RANGE : 0); if (!(quick->key_parts=key_part=(KEY_PART *) alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts))) diff --git a/sql/records.cc b/sql/records.cc index fd46506203f..415e75a467b 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -99,11 +99,12 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, info->read_record=rr_sequential; table->file->rnd_init(); /* We can use record cache if we don't update dynamic length tables */ - if (use_record_cache > 0 || - (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY || - !(table->db_options_in_use & HA_OPTION_PACK_RECORD) || - (use_record_cache < 0 && - !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE))) + if (!table->no_cache && + (use_record_cache > 0 || + (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY || + !(table->db_options_in_use & HA_OPTION_PACK_RECORD) || + (use_record_cache < 0 && + !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE)))) VOID(table->file->extra_opt(HA_EXTRA_CACHE, thd->variables.read_buff_size)); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 03a359d44e7..a395396be2d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1202,11 +1202,11 @@ static const char *calc_ip(const char *ip, long *val, char end) static void update_hostname(acl_host_and_ip *host, const char *hostname) { host->hostname=(char*) hostname; // This will not be modified! - if (hostname && + if (!hostname || (!(hostname=calc_ip(hostname,&host->ip,'/')) || !(hostname=calc_ip(hostname+1,&host->ip_mask,'\0')))) { - host->ip=host->ip_mask=0; // Not a masked ip + host->ip= host->ip_mask=0; // Not a masked ip } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d59dda43d67..01d6500260f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -56,7 +56,6 @@ static int check_for_max_user_connections(USER_CONN *uc); static void decrease_user_connections(USER_CONN *uc); static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); -static bool check_dup(const char *db, const char *name, TABLE_LIST *tables); static void mysql_init_query(THD *thd); static void remove_escape(char *name); static void refresh_status(void); @@ -3600,7 +3599,7 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b) /* Check if name is used in table list */ -static bool check_dup(const char *db, const char *name, TABLE_LIST *tables) +bool check_dup(const char *db, const char *name, TABLE_LIST *tables) { for (; tables ; tables=tables->next) if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db)) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 892ad02bb5b..22864dedc49 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1261,7 +1261,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, } while (keyuse->table == table && keyuse->key == key); if (eq_part == PREV_BITS(uint,table->key_info[key].key_parts) && - (table->key_info[key].flags & HA_NOSAME) && + ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) == + HA_NOSAME) && !table->fulltext_searched) { if (const_ref == eq_part) @@ -2020,7 +2021,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, if (found_part == PREV_BITS(uint,keyinfo->key_parts)) { /* use eq key */ max_key_part= (uint) ~0; - if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) + if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | + HA_END_SPACE_KEY)) == HA_NOSAME) { tmp=prev_record_reads(join,found_ref); records=1.0; @@ -2520,8 +2522,8 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, if (j->type == JT_FT) /* no-op */; else if (j->type == JT_CONST) j->table->const_table=1; - else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) - != HA_NOSAME) || + else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | + HA_END_SPACE_KEY)) != HA_NOSAME) || keyparts != keyinfo->key_parts) j->type=JT_REF; /* Must read with repeat */ else if (ref_key == j->ref.key_copy) @@ -5814,7 +5816,7 @@ part_of_refkey(TABLE *table,Field *field) for (uint part=0 ; part < ref_parts ; part++,key_part++) if (field->eq(key_part->field) && - !(key_part->key_part_flag & HA_PART_KEY)) + !(key_part->key_part_flag & HA_PART_KEY_SEG)) return table->reginfo.join_tab->ref.items[part]; } return (Item*) 0; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 94ecf33b9c6..d827d8c403c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -288,10 +288,10 @@ static int sort_keys(KEY *a, KEY *b) { if (!(b->flags & HA_NOSAME)) return -1; - if ((a->flags ^ b->flags) & HA_NULL_PART_KEY) + if ((a->flags ^ b->flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) { /* Sort NOT NULL keys before other keys */ - return (a->flags & HA_NULL_PART_KEY) ? 1 : -1; + return (a->flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; } if (a->name == primary_key_name) return -1; @@ -1695,8 +1695,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } /* - ** Collect all keys which isn't in drop list. Add only those - ** for which some fields exists. + Collect all keys which isn't in drop list. Add only those + for which some fields exists. */ List_iterator key_it(keys); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d5034644830..af5c48fdb87 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -544,6 +544,26 @@ int multi_update::prepare(List ¬_used_values) for (i=0 ; i < table_count ; i++) set_if_bigger(max_fields, fields_for_table[i]->elements); copy_field= new Copy_field[max_fields]; + + /* + Mark all copies of tables that are updates to ensure that + init_read_record() will not try to enable a cache on them + + The problem is that for queries like + + UPDATE t1, t1 AS t2 SET t1.b=t2.c WHERE t1.a=t2.a; + + the row buffer may contain things that doesn't match what is on disk + which will cause an error when reading a row. + (This issue is mostly relevent for MyISAM tables) + */ + for (table_ref= all_tables; table_ref; table_ref=table_ref->next) + { + TABLE *table=table_ref->table; + if (!(tables_to_update & table->map) && + check_dup(table_ref->db, table_ref->real_name, update_tables)) + table->no_cache= 1; // Disable row cache + } DBUG_RETURN(thd->fatal_error != 0); } @@ -684,7 +704,7 @@ multi_update::~multi_update() { TABLE_LIST *table; for (table= update_tables ; table; table= table->next) - table->table->no_keyread=0; + table->table->no_keyread= table->table->no_cache= 0; if (tmp_tables) { diff --git a/sql/table.cc b/sql/table.cc index 0789f7469e7..c8def7441fd 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -430,14 +430,17 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) { /* - If the UNIQUE key don't have NULL columns, declare this as - a primary key. + If the UNIQUE key doesn't have NULL columns and is not a part key + declare this as a primary key. */ primary_key=key; for (i=0 ; i < keyinfo->key_parts ;i++) { - if (!key_part[i].fieldnr || - outparam->field[key_part[i].fieldnr-1]->null_ptr) + uint fieldnr= key_part[i].fieldnr; + if (!fieldnr || + outparam->field[fieldnr-1]->null_ptr || + outparam->field[fieldnr-1]->key_length() != + key_part[i].length) { primary_key=MAX_KEY; // Can't be used break; @@ -476,6 +479,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, keyinfo->extra_length+=HA_KEY_BLOB_LENGTH; key_part->store_length+=HA_KEY_BLOB_LENGTH; keyinfo->key_length+= HA_KEY_BLOB_LENGTH; + /* + Mark that there may be many matching values for one key + combination ('a', 'a ', 'a '...) + */ + if (!(field->flags & BINARY_FLAG)) + keyinfo->flags|= HA_END_SPACE_KEY; } if (i == 0 && key != primary_key) field->flags |= @@ -513,7 +522,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, } if (field->key_length() != key_part->length) { - key_part->key_part_flag|= HA_PART_KEY; + key_part->key_part_flag|= HA_PART_KEY_SEG; if (field->type() != FIELD_TYPE_BLOB) { // Create a new field field=key_part->field=field->new_field(&outparam->mem_root, @@ -527,7 +536,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, as we need to test for NULL = NULL. */ if (field->real_maybe_null()) - key_part->key_part_flag|= HA_PART_KEY; + key_part->key_part_flag|= HA_PART_KEY_SEG; } else { // Error: shorten key diff --git a/sql/table.h b/sql/table.h index 57be97ffbda..f3b0e148cc0 100644 --- a/sql/table.h +++ b/sql/table.h @@ -101,7 +101,7 @@ struct st_table { my_bool fulltext_searched; my_bool crashed; my_bool is_view; - my_bool no_keyread; + my_bool no_keyread, no_cache; Field *next_number_field, /* Set if next_number is activated */ *found_next_number_field, /* Set on open */ *rowid_field; diff --git a/sql/time.cc b/sql/time.cc index bf218fa58ab..5dc229b1d88 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -125,6 +125,8 @@ long my_gmt_sec(TIME *t, long *my_timezone) tmp-=t->minute*60 + t->second; // Move to previous hour } *my_timezone= current_timezone; + if (tmp < 0 && t->year <= 1900+YY_PART_YEAR) + tmp= 0; return (long) tmp; } /* my_gmt_sec */ @@ -445,7 +447,7 @@ time_t str_to_timestamp(const char *str,uint length) if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) return(0); - if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) { current_thd->cuted_fields++; return(0); -- cgit v1.2.1 From 0a79eedb5d6dfb24640b49288b9fdb003c6b00b2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Dec 2003 13:14:59 -0800 Subject: sql_delete.cc, sql_update.cc, sql_class.h: Simplification of the previous fix for multi-update/delete. sql/sql_class.h: Simplification of the previous fix for multi-update/delete. sql/sql_update.cc: Simplification of the previous fix for multi-update/delete. sql/sql_delete.cc: Simplification of the previous fix for multi-update/delete. --- sql/sql_class.h | 4 +--- sql/sql_delete.cc | 11 +++++------ sql/sql_update.cc | 5 ++--- 3 files changed, 8 insertions(+), 12 deletions(-) (limited to 'sql') diff --git a/sql/sql_class.h b/sql/sql_class.h index c487e212e24..0d0e0d7fbc5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -844,11 +844,10 @@ class multi_delete : public select_result TABLE_LIST *delete_tables, *table_being_deleted; Unique **tempfiles; THD *thd; - ha_rows deleted; + ha_rows deleted, found; uint num_of_tables; int error; bool do_delete, transactional_tables, log_delayed, normal_tables; - bool tempfiles_inited; public: multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables); @@ -876,7 +875,6 @@ class multi_update : public select_result Copy_field *copy_field; enum enum_duplicates handle_duplicates; bool do_update, trans_safe, transactional_tables, log_delayed; - bool tmp_tables_inited; public: multi_update(THD *thd_arg, TABLE_LIST *ut, List *fields, diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 399f237bf2f..bdf2cf85749 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -234,10 +234,9 @@ extern "C" int refposcmp2(void* arg, const void *a,const void *b) multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables_arg) - : delete_tables(dt), thd(thd_arg), deleted(0), + : delete_tables(dt), thd(thd_arg), deleted(0), found(0), num_of_tables(num_of_tables_arg), error(0), - do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0), - tempfiles_inited(0) + do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0) { tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1)); } @@ -298,7 +297,6 @@ multi_delete::initialize_tables(JOIN *join) table->file->ref_length, MEM_STRIP_BUF_SIZE); } - tempfiles_inited= 1; init_ftfuncs(thd,1); DBUG_RETURN(thd->fatal_error != 0); } @@ -339,6 +337,7 @@ bool multi_delete::send_data(List &values) continue; table->file->position(table->record[0]); + found++; if (secure_counter < 0) { @@ -414,7 +413,7 @@ int multi_delete::do_deletes(bool from_send_error) if (from_send_error) { - /* Found out table number for 'table_being_deleted' */ + /* Found out table number for 'table_being_deleted*/ for (TABLE_LIST *aux=delete_tables; aux != table_being_deleted; aux=aux->next) @@ -424,7 +423,7 @@ int multi_delete::do_deletes(bool from_send_error) table_being_deleted = delete_tables; do_delete= 0; - if (!tempfiles_inited) + if (!found) DBUG_RETURN(0); for (table_being_deleted=table_being_deleted->next; table_being_deleted ; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 19df0661db3..959abcae39c 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -440,7 +440,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, :all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list), values(value_list), table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg), - do_update(1), trans_safe(0), tmp_tables_inited(0) + do_update(1), trans_safe(0) {} @@ -622,7 +622,6 @@ multi_update::initialize_tables(JOIN *join) DBUG_RETURN(1); tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE); } - tmp_tables_inited= 1; DBUG_RETURN(0); } @@ -823,7 +822,7 @@ int multi_update::do_updates(bool from_send_error) do_update= 0; // Don't retry this function - if (!tmp_tables_inited) + if (!found) DBUG_RETURN(0); for (cur_table= update_tables; cur_table ; cur_table= cur_table->next) { -- cgit v1.2.1 From 51c54cd7744103b4876c61dca3662ed91d3a8dea Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Dec 2003 21:26:44 -0400 Subject: added checking for old cuted value in Field_enum::store (bug #2023) mysql-test/r/type_enum.result: added tests for wrong enum values (bug #2023) mysql-test/t/type_enum.test: added tests for wrong enum values (bug #2023) --- sql/field.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index d43089ec35c..a2734835cf9 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4623,7 +4623,7 @@ void Field_enum::store(const char *from,uint length) uint tmp=find_enum(typelib,from,length); if (!tmp) { - if (length < 6) // Can't be more than 99999 enums + if (from && length < 6) // Can't be more than 99999 enums { /* This is for reading numbers with LOAD DATA INFILE */ char buff[7], *end; -- cgit v1.2.1 From 5bbc3afd6b3f7adca5d622a95556422dbc1d3fea Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Dec 2003 22:02:50 -0400 Subject: refixed last vva patch with monty's instructions --- sql/field.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index a2734835cf9..43244a2f8a6 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4623,7 +4623,7 @@ void Field_enum::store(const char *from,uint length) uint tmp=find_enum(typelib,from,length); if (!tmp) { - if (from && length < 6) // Can't be more than 99999 enums + if (length < 6) // Can't be more than 99999 enums { /* This is for reading numbers with LOAD DATA INFILE */ char buff[7], *end; @@ -4721,7 +4721,7 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)), { uint tmp=(uint) Field_enum::val_int(); if (!tmp || tmp > typelib->count) - val_ptr->length(0); + val_ptr->set((char*)"",0); else val_ptr->set((const char*) typelib->type_names[tmp-1], (uint) strlen(typelib->type_names[tmp-1])); -- cgit v1.2.1 From afb07566181f3bca7f49f3ac5f7fc0deadccf0c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Dec 2003 06:39:52 +0200 Subject: Extend max_allowed_packet to 2G in mysql and mysqldump (Bug #2105) Don't dump data for MRG_ISAM or MRG_MYISAM tables. (Bug #1846) Ensure that 'lower_case_table_names' is always set on case insensitive file systems. (Bug #1812) One can now configure MySQL as windows service as a normal user. (Bug #1802) Database names is now compared with lower case in ON clause when lower_case_table_names is set. (Bug #1736) IGNORE ... LINES option didn't work when used with fixed length rows. (Bug #1704) Change INSERT DELAYED ... SELECT... to INSERT .... SELECT (Bug #1983) Safety fix for service 'mysql start' (Bug #1815) client/mysql.cc: Extend max_allowed_packet to 2G (Bug #2105) client/mysqldump.c: Extend max_allowed_packet to 2G (Bug #2105) Don't dump data for MRG_ISAM or MRG_MYISAM tables. (Bug #1846) configure.in: Test for file linux/config.h include/my_global.h: Portability fix (Bug #1924) mysql-test/r/insert.result: Update test results mysql-test/r/loaddata.result: Update test results mysql-test/r/lowercase_table.result: Update test results mysql-test/t/insert.test: Test INSERT ... DELAYED ... SELECT mysql-test/t/loaddata.test: Added test of LOAD DATA INFILE ... IGNORE # LINES for fixed size tables mysql-test/t/lowercase_table.test: Test mixed lower/uppercase database names sql/item.cc: Made function not inline (to make it easier to modify it without recompilation of all files) sql/item.h: Moved function to item.cc sql/mysqld.cc: Merge pidfile create code Ensure that 'lower_case_table_names' is always set on case insensitive file systems. (Bug #1812) sql/nt_servc.cc: One can now configure MySQL as windows service as a normal user. (Bug #1802) sql/sql_base.cc: Database names is now compared with lower case in ON clause when lower_case_table_names is set. (Bug #1736) sql/sql_class.h: Fixed type sql/sql_load.cc: IGNORE ... LINES option didn't work when used with fixed length rows. (Bug #1704) sql/sql_parse.cc: Change INSERT DELAYED ... SELECT... to INSERT .... SELECT strings/ctype-tis620.c: Ensure that memory is freed properly (Partly becasue of bug #1770) Bar should check the proposed patch in #1770 if we can use it support-files/mysql.server.sh: Safety fix (Bug #1815) --- sql/item.cc | 8 +++++ sql/item.h | 4 +-- sql/mysqld.cc | 92 ++++++++++++++++++++++++++++++++++++++++++-------------- sql/nt_servc.cc | 4 +-- sql/sql_base.cc | 13 ++++++++ sql/sql_class.h | 2 +- sql/sql_load.cc | 63 +++++++++++++++++++++++++++++--------- sql/sql_parse.cc | 13 +++++--- 8 files changed, 152 insertions(+), 47 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 60fc383d757..fcc9372773a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -117,6 +117,14 @@ bool Item::get_time(TIME *ltime) return 0; } +Item_ident::Item_ident(const char *db_name_par,const char *table_name_par, + const char *field_name_par) + :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par) +{ + name = (char*) field_name_par; +} + + Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) { set_field(f); diff --git a/sql/item.h b/sql/item.h index e8a6313b6a0..f96f4cd506a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -119,9 +119,7 @@ public: const char *table_name; const char *field_name; Item_ident(const char *db_name_par,const char *table_name_par, - const char *field_name_par) - :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par) - { name = (char*) field_name_par; } + const char *field_name_par); const char *full_name() const; unsigned int size_of() { return sizeof(*this);} }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b75a94a261c..1bdb2300aba 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -500,6 +500,8 @@ static uint set_maximum_open_files(uint max_file_limit); static ulong find_bit_type(const char *x, TYPELIB *bit_lib); static void clean_up(bool print_message); static void clean_up_mutexes(void); +static int test_if_case_insensitive(const char *dir_name); +static void create_pid_file(); /**************************************************************************** ** Code to end mysqld @@ -1459,17 +1461,7 @@ static void start_signal_handler(void) { // Save vm id of this process if (!opt_bootstrap) - { - File pidFile; - if ((pidFile = my_create(pidfile_name,0664, - O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) - { - char buff[21]; - sprintf(buff,"%lu\n",(ulong) getpid()); - (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME)); - (void) my_close(pidFile,MYF(0)); - } - } + create_pid_file(); // no signal handler } @@ -1753,17 +1745,8 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) /* Save pid to this process (or thread on Linux) */ if (!opt_bootstrap) - { - File pidFile; - if ((pidFile = my_create(pidfile_name,0664, - O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) - { - char buff[21]; - sprintf(buff,"%lu",(ulong) getpid()); - (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME)); - (void) my_close(pidFile,MYF(0)); - } - } + create_pid_file(); + #ifdef HAVE_STACK_TRACE_ON_SEGV if (opt_do_pstack) { @@ -4963,6 +4946,17 @@ static void fix_paths(void) if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE)))) exit(1); } + + /* + Ensure that lower_case_table_names is set on system where we have case + insensitive names. If this is not done the users MyISAM tables will + get corrupted if accesses with names of different case. + */ + if (!lower_case_table_names && + test_if_case_insensitive(mysql_real_data_home) == 1) + { + sql_print_error("Warning: Setting lower_case_table_names=1 becasue file system %s is case insensitve", mysql_real_data_home); + } } @@ -5096,6 +5090,60 @@ skipp: ; } /* find_bit_type */ +/* + Check if file system used for databases is case insensitive + + SYNOPSIS + test_if_case_sensitive() + dir_name Directory to test + + RETURN + -1 Don't know (Test failed) + 0 File system is case sensitive + 1 File system is case insensitive +*/ + +static int test_if_case_insensitive(const char *dir_name) +{ + int result= 0; + File file; + char buff[FN_REFLEN], buff2[FN_REFLEN]; + MY_STAT stat_info; + + fn_format(buff, glob_hostname, dir_name, ".lower-test", + MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR); + fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST", + MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR); + (void) my_delete(buff2, MYF(0)); + if ((file= my_create(buff, 0666, O_RDWR, MYF(0))) < 0) + { + sql_print_error("Warning: Can't create test file %s", buff); + return -1; + } + my_close(file, MYF(0)); + if (my_stat(buff2, &stat_info, MYF(0))) + result= 1; // Can access file + (void) my_delete(buff, MYF(MY_WME)); + return result; +} + + +/* Create file to store pid number */ + +static void create_pid_file() +{ + File file; + if ((file = my_create(pidfile_name,0664, + O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) + { + char buff[21]; + sprintf(buff,"%lu\n",(ulong) getpid()); + (void) my_write(file, buff,strlen(buff),MYF(MY_WME)); + (void) my_close(file, MYF(0)); + } +} + + /***************************************************************************** Instantiate templates *****************************************************************************/ diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index b18d3d00d88..8a3757a9768 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -496,9 +496,9 @@ BOOL NTService::IsService(LPCSTR ServiceName) BOOL ret_value=FALSE; SC_HANDLE service, scm; - if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)) + if ((scm= OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE))) { - if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS ))) + if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS ))) { ret_value=TRUE; CloseServiceHandle(service); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index dd80062d6e7..e65b84ff184 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1721,6 +1721,19 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) const char *table_name=item->table_name; const char *name=item->field_name; uint length=(uint) strlen(name); + char name_buff[NAME_LEN+1]; + + if (db && lower_case_table_names) + { + /* + convert database to lower case for comparision. + We can't do this in Item_field as this would change the + 'name' of the item which may be used in the select list + */ + strmake(name_buff, db, sizeof(name_buff)-1); + casedn_str(name_buff); + db= name_buff; + } if (table_name) { /* Qualified field */ diff --git a/sql/sql_class.h b/sql/sql_class.h index 0d0e0d7fbc5..e4e118c0b29 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -608,7 +608,7 @@ public: String *field_term,*enclosed,*line_term,*line_start,*escaped; bool opt_enclosed; bool dumpfile; - uint skip_lines; + ulong skip_lines; sql_exchange(char *name,bool dumpfile_flag); ~sql_exchange() {} }; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index e692e7b8dab..7c3e7b8e877 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -71,10 +71,11 @@ public: }; static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table, - List &fields, READ_INFO &read_info); + List &fields, READ_INFO &read_info, + ulong skip_lines); static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, List &fields, READ_INFO &read_info, - String &enclosed); + String &enclosed, ulong skip_lines); int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, @@ -85,14 +86,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, File file; TABLE *table; int error; - String *field_term=ex->field_term,*escaped=ex->escaped, - *enclosed=ex->enclosed; + String *field_term=ex->field_term,*escaped=ex->escaped; + String *enclosed=ex->enclosed; bool is_fifo=0; LOAD_FILE_INFO lf_info; char *db = table_list->db; // This is never null /* If no current database, use database where table is located */ char *tdb= thd->db ? thd->db : db; bool transactional_table, log_delayed; + ulong skip_lines= ex->skip_lines; DBUG_ENTER("mysql_load"); #ifdef EMBEDDED_LIBRARY @@ -235,16 +237,18 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, thd->count_cuted_fields=1; /* calc cuted fields */ thd->cuted_fields=0L; - if (ex->line_term->length() && field_term->length()) + /* Skip lines if there is a line terminator */ + if (ex->line_term->length()) { - // ex->skip_lines needs to be preserved for logging - uint skip_lines = ex->skip_lines; - while (skip_lines--) + /* ex->skip_lines needs to be preserved for logging */ + while (skip_lines > 0) { + skip_lines--; if (read_info.next_line()) break; } } + if (!(error=test(read_info.error))) { uint save_time_stamp=table->time_stamp; @@ -260,9 +264,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->file->deactivate_non_unique_index((ha_rows) 0); table->copy_blobs=1; if (!field_term->length() && !enclosed->length()) - error=read_fixed_length(thd,info,table,fields,read_info); + error=read_fixed_length(thd,info,table,fields,read_info, + skip_lines); else - error=read_sep_field(thd,info,table,fields,read_info,*enclosed); + error=read_sep_field(thd,info,table,fields,read_info,*enclosed, + skip_lines); if (table->file->extra(HA_EXTRA_NO_CACHE)) error=1; /* purecov: inspected */ if (table->file->activate_all_index(thd)) @@ -271,7 +277,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->time_stamp=save_time_stamp; table->next_number_field=0; } - if (file >= 0) my_close(file,MYF(0)); + if (file >= 0) + my_close(file,MYF(0)); free_blobs(table); /* if pack_blob was used */ table->copy_blobs=0; thd->count_cuted_fields=0; /* Don`t calc cuted fields */ @@ -369,7 +376,7 @@ err: static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, - READ_INFO &read_info) + READ_INFO &read_info, ulong skip_lines) { List_iterator_fast it(fields); Item_field *sql_field; @@ -388,6 +395,17 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, my_error(ER_SERVER_SHUTDOWN,MYF(0)); DBUG_RETURN(1); } + if (skip_lines) + { + /* + We could implement this with a simple seek if: + - We are not using DATA INFILE LOCAL + - escape character is "" + - line starting prefix is "" + */ + skip_lines--; + continue; + } it.rewind(); byte *pos=read_info.row_start; #ifdef HAVE_purify @@ -444,7 +462,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, List &fields, READ_INFO &read_info, - String &enclosed) + String &enclosed, ulong skip_lines) { List_iterator_fast it(fields); Item_field *sql_field; @@ -494,6 +512,12 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, } if (read_info.error) break; + if (skip_lines) + { + if (!--skip_lines) + thd->cuted_fields= 0L; // Reset warnings + continue; + } if (sql_field) { // Last record if (sql_field == (Item_field*) fields.head()) @@ -821,7 +845,18 @@ found_eof: } /* -** One can't use fixed length with multi-byte charset ** + Read a row with fixed length. + + NOTES + The row may not be fixed size on disk if there are escape + characters in the file. + + IMPLEMENTATION NOTE + One can't use fixed length with multi-byte charset ** + + RETURN + 0 ok + 1 error */ int READ_INFO::read_fixed_length() diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 01d6500260f..d59a26f5ce8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1971,12 +1971,11 @@ mysql_execute_command(void) case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT_SELECT: { - - /* - Check that we have modify privileges for the first table and - select privileges for the rest - */ { + /* + Check that we have modify privileges for the first table and + select privileges for the rest + */ ulong privilege= (lex->sql_command == SQLCOM_INSERT_SELECT ? INSERT_ACL : INSERT_ACL | DELETE_ACL); TABLE_LIST *save_next=tables->next; @@ -1989,6 +1988,10 @@ mysql_execute_command(void) if ((res=check_table_access(thd, SELECT_ACL, save_next))) goto error; } + /* Fix lock for first table */ + if (tables->lock_type == TL_WRITE_DELAYED) + tables->lock_type == TL_WRITE; + /* Don't unlock tables until command is written to binary log */ select_lex->options|= SELECT_NO_UNLOCK; -- cgit v1.2.1 From c324fddc9cbeef8d56030b3c286b77c83914ff13 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Dec 2003 08:12:07 -0500 Subject: Fixed bug in last push found by valgrind myisam/mi_dbug.c: Added comment to warn about probabably unimportant valgrind warning sql/opt_range.cc: Fixed bug in last push (did not fill max string properly with end space) sql/sql_update.cc: Initalize not initialized variable --- sql/opt_range.cc | 15 +++++++-------- sql/sql_update.cc | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 74fa237fd73..74e3f855db7 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1062,7 +1062,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, if (field->key_type() == HA_KEYTYPE_VARTEXT) copies= 2; str= str2= (char*) alloc_root(param->mem_root, - (key_part->part_length+maybe_null)*copies); + (key_part->part_length+maybe_null)*copies+1); if (!str) DBUG_RETURN(0); if (maybe_null) @@ -1078,16 +1078,15 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, uint length= uint2korr(str+maybe_null); char *end; str2= str+ key_part->part_length + maybe_null; - /* remove end space. The 2 is for the packed length */ - while (length > 0 && str[length+2+maybe_null-1] == ' ') + /* remove end space */ + while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ') length--; int2store(str+maybe_null, length); /* Create key that is space filled */ - memcpy(str2, str, length+2+maybe_null); - end= str2+ maybe_null + key_part->part_length; - for (char *pos= str2+ 2+ length + maybe_null; pos < end ; pos++) - *pos++= ' '; - int2store(str2+maybe_null, key_part->part_length); + memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null); + bfill(str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null, + key_part->part_length-length - HA_KEY_BLOB_LENGTH, ' '); + int2store(str2+maybe_null, key_part->part_length - HA_KEY_BLOB_LENGTH); } if (!(tree=new SEL_ARG(field,str,str2))) DBUG_RETURN(0); // out of memory diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 36ceef23740..27b498d350f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -440,7 +440,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, :all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list), values(value_list), table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg), - do_update(1), trans_safe(0) + do_update(1), trans_safe(0), transactional_tables(1) {} -- cgit v1.2.1 From e97722e495495468ef8a3c5e12d7080738a99841 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 16 Dec 2003 11:10:50 +0100 Subject: Fix for BUG#2083 "EE_ error codes (EE_DELETE, EE_WRITE) end up in the binlog, making slave stop". The problem was that during execution of the command on the master, an error can occur (for example, not space left on device, then mysqld waits and when there is space it completes successfully: so finally it worked but the error EE_WRITE remains in thd->net.last_errno and thd->net.last_error). To know if finally the command succeeded, we test the 'error' variable in every place, and if it shows no failure we reset thd->net.last_err* using the function THD::clear_error() which is backported from 4.1. A new test to see if now only real errors get to the binlog (note: the test uses "rm"). Also a bit of memory free/alloc saving in log_event.cc (do not free the whole mem_root after every query in the slave SQL thread: we can keep the initial block of it; which will be freed when the thread terminates). sql/log_event.cc: In the slave SQL thread, it's a waste to free the initial block of the mem_root after every query. We can instead keep it. It will be freed when the thread terminates (in THD::~THD()). sql/sql_acl.cc: clear the error in thd->net.last_errno as there was no error sql/sql_base.cc: clear the error in thd->net.last_errno as there was no error sql/sql_class.h: Backport of THD::clear_error() from 4.1: clears the error in thd->net.last_errno sql/sql_db.cc: clear the error in thd->net.last_errno as there was no error sql/sql_delete.cc: clear the error in thd->net.last_errno as there was no error sql/sql_insert.cc: clear the error in thd->net.last_errno as there was no error sql/sql_parse.cc: clear the error in thd->net.last_errno as there was no error sql/sql_rename.cc: clear the error in thd->net.last_errno as there was no error sql/sql_table.cc: clear the error in thd->net.last_errno as there was no error sql/sql_update.cc: clear the error in thd->net.last_errno as there was no error --- sql/log_event.cc | 6 +++--- sql/sql_acl.cc | 1 + sql/sql_base.cc | 2 +- sql/sql_class.h | 9 +++++++++ sql/sql_db.cc | 2 ++ sql/sql_delete.cc | 5 +++++ sql/sql_insert.cc | 6 +++++- sql/sql_parse.cc | 2 ++ sql/sql_rename.cc | 1 + sql/sql_table.cc | 5 +++++ sql/sql_update.cc | 4 ++++ 11 files changed, 38 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/log_event.cc b/sql/log_event.cc index 9779b7401dd..4413a77c364 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1922,7 +1922,7 @@ Default database: '%s'", // assume no convert for next query unless set explictly thd->variables.convert_set = 0; close_thread_tables(thd); - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return (thd->query_error ? thd->query_error : Log_event::exec_event(rli)); } @@ -2094,10 +2094,10 @@ Slave: load data infile on table '%s' at log position %s in log \ slave_print_error(rli,sql_errno,"\ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", err, (char*)table_name, print_slave_db_safe(db)); - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return 1; } - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); if (thd->fatal_error) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 03a359d44e7..e8e2f808b7e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1130,6 +1130,7 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->user ? acl_user->user : "", acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); + thd->clear_error(); mysql_update_log.write(thd, buff, query_length); Query_log_event qinfo(thd, buff, query_length, 0); mysql_bin_log.write(&qinfo); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e4694adb9a2..cf42109fb9a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -575,8 +575,8 @@ void close_temporary_tables(THD *thd) if (query && found_user_tables && mysql_bin_log.is_open()) { /* The -1 is to remove last ',' */ + thd->clear_error(); Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0); - qinfo.error_code=0; mysql_bin_log.write(&qinfo); } thd->temporary_tables=0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 9287a0c8c79..2899c643536 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -590,6 +590,15 @@ public: void add_changed_table(TABLE *table); void add_changed_table(const char *key, long key_length); CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length); +#ifndef EMBEDDED_LIBRARY + inline void clear_error() + { + net.last_error[0]= 0; + net.last_errno= 0; + } +#else + void clear_error(); +#endif }; /* Flags for the THD::system_thread (bitmap) variable */ diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 6251b1ec624..6c11067ac8f 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -86,6 +86,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -176,6 +177,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 34a79ecd78d..ef90cd55730 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -175,6 +175,8 @@ cleanup: mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -479,6 +481,8 @@ bool multi_delete::send_eof() mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && !normal_tables) @@ -591,6 +595,7 @@ end: mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, thd->tmp_table); mysql_bin_log.write(&qinfo); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3414e76e092..00545f04c44 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -310,6 +310,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -1196,7 +1198,7 @@ bool delayed_insert::handle_inserts(void) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); using_ignore=1; } - thd.net.last_errno = 0; // reset error for binlog + thd.clear_error(); // reset error for binlog if (write_record(table,&info)) { info.error_count++; // Ignore errors @@ -1391,6 +1393,8 @@ bool select_insert::send_eof() mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + if (!error) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, table->file->has_transactions()); mysql_bin_log.write(&qinfo); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c867112bb2a..9be861cf2c9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2461,6 +2461,7 @@ mysql_execute_command(void) mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -2481,6 +2482,7 @@ mysql_execute_command(void) mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index d7e998264f3..05d31c173d3 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -82,6 +82,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 94ecf33b9c6..07fc6971502 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -237,6 +237,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, tmp_table_deleted && !some_tables_deleted); mysql_bin_log.write(&qinfo); @@ -779,6 +780,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, test(create_info->options & HA_LEX_CREATE_TMP_TABLE)); @@ -1561,6 +1563,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -1931,6 +1934,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -2063,6 +2067,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d5034644830..74a4c80bfce 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -319,6 +319,8 @@ int mysql_update(THD *thd, mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + if (error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && transactional_table) @@ -939,6 +941,8 @@ bool multi_update::send_eof() mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { + if (local_error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && trans_safe) -- cgit v1.2.1 From 3357bc7ea31aa3432394d0a1a17c1b9b37547897 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 16 Dec 2003 13:20:17 +0200 Subject: Portability fixes (mostly test suite) Make ENGINE= an alias for TYPE= (Compabiltiy with 4.1) Fix when using symlinked data files and realpath() is not working client/mysqltest.c: Copied mysqltest from 4.1 and modified this to compile in 4.0 This was needed to get replace_columns to work. include/my_sys.h: Stop compiler warnings about alloca on freebsd myisam/mi_check.c: Fix when using symlinked data files and realpath() is not working mysql-test/r/handler.result: test engine= mysql-test/r/rpl_max_relay_size.result: Use replace_columns to replace some 'not constant' columns mysql-test/r/rpl_rotate_logs.result: Use replace_columns to replace some 'not constant' columns mysql-test/r/rpl_trunc_binlog.result: Use replace_columns to replace some 'not constant' columns mysql-test/t/handler.test: test engine= mysql-test/t/rpl_log_pos.test: Use replace_columns to replace some 'not constant' columns mysql-test/t/rpl_max_relay_size.test: Use replace_columns to replace some 'not constant' columns mysql-test/t/rpl_rotate_logs.test: Use replace_columns to replace some 'not constant' columns mysql-test/t/rpl_trunc_binlog.test: Use replace_columns to replace some 'not constant' columns mysys/my_symlink.c: More debugging sql/lex.h: Make ENGINE= an alias for TYPE= sql/mysqld.cc: Code cleanup strings/strto.c: Fix for True64 strings/strtoll.c: Fix for True64 strings/strtoull.c: Remove not needed include file --- sql/lex.h | 1 + sql/mysqld.cc | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/lex.h b/sql/lex.h index 3bbe1da185e..10ba11f2169 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -131,6 +131,7 @@ static SYMBOL symbols[] = { { "DYNAMIC", SYM(DYNAMIC_SYM),0,0}, { "END", SYM(END),0,0}, { "ELSE", SYM(ELSE),0,0}, + { "ENGINE", SYM(TYPE_SYM),0,0}, /* Alias for TYPE= */ { "ESCAPE", SYM(ESCAPE_SYM),0,0}, { "ESCAPED", SYM(ESCAPED),0,0}, { "ENABLE", SYM(ENABLE_SYM),0,0}, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1bdb2300aba..cc17b4e97fd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2593,8 +2593,8 @@ int main(int argc, char **argv) { char file_path[FN_REFLEN]; my_path(file_path, argv[0], ""); /* Find name in path */ - fn_format(file_path,argv[0],file_path,"",MY_REPLACE_DIR+ - MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS); + fn_format(file_path,argv[0],file_path,"", + MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS); if (argc == 2) { if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME, -- cgit v1.2.1 From 4bdfe0fb0107f2fb3e9cfb1c8a417e1028c67dcc Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 16 Dec 2003 14:40:57 +0200 Subject: Fixes for last pull libmysqld/lib_sql.cc: Fixed compilation error in embedded library (from last pull) sql/field.cc: Safer timestamp year checking (as 1969 can be in timestamp) --- sql/field.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 05779a312d8..feab607400c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2589,7 +2589,7 @@ void Field_timestamp::store(longlong nr) { long not_used; - if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) { current_thd->cuted_fields++; timestamp=0; -- cgit v1.2.1